forked from espressif/esp-protocols
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmulti_netif_main.c
141 lines (127 loc) · 4.87 KB
/
multi_netif_main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
* 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]);
}
}
}