Files
esp-protocols/examples/esp_netif/multiple_netifs/main/multi_netif_main.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

130 lines
4.1 KiB
C
Raw Normal View History

/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Multiple Network Interface Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <lwip/dns.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "nvs_flash.h"
#include "iface_info.h"
iface_info_t *eth_init(int prio);
iface_info_t *wifi_init(int prio);
iface_info_t *ppp_init(int prio);
esp_err_t check_connectivity(const char *host);
#define HOST "www.espressif.com"
#define ETH_PRIO 200
#define WIFI_PRIO 100
#define PPP_PRIO 50
static const char *TAG = "app_main";
static ssize_t get_default(iface_info_t *list[], size_t num)
{
esp_netif_t *default_netif = esp_netif_get_default_netif();
if (default_netif == NULL) {
ESP_LOGE(TAG, "default netif is NULL!");
return -1;
}
ESP_LOGI(TAG, "Default netif: %s", esp_netif_get_desc(default_netif));
for (int i = 0; i < num; ++i) {
if (list[i] && list[i]->netif == default_netif) {
ESP_LOGI(TAG, "Default interface: %s", list[i]->name);
return i;
}
}
// not found
return -2;
}
void app_main(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_ERROR_CHECK(esp_netif_init());
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
// all interfaces
iface_info_t *ifaces[] = {
eth_init(ETH_PRIO),
wifi_init(WIFI_PRIO),
ppp_init(PPP_PRIO),
};
size_t num_of_ifaces = sizeof(ifaces) / sizeof(ifaces[0]);
while (true) {
dns_clear_cache();
vTaskDelay(pdMS_TO_TICKS(2000));
ssize_t i = get_default(ifaces, num_of_ifaces);
if (i == -1) { // default netif is NULL, probably all interfaces are down -> retry
continue;
} else if (i < 0) {
break; // some other error, exit
}
esp_err_t connect_status = check_connectivity(HOST);
if (connect_status == ESP_OK) {
// connectivity ok
continue;
}
if (connect_status == ESP_ERR_NOT_FOUND) {
// set the default DNS info to global DNS server list
for (int j = 0; j < 2; ++j) {
esp_netif_dns_info_t dns_info;
esp_netif_get_dns_info(ifaces[i]->netif, j, &dns_info);
if (memcmp(&dns_info.ip, &ifaces[i]->dns[j].ip, sizeof(esp_ip_addr_t)) == 0) {
connect_status = ESP_FAIL;
} else {
esp_netif_set_dns_info(ifaces[i]->netif, j, &ifaces[i]->dns[j]);
ESP_LOGI(TAG, "Reconfigured DNS%i=" IPSTR, j, IP2STR(&ifaces[i]->dns[j].ip.u_addr.ip4));
}
}
}
if (connect_status == ESP_FAIL) {
ESP_LOGE(TAG, "No connection via the default netif!");
// try to switch interfaces manually
// WARNING: Once we set_default_netif() manually, we disable the automatic prio-routing
int next = (i + 1) % num_of_ifaces;
while (ifaces[i] != ifaces[next]) {
if (ifaces[next]->connected) {
ESP_LOGE(TAG, "Trying another interface: %s", ifaces[next]->name);
esp_netif_set_default_netif(ifaces[next]->netif);
break;
}
++next;
next = next % num_of_ifaces;
}
}
}
ESP_LOGI(TAG, "Stop and cleanup all interfaces");
for (int i = 0; i < num_of_ifaces; ++i) {
if (ifaces[i]) {
ifaces[i]->destroy(ifaces[i]);
}
}
}