diff --git a/components/esp_netif/include/esp_netif.h b/components/esp_netif/include/esp_netif.h index 849e5fa87fe..5b863cd379c 100644 --- a/components/esp_netif/include/esp_netif.h +++ b/components/esp_netif/include/esp_netif.h @@ -862,6 +862,43 @@ int esp_netif_get_all_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[]); */ int esp_netif_get_all_preferred_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[]); +#if CONFIG_LWIP_ND6_SUPPORT_STATIC_ENTRIES +/** + * @brief Add or update a static (permanent) IPv6 neighbor cache entry + * + * Installs a fixed IPv6 -> link-layer address mapping that bypasses Neighbor + * Discovery: no Neighbor Solicitation/Advertisement is exchanged for this + * address, the entry never ages out and is never overwritten by incoming + * advertisements. Calling again with the same address updates the mapping. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] addr Neighbor's IPv6 address + * @param[in] mac Neighbor's link-layer address (interface hwaddr_len bytes) + * + * @return + * - ESP_OK on success + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS on invalid arguments + * - ESP_FAIL if the entry could not be installed (e.g. neighbor cache full) + */ +esp_err_t esp_netif_add_static_neighbor(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr, const uint8_t *mac); + +/** + * @brief Remove a static IPv6 neighbor cache entry + * + * Removes an entry previously added with esp_netif_add_static_neighbor(). + * Dynamic (non-static) entries are left untouched. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] addr Neighbor's IPv6 address + * + * @return + * - ESP_OK on success + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS on invalid arguments + * - ESP_FAIL if no matching static entry exists + */ +esp_err_t esp_netif_remove_static_neighbor(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr); +#endif /* CONFIG_LWIP_ND6_SUPPORT_STATIC_ENTRIES */ + /** * @brief Cause the TCP/IP stack to add an IPv6 address to the interface * diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c index 1d97405f477..4ea02f94877 100644 --- a/components/esp_netif/lwip/esp_netif_lwip.c +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -2483,6 +2483,56 @@ int esp_netif_get_all_preferred_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip } return addr_count; } + +#if CONFIG_LWIP_ND6_SUPPORT_STATIC_ENTRIES +typedef struct { + const esp_ip6_addr_t *addr; + const uint8_t *mac; +} esp_netif_static_neighbor_t; + +static esp_err_t esp_netif_add_static_neighbor_api(esp_netif_api_msg_t *msg) +{ + esp_netif_t *esp_netif = msg->esp_netif; + const esp_netif_static_neighbor_t *nbr = msg->data; + ip6_addr_t ip6; + + memcpy(&ip6, nbr->addr, sizeof(ip6_addr_t)); + if (nd6_add_static_neighbor(esp_netif->lwip_netif, &ip6, nbr->mac) != ERR_OK) { + return ESP_FAIL; + } + return ESP_OK; +} + +esp_err_t esp_netif_add_static_neighbor(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr, const uint8_t *mac) +{ + if (esp_netif == NULL || esp_netif->lwip_netif == NULL || addr == NULL || mac == NULL) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + esp_netif_static_neighbor_t nbr = { .addr = addr, .mac = mac }; + return esp_netif_lwip_ipc_call(esp_netif_add_static_neighbor_api, esp_netif, &nbr); +} + +static esp_err_t esp_netif_remove_static_neighbor_api(esp_netif_api_msg_t *msg) +{ + esp_netif_t *esp_netif = msg->esp_netif; + const esp_ip6_addr_t *addr = msg->data; + ip6_addr_t ip6; + + memcpy(&ip6, addr, sizeof(ip6_addr_t)); + if (nd6_remove_static_neighbor(esp_netif->lwip_netif, &ip6) != ERR_OK) { + return ESP_FAIL; + } + return ESP_OK; +} + +esp_err_t esp_netif_remove_static_neighbor(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr) +{ + if (esp_netif == NULL || esp_netif->lwip_netif == NULL || addr == NULL) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + return esp_netif_lwip_ipc_call(esp_netif_remove_static_neighbor_api, esp_netif, (void *)addr); +} +#endif /* CONFIG_LWIP_ND6_SUPPORT_STATIC_ENTRIES */ #endif esp_netif_flags_t esp_netif_get_flags(esp_netif_t *esp_netif) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index c45c70afefb..9500ed266b2 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -116,6 +116,15 @@ menu "LWIP" This option is used to disable the Network Discovery Protocol (NDP) if it is not required. Please use this option with caution, as the NDP is essential for IPv6 functionality within a local network. + config LWIP_ND6_SUPPORT_STATIC_ENTRIES + bool "Enable API for static IPv6 neighbor cache entries" + default n + depends on LWIP_ND6 + help + Enable APIs to add/remove permanent IPv6->MAC neighbor cache entries + that bypass Neighbor Discovery (no NS/NA). IPv6 counterpart of + ETHARP_SUPPORT_STATIC_ENTRIES. + config LWIP_FORCE_ROUTER_FORWARDING bool "LWIP Force Router Forwarding Enable/Disable" default n diff --git a/components/lwip/lwip b/components/lwip/lwip index 6233a15612e..9d2d804124d 160000 --- a/components/lwip/lwip +++ b/components/lwip/lwip @@ -1 +1 @@ -Subproject commit 6233a15612ea601ee866145f3ca0c46b7c36858f +Subproject commit 9d2d804124d0ada89777cfac83e0df2cfdef117d diff --git a/components/lwip/port/include/lwipopts.h b/components/lwip/port/include/lwipopts.h index 268caae8942..85e7b6037c2 100644 --- a/components/lwip/port/include/lwipopts.h +++ b/components/lwip/port/include/lwipopts.h @@ -1242,6 +1242,19 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min) #define LWIP_ND6 0 #endif +/** + * LWIP_ND6_SUPPORT_STATIC_ENTRIES==1: enable nd6_add_static_neighbor() and + * nd6_remove_static_neighbor() to manage permanent IPv6->MAC neighbor cache + * entries that bypass Neighbor Discovery (no NS/NA). Applied per-(netif,address) + * and does not affect NDP on other interfaces. IPv6 counterpart of + * ETHARP_SUPPORT_STATIC_ENTRIES. + */ +#ifdef CONFIG_LWIP_ND6_SUPPORT_STATIC_ENTRIES +#define LWIP_ND6_SUPPORT_STATIC_ENTRIES 1 +#else +#define LWIP_ND6_SUPPORT_STATIC_ENTRIES 0 +#endif + /** * LWIP_FORCE_ROUTER_FORWARDING==1: the router flag in NA packet will always set to 1, * otherwise, never set router flag for NA packets.