mirror of
				https://github.com/espressif/esp-protocols.git
				synced 2025-11-04 00:21:37 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			142 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * SPDX-FileCopyrightText: 2023-2024 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 *example_eth_init(int prio);
 | 
						|
iface_info_t *example_wifi_init(int prio);
 | 
						|
iface_info_t *example_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[] = {
 | 
						|
        example_eth_init(ETH_PRIO),
 | 
						|
        example_wifi_init(WIFI_PRIO),
 | 
						|
        example_ppp_init(PPP_PRIO),
 | 
						|
    };
 | 
						|
    size_t num_of_ifaces = sizeof(ifaces) / sizeof(ifaces[0]);
 | 
						|
 | 
						|
    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();
 | 
						|
#endif
 | 
						|
        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) {
 | 
						|
#ifndef CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF
 | 
						|
            // 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) {
 | 
						|
                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));
 | 
						|
                }
 | 
						|
            }
 | 
						|
#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) {
 | 
						|
            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]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |