1 /*
2 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "esp_netif.h"
8 #include "sys/queue.h"
9 #include "esp_log.h"
10 #include "freertos/FreeRTOS.h"
11 #include "freertos/semphr.h"
12 #include "esp_netif_private.h"
13 #include <string.h>
14
15 //
16 // Purpose of this module is to provide list of esp-netif structures
17 // - this module has no dependency on a specific network stack (lwip)
18 //
19
20 static const char *TAG = "esp_netif_objects";
21
22 typedef struct slist_netifs_s slist_netifs_t;
23 struct slist_netifs_s {
24 esp_netif_t *netif;
25 SLIST_ENTRY(slist_netifs_s) next;
26 };
27
28 SLIST_HEAD(slisthead, slist_netifs_s) s_head = { .slh_first = NULL, };
29
30 static size_t s_esp_netif_counter = 0;
31 static SemaphoreHandle_t s_list_lock = NULL;
32
33 ESP_EVENT_DEFINE_BASE(IP_EVENT);
34
esp_netif_list_lock(void)35 esp_err_t esp_netif_list_lock(void)
36 {
37 if (s_list_lock == NULL) {
38 s_list_lock = xSemaphoreCreateMutex();
39 if (s_list_lock == NULL) {
40 return ESP_ERR_NO_MEM;
41 }
42 }
43 xSemaphoreTake(s_list_lock, portMAX_DELAY);
44 return ESP_OK;
45 }
46
esp_netif_list_unlock(void)47 void esp_netif_list_unlock(void)
48 {
49 assert(s_list_lock);
50 xSemaphoreGive(s_list_lock);
51 if (s_esp_netif_counter == 0) {
52 vQueueDelete(s_list_lock);
53 s_list_lock = NULL;
54 }
55 }
56
57 //
58 // List manipulation functions
59 //
esp_netif_add_to_list(esp_netif_t * netif)60 esp_err_t esp_netif_add_to_list(esp_netif_t *netif)
61 {
62 esp_err_t ret;
63 struct slist_netifs_s *item = calloc(1, sizeof(struct slist_netifs_s));
64 ESP_LOGD(TAG, "%s %p", __func__, netif);
65 if (item == NULL) {
66 return ESP_ERR_NO_MEM;
67 }
68 item->netif = netif;
69
70 if ((ret = esp_netif_list_lock()) != ESP_OK) {
71 free(item);
72 return ret;
73 }
74
75 SLIST_INSERT_HEAD(&s_head, item, next);
76 ++s_esp_netif_counter;
77 ESP_LOGD(TAG, "%s netif added successfully (total netifs: %d)", __func__, s_esp_netif_counter);
78 esp_netif_list_unlock();
79 return ESP_OK;
80 }
81
82
esp_netif_remove_from_list(esp_netif_t * netif)83 esp_err_t esp_netif_remove_from_list(esp_netif_t *netif)
84 {
85 struct slist_netifs_s *item;
86 esp_err_t ret;
87 if ((ret = esp_netif_list_lock()) != ESP_OK) {
88 return ret;
89 }
90 ESP_LOGV(TAG, "%s %p", __func__, netif);
91
92 SLIST_FOREACH(item, &s_head, next) {
93 if (item->netif == netif) {
94 SLIST_REMOVE(&s_head, item, slist_netifs_s, next);
95 assert(s_esp_netif_counter > 0);
96 --s_esp_netif_counter;
97 ESP_LOGD(TAG, "%s netif successfully removed (total netifs: %d)", __func__, s_esp_netif_counter);
98 free(item);
99 esp_netif_list_unlock();
100 return ESP_OK;
101 }
102 }
103 esp_netif_list_unlock();
104 return ESP_ERR_NOT_FOUND;
105 }
106
esp_netif_get_nr_of_ifs(void)107 size_t esp_netif_get_nr_of_ifs(void)
108 {
109 return s_esp_netif_counter;
110 }
111
esp_netif_next(esp_netif_t * netif)112 esp_netif_t* esp_netif_next(esp_netif_t* netif)
113 {
114 esp_err_t ret;
115 esp_netif_t* result;
116 if ((ret = esp_netif_list_lock()) != ESP_OK) {
117 ESP_LOGE(TAG, "Failed to lock esp-netif list with %d", ret);
118 return NULL;
119 }
120 result = esp_netif_next_unsafe(netif);
121 esp_netif_list_unlock();
122 return result;
123 }
124
esp_netif_next_unsafe(esp_netif_t * netif)125 esp_netif_t* esp_netif_next_unsafe(esp_netif_t* netif)
126 {
127 ESP_LOGV(TAG, "%s %p", __func__, netif);
128 struct slist_netifs_s *item;
129 // Getting the first netif if argument is NULL
130 if (netif == NULL) {
131 item = SLIST_FIRST(&s_head);
132 return (item == NULL) ? NULL : item->netif;
133 }
134 // otherwise the next one (after the supplied netif)
135 SLIST_FOREACH(item, &s_head, next) {
136 if (item->netif == netif) {
137 item = SLIST_NEXT(item, next);
138 return (item == NULL) ? NULL : item->netif;
139 }
140 }
141 return NULL;
142 }
143
esp_netif_is_netif_listed(esp_netif_t * esp_netif)144 bool esp_netif_is_netif_listed(esp_netif_t *esp_netif)
145 {
146 struct slist_netifs_s *item;
147 esp_err_t ret;
148 if ((ret = esp_netif_list_lock()) != ESP_OK) {
149 ESP_LOGE(TAG, "Failed to lock esp-netif list with %d", ret);
150 return false;
151 }
152
153 SLIST_FOREACH(item, &s_head, next) {
154 if (item->netif == esp_netif) {
155 esp_netif_list_unlock();
156 return true;
157 }
158 }
159 esp_netif_list_unlock();
160 return false;
161 }
162
esp_netif_get_handle_from_ifkey(const char * if_key)163 esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key)
164 {
165 struct slist_netifs_s *item;
166 esp_err_t ret;
167 if ((ret = esp_netif_list_lock()) != ESP_OK) {
168 ESP_LOGE(TAG, "Failed to lock esp-netif list with %d", ret);
169 return NULL;
170 }
171
172 SLIST_FOREACH(item, &s_head, next) {
173 esp_netif_t *esp_netif = item->netif;
174 if (strcmp(if_key, esp_netif_get_ifkey(esp_netif)) == 0) {
175 esp_netif_list_unlock();
176 return esp_netif;
177 }
178 }
179 esp_netif_list_unlock();
180 return NULL;
181 }
182