fix(examples): Make multi-netif example working with DNS_PER_DEFAULT_NETIF feature

This commit is contained in:
David Cermak
2024-07-08 10:25:24 +02:00
parent b710dbd2ad
commit bc8ac4c684
7 changed files with 47 additions and 14 deletions

View File

@ -19,6 +19,14 @@ This example demonstrates working with multiple different interfaces with differ
* It tries to reconfigure DNS server if host name resolution fails * It tries to reconfigure DNS server if host name resolution fails
* It tries to manually change the default interface if connection fails * It tries to manually change the default interface if connection fails
### Handling DNS server across interfaces
This example also demonstrates how DNS servers could be handled on network interface level, as lwIP used global DNS server information.
All network interfaces store their DNS info upon acquiring an IP in the internal structure (in the application code) and the DNS servers are restored if host name resolution fails.
This functionality is handled in IDF (supported from v5.3) automatically if `CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF` is enabled, the DNS server info keeps updating per network interface in IDF layers. This examples uses the IDF functionality if `CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF=1`.
### Hardware Required ### Hardware Required
To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html). To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html).

View File

@ -54,4 +54,14 @@ menu "Example Configuration"
bool "Using simple UART-PPP driver" bool "Using simple UART-PPP driver"
endchoice endchoice
config EXAMPLE_DEMONSTRATE_DNS_CLEAR_CACHE
bool "Run DNS clear cache"
default n
help
This example will cleanup the DNS cache
every iteration of the demo network operation.
This forces the TCP/IP stack to always resolve DNS names,
thus exercising potentially invalid DNS configuration.
Set this to "y" for testing, but keep as "n" for production.
endmenu endmenu

View File

