fix(esp_netif): Mark esp_netif_next deprecated and fix usages

* Uses netif_find_if() in IPv6 examples
* Fixes esp_netif_next() usage in L2TAP
This commit is contained in:
David Cermak 2023-10-03 17:38:18 +02:00
parent 606363897c
commit 88d18e9a40
7 changed files with 97 additions and 118 deletions

View File

@ -979,11 +979,29 @@ int32_t esp_netif_get_event_id(esp_netif_t *esp_netif, esp_netif_ip_event_type_t
* to get atomic access between iteration steps rather that within a single iteration. * to get atomic access between iteration steps rather that within a single iteration.
* Therefore it is recommended to iterate over the interfaces inside esp_netif_tcpip_exec() * Therefore it is recommended to iterate over the interfaces inside esp_netif_tcpip_exec()
* *
* @note This API is deprecated. Please use esp_netif_next_unsafe() directly if all the system
* interfaces are under your control and you can safely iterate over them.
* Otherwise, iterate over interfaces using esp_netif_tcpip_exec(), or use esp_netif_find_if()
* to search in the list of netifs with defined predicate.
*
* @param[in] esp_netif Handle to esp-netif instance * @param[in] esp_netif Handle to esp-netif instance
* *
* @return First netif from the list if supplied parameter is NULL, next one otherwise * @return First netif from the list if supplied parameter is NULL, next one otherwise
*/ */
esp_netif_t *esp_netif_next(esp_netif_t *esp_netif); esp_netif_t *esp_netif_next(esp_netif_t *esp_netif)
__attribute__((deprecated("use esp_netif_next_unsafe() either directly or via esp_netif_tcpip_exec")));
/**
* @brief Iterates over list of interfaces without list locking. Returns first netif if NULL given as parameter
*
* Used for bulk search loops within TCPIP context, e.g. using esp_netif_tcpip_exec(), or if we're sure
* that the iteration is safe from our application perspective (e.g. no interface is removed between iterations)
*
* @param[in] esp_netif Handle to esp-netif instance
*
* @return First netif from the list if supplied parameter is NULL, next one otherwise
*/
esp_netif_t* esp_netif_next_unsafe(esp_netif_t* esp_netif);
/** /**
* @brief Predicate callback for esp_netif_find_if() used to find interface * @brief Predicate callback for esp_netif_find_if() used to find interface
@ -992,7 +1010,7 @@ esp_netif_t *esp_netif_next(esp_netif_t *esp_netif);
typedef bool (*esp_netif_find_predicate_t)(esp_netif_t *netif, void *ctx); typedef bool (*esp_netif_find_predicate_t)(esp_netif_t *netif, void *ctx);
/** /**
* @brief Return a netif pointer for the interface that meets criteria defined * @brief Return a netif pointer for the first interface that meets criteria defined
* by the callback * by the callback
* *
* @param fn Predicate function returning true for the desired interface * @param fn Predicate function returning true for the desired interface

View File

@ -812,7 +812,7 @@ static esp_err_t esp_netif_find_if_api(esp_netif_api_msg_t *msg)
{ {
find_if_api_t *find_if_api = msg->data; find_if_api_t *find_if_api = msg->data;
esp_netif_t *esp_netif = NULL; esp_netif_t *esp_netif = NULL;
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) { while ((esp_netif = esp_netif_next_unsafe(esp_netif)) != NULL) {
if (find_if_api->fn(esp_netif, find_if_api->ctx)) { if (find_if_api->fn(esp_netif, find_if_api->ctx)) {
*msg->p_esp_netif = esp_netif; *msg->p_esp_netif = esp_netif;
return ESP_OK; return ESP_OK;

View File

@ -107,31 +107,6 @@ esp_err_t esp_netif_add_to_list_unsafe(esp_netif_t* netif);
*/ */
esp_err_t esp_netif_remove_from_list_unsafe(esp_netif_t* netif); esp_err_t esp_netif_remove_from_list_unsafe(esp_netif_t* netif);
/**
* @brief Iterates over list of interfaces without list locking. Returns first netif if NULL given as parameter
*
* Used for bulk search loops to avoid locking and unlocking every iteration. esp_netif_list_lock and esp_netif_list_unlock
* must be used to guard the search loop
*
* @param[in] esp_netif Handle to esp-netif instance
*
* @return First netif from the list if supplied parameter is NULL, next one otherwise
*/
esp_netif_t* esp_netif_next_unsafe(esp_netif_t* netif);
/**
* @brief Locking network interface list. Use only in connection with esp_netif_next_unsafe
*
* @return ESP_OK on success, specific mutex error if failed to lock
*/
esp_err_t esp_netif_list_lock(void);
/**
* @brief Unlocking network interface list. Use only in connection with esp_netif_next_unsafe
*
*/
void esp_netif_list_unlock(void);
/** /**
* @brief Iterates over list of registered interfaces to check if supplied netif is listed * @brief Iterates over list of registered interfaces to check if supplied netif is listed
* *

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -333,6 +333,12 @@ static int l2tap_close(int fd)
return 0; return 0;
} }
// used to find a netif with the attached driver matching the argument
static bool netif_driver_matches(esp_netif_t *netif, void* driver)
{
return esp_netif_get_io_driver(netif) == driver;
}
static int l2tap_ioctl(int fd, int cmd, va_list args) static int l2tap_ioctl(int fd, int cmd, va_list args)
{ {
esp_netif_t *esp_netif; esp_netif_t *esp_netif;
@ -383,11 +389,8 @@ static int l2tap_ioctl(int fd, int cmd, va_list args)
case L2TAP_G_INTF_DEVICE: ; case L2TAP_G_INTF_DEVICE: ;
const char **str_p = va_arg(args, const char **); const char **str_p = va_arg(args, const char **);
*str_p = NULL; *str_p = NULL;
esp_netif = NULL; if ((esp_netif = esp_netif_find_if(netif_driver_matches, s_l2tap_sockets[fd].driver_handle)) != NULL) {
while ((esp_netif = esp_netif_next(esp_netif)) != NULL) { *str_p = esp_netif_get_ifkey(esp_netif);
if (s_l2tap_sockets[fd].driver_handle == esp_netif_get_io_driver(esp_netif)) {
*str_p = esp_netif_get_ifkey(esp_netif);
}
} }
break; break;
case L2TAP_S_DEVICE_DRV_HNDL: ; case L2TAP_S_DEVICE_DRV_HNDL: ;

View File

@ -43,23 +43,22 @@ bool example_is_our_netif(const char *prefix, esp_netif_t *netif)
return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0; return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix) - 1) == 0;
} }
esp_netif_t *get_example_netif_from_desc(const char *desc) static bool netif_desc_matches_with(esp_netif_t *netif, void *ctx)
{ {
esp_netif_t *netif = NULL; return strcmp(ctx, esp_netif_get_desc(netif)) == 0;
while ((netif = esp_netif_next(netif)) != NULL) {
if (strcmp(esp_netif_get_desc(netif), desc) == 0) {
return netif;
}
}
return netif;
} }
void example_print_all_netif_ips(const char *prefix) esp_netif_t *get_example_netif_from_desc(const char *desc)
{ {
return esp_netif_find_if(netif_desc_matches_with, (void*)desc);
}
static esp_err_t print_all_ips_tcpip(void* ctx)
{
const char *prefix = ctx;
// iterate over active interfaces, and print out IPs of "our" netifs // iterate over active interfaces, and print out IPs of "our" netifs
esp_netif_t *netif = NULL; esp_netif_t *netif = NULL;
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) { while ((netif = esp_netif_next_unsafe(netif)) != NULL) {
netif = esp_netif_next(netif);
if (example_is_our_netif(prefix, netif)) { if (example_is_our_netif(prefix, netif)) {
ESP_LOGI(TAG, "Connected to %s", esp_netif_get_desc(netif)); ESP_LOGI(TAG, "Connected to %s", esp_netif_get_desc(netif));
#if CONFIG_LWIP_IPV4 #if CONFIG_LWIP_IPV4
@ -78,6 +77,13 @@ void example_print_all_netif_ips(const char *prefix)
#endif #endif
} }
} }
return ESP_OK;
}
void example_print_all_netif_ips(const char *prefix)
{
// Print all IPs in TCPIP context to avoid potential races of removing/adding netifs when iterating over the list
esp_netif_tcpip_exec(print_all_ips_tcpip, (void*) prefix);
} }

View File

@ -215,34 +215,41 @@ static void send_ping(char *src_addr_str, char *dst_addr_str, char *interface)
free(msghdr.msg_control); free(msghdr.msg_control);
} }
/**
* @brief API struct to pass interface name and source addresses in TCPIP context
*
* @param[out] interface Name of the interface.
* @param[out] src_addr_str Global/Unique local IPv6 address of the interface
*/
typedef struct src_iface_api {
char *interface;
char *src_addr_str;
} src_iface_api_t;
/** /**
* @brief Goes over each interface and searches for one Global/Unique local IPv6 address. * @brief Goes over each interface and searches for one Global/Unique local IPv6 address.
* Returns the interface name and IPv6 address of the interface in case of success. * Returns the interface name and IPv6 address of the interface in case of success.
* *
* @param[out] interface Name of the interface.
* @param[out] src_addr_str Global/Unique local IPv6 address of the interface
* @return * @return
* >0 : Successfully found an interface with Global/Unique local IPv6 address. * ESP_OK : Successfully found an interface with Global/Unique local IPv6 address.
* -1 : Unable to to find a valid interface with Global/Unique local IPv6 address. * ESP_FAIL : Unable to to find a valid interface with Global/Unique local IPv6 address.
*/ */
bool get_src_iface(char *interface, char *src_addr_str) static esp_err_t get_src_iface(void* ctx)
{ {
src_iface_api_t *api = ctx;
esp_netif_t *netif = NULL; esp_netif_t *netif = NULL;
int ip6_addrs_count = 0; int ip6_addrs_count = 0;
esp_ip6_addr_t ip6[LWIP_IPV6_NUM_ADDRESSES]; esp_ip6_addr_t ip6[LWIP_IPV6_NUM_ADDRESSES];
esp_err_t ret = ESP_FAIL;
// Get interface details and own global ipv6 address // Get interface details and own global ipv6 address
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) { while ((netif = esp_netif_next_unsafe(netif)) != NULL) {
netif = esp_netif_next(netif); esp_err_t ret = esp_netif_get_netif_impl_name(netif, api->interface);
ret = esp_netif_get_netif_impl_name(netif, interface);
if ((ESP_FAIL == ret) || (NULL == netif)) { if ((ESP_FAIL == ret) || (NULL == netif)) {
ESP_LOGE(TAG, "No interface available"); ESP_LOGE(TAG, "No interface available");
return false; return ESP_FAIL;
} }
ESP_LOGI(TAG, "Interface: %s", interface); ESP_LOGI(TAG, "Interface: %s", api->interface);
ip6_addrs_count = esp_netif_get_all_ip6(netif, ip6); ip6_addrs_count = esp_netif_get_all_ip6(netif, ip6);
for (int j = 0; j < ip6_addrs_count; ++j) { for (int j = 0; j < ip6_addrs_count; ++j) {
@ -252,13 +259,13 @@ bool get_src_iface(char *interface, char *src_addr_str)
if ((ESP_IP6_ADDR_IS_GLOBAL == ipv6_type) || if ((ESP_IP6_ADDR_IS_GLOBAL == ipv6_type) ||
(ESP_IP6_ADDR_IS_UNIQUE_LOCAL == ipv6_type)) { (ESP_IP6_ADDR_IS_UNIQUE_LOCAL == ipv6_type)) {
// Break as we have the source address // Break as we have the source address
sprintf(src_addr_str, IPV6STR, IPV62STR(ip6[j])); sprintf(api->src_addr_str, IPV6STR, IPV62STR(ip6[j]));
return true; return ESP_OK;
} }
} }
} }
return false; return ESP_FAIL;
} }
@ -268,7 +275,8 @@ static void ping6_test_task(void *pvParameters)
char interface[10]; char interface[10];
char dst_addr_str[] = CONFIG_EXAMPLE_DST_IPV6_ADDR; char dst_addr_str[] = CONFIG_EXAMPLE_DST_IPV6_ADDR;
if (true == get_src_iface(interface, src_addr_str)) { src_iface_api_t api = { .interface = interface, .src_addr_str = src_addr_str };
if (esp_netif_tcpip_exec(get_src_iface, &api) == ESP_OK) {
ESP_LOGI(TAG, "Source address: %s", src_addr_str); ESP_LOGI(TAG, "Source address: %s", src_addr_str);
ESP_LOGI(TAG, "Destination address: %s", dst_addr_str); ESP_LOGI(TAG, "Destination address: %s", dst_addr_str);
ESP_LOGI(TAG, "Interface name: %s", interface); ESP_LOGI(TAG, "Interface name: %s", interface);

View File

@ -84,78 +84,48 @@ static int get_src_iface(char *interface)
} }
#else #else
static esp_netif_t *get_esp_netif_from_iface(char *interface_i)
{
esp_netif_t *netif = NULL;
esp_err_t ret = ESP_FAIL;
char iface[10];
// Get interface details and own global ipv6 address
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) {
netif = esp_netif_next(netif);
ret = esp_netif_get_netif_impl_name(netif, iface);
if ((ESP_FAIL == ret) || (NULL == netif)) {
ESP_LOGE(TAG, "No interface available");
return NULL;
}
if (0 == strcmp(interface_i, iface)) {
return netif;
}
}
return NULL;
}
/** /**
* @brief In case of Auto mode returns the interface name with a valid IPv6 address or * @brief In case of Auto mode returns the interface name with a valid IPv6 address or
* In case the user has specified interface, validates and returns the interface name. * In case the user has specified interface, validates and returns the interface name.
* *
* @param[out] interface Name of the interface in as a string. * This function is a predicate for esp_netif_find_if() API, and it uses the underlying
* network interface name as a context parameter
* *
* @return 0 incase of success. * @return true if we found the appropriate interface, false if not
*/ */
static int get_src_iface(char *interface) static bool choose_netif(esp_netif_t *netif, void* ctx)
{ {
esp_netif_t *netif = NULL; char *interface = ctx;
esp_err_t ret = ESP_FAIL;
int ip6_addrs_count = 0;
esp_ip6_addr_t ip6[LWIP_IPV6_NUM_ADDRESSES]; esp_ip6_addr_t ip6[LWIP_IPV6_NUM_ADDRESSES];
// Get interface details and own global ipv6 address esp_err_t ret = esp_netif_get_netif_impl_name(netif, interface);
for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) {
netif = esp_netif_next(netif);
ret = esp_netif_get_netif_impl_name(netif, interface);
if ((ESP_FAIL == ret) || (NULL == netif)) {
ESP_LOGE(TAG, "No interface available");
return -1;
}
if ((ESP_FAIL == ret) || (NULL == netif)) {
ESP_LOGE(TAG, "No interface available");
return false;
}
#if defined(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE) #if defined(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE)
if (!strcmp(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE_NAME, interface)) { if (!strcmp(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE_NAME, interface)) {
ESP_LOGI(TAG, "Interface: %s", interface); ESP_LOGI(TAG, "Interface: %s", interface);
return 0; return true;
} }
#else #else
ip6_addrs_count = esp_netif_get_all_ip6(netif, ip6); int ip6_addrs_count = esp_netif_get_all_ip6(netif, ip6);
for (int j = 0; j < ip6_addrs_count; ++j) { for (int j = 0; j < ip6_addrs_count; ++j) {
esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j])); esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&(ip6[j]));
if ((ESP_IP6_ADDR_IS_GLOBAL == ipv6_type) || if ((ESP_IP6_ADDR_IS_GLOBAL == ipv6_type) ||
(ESP_IP6_ADDR_IS_UNIQUE_LOCAL == ipv6_type) || (ESP_IP6_ADDR_IS_UNIQUE_LOCAL == ipv6_type) ||
(ESP_IP6_ADDR_IS_LINK_LOCAL == ipv6_type)) { (ESP_IP6_ADDR_IS_LINK_LOCAL == ipv6_type)) {
// Break as we have the source address // Break as we have the source address
ESP_LOGI(TAG, "Interface: %s", interface); ESP_LOGI(TAG, "Interface: %s", interface);
return 0; return true;
}
} }
#endif // #if defined(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE)
} }
#endif // #if defined(CONFIG_EXAMPLE_USER_SPECIFIED_IFACE)
return -1; return false;
} }
#endif // #if defined(CONFIG_IDF_TARGET_LINUX) #endif // #if defined(CONFIG_IDF_TARGET_LINUX)
@ -191,12 +161,11 @@ void tcp_client(void)
} }
ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT); ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT);
#if defined(CONFIG_IDF_TARGET_LINUX)
if (0 != get_src_iface(interface)) { if (0 != get_src_iface(interface)) {
ESP_LOGE(TAG, "Interface: Unavailable"); ESP_LOGE(TAG, "Interface: Unavailable");
break; break;
} }
#if defined(CONFIG_IDF_TARGET_LINUX)
memset (&ifr, 0, sizeof(ifr)); memset (&ifr, 0, sizeof(ifr));
snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface); snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
if (ioctl (sock, SIOCGIFINDEX, &ifr) < 0) { if (ioctl (sock, SIOCGIFINDEX, &ifr) < 0) {
@ -208,13 +177,13 @@ void tcp_client(void)
ESP_LOGI(TAG, "Interface index: %d", dest_addr.sin6_scope_id); ESP_LOGI(TAG, "Interface index: %d", dest_addr.sin6_scope_id);
#endif #endif
#else #else
if (NULL == (netif = get_esp_netif_from_iface(interface))) { if (NULL == (netif = esp_netif_find_if(choose_netif, interface))) {
ESP_LOGE(TAG, "Failed to find interface "); ESP_LOGE(TAG, "Failed to find interface ");
break; break;
} }
#if defined(CONFIG_EXAMPLE_IPV6) #if defined(CONFIG_EXAMPLE_IPV6)
dest_addr.sin6_scope_id = esp_netif_get_netif_impl_index(netif); dest_addr.sin6_scope_id = esp_netif_get_netif_impl_index(netif);
ESP_LOGI(TAG, "Interface index: %d", dest_addr.sin6_scope_id); ESP_LOGI(TAG, "Interface index: %" PRIu32, dest_addr.sin6_scope_id);
#endif #endif
#endif #endif