From c2535bb40bc2176b76ea8d000e6714d9d8b03814 Mon Sep 17 00:00:00 2001
From: Joel Cunningham <joel.cunningham@me.com>
Date: Tue, 14 Nov 2017 14:38:10 -0600
Subject: [PATCH] netconn: Add thread safe ARP cache APIs (task #14724)

Adds thread safe netconn ARP cache APIs
---
 CHANGELOG              |  3 +++
 src/api/api_lib.c      | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/include/lwip/api.h | 15 +++++++++++
 3 files changed, 87 insertions(+)

diff --git a/CHANGELOG b/CHANGELOG
index c43ece38..5877b286 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,9 @@ HISTORY
 
   ++ New features:
 
+  2017-11-14: Joel Cunningham
+  * netconn: Add thread safe ARP cache APIs (task #14724)
+
   2017-11-06: Axel Lin
   * TCP: kill existing connections with a LOWER priority than the one currently being opened.
     Previous implementations also kill existing connections of the SAME priority.
diff --git a/src/api/api_lib.c b/src/api/api_lib.c
index b92cf3b9..9640fe32 100644
--- a/src/api/api_lib.c
+++ b/src/api/api_lib.c
@@ -68,6 +68,9 @@
 #include "lwip/priv/api_msg.h"
 #include "lwip/priv/tcp_priv.h"
 #include "lwip/priv/tcpip_priv.h"
+#if LWIP_ARP && LWIP_IPV4
+#include "lwip/etharp.h"
+#endif /* LWIP_ARP && LWIP_IPV4 */
 
 #include <string.h>
 
@@ -1251,6 +1254,72 @@ netconn_gethostbyname(const char *name, ip_addr_t *addr)
 }
 #endif /* LWIP_DNS*/
 
+#if LWIP_ARP && LWIP_IPV4
+/**
+ * @ingroup netconn_common
+ * Add or update an entry in the ARP cache.
+ * For an update, ipaddr is used to find the cache entry.
+ *
+ * @param ipaddr IPv4 address of cache entry
+ * @param ethaddr hardware address mapped to ipaddr
+ * @param type type of ARP cache entry
+ * @return ERR_OK: entry added/updated, else error from err_t
+ */
+err_t
+netconn_arp_add(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, enum netconn_arp_entry type)
+{
+  err_t err;
+
+  /* We only support permanent entries currently */
+  LWIP_UNUSED_ARG(type);
+
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+#if LWIP_TCPIP_CORE_LOCKING
+  LOCK_TCPIP_CORE();
+  err = etharp_add_static_entry(ipaddr, ethaddr);
+  UNLOCK_TCPIP_CORE();
+#else
+  err = ERR_VAL;
+#endif /* LWIP_TCPIP_CORE_LOCKING */
+#else
+  err = ERR_VAL;
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+
+  return err;
+}
+
+/**
+ * @ingroup netconn_common
+ * Remove an entry in the ARP cache identified by ipaddr
+ *
+ * @param ipaddr IPv4 address of cache entry
+ * @param type type of ARP cache entry
+ * @return ERR_OK: entry removed, else error from err_t
+ */
+err_t
+netconn_arp_remove(const ip4_addr_t *ipaddr, enum netconn_arp_entry type)
+{
+  err_t err;
+
+  /* We only support permanent entries currently */
+  LWIP_UNUSED_ARG(type);
+
+#if ETHARP_SUPPORT_STATIC_ENTRIES
+#if LWIP_TCPIP_CORE_LOCKING
+  LOCK_TCPIP_CORE();
+  err = etharp_remove_static_entry(ipaddr);
+  UNLOCK_TCPIP_CORE();
+#else
+  err = ERR_VAL;
+#endif /* LWIP_TCPIP_CORE_LOCKING */
+#else
+  err = ERR_VAL;
+#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
+
+  return err;
+}
+#endif /* LWIP_ARP && LWIP_IPV4 */
+
 #if LWIP_NETCONN_SEM_PER_THREAD
 void
 netconn_thread_init(void)
diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h
index f6175ff0..8df2b1d6 100644
--- a/src/include/lwip/api.h
+++ b/src/include/lwip/api.h
@@ -48,6 +48,9 @@
 #include "lwip/sys.h"
 #include "lwip/ip_addr.h"
 #include "lwip/err.h"
+#if LWIP_ARP && LWIP_IPV4
+#include "lwip/prot/ethernet.h"
+#endif /* LWIP_ARP && LWIP_IPV4 */
 
 #ifdef __cplusplus
 extern "C" {
@@ -197,6 +200,14 @@ enum netconn_igmp {
 #define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */
 #endif /* LWIP_DNS */
 
+#if LWIP_ARP && LWIP_IPV4
+/* Used for netconn_arp_* APIs */
+enum netconn_arp_entry {
+  NETCONN_ARP_PERM /* Permanent entry */
+  /* Other entry types can be added here */
+};
+#endif /* LWIP_ARP && LWIP_IPV4 */
+
 /* forward-declare some structs to avoid to include their headers */
 struct ip_pcb;
 struct tcp_pcb;
@@ -353,6 +364,10 @@ err_t   netconn_gethostbyname(const char *name, ip_addr_t *addr);
 #define netconn_gethostbyname_addrtype(name, addr, dns_addrtype) netconn_gethostbyname(name, addr)
 #endif /* LWIP_IPV4 && LWIP_IPV6 */
 #endif /* LWIP_DNS */
+#if LWIP_ARP && LWIP_IPV4
+err_t netconn_arp_add(const ip4_addr_t *ipaddr, struct eth_addr *ethaddr, enum netconn_arp_entry type);
+err_t netconn_arp_remove(const ip4_addr_t *ipaddr, enum netconn_arp_entry type);
+#endif /* LWIP_ARP && LWIP_IPV4 */
 
 err_t   netconn_err(struct netconn *conn);
 #define netconn_recv_bufsize(conn)      ((conn)->recv_bufsize)
-- 
2.14.1