@ -95,7 +95,7 @@ static void eth_destroy(iface_info_t *info)
free(eth_info); free(eth_info);
} }
iface_info_t *eth_init(int prio) iface_info_t *example_eth_init(int prio)
{ {
struct eth_info_t *eth_info = malloc(sizeof(struct eth_info_t)); struct eth_info_t *eth_info = malloc(sizeof(struct eth_info_t));
assert(eth_info); assert(eth_info);
@ -124,7 +124,7 @@ iface_info_t *eth_init(int prio)
eth_info->parent.netif = esp_netif_new(&cfg); eth_info->parent.netif = esp_netif_new(&cfg);
eth_info->glue = esp_eth_new_netif_glue(eth_info->eth_handle); eth_info->glue = esp_eth_new_netif_glue(eth_info->eth_handle);
// Attach Ethernet driver to TCP/IP stack // Attach Ethernet driver to TCP/IP stack
ESP_ERROR_CHECK(esp_netif_attach(eth_info->parent.netif, eth_info->glue )); ESP_ERROR_CHECK(esp_netif_attach(eth_info->parent.netif, eth_info->glue));
// Register user defined event handers // Register user defined event handers
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_info)); ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, eth_info));

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@ -23,9 +23,9 @@
#include "nvs_flash.h" #include "nvs_flash.h"
#include "iface_info.h" #include "iface_info.h"
iface_info_t *eth_init(int prio); iface_info_t *example_eth_init(int prio);
iface_info_t *wifi_init(int prio); iface_info_t *example_wifi_init(int prio);
iface_info_t *ppp_init(int prio); iface_info_t *example_ppp_init(int prio);
esp_err_t check_connectivity(const char *host); esp_err_t check_connectivity(const char *host);
#define HOST "www.espressif.com" #define HOST "www.espressif.com"
@ -69,14 +69,18 @@ void app_main(void)
// all interfaces // all interfaces
iface_info_t *ifaces[] = { iface_info_t *ifaces[] = {
eth_init(ETH_PRIO), example_eth_init(ETH_PRIO),
wifi_init(WIFI_PRIO), example_wifi_init(WIFI_PRIO),
ppp_init(PPP_PRIO), example_ppp_init(PPP_PRIO),
}; };
size_t num_of_ifaces = sizeof(ifaces) / sizeof(ifaces[0]); size_t num_of_ifaces = sizeof(ifaces) / sizeof(ifaces[0]);
while (true) { while (true) {
#ifdef CONFIG_EXAMPLE_DEMONSTRATE_DNS_CLEAR_CACHE
// For demonstration purposes we clear DNS table every iteration to exercise
// a condition of DNS servers being misconfigured
dns_clear_cache(); dns_clear_cache();
#endif
vTaskDelay(pdMS_TO_TICKS(2000)); vTaskDelay(pdMS_TO_TICKS(2000));
ssize_t i = get_default(ifaces, num_of_ifaces); ssize_t i = get_default(ifaces, num_of_ifaces);
if (i == -1) { // default netif is NULL, probably all interfaces are down -> retry if (i == -1) { // default netif is NULL, probably all interfaces are down -> retry
@ -91,7 +95,9 @@ void app_main(void)
continue; continue;
} }
if (connect_status == ESP_ERR_NOT_FOUND) { if (connect_status == ESP_ERR_NOT_FOUND) {
#ifndef CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF
// set the default DNS info to global DNS server list // set the default DNS info to global DNS server list
// manually if DNS_PER_DEFAULT_NETIF if OFF or not-supported
for (int j = 0; j < 2; ++j) { for (int j = 0; j < 2; ++j) {
esp_netif_dns_info_t dns_info; esp_netif_dns_info_t dns_info;
esp_netif_get_dns_info(ifaces[i]->netif, j, &dns_info); esp_netif_get_dns_info(ifaces[i]->netif, j, &dns_info);
@ -102,6 +108,12 @@ void app_main(void)
ESP_LOGI(TAG, "Reconfigured DNS%i=" IPSTR, j, IP2STR(&ifaces[i]->dns[j].ip.u_addr.ip4)); ESP_LOGI(TAG, "Reconfigured DNS%i=" IPSTR, j, IP2STR(&ifaces[i]->dns[j].ip.u_addr.ip4));
} }
} }
#else
// simulate that the (default) netif is brought UP
// this is only needed, since we explicitly clear DNS servers every iteration using dns_clear_cache()
// (for demonstration purpose only, won't be needed in your project, unless you delete DNS info for some reasons)
esp_netif_action_connected(ifaces[i]->netif, NULL, 0, NULL);
#endif
} }
if (connect_status == ESP_FAIL) { if (connect_status == ESP_FAIL) {
ESP_LOGE(TAG, "No connection via the default netif!"); ESP_LOGE(TAG, "No connection via the default netif!");

View File

@ -85,7 +85,7 @@ static void ppp_destroy(iface_info_t *info)
free(info); free(info);
} }
iface_info_t *init_ppp(int prio) iface_info_t *example_ppp_init(int prio)
{ {
struct ppp_info_t *ppp_info = calloc(1, sizeof(struct ppp_info_t)); struct ppp_info_t *ppp_info = calloc(1, sizeof(struct ppp_info_t));
assert(ppp_info); assert(ppp_info);

View File

@ -75,7 +75,7 @@ static void wifi_destroy(iface_info_t *info)
free(info); free(info);
} }
iface_info_t *wifi_init(int prio) iface_info_t *example_wifi_init(int prio)
{ {
struct iface_info_t *wifi_info = malloc(sizeof(iface_info_t)); struct iface_info_t *wifi_info = malloc(sizeof(iface_info_t));
assert(wifi_info); assert(wifi_info);
@ -100,9 +100,9 @@ iface_info_t *wifi_init(int prio)
.password = CONFIG_ESP_WIFI_PASSWORD, .password = CONFIG_ESP_WIFI_PASSWORD,
}, },
}; };
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start() ); ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "wifi_init_sta finished."); ESP_LOGI(TAG, "wifi_init_sta finished.");

View File

@ -1,2 +1,5 @@
# You can use CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF
# to perform DNS server updates automatically in esp_netif layers
# instead of manually as it is demonstrated in this example
CONFIG_LWIP_PPP_SUPPORT=y CONFIG_LWIP_PPP_SUPPORT=y
CONFIG_LWIP_PPP_NOTIFY_PHASE_SUPPORT=y CONFIG_LWIP_PPP_NOTIFY_PHASE_SUPPORT=y