From ffe043b1a81a0f9e1cc2cfa8873e21318ec89143 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 28 Jun 2019 16:47:34 +0200 Subject: [PATCH] esp_netif: Introduction of esp-netif component as a replacement of tcpip_adpter - provides object oriented access to network intefaces - not limited to default netifs - more generic abstraction to network input output functions - event handler registration removed from component responsibility - backward compatibility layer for legacy tcpip_apapter APIs Closes IDF-39 --- components/esp_eth/CMakeLists.txt | 2 +- components/esp_eth/include/esp_eth.h | 28 +- components/esp_eth/src/esp_eth.c | 105 +- components/esp_eth/test/test_emac.c | 2 +- components/esp_event/CMakeLists.txt | 2 +- components/esp_event/event_send_compat.inc | 14 +- .../esp_event/include/esp_event_legacy.h | 2 +- components/esp_netif/CMakeLists.txt | 8 + .../{tcpip_adapter => esp_netif}/Kconfig | 13 +- components/esp_netif/README.md | 81 + components/esp_netif/component.mk | 6 + components/esp_netif/esp_netif_defaults.c | 95 ++ components/esp_netif/esp_netif_handlers.c | 125 ++ components/esp_netif/esp_netif_objects.c | 102 ++ components/esp_netif/include/esp_netif.h | 641 ++++++++ .../esp_netif/include/esp_netif_defaults.h | 114 ++ .../esp_netif/include/esp_netif_ip_addr.h | 88 + .../esp_netif/include/esp_netif_net_stack.h | 41 + .../esp_netif/include/esp_netif_types.h | 223 +++ components/esp_netif/lwip/esp_netif_lwip.c | 1444 +++++++++++++++++ .../esp_netif/lwip/esp_netif_lwip_defaults.c | 44 + .../esp_netif/lwip/esp_netif_lwip_internal.h | 70 + .../private_include/esp_netif_private.h | 114 ++ components/esp_netif/test/CMakeLists.txt | 5 + components/esp_netif/test/component.mk | 5 + components/esp_netif/test/test_esp_netif.c | 56 + components/esp_wifi/CMakeLists.txt | 3 +- components/esp_wifi/include/esp_mesh.h | 1 + .../esp_wifi/include/esp_wifi_default.h | 28 + components/esp_wifi/src/wifi_default.c | 244 +++ components/esp_wifi/src/wifi_init.c | 4 + components/lwip/CMakeLists.txt | 3 +- components/lwip/apps/dhcpserver/dhcpserver.c | 38 +- components/lwip/lwip | 2 +- components/lwip/port/esp32/include/lwipopts.h | 2 +- .../port/esp32/include/netif/dhcp_state.h | 2 +- .../port/esp32/include/netif/ethernetif.h | 2 +- .../lwip/port/esp32/include/netif/nettestif.h | 33 - .../lwip/port/esp32/include/netif/wlanif.h | 5 +- components/lwip/port/esp32/netif/dhcp_state.c | 40 +- components/lwip/port/esp32/netif/ethernetif.c | 27 +- components/lwip/port/esp32/netif/nettestif.c | 105 -- components/lwip/port/esp32/netif/wlanif.c | 49 +- components/mdns/mdns.c | 2 +- components/tcpip_adapter/CMakeLists.txt | 4 +- components/tcpip_adapter/event_handlers.c | 312 ---- .../tcpip_adapter/include/tcpip_adapter.h | 770 +-------- .../tcpip_adapter_compat.h | 40 + .../include/tcpip_adapter_internal.h | 66 - components/tcpip_adapter/sdkconfig.rename | 5 - .../tcpip_adapter/tcpip_adapter_compat.c | 274 ++++ components/tcpip_adapter/tcpip_adapter_lwip.c | 1305 --------------- components/wifi_provisioning/src/handlers.c | 10 +- .../system/network_tests/main/CMakeLists.txt | 2 +- .../network_tests/main/lwip_test_netif.c | 125 ++ .../system/network_tests/main/net_suite.c | 40 +- 56 files changed, 4344 insertions(+), 2629 deletions(-) create mode 100644 components/esp_netif/CMakeLists.txt rename components/{tcpip_adapter => esp_netif}/Kconfig (67%) create mode 100644 components/esp_netif/README.md create mode 100644 components/esp_netif/component.mk create mode 100644 components/esp_netif/esp_netif_defaults.c create mode 100644 components/esp_netif/esp_netif_handlers.c create mode 100644 components/esp_netif/esp_netif_objects.c create mode 100644 components/esp_netif/include/esp_netif.h create mode 100644 components/esp_netif/include/esp_netif_defaults.h create mode 100644 components/esp_netif/include/esp_netif_ip_addr.h create mode 100644 components/esp_netif/include/esp_netif_net_stack.h create mode 100644 components/esp_netif/include/esp_netif_types.h create mode 100644 components/esp_netif/lwip/esp_netif_lwip.c create mode 100644 components/esp_netif/lwip/esp_netif_lwip_defaults.c create mode 100644 components/esp_netif/lwip/esp_netif_lwip_internal.h create mode 100644 components/esp_netif/private_include/esp_netif_private.h create mode 100644 components/esp_netif/test/CMakeLists.txt create mode 100644 components/esp_netif/test/component.mk create mode 100644 components/esp_netif/test/test_esp_netif.c create mode 100644 components/esp_wifi/src/wifi_default.c delete mode 100644 components/lwip/port/esp32/include/netif/nettestif.h delete mode 100644 components/lwip/port/esp32/netif/nettestif.c delete mode 100644 components/tcpip_adapter/event_handlers.c create mode 100644 components/tcpip_adapter/include/tcpip_adapter_compatible/tcpip_adapter_compat.h delete mode 100644 components/tcpip_adapter/include/tcpip_adapter_internal.h delete mode 100644 components/tcpip_adapter/sdkconfig.rename create mode 100644 components/tcpip_adapter/tcpip_adapter_compat.c delete mode 100644 components/tcpip_adapter/tcpip_adapter_lwip.c create mode 100644 examples/system/network_tests/main/lwip_test_netif.c diff --git a/components/esp_eth/CMakeLists.txt b/components/esp_eth/CMakeLists.txt index 73f559e5b..894966d34 100644 --- a/components/esp_eth/CMakeLists.txt +++ b/components/esp_eth/CMakeLists.txt @@ -30,5 +30,5 @@ idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${include} LDFRAGMENTS ${linker} REQUIRES "esp_event" - PRIV_REQUIRES "tcpip_adapter" "driver" "log") + PRIV_REQUIRES "esp_netif" "driver" "log") diff --git a/components/esp_eth/include/esp_eth.h b/components/esp_eth/include/esp_eth.h index 0d40d0956..39393e823 100644 --- a/components/esp_eth/include/esp_eth.h +++ b/components/esp_eth/include/esp_eth.h @@ -85,6 +85,7 @@ typedef struct { * - ESP_FAIL: error occurred when processing extra lowlevel deinitialization */ esp_err_t (*on_lowlevel_deinit_done)(esp_eth_handle_t eth_handle); + } esp_eth_config_t; /** @@ -101,6 +102,15 @@ typedef struct { .on_lowlevel_deinit_done = NULL, \ } +/** +* @brief Default esp-netif driver related configuration +* +*/ +#define ESP_NETIF_DRIVER_DEFAULT_ETH _g_eth_driver_ifconfig + +struct esp_netif_driver_ifconfig; +extern const struct esp_netif_driver_ifconfig *_g_eth_driver_ifconfig; + /** * @brief Install Ethernet driver * @@ -139,7 +149,7 @@ esp_err_t esp_eth_driver_uninstall(esp_eth_handle_t hdl); * - ESP_ERR_INVALID_ARG: transmit frame buffer failed because of some invalid argument * - ESP_FAIL: transmit frame buffer failed because some other error occurred */ -esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, uint8_t *buf, uint32_t length); +esp_err_t esp_eth_transmit(void* hdl, void *buf, uint32_t length); /** * @brief General Receive @@ -174,6 +184,22 @@ esp_err_t esp_eth_receive(esp_eth_handle_t hdl, uint8_t *buf, uint32_t *length); */ esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data); +/** + * @brief Register default ethernet handlers + * + * @param[in] esp_netif esp network interface handle created for this driver + * (note: appropriate ethernet handle not yet properly initialized when setting up + * default handlers) + */ +esp_err_t esp_eth_set_default_handlers(void* esp_netif); + +/** + * @brief Unregister default ethernet handlers + * + * @param[in] esp_netif esp network interface handle created for this driver + */ +esp_err_t esp_eth_clear_default_handlers(void* esp_netif); + #ifdef __cplusplus } #endif diff --git a/components/esp_eth/src/esp_eth.c b/components/esp_eth/src/esp_eth.c index adef9096e..fcd5991f5 100644 --- a/components/esp_eth/src/esp_eth.c +++ b/components/esp_eth/src/esp_eth.c @@ -18,6 +18,8 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/timers.h" +#include "esp_netif.h" +#include "tcpip_adapter_compatible/tcpip_adapter_compat.h" static const char *TAG = "esp_eth"; #define ETH_CHECK(a, str, goto_tag, ret_value, ...) \ @@ -33,6 +35,15 @@ static const char *TAG = "esp_eth"; ESP_EVENT_DEFINE_BASE(ETH_EVENT); +// Default driver interface config, at the init moment doesn't include driver handle, as it is created +// in starup phase, netif is updated in event handler on eth_start event with valid ethernet driver handle +static const esp_netif_driver_ifconfig_t _s_eth_driver_ifconfig = { + .handle = NULL, + .transmit = esp_eth_transmit, +}; + +const esp_netif_driver_ifconfig_t *_g_eth_driver_ifconfig = &_s_eth_driver_ifconfig; + /** * @brief The Ethernet driver mainly consists of PHY, MAC and * the mediator who will handle the request/response from/to MAC, PHY and Users. @@ -44,6 +55,7 @@ ESP_EVENT_DEFINE_BASE(ETH_EVENT); * In the callback, user can do any low level operations (e.g. enable/disable crystal clock). */ typedef struct { + esp_netif_driver_base_t base; esp_eth_mediator_t mediator; esp_eth_phy_t *phy; esp_eth_mac_t *mac; @@ -83,7 +95,7 @@ static esp_err_t eth_stack_input(esp_eth_mediator_t *eth, uint8_t *buffer, uint3 { esp_eth_driver_t *eth_driver = __containerof(eth, esp_eth_driver_t, mediator); if (!eth_driver->stack_input) { - return tcpip_adapter_eth_input(buffer, length, NULL); + return esp_netif_receive(eth_driver->base.netif, buffer, length, NULL); } else { return eth_driver->stack_input((esp_eth_handle_t)eth_driver, buffer, length); } @@ -154,6 +166,37 @@ static void eth_check_link_timer_cb(TimerHandle_t xTimer) // It's helpful for us to support multiple Ethernet port on ESP32. ////////////////////////////////////////////////////////////////////////////////////////////// +static esp_err_t esp_eth_driver_start(esp_netif_t * esp_netif, void * args) +{ + esp_err_t ret = ESP_OK; + esp_eth_driver_t *eth_driver = args; + eth_driver->base.netif = esp_netif; + // Update esp-netif with already created ethernet handle + + esp_netif_driver_ifconfig_t driver_ifconfig = { + .handle = eth_driver, + .transmit = esp_eth_transmit, + }; + esp_netif_config_t cfg = { + .driver = &driver_ifconfig, + + }; + ESP_ERROR_CHECK(esp_netif_configure(esp_netif, &cfg)); + uint8_t eth_mac[6]; + esp_eth_ioctl(eth_driver, ETH_CMD_G_MAC_ADDR, eth_mac); + ESP_LOGI(TAG, "%x %x %x %x %x %x", eth_mac[0], eth_mac[1], eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]); + + esp_netif_set_mac(esp_netif, eth_mac); + ESP_LOGI(TAG, "ETH netif started"); + + ETH_CHECK(esp_event_post(ETH_EVENT, ETHERNET_EVENT_START, ð_driver, sizeof(eth_driver), 0) == ESP_OK, + "send ETHERNET_EVENT_START event failed", err_event, ESP_FAIL); + return ret; +err_event: + esp_eth_driver_uninstall(eth_driver); + return ret; +} + esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_t *out_hdl) { esp_err_t ret = ESP_OK; @@ -184,12 +227,10 @@ esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_ eth_driver, eth_check_link_timer_cb); ETH_CHECK(eth_driver->check_link_timer, "create eth_link_timer failed", err_create_timer, ESP_FAIL); ETH_CHECK(xTimerStart(eth_driver->check_link_timer, 0) == pdPASS, "start eth_link_timer failed", err_start_timer, ESP_FAIL); - ETH_CHECK(esp_event_post(ETH_EVENT, ETHERNET_EVENT_START, ð_driver, sizeof(eth_driver), 0) == ESP_OK, - "send ETHERNET_EVENT_START event failed", err_event, ESP_FAIL); + eth_driver->base.post_attach = esp_eth_driver_start; *out_hdl = (esp_eth_handle_t)eth_driver; + tcpip_adapter_start_eth(eth_driver); return ESP_OK; -err_event: - xTimerStop(eth_driver->check_link_timer, 0); err_start_timer: xTimerDelete(eth_driver->check_link_timer, 0); err_create_timer: @@ -221,7 +262,7 @@ err: return ret; } -esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, uint8_t *buf, uint32_t length) +esp_err_t esp_eth_transmit(void* hdl, void *buf, uint32_t length) { esp_err_t ret = ESP_OK; esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; @@ -282,3 +323,55 @@ esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data) err: return ret; } + +esp_err_t esp_eth_clear_default_handlers(void* esp_netif) +{ + esp_err_t ret; + ETH_CHECK(esp_netif, "esp-netif handle can't be null", fail, ESP_ERR_INVALID_ARG); + + esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start); + esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_STOP, esp_netif_action_stop); + esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, esp_netif_action_connected); + esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, esp_netif_action_disconnected); + esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, esp_netif_action_got_ip); + return ESP_OK; +fail: + return ret; +} + +esp_err_t esp_eth_set_default_handlers(void* esp_netif) +{ + esp_err_t ret; + ETH_CHECK(esp_netif, "esp-netif handle can't be null", fail, ESP_ERR_INVALID_ARG); + + ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_STOP, esp_netif_action_stop, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, esp_netif_action_connected, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, esp_netif_action_disconnected, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, esp_netif_action_got_ip, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + return ESP_OK; + +fail: + esp_eth_clear_default_handlers(esp_netif); + return ret; +} diff --git a/components/esp_eth/test/test_emac.c b/components/esp_eth/test/test_emac.c index dc2e67128..368494cbf 100644 --- a/components/esp_eth/test/test_emac.c +++ b/components/esp_eth/test/test_emac.c @@ -62,7 +62,7 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base, { EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; - const tcpip_adapter_ip_info_t *ip_info = &event->ip_info; + const tcpip_adapter_ip_info_t *ip_info = (tcpip_adapter_ip_info_t *)&event->ip_info; ESP_LOGI(TAG, "Ethernet Got IP Address"); ESP_LOGI(TAG, "~~~~~~~~~~~"); diff --git a/components/esp_event/CMakeLists.txt b/components/esp_event/CMakeLists.txt index da463ff1f..9c1d7da5f 100644 --- a/components/esp_event/CMakeLists.txt +++ b/components/esp_event/CMakeLists.txt @@ -11,7 +11,7 @@ idf_component_register(SRCS "default_event_loop.c" "event_send.c" INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "private_include" - REQUIRES log tcpip_adapter + REQUIRES log esp_netif PRIV_REQUIRES ${priv_requires} LDFRAGMENTS linker.lf) diff --git a/components/esp_event/event_send_compat.inc b/components/esp_event/event_send_compat.inc index 721e8cd82..7e1e59ef8 100644 --- a/components/esp_event/event_send_compat.inc +++ b/components/esp_event/event_send_compat.inc @@ -16,7 +16,7 @@ #include "esp_log.h" #include "esp_event_legacy.h" #include "esp_wifi_types.h" -#include "tcpip_adapter.h" +#include "esp_netif.h" #if CONFIG_ETH_ENABLED #include "esp_eth.h" #endif @@ -271,16 +271,8 @@ static void esp_system_event_debug(const system_event_t* event) break; } case SYSTEM_EVENT_GOT_IP6: { - const ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip; - ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STA_GOT_IP6 address %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", - IP6_ADDR_BLOCK1(addr), - IP6_ADDR_BLOCK2(addr), - IP6_ADDR_BLOCK3(addr), - IP6_ADDR_BLOCK4(addr), - IP6_ADDR_BLOCK5(addr), - IP6_ADDR_BLOCK6(addr), - IP6_ADDR_BLOCK7(addr), - IP6_ADDR_BLOCK8(addr)); + const esp_ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip; + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STA_GOT_IP6 address %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", IPV62STR(*addr)); break; } #if CONFIG_IDF_TARGET_ESP32 diff --git a/components/esp_event/include/esp_event_legacy.h b/components/esp_event/include/esp_event_legacy.h index 139c81763..00d402c43 100644 --- a/components/esp_event/include/esp_event_legacy.h +++ b/components/esp_event/include/esp_event_legacy.h @@ -19,7 +19,7 @@ #include "esp_err.h" #include "esp_wifi_types.h" -#include "tcpip_adapter.h" +#include "esp_netif.h" #ifdef __cplusplus extern "C" { diff --git a/components/esp_netif/CMakeLists.txt b/components/esp_netif/CMakeLists.txt new file mode 100644 index 000000000..bdcdd80bb --- /dev/null +++ b/components/esp_netif/CMakeLists.txt @@ -0,0 +1,8 @@ +idf_component_register(SRCS "esp_netif_handlers.c" + "esp_netif_objects.c" + "esp_netif_defaults.c" + "lwip/esp_netif_lwip.c" + "lwip/esp_netif_lwip_defaults.c" + INCLUDE_DIRS include + PRIV_INCLUDE_DIRS lwip private_include + REQUIRES lwip esp_eth tcpip_adapter) diff --git a/components/tcpip_adapter/Kconfig b/components/esp_netif/Kconfig similarity index 67% rename from components/tcpip_adapter/Kconfig rename to components/esp_netif/Kconfig index 6b409d38b..fd693386f 100644 --- a/components/tcpip_adapter/Kconfig +++ b/components/esp_netif/Kconfig @@ -1,6 +1,6 @@ -menu "TCP/IP Adapter" +menu "ESP NETIF Adapter" - config NETIF_IP_LOST_TIMER_INTERVAL + config ESP_NETIF_IP_LOST_TIMER_INTERVAL int "IP Address lost timer interval (seconds)" range 0 65535 default 120 @@ -13,7 +13,7 @@ menu "TCP/IP Adapter" the timer expires. The IP lost timer is stopped if the station get the IP again before the timer expires. - choice NETIF_USE_TCPIP_STACK_LIB + choice ESP_NETIF_USE_TCPIP_STACK_LIB prompt "TCP/IP Stack Library" default TCPIP_LWIP help @@ -24,4 +24,11 @@ menu "TCP/IP Adapter" lwIP is a small independent implementation of the TCP/IP protocol suite. endchoice + config ESP_NETIF_USE_TCPIP_ADAPTER_COMPATIBLE_LAYER + bool "Enable backward compatible tcpip_adapter interface" + default y + help + Backward compatible interface to tcpip_adapter is enabled by default to support + legacy tcpip stack initialisation code. Disable this option to use only esp-netif + interface. endmenu diff --git a/components/esp_netif/README.md b/components/esp_netif/README.md new file mode 100644 index 000000000..4231a4272 --- /dev/null +++ b/components/esp_netif/README.md @@ -0,0 +1,81 @@ +# ESP-NETIF architecture + + | (A) USER CODE | + | | + .............| init settings events | + . +----------------------------------------+ + . . | * + . . V * + --------+ +===========================+ * +-----------------------+ + | | new/config get/set | * | | + | | |...*.....| init | + | |---------------------------| * | | + init | | |**** | | + start |********| event handler |*********| DHCP | + stop | | | | | + | |---------------------------| | | + | | | | NETIF | + +-----| | | +-----------------+ | + | glue|----<---| esp_netif_transmit |--<------| netif_output | | + | | | | | | | + | |---->---| esp_netif_receive |-->------| netif_input | | + | | | | + ----------------+ | + | |....<...| esp_netif_free_rx_buffer |...<.....| packet buffer | + +-----| | | | | + | | | | | + (B) | | | +-----------------------+ + --------+ +===========================+ + communication NETWORK STACK + DRIVER ESP-NETIF + + +## Components: + +### A) User code, boiler plate +Overall application interaction with communication media and network stack + + * initialization code + - create a new instance of ESP-NETIF + - configure the object with + 1) netif specific options (flags, behaviour, name) + 2) network stack options (netif init and input functions, not publicly available) + 3) IO driver specific options (transmit, tx_free functions, IO driver handle) + - setup event handlers + - use default handlers for common interfaces defined in IO drivers; or define a specific handlers + for customised behaviour/new interfaces + - register handlers for app related events (such as IP lost/acquired) + - interact with network interfaces using ESP-NETIF API + +### B) Communication driver, IO driver, media driver + * event handler + - define behaviour patterns of interaction with ESP-NETIF (example: ehternet link-up -> turn netif on) + * glue IO layer: adapt the input/output functions to use esp-netif transmit/input/free_rx + - install driver_transmit to appropriate ESP-NETIF object, so that outgoing packets from + network stack are passed to the IO driver + - calls esp_netif_receive to pass incoming data to network stack + +### C) ESP-NETIF, former tcpip_adapter +* init API (new, configure) +* IO API: for passing data between IO driver and network stack +* event/actiona API (esp-netif lifecycle management) + - building blocks for designing event handlers +* setters, getters +* network stack abstraction: enabling user interaction with TCP/IP stack + - netif up/down + - dhcp server, client + - dns api +* driver conversion utilities + +### D) Network stack: no public interaction with user code (wrtt interfaces) + + +## Data/event flow: + +* `........` Initialization line from user code to esp-netif and comm driver + +* `--<--->--` Data packets going from communication media to tcpip stack and back + +* `********` Events agregated in ESP-NETIP propagates to driver, user code and network stack + +* `|` User settings and runtime configuration + diff --git a/components/esp_netif/component.mk b/components/esp_netif/component.mk new file mode 100644 index 000000000..c45836aba --- /dev/null +++ b/components/esp_netif/component.mk @@ -0,0 +1,6 @@ +# +# Component Makefile +# +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_PRIV_INCLUDEDIRS := private_include lwip +COMPONENT_SRCDIRS := . lwip \ No newline at end of file diff --git a/components/esp_netif/esp_netif_defaults.c b/components/esp_netif/esp_netif_defaults.c new file mode 100644 index 000000000..abbb76da4 --- /dev/null +++ b/components/esp_netif/esp_netif_defaults.c @@ -0,0 +1,95 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_netif.h" +#include "esp_event.h" +#include "esp_wifi_default.h" +#include "esp_eth.h" + +// +// Purpose of this module is to provide +// - general esp-netif definitions of default objects for STA, AP, ETH +// - default init / create functions for basic default interfaces +// + +#define IP4TOUINT32(a,b,c,d) (((uint32_t)((a) & 0xffU) << 24) | \ + ((uint32_t)((b) & 0xffU) << 16) | \ + ((uint32_t)((c) & 0xffU) << 8) | \ + (uint32_t)((d) & 0xffU)) + +#define IP4TOADDR(a,b,c,d) esp_netif_htonl(IP4TOUINT32(a, b, c, d)) + + +// +// Default configuration of common interfaces, such as STA, AP, ETH +// +const esp_netif_inherent_config_t _g_esp_netif_inherent_sta_config = { + .flags = ESP_NETIF_DHCPC | ESP_NETIF_FLAG_GARP | ESP_NETIF_FLAG_EVENT_IP_MODIFIED, + .lost_ip_event = IP_EVENT_STA_LOST_IP, + .get_ip_event = IP_EVENT_STA_GOT_IP, + .if_key = "WIFI_STA_DEF", + .if_type = ESP_NETIF_TYPE_STA, + .route_prio = 100 +}; + +static const esp_netif_ip_info_t soft_ap_ip = { + .ip = { .addr = IP4TOADDR( 192, 168, 8, 1) }, + .gw = { .addr = IP4TOADDR( 192, 168, 8, 1) }, + .netmask = { .addr = IP4TOADDR( 255, 255, 255, 0) }, + +}; + +const esp_netif_inherent_config_t _g_esp_netif_inherent_ap_config = { + .flags = ESP_NETIF_DHCPS | ESP_NETIF_FLAG_AUTOUP, + .ip_info = (esp_netif_ip_info_t*)&soft_ap_ip, + .if_key = "WIFI_AP_DEF", + .if_type = ESP_NETIF_TYPE_AP, + .route_prio = 10 +}; + +const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config = { + .get_ip_event = IP_EVENT_ETH_GOT_IP, + .lost_ip_event = 0, + .flags = ESP_NETIF_DHCPC | ESP_NETIF_FLAG_GARP | ESP_NETIF_FLAG_EVENT_IP_MODIFIED, + .if_key = "ETH_DEF", + .if_type = ESP_NETIF_TYPE_ETH, + .route_prio = 50 +}; + +esp_netif_t* esp_netif_create_default_wifi_ap(void) +{ + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_WIFI_AP(); + esp_netif_t *netif = esp_netif_new(&cfg); + assert(netif); + esp_wifi_set_default_wifi_ap_handlers(netif); + return netif; +} + +esp_netif_t* esp_netif_create_default_wifi_sta(void) +{ + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_WIFI_STA(); + esp_netif_t *netif = esp_netif_new(&cfg); + assert(netif); + esp_wifi_set_default_wifi_sta_handlers(netif); + return netif; +} + +esp_netif_t* esp_netif_create_default_eth(void * eth_driver) +{ + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); + esp_netif_t* eth_netif = esp_netif_new(&cfg); + assert(eth_netif); + ESP_ERROR_CHECK(esp_netif_attach(eth_netif, eth_driver)); + return eth_netif; +} \ No newline at end of file diff --git a/components/esp_netif/esp_netif_handlers.c b/components/esp_netif/esp_netif_handlers.c new file mode 100644 index 000000000..8aac2e79f --- /dev/null +++ b/components/esp_netif/esp_netif_handlers.c @@ -0,0 +1,125 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "esp_netif.h" +#include "esp_event.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_netif_private.h" + +// +// Purpose of this module is to define general event handler primitives +// enabling application code to them either directly or with minimal modification +// for example with a separate pre/post handler. +// This module has no dependency on a specific network stack (lwip) +// + +static const char *TAG = "esp_netif_handlers"; + +#define _STR(x) #x + +/** + * @brief This function converts interface type to string, which + * helps with backward compatibility of test infrastructure + * to check for standard message that specific interface (sta, ap, eth) + * obtained IP address + */ +static const char* get_netif_type(esp_netif_t* netif) { + const char* s_esp_netif_type_desc[] = { + _STR(ESP_NETIF_TYPE_UNKNOWN), + "sta", + "ap", + "eth", + _STR(ESP_NETIF_TYPE_OTHER) + }; + size_t type_nr = esp_netif_get_type(netif); + if (type_nr > sizeof(s_esp_netif_type_desc)/sizeof(s_esp_netif_type_desc[0])) { + type_nr = 0; + } + return s_esp_netif_type_desc[type_nr]; +} + + +void esp_netif_action_start(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data) +{ + ESP_LOGD(TAG, "esp_netif action has started with netif%p from event_id=%d", esp_netif, event_id); + esp_netif_start(esp_netif); +} + +void esp_netif_action_stop(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data) +{ + ESP_LOGD(TAG, "esp_netif action stopped with netif%p from event_id=%d", esp_netif, event_id); + esp_netif_stop(esp_netif); +} + +void esp_netif_action_connected(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data) +{ + esp_netif_dhcp_status_t status; + + ESP_LOGD(TAG, "esp_netif action connected with netif%p from event_id=%d", esp_netif, event_id); + esp_netif_up(esp_netif); + + esp_netif_dhcpc_get_status(esp_netif, &status); + if (status == ESP_NETIF_DHCP_INIT) { + esp_netif_dhcpc_start(esp_netif); + } else if (status == ESP_NETIF_DHCP_STOPPED) { + // + esp_netif_ip_info_t ip; + esp_netif_ip_info_t old_ip; + + esp_netif_get_ip_info(esp_netif, &ip); + esp_netif_get_old_ip_info(esp_netif, &old_ip); + + if (esp_netif_is_valid_static_ip(&ip)) { + ip_event_got_ip_t evt = { + .esp_netif = esp_netif, + .if_index = -1, // to indicate ptr to if used + .ip_changed = false, + }; + + if (memcmp(&ip, &old_ip, sizeof(ip))) { + evt.ip_changed = true; + } + + memcpy(&evt.ip_info, &ip, sizeof(esp_netif_ip_info_t)); + esp_netif_set_old_ip_info(esp_netif, &ip); + + ESP_NETIF_CALL_CHECK("esp_event_send_internal in esp_netif_action_connected", + esp_event_send_internal(IP_EVENT, esp_netif_get_event_id(esp_netif, ESP_NETIF_IP_EVENT_GOT_IP) , + &evt, sizeof(evt), 0), ESP_OK); + ESP_LOGD(TAG, "static ip: ip changed=%d", evt.ip_changed); + } else { + ESP_LOGE(TAG, "invalid static ip"); + } + } +} + +void esp_netif_action_disconnected(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data) +{ + ESP_LOGD(TAG, "esp_netif action connected with netif%p from event_id=%d", esp_netif, event_id); + esp_netif_down(esp_netif); + +} + +void esp_netif_action_got_ip(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data) +{ + ESP_LOGD(TAG, "esp_netif action got_ip with netif%p from event_id=%d", esp_netif, event_id); + const ip_event_got_ip_t *event = (const ip_event_got_ip_t *) data; + ESP_LOGI(TAG, "%s ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR, get_netif_type(esp_netif), + IP2STR(&event->ip_info.ip), + IP2STR(&event->ip_info.netmask), + IP2STR(&event->ip_info.gw)); +} + diff --git a/components/esp_netif/esp_netif_objects.c b/components/esp_netif/esp_netif_objects.c new file mode 100644 index 000000000..1eba1930e --- /dev/null +++ b/components/esp_netif/esp_netif_objects.c @@ -0,0 +1,102 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_netif.h" +#include "sys/queue.h" +#include "esp_log.h" + +// +// Purpose of this module is to provide list of esp-netif structures +// - this module has no dependency on a specific network stack (lwip) +// + +static const char *TAG = "esp_netif_objects"; + +//#define ESP_NETIF_TYPE_DEFINE(id) const esp_netif_type_t id = #id + +typedef struct slist_netifs_s slist_netifs_t; +struct slist_netifs_s { + esp_netif_t *netif; + SLIST_ENTRY(slist_netifs_s) next; +}; + +SLIST_HEAD(slisthead, slist_netifs_s) s_head = { .slh_first = NULL, }; + +static size_t s_esp_netif_counter = 0; + +ESP_EVENT_DEFINE_BASE(IP_EVENT); + +//ESP_NETIF_TYPE_DEFINE(ESP_NETIF_TYPE_STA); +//ESP_NETIF_TYPE_DEFINE(ESP_NETIF_TYPE_AP); +//ESP_NETIF_TYPE_DEFINE(ESP_NETIF_TYPE_ETH); + + +// +// List manipulation functions +// +esp_err_t esp_netif_add_to_list(esp_netif_t *netif) +{ + struct slist_netifs_s *item = calloc(1, sizeof(struct slist_netifs_s)); + ESP_LOGD(TAG, "%s %p", __func__, netif); + if (item == NULL) { + return ESP_ERR_NO_MEM; + } + item->netif = netif; + + SLIST_INSERT_HEAD(&s_head, item, next); + ++s_esp_netif_counter; + ESP_LOGD(TAG, "%s netif added successfully (total netifs: %d)", __func__, s_esp_netif_counter); + return ESP_OK; +} + + +esp_err_t esp_netif_remove_from_list(esp_netif_t *netif) +{ + struct slist_netifs_s *item; + ESP_LOGV(TAG, "%s %p", __func__, netif); + SLIST_FOREACH(item, &s_head, next) { + if (item->netif == netif) { + SLIST_REMOVE(&s_head, item, slist_netifs_s, next); + assert(s_esp_netif_counter > 0); + --s_esp_netif_counter; + ESP_LOGD(TAG, "%s netif successfully removed (total netifs: %d)", __func__, s_esp_netif_counter); + free(item); + return ESP_OK; + } + } + return ESP_ERR_NOT_FOUND; +} + +size_t esp_netif_get_nr_of_ifs(void) +{ + return s_esp_netif_counter; +} + +esp_netif_t* esp_netif_next(esp_netif_t* netif) +{ + ESP_LOGV(TAG, "%s %p", __func__, netif); + struct slist_netifs_s *item; + if (netif == NULL) { + item = SLIST_FIRST(&s_head); + return (item == NULL) ? NULL : item->netif; + } else { + SLIST_FOREACH(item, &s_head, next) { + if (item->netif == netif) { + item = SLIST_NEXT(item, next); + return (item == NULL) ? NULL : item->netif; + } + } + } + return NULL; +} \ No newline at end of file diff --git a/components/esp_netif/include/esp_netif.h b/components/esp_netif/include/esp_netif.h new file mode 100644 index 000000000..6cd8b13dd --- /dev/null +++ b/components/esp_netif/include/esp_netif.h @@ -0,0 +1,641 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_NETIF_H_ +#define _ESP_NETIF_H_ + +#include +#include "esp_wifi_types.h" +#include "sdkconfig.h" +#include "esp_netif_ip_addr.h" +#include "esp_netif_types.h" +#include "esp_netif_defaults.h" + +// +// 1) Initialization API: +// + +/** + * @brief Initialize the underlying TCP/IP stack + * + * @return + * - ESP_OK on success + * - ESP_FAIL if initializing failed + + * @note This function should be called exactly once from application code, when the application starts up. + */ +esp_err_t esp_netif_init(void); + +/** + * @brief Deinitialize the esp-netif component (and the underlying TCP/IP stack) + * + * Note: Deinitialization is not supported yet + * + * @return + * - ESP_ERR_INVALID_STATE if esp_netif not initialized + * - ESP_ERR_NOT_SUPPORTED otherwise + */ +esp_err_t esp_netif_deinit(void); + +/** + * @brief Creates an instance of new esp-netif object based on provided config + * + * @param[in] esp_netif_config pointer esp-netif configuration + * + * @return + * - pointer to esp-netif object on success + * - NULL otherwise + */ +esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config); + +/** + * @brief Destroys the esp_netif object + * + * @param[in] pointer to the object to be deleted + */ +void esp_netif_destroy(esp_netif_t *esp_netif); + +/** + * @brief Configures the esp_netif object + * + * Note: if some of the configuration parameter is null, the corresponding config + * option is skipped. This enables calling this function multiple times to configure + * different parts related to for example network stack or io driver separately + * + * @param[inout] pointer to the object to be configured + * @param[in] esp_netif_config pointer esp-netif configuration + * @return + * - ESP_OK + * + */ +esp_err_t esp_netif_configure(esp_netif_t *esp_netif, + const esp_netif_config_t *esp_netif_config); + +esp_err_t esp_netif_attach(esp_netif_t *esp_netif, esp_netif_iodriver_handle driver_handle); + +// +// 2) Input - Output APIs +// + +/** + * @brief Outputs packets from the TCP/IP stack to the media to be transmitted + * + * This function gets called from network stack to output packets to IO driver. + * + * @note This function is installed automatically for default interfaces. + * Custom interface may need to install if the rx buffer passed as pointer and the IO driver has to + * deallocate the data in driver context + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] void* buffer: rx buffer pointer + */ +esp_err_t esp_netif_transmit(esp_netif_t *esp_netif, void* data, size_t len); + +/** + * @brief Free the rx buffer allocated by the media driver + * + * This function gets called from network stack when the rx buffer to be freed in media driver context. + * + * @note This function is installed automatically for default interfaces. + * Custom interface may need to install if the rx buffer passed as pointer and the IO driver has to + * deallocate the data in driver context + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] void* buffer: rx buffer pointer + */ +void esp_netif_free_rx_buffer(void *esp_netif, void* buffer); + +/** + * @brief Passes the raw packets from communication media to the appropriate TCP/IP stack + * + * This function is called from the configured (peripheral) driver layer. + * The data are then forwarded as frames to the TCP/IP stack. + * + * @note Installation happens automatically for default interfaces; custom IO drivers must install + * this function so that it is called on a reception of incoming packet + * + * @note Application code does not usually need to call this function directly. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] buffer Received data + * @param[in] len Length of the data frame + * @param[in] eb Pointer to internal buffer (used in Wi-Fi driver) + * + * @return + * - ESP_OK + */ +esp_err_t esp_netif_receive(esp_netif_t *esp_netif, void *buffer, size_t len, void *eb); + +// +// 3) ESP-NETIF lifecycle +// + + +/** + * @brief Default building block for network interface action upon IO driver start event + * Creates network interface, if AUTOUP enabled turns the interface on, + * if DHCPS enabled starts dhcp server + * + * @note This API can be directly used as event handler + * + * @param[in] esp_netif Handle to esp-netif instance + * @param base + * @param event_id + * @param data + */ +void esp_netif_action_start(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data); + +/** + * @brief Default building block for network interface action upon IO driver stop event + * + * @note This API can be directly used as event handler + * + * @param[in] esp_netif Handle to esp-netif instance + * @param base + * @param event_id + * @param data + */ +void esp_netif_action_stop(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data); + +/** + * @brief Default building block for network interface action upon IO driver connected event + * + * @note This API can be directly used as event handler + * + * @param[in] esp_netif Handle to esp-netif instance + * @param base + * @param event_id + * @param data + */ +void esp_netif_action_connected(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data); + +/** + * @brief Default building block for network interface action upon IO driver disconnected event + * + * @note This API can be directly used as event handler + * + * @param[in] esp_netif Handle to esp-netif instance + * @param base + * @param event_id + * @param data + */ +void esp_netif_action_disconnected(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data); + +/** + * @brief Default building block for network interface action upon network got IP event + * + * @note This API can be directly used as event handler + * + * @param[in] esp_netif Handle to esp-netif instance + * @param base + * @param event_id + * @param data + */ +void esp_netif_action_got_ip(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data); + +// +/// 4) Configuration (getter - setters) +// +/** + * @brief Set the hostname of an interface + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] hostname New hostname for the interface. Maximum length 32 bytes. + * + * @return + * - ESP_OK - success + * - ESP_ERR_ESP_NETIF_IF_NOT_READY - interface status error + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS - parameter error + */ +esp_err_t esp_netif_set_hostname(esp_netif_t *esp_netif, const char *hostname); + +/** + * @brief Get interface hostname. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[out] hostname Returns a pointer to the hostname. May be NULL if no hostname is set. If set non-NULL, pointer remains valid (and string may change if the hostname changes). + * + * @return + * - ESP_OK - success + * - ESP_ERR_ESP_NETIF_IF_NOT_READY - interface status error + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS - parameter error + */ +esp_err_t esp_netif_get_hostname(esp_netif_t *esp_netif, const char **hostname); + +/** + * @brief Test if supplied interface is up or down + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - true - Interface is up + * - false - Interface is down + */ +bool esp_netif_is_netif_up(esp_netif_t *esp_netif); + +/** + * @brief Get interface's IP address information + * + * If the interface is up, IP information is read directly from the TCP/IP stack. + * If the interface is down, IP information is read from a copy kept in the ESP-NETIF instance + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[out] ip_info If successful, IP information will be returned in this argument. + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + */ +esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info); + +/** + * @brief Get interface's old IP information + * + * Returns an "old" IP address previously stored for the interface when the valid IP changed. + * + * If the IP lost timer has expired (meaning the interface was down for longer than the configured interval) + * then the old IP information will be zero. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[out] ip_info If successful, IP information will be returned in this argument. + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + */ +esp_err_t esp_netif_get_old_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info); + +/** + * @brief Set interface's IP address information + * + * This function is mainly used to set a static IP on an interface. + * + * If the interface is up, the new IP information is set directly in the TCP/IP stack. + * + * The copy of IP information kept in the ESP-NETIF instance is also updated (this + * copy is returned if the IP is queried while the interface is still down.) + * + * @note DHCP client/server must be stopped (if enabled for this interface) before setting new IP information. + * + * @note Calling this interface for may generate a SYSTEM_EVENT_STA_GOT_IP or SYSTEM_EVENT_ETH_GOT_IP event. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] ip_info IP information to set on the specified interface + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + * - ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED If DHCP server or client is still running + */ +esp_err_t esp_netif_set_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_info_t *ip_info); + +/** + * @brief Set interface old IP information + * + * This function is called from the DHCP client (if enabled), before a new IP is set. + * It is also called from the default handlers for the SYSTEM_EVENT_STA_CONNECTED and SYSTEM_EVENT_ETH_CONNECTED events. + * + * Calling this function stores the previously configured IP, which can be used to determine if the IP changes in the future. + * + * If the interface is disconnected or down for too long, the "IP lost timer" will expire (after the configured interval) and set the old IP information to zero. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] ip_info Store the old IP information for the specified interface + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + */ +esp_err_t esp_netif_set_old_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_info_t *ip_info); + + +// +// 5) Network stack related API +// + +// +// DHCP +// +/** + * @brief Set or Get DHCP server option + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] opt_op ESP_NETIF_OP_SET to set an option, ESP_NETIF_OP_GET to get an option. + * @param[in] opt_id Option index to get or set, must be one of the supported enum values. + * @param[inout] opt_val Pointer to the option parameter. + * @param[in] opt_len Length of the option parameter. + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + * - ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED + * - ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED + */ +esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val, uint32_t opt_len); + +esp_err_t esp_netif_dhcpc_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val, uint32_t opt_len); + +/** + * @brief Start DHCP client (only if enabled in interface object) + * + * @note The default event handlers for the SYSTEM_EVENT_STA_CONNECTED and SYSTEM_EVENT_ETH_CONNECTED events call this function. + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + * - ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED + * - ESP_ERR_ESP_NETIF_DHCPC_START_FAILED + */ +esp_err_t esp_netif_dhcpc_start(esp_netif_t *esp_netif); + +/** + * @brief Stop DHCP client (only if enabled in interface object) + * + * @note Calling action_netif_stop() will also stop the DHCP Client if it is running. + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + * - ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED + * - ESP_ERR_ESP_NETIF_IF_NOT_READY + */ +esp_err_t esp_netif_dhcpc_stop(esp_netif_t *esp_netif); + +/** + * @brief Get DHCP client status + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[out] status If successful, the status of DHCP client will be returned in this argument. + * + * @return + * - ESP_OK + */ +esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status); + +/** + * @brief Get DHCP Server status + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[out] status If successful, the status of the DHCP server will be returned in this argument. + * + * @return + * - ESP_OK + */ +esp_err_t esp_netif_dhcps_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status); + +/** + * @brief Start DHCP server (only if enabled in interface object) + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + * - ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED + */ +esp_err_t esp_netif_dhcps_start(esp_netif_t *esp_netif); + +/** + * @brief Stop DHCP server (only if enabled in interface object) + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + * - ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED + * - ESP_ERR_ESP_NETIF_IF_NOT_READY + */ +esp_err_t esp_netif_dhcps_stop(esp_netif_t *esp_netif); + +// +// DNS: +// +/** + * @brief Set DNS Server information + * + * This function behaves differently if DHCP server or client is enabled + * + * If DHCP client is enabled, main and backup DNS servers will be updated automatically + * from the DHCP lease if the relevant DHCP options are set. Fallback DNS Server is never updated from the DHCP lease + * and is designed to be set via this API. + * If DHCP client is disabled, all DNS server types can be set via this API only. + * + * If DHCP server is enabled, the Main DNS Server setting is used by the DHCP server to provide a DNS Server option + * to DHCP clients (Wi-Fi stations). + * - The default Main DNS server is typically the IP of the Wi-Fi AP interface itself. + * - This function can override it by setting server type ESP_NETIF_DNS_MAIN. + * - Other DNS Server types are not supported for the Wi-Fi AP interface. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] type Type of DNS Server to set: ESP_NETIF_DNS_MAIN, ESP_NETIF_DNS_BACKUP, ESP_NETIF_DNS_FALLBACK + * @param[in] dns DNS Server address to set + * + * @return + * - ESP_OK on success + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS invalid params + */ +esp_err_t esp_netif_set_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns); + +/** + * @brief Get DNS Server information + * + * Return the currently configured DNS Server address for the specified interface and Server type. + * + * This may be result of a previous call to esp_netif_set_dns_info(). If the interface's DHCP client is enabled, + * the Main or Backup DNS Server may be set by the current DHCP lease. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] type Type of DNS Server to get: ESP_NETIF_DNS_MAIN, ESP_NETIF_DNS_BACKUP, ESP_NETIF_DNS_FALLBACK + * @param[out] dns DNS Server result is written here on success + * + * @return + * - ESP_OK on success + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS invalid params + */ +esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns); +/** + * @brief Set the mac address for the interface instance + + * @param[in] esp_netif Handle to esp-netif instance + * @param[in] mac Desired mac address for the related network interface + * @return ESP_OK + */ +esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[]); + +/** + * @brief Create interface link-local IPv6 address + * + * Cause the TCP/IP stack to create a link-local IPv6 address for the specified interface. + * + * This function also registers a callback for the specified interface, so that if the link-local address becomes + * verified as the preferred address then a SYSTEM_EVENT_GOT_IP6 event will be sent. + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + */ +esp_err_t esp_netif_create_ip6_linklocal(esp_netif_t *esp_netif); + +/** + * @brief Get interface link-local IPv6 address + * + * If the specified interface is up and a preferred link-local IPv6 address + * has been created for the interface, return a copy of it. + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[out] if_ip6 IPv6 information will be returned in this argument if successful. + * + * @return + * - ESP_OK + * - ESP_FAIL If interface is down, does not have a link-local IPv6 address, + * or the link-local IPv6 address is not a preferred address. + */ +esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6); + +/** + * @brief Sets IPv4 address to the specified octets + * + * @param[out] addr IP address to be set + * @param a the first octet (127 for IP 127.0.0.1) + * @param b + * @param c + * @param d + */ +void esp_netif_set_ip4_addr(esp_ip4_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d); + + +/** + * @brief Converts numeric IP address into decimal dotted ASCII representation. + * + * @param addr ip address in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char * esp_ip4addr_ntoa(const esp_ip4_addr_t *addr, char *buf, int buflen); + +// +// 6) Driver conversion utilities to related keys, flags, implementation handle, list of netifs +// + +/** + * @brief Gets media driver handle for this esp-netif instance + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return opaque pointer of related IO driver + */ +esp_netif_iodriver_handle esp_netif_get_io_driver(esp_netif_t *esp_netif); + +/** + * @brief Searches over a list of created objects to find an instance with supplied if key + * + * @param if_key Textual description of network interface + * + * @return Handle to esp-netif instance + */ +esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key); + +/** + * @brief Returns configured flags for this interface + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return Configuration flags + */ +esp_netif_flags_t esp_netif_get_flags(esp_netif_t *esp_netif); + +/** + * @brief Returns configured interface key for this esp-netif instance + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return Textual description of related interface + */ +char *esp_netif_get_ifkey(esp_netif_t *esp_netif); + +/** + * @brief Returns configured interface type for this esp-netif instance + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return Enumerated type of this interface, such as station, AP, ethernet + */ +esp_netif_type_t esp_netif_get_type(esp_netif_t *esp_netif); + +/** + * @brief Returns configured event for this esp-netif instance and supplied event type + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @param event_type (either get or lost IP) + * + * @return specific event id which is configured to be raised if the interface lost or acquired IP address + */ +uint32_t esp_netif_get_event_id(esp_netif_t *esp_netif, esp_netif_ip_event_type_t event_type); + +// +// 7) esp_netif list API +// +/** + * @brief Iterates over list of interfaces. Returns first netif if NULL given as parameter + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return First netif from the list if supplied parameter is NULL, next one otherwise + */ +esp_netif_t* esp_netif_next(esp_netif_t* netif); + +/** + * @brief Returns number of registered esp_netif objects + * + * @return Number of esp_netifs + */ +size_t esp_netif_get_nr_of_ifs(void); + +// +// 8) MISC: List of STAs +// + +/** + * @brief Get IP information for stations connected to the Wi-Fi AP interface + * + * @param[in] wifi_sta_list Wi-Fi station info list, returned from esp_wifi_ap_get_sta_list() + * @param[out] tcpip_sta_list IP layer station info list, corresponding to MAC addresses provided in wifi_sta_list + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_NO_MEM + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + */ +esp_err_t esp_netif_get_sta_list(const wifi_sta_list_t *wifi_sta_list, esp_netif_sta_list_t *tcpip_sta_list); + +int esp_netif_get_netif_index(esp_netif_t *esp_netif); + +#if CONFIG_ESP_NETIF_USE_TCPIP_ADAPTER_COMPATIBLE_LAYER +// +// 8) Compatibility layer +// +#include "tcpip_adapter.h" +#endif + +#endif /* _ESP_NETIF_H_ */ diff --git a/components/esp_netif/include/esp_netif_defaults.h b/components/esp_netif/include/esp_netif_defaults.h new file mode 100644 index 000000000..19b7208e9 --- /dev/null +++ b/components/esp_netif/include/esp_netif_defaults.h @@ -0,0 +1,114 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_NETIF_DEFAULTS_H +#define _ESP_NETIF_DEFAULTS_H + +// +// Macros to assemble master configs with partial configs from netif, stack and driver +// + +/** + * @brief Default configuration reference of ethernet interface + */ +#define ESP_NETIF_DEFAULT_ETH() \ + { \ + .base = ESP_NETIF_BASE_DEFAULT_ETH, \ + .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH, \ + .driver = ESP_NETIF_DRIVER_DEFAULT_ETH, \ + } + +/** + * @brief Default configuration reference of WIFI AP + */ +#define ESP_NETIF_DEFAULT_WIFI_AP() \ +{ \ + .base = ESP_NETIF_BASE_DEFAULT_WIFI_AP, \ + .stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP, \ + .driver = ESP_NETIF_DRIVER_DEFAULT_WIFI_AP, \ + } + +/** +* @brief Default configuration reference of WIFI STA +*/ +#define ESP_NETIF_DEFAULT_WIFI_STA() \ + { \ + .base = ESP_NETIF_BASE_DEFAULT_WIFI_STA, \ + .stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA, \ + .driver = ESP_NETIF_DRIVER_DEFAULT_WIFI_STA, \ + } +/** + * @brief Default base config (esp-netif inherent) of WIFI STA + */ +#define ESP_NETIF_BASE_DEFAULT_WIFI_STA &_g_esp_netif_inherent_sta_config + +/** + * @brief Default base config (esp-netif inherent) of WIFI AP + */ +#define ESP_NETIF_BASE_DEFAULT_WIFI_AP &_g_esp_netif_inherent_ap_config + +/** + * @brief Default base config (esp-netif inherent) of ethernet interface + */ +#define ESP_NETIF_BASE_DEFAULT_ETH &_g_esp_netif_inherent_eth_config + +#define ESP_NETIF_NETSTACK_DEFAULT_ETH _g_esp_netif_netstack_default_eth +#define ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA _g_esp_netif_netstack_default_wifi_sta +#define ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP _g_esp_netif_netstack_default_wifi_ap +// +// Include default network stacks configs +// - Network stack configurations are provided in a specific network stack +// implementation that is invisible to user API +// - Here referenced only as opaque pointers +// +extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_eth; +extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta; +extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap; + +// +// Include default common configs inherent to esp-netif +// - These inherent configs are defined in esp_netif_defaults.c and describe +// common behavioural patters for common interfaces such as STA, AP, ETH +// +extern const esp_netif_inherent_config_t _g_esp_netif_inherent_sta_config; +extern const esp_netif_inherent_config_t _g_esp_netif_inherent_ap_config; +extern const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config; + +// +// API for creating default interfaces +// + +/** + * @brief Creates default WIFI AP. In case of any init error this API aborts. + * + * @return pointer to esp-netif instance + */ +esp_netif_t* esp_netif_create_default_wifi_ap(void); + +/** + * @brief Creates default WIFI STA. In case of any init error this API aborts. + * + * @return pointer to esp-netif instance + */ +esp_netif_t* esp_netif_create_default_wifi_sta(void); + +/** + * @brief Creates default ethernet interface. In case of any init error this API aborts. + * + * @return pointer to esp-netif instance + */ +esp_netif_t* esp_netif_create_default_eth(void * eth_driver); + + +#endif //_ESP_NETIF_DEFAULTS_H diff --git a/components/esp_netif/include/esp_netif_ip_addr.h b/components/esp_netif/include/esp_netif_ip_addr.h new file mode 100644 index 000000000..1680ac976 --- /dev/null +++ b/components/esp_netif/include/esp_netif_ip_addr.h @@ -0,0 +1,88 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_NETIF_IP_ADDR_H_ +#define _ESP_NETIF_IP_ADDR_H_ + +#include +#if BYTE_ORDER == BIG_ENDIAN +#define esp_netif_htonl(x) ((uint32_t)(x)) +#else +#define esp_netif_htonl(x) ((((x) & (uint32_t)0x000000ffUL) << 24) | \ + (((x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((x) & (uint32_t)0xff000000UL) >> 24)) +#endif +// Access address in 16-bit block +#define ESP_IP6_ADDR_BLOCK1(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[0]) >> 16) & 0xffff)) +#define ESP_IP6_ADDR_BLOCK2(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[0])) & 0xffff)) +#define ESP_IP6_ADDR_BLOCK3(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[1]) >> 16) & 0xffff)) +#define ESP_IP6_ADDR_BLOCK4(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[1])) & 0xffff)) +#define ESP_IP6_ADDR_BLOCK5(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[2]) >> 16) & 0xffff)) +#define ESP_IP6_ADDR_BLOCK6(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[2])) & 0xffff)) +#define ESP_IP6_ADDR_BLOCK7(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[3]) >> 16) & 0xffff)) +#define ESP_IP6_ADDR_BLOCK8(ip6addr) ((uint16_t)((esp_netif_htonl((ip6addr)->addr[3])) & 0xffff)) + +#define IPSTR "%d.%d.%d.%d" +#define esp_ip4_addr_get_byte(ipaddr, idx) (((const uint8_t*)(&(ipaddr)->addr))[idx]) +#define esp_ip4_addr1(ipaddr) esp_ip4_addr_get_byte(ipaddr, 0) +#define esp_ip4_addr2(ipaddr) esp_ip4_addr_get_byte(ipaddr, 1) +#define esp_ip4_addr3(ipaddr) esp_ip4_addr_get_byte(ipaddr, 2) +#define esp_ip4_addr4(ipaddr) esp_ip4_addr_get_byte(ipaddr, 3) + + +#define esp_ip4_addr1_16(ipaddr) ((uint16_t)esp_ip4_addr1(ipaddr)) +#define esp_ip4_addr2_16(ipaddr) ((uint16_t)esp_ip4_addr2(ipaddr)) +#define esp_ip4_addr3_16(ipaddr) ((uint16_t)esp_ip4_addr3(ipaddr)) +#define esp_ip4_addr4_16(ipaddr) ((uint16_t)esp_ip4_addr4(ipaddr)) + +#define IP2STR(ipaddr) esp_ip4_addr1_16(ipaddr), \ + esp_ip4_addr2_16(ipaddr), \ + esp_ip4_addr3_16(ipaddr), \ + esp_ip4_addr4_16(ipaddr) + +#define IPV6STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" + +#define IPV62STR(ipaddr) ESP_IP6_ADDR_BLOCK1(&(ipaddr)), \ + ESP_IP6_ADDR_BLOCK2(&(ipaddr)), \ + ESP_IP6_ADDR_BLOCK3(&(ipaddr)), \ + ESP_IP6_ADDR_BLOCK4(&(ipaddr)), \ + ESP_IP6_ADDR_BLOCK5(&(ipaddr)), \ + ESP_IP6_ADDR_BLOCK6(&(ipaddr)), \ + ESP_IP6_ADDR_BLOCK7(&(ipaddr)), \ + ESP_IP6_ADDR_BLOCK8(&(ipaddr)) + + +struct esp_ip6_addr { + uint32_t addr[4]; + uint8_t zone; +}; + +struct esp_ip4_addr { + uint32_t addr; +}; + +typedef struct esp_ip4_addr esp_ip4_addr_t; + +typedef struct esp_ip6_addr esp_ip6_addr_t; + +typedef struct _ip_addr { + union { + esp_ip6_addr_t ip6; + esp_ip4_addr_t ip4; + } u_addr; + uint8_t type; +} esp_ip_addr_t; + +#endif //_ESP_NETIF_IP_ADDR_H_ diff --git a/components/esp_netif/include/esp_netif_net_stack.h b/components/esp_netif/include/esp_netif_net_stack.h new file mode 100644 index 000000000..bfef36fd0 --- /dev/null +++ b/components/esp_netif/include/esp_netif_net_stack.h @@ -0,0 +1,41 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_NETIF_NET_STACK_H_ +#define _ESP_NETIF_NET_STACK_H_ + +// +// Network stack API: This ESP-NETIF API are supposed to be called only from internals of TCP/IP stack +// + +/** + * @brief Returns esp-netif handle + * + * @param[in] dev opaque ptr to network interface of specific TCP/IP stack + * + * @return handle to related esp-netif instance + */ +esp_netif_t* esp_netif_get_handle_from_netif_impl(void *dev); + + +/** + * @brief Returns network stack specific implementation handle + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return handle to related network stack netif handle + */ +void* esp_netif_get_netif_impl(esp_netif_t *esp_netif); + +#endif //_ESP_NETIF_NET_STACK_H_ diff --git a/components/esp_netif/include/esp_netif_types.h b/components/esp_netif/include/esp_netif_types.h new file mode 100644 index 000000000..5ce7837c1 --- /dev/null +++ b/components/esp_netif/include/esp_netif_types.h @@ -0,0 +1,223 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_NETIF_TYPES_H_ +#define _ESP_NETIF_TYPES_H_ + +/** + * @brief Definition of ESP-NETIF based errors + */ +#define ESP_ERR_ESP_NETIF_BASE 0x5000 +#define ESP_ERR_ESP_NETIF_INVALID_PARAMS ESP_ERR_ESP_NETIF_BASE + 0x01 +#define ESP_ERR_ESP_NETIF_IF_NOT_READY ESP_ERR_ESP_NETIF_BASE + 0x02 +#define ESP_ERR_ESP_NETIF_DHCPC_START_FAILED ESP_ERR_ESP_NETIF_BASE + 0x03 +#define ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED ESP_ERR_ESP_NETIF_BASE + 0x04 +#define ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED ESP_ERR_ESP_NETIF_BASE + 0x05 +#define ESP_ERR_ESP_NETIF_NO_MEM ESP_ERR_ESP_NETIF_BASE + 0x06 +#define ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED ESP_ERR_ESP_NETIF_BASE + 0x07 +#define ESP_ERR_ESP_NETIF_DRIVER_ATACH_FAILED ESP_ERR_ESP_NETIF_BASE + 0x08 + + +/** @brief Type of esp_netif_object server */ +struct esp_netif_obj; + +typedef struct esp_netif_obj esp_netif_t; + + +/** @brief Type of DNS server */ +typedef enum { + ESP_NETIF_DNS_MAIN= 0, /**< DNS main server address*/ + ESP_NETIF_DNS_BACKUP, /**< DNS backup server address (Wi-Fi STA and Ethernet only) */ + ESP_NETIF_DNS_FALLBACK, /**< DNS fallback server address (Wi-Fi STA and Ethernet only) */ + ESP_NETIF_DNS_MAX +} esp_netif_dns_type_t; + +/** @brief DNS server info */ +typedef struct { + esp_ip_addr_t ip; /**< IPV4 address of DNS server */ +} esp_netif_dns_info_t; + +/** @brief Status of DHCP client or DHCP server */ +typedef enum { + ESP_NETIF_DHCP_INIT = 0, /**< DHCP client/server is in initial state (not yet started) */ + ESP_NETIF_DHCP_STARTED, /**< DHCP client/server has been started */ + ESP_NETIF_DHCP_STOPPED, /**< DHCP client/server has been stopped */ + ESP_NETIF_DHCP_STATUS_MAX +} esp_netif_dhcp_status_t; + + +/** @brief Mode for DHCP client or DHCP server option functions */ +typedef enum{ + ESP_NETIF_OP_START = 0, + ESP_NETIF_OP_SET, /**< Set option */ + ESP_NETIF_OP_GET, /**< Get option */ + ESP_NETIF_OP_MAX +} esp_netif_dhcp_option_mode_t; + +/** @brief Supported options for DHCP client or DHCP server */ +typedef enum{ + ESP_NETIF_DOMAIN_NAME_SERVER = 6, /**< Domain name server */ + ESP_NETIF_ROUTER_SOLICITATION_ADDRESS = 32, /**< Solicitation router address */ + ESP_NETIF_REQUESTED_IP_ADDRESS = 50, /**< Request specific IP address */ + ESP_NETIF_IP_ADDRESS_LEASE_TIME = 51, /**< Request IP address lease time */ + ESP_NETIF_IP_REQUEST_RETRY_TIME = 52, /**< Request IP address retry counter */ +} esp_netif_dhcp_option_id_t; + +/** IP event declarations */ +typedef enum { + IP_EVENT_STA_GOT_IP, /*!< ESP32 station got IP from connected AP */ + IP_EVENT_STA_LOST_IP, /*!< ESP32 station lost IP and the IP is reset to 0 */ + IP_EVENT_AP_STAIPASSIGNED, /*!< ESP32 soft-AP assign an IP to a connected station */ + IP_EVENT_GOT_IP6, /*!< ESP32 station or ap or ethernet interface v6IP addr is preferred */ + IP_EVENT_ETH_GOT_IP, /*!< ESP32 ethernet got IP from connected AP */ +} ip_event_t; + +/** @brief IP event base declaration */ +ESP_EVENT_DECLARE_BASE(IP_EVENT); + +/** Event structure for IP_EVENT_STA_GOT_IP, IP_EVENT_ETH_GOT_IP events */ + +typedef struct { + esp_ip4_addr_t ip; /**< Interface IPV4 address */ + esp_ip4_addr_t netmask; /**< Interface IPV4 netmask */ + esp_ip4_addr_t gw; /**< Interface IPV4 gateway address */ +} esp_netif_ip_info_t; + +/** @brief IPV6 IP address information + */ +typedef struct { + esp_ip6_addr_t ip; /**< Interface IPV6 address */ +} esp_netif_ip6_info_t; + +typedef struct { + int if_index; /*!< Interface index for which the event is received (left for legacy compilation) */ + esp_netif_t *esp_netif; /*!< Pointer to corresponding esp-netif object */ + esp_netif_ip_info_t ip_info; /*!< IP address, netmask, gatway IP address */ + bool ip_changed; /*!< Whether the assigned IP has changed or not */ +} ip_event_got_ip_t; + +/** Event structure for IP_EVENT_GOT_IP6 event */ +typedef struct { + int if_index; /*!< Interface index for which the event is received (left for legacy compilation) */ + esp_netif_t *esp_netif; /*!< Pointer to corresponding esp-netif object */ + esp_netif_ip6_info_t ip6_info; /*!< IPv6 address of the interface */ +} ip_event_got_ip6_t; + +/** Event structure for IP_EVENT_AP_STAIPASSIGNED event */ +typedef struct { + esp_ip4_addr_t ip; /*!< IP address which was assigned to the station */ +} ip_event_ap_staipassigned_t; + + +typedef struct { + uint8_t mac[6]; /**< Station MAC address */ + esp_ip4_addr_t ip; /**< Station assigned IP address */ +} esp_netif_sta_info_t; + + +typedef struct { + esp_netif_sta_info_t sta[ESP_WIFI_MAX_CONN_NUM]; /**< Connected stations */ + int num; /**< Number of connected stations */ +} esp_netif_sta_list_t; + +typedef enum esp_netif_flags { + ESP_NETIF_DHCPC = 1 << 0, + ESP_NETIF_DHCPS = 1 << 1, + ESP_NETIF_FLAG_AUTOUP = 1 << 2, + ESP_NETIF_FLAG_GARP = 1 << 3, + ESP_NETIF_FLAG_EVENT_IP_MODIFIED = 1 << 4 +} esp_netif_flags_t; + +typedef enum esp_netif_type { + ESP_NETIF_TYPE_UNKNOWN, + ESP_NETIF_TYPE_STA, + ESP_NETIF_TYPE_AP, + ESP_NETIF_TYPE_ETH, + ESP_NETIF_TYPE_OTHER, + ESP_NETIF_TYPE_MAX +} esp_netif_type_t; + +typedef enum esp_netif_ip_event_type { + ESP_NETIF_IP_EVENT_GOT_IP = 1, + ESP_NETIF_IP_EVENT_LOST_IP = 2, +} esp_netif_ip_event_type_t; + + +// +// ESP-NETIF interface configuration: +// 1) general (behavioral) config (esp_netif_config_t) +// 2) (peripheral) driver specific config (esp_netif_driver_ifconfig_t) +// 3) network stack specific config (esp_netif_net_stack_ifconfig_t) -- no publicly available +// + +typedef struct esp_netif_inherent_config { + esp_netif_flags_t flags; /*!< flags that define esp-netif behavior */ + uint8_t mac[6]; /*!< initial mac address for this interface */ + esp_netif_ip_info_t* ip_info; /*!< initial ip address for this interface */ + uint32_t get_ip_event; /*!< event id to be raised when interface gets an IP */ + uint32_t lost_ip_event; /*!< event id to be raised when interface losts its IP */ + esp_netif_type_t if_type; /*!< enum type of the interface */ + const char * if_key; /*!< string identifier of the interface */ + int route_prio; /*!< numeric priority of this interface to become a default + routing if (if other netifs are up) */ +} esp_netif_inherent_config_t; + +typedef struct esp_netif_config esp_netif_config_t; + +/** + * @brief IO driver handle type + */ +typedef void * esp_netif_iodriver_handle; + +typedef struct esp_netif_driver_base_s { + esp_err_t (*post_attach)(esp_netif_t *netif, esp_netif_iodriver_handle h); + esp_netif_t *netif; +} esp_netif_driver_base_t; + +/** + * @brief Specific IO driver configuration + */ +struct esp_netif_driver_ifconfig { + esp_netif_iodriver_handle handle; + esp_err_t (*transmit)(void *h, void *buffer, size_t len); + void (*driver_free_rx_buffer)(void *h, void* buffer); +}; + +//typedef struct esp_netif_net_stack_ifconfig esp_netif_net_stack_ifconfig_t; +typedef struct esp_netif_driver_ifconfig esp_netif_driver_ifconfig_t; + +/** + * @brief Specific L3 network stack configuration + */ +typedef enum esp_netif_netstack_type { + ESP_NETIF_NETWORK_STACK_IS_LWIP = 0, + ESP_NETIF_NETWORK_STACK_MAX, +} esp_netif_netstack_type_t; + +typedef struct esp_netif_netstack_base_config { + esp_netif_netstack_type_t type; +} esp_netif_netstack_base_config_t; + +typedef struct esp_netif_netstack_config esp_netif_netstack_config_t; + +/** + * @brief Generic esp_netif configuration + */ +struct esp_netif_config { + const esp_netif_inherent_config_t *base; + const esp_netif_driver_ifconfig_t *driver; + const esp_netif_netstack_config_t *stack; +}; + +#endif // _ESP_NETIF_TYPES_H_ \ No newline at end of file diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c new file mode 100644 index 000000000..6ff408ec4 --- /dev/null +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -0,0 +1,1444 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "esp_netif_lwip_internal.h" + +#include "esp_netif.h" +#include "esp_netif_private.h" +#include "esp_netif_net_stack.h" + +#if CONFIG_TCPIP_LWIP + +#include "lwip/inet.h" +#include "lwip/tcpip.h" +#include "lwip/dhcp.h" +#include "lwip/ip_addr.h" +#include "lwip/ip6_addr.h" +#include "lwip/nd6.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/netif.h" +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ +#include "lwip/dns.h" +#endif +#include "esp_netif_lwip_internal.h" + +#include "dhcpserver/dhcpserver.h" +#include "dhcpserver/dhcpserver_options.h" + +#include "esp_event.h" +#include "esp_log.h" +#include "lwip/ip_addr.h" + +// +// This is the main module implementing lwip interaction with esp-netif +// + +#define ESP_NETIF_HOSTNAME_MAX_SIZE 32 + +typedef enum esp_netif_action { + ESP_NETIF_UNDEF, + ESP_NETIF_STARTED, + ESP_NETIF_STOPPED, +} esp_netif_action_t; + +extern sys_thread_t g_lwip_task; + +static const char *TAG = "esp_netif_lwip"; + +static sys_sem_t api_sync_sem = NULL; +static sys_sem_t api_lock_sem = NULL; +static bool tcpip_initialized = false; +static esp_netif_t *s_last_default_esp_netif = NULL; + +static int esp_netif_ipc_check(esp_netif_api_msg_t *msg); + +/** + * @brief Main esp-netif container with interface related information + * + * + */ +struct esp_netif_obj { + // default interface addresses + uint8_t mac[6]; + esp_netif_ip_info_t* ip_info; + esp_netif_ip_info_t* ip_info_old; + + // lwip netif related + struct netif* lwip_netif; + err_t (*lwip_init_fn)(struct netif*); + void (*lwip_input_fn)(struct netif *netif, void *buffer, size_t len, void *eb); + + // io driver related + void* driver_handle; + esp_err_t (*driver_transmit)(void *h, void *buffer, size_t len); + void (*driver_free_rx_buffer)(void *h, void* buffer); + + // dhcp related + esp_netif_dhcp_status_t dhcpc_status; + esp_netif_dhcp_status_t dhcps_status; + bool timer_running; + + // event translation + ip_event_t get_ip_event; + ip_event_t lost_ip_event; + + // misc flags, types, keys, priority + esp_netif_flags_t flags; + char * hostname; + char * if_key; + esp_netif_type_t if_type; + int route_prio; +}; + +/** + * @brief This function sets default routing netif based on priorities of all interfaces which are up + * @param esp_netif current interface which just updated state + * @param action updating action (on-off) + * + * @note: This function must be called from lwip thread + * + */ +static void esp_netif_update_default_netif(esp_netif_t *esp_netif, esp_netif_action_t action) { + switch (action) { + case ESP_NETIF_STARTED: + if (s_last_default_esp_netif && esp_netif_is_netif_up(s_last_default_esp_netif) + && (s_last_default_esp_netif->route_prio > esp_netif->route_prio)) { + netif_set_default(s_last_default_esp_netif->lwip_netif); + } else if (esp_netif_is_netif_up(esp_netif)) { + s_last_default_esp_netif = esp_netif; + netif_set_default(s_last_default_esp_netif->lwip_netif); + } + break; + default: + case ESP_NETIF_STOPPED: + { + esp_netif_t *netif = esp_netif_next(NULL); + s_last_default_esp_netif = NULL; + while (netif) { + if (esp_netif_is_netif_up(netif)) { + if (s_last_default_esp_netif && esp_netif_is_netif_up(s_last_default_esp_netif)) { + if (netif->route_prio > s_last_default_esp_netif->route_prio) { + s_last_default_esp_netif = netif; + } // else not needed, as the s_last_default_esp_netif is correct + } else { + // s_last_default is either not set or down, current netif is up + s_last_default_esp_netif = netif; + } + } + netif = esp_netif_next(netif); + } + if (s_last_default_esp_netif && esp_netif_is_netif_up(s_last_default_esp_netif)) { + netif_set_default(s_last_default_esp_netif->lwip_netif); + } + } break; + } +} + +void esp_netif_set_ip4_addr(esp_ip4_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d) +{ + ip4_addr_t *address = (ip4_addr_t*)addr; + IP4_ADDR(address, a, b, c, d); +} + +char * esp_ip4addr_ntoa(const esp_ip4_addr_t *addr, char *buf, int buflen) +{ + return ip4addr_ntoa_r((ip4_addr_t *)addr, buf, buflen); +} + +esp_netif_iodriver_handle esp_netif_get_io_driver(esp_netif_t *esp_netif) +{ + return esp_netif->driver_handle; +} + +esp_netif_t* esp_netif_get_handle_from_netif_impl(void *dev) +{ + struct netif *lwip_netif = dev; + return lwip_netif->state; +} + +void* esp_netif_get_netif_impl(esp_netif_t *esp_netif) +{ + return esp_netif->lwip_netif; +} + +esp_err_t esp_netif_init(void) +{ + if (tcpip_initialized == false) { + tcpip_initialized = true; + tcpip_init(NULL, NULL); + ESP_LOGD(TAG, "LwIP stack has been initialized"); + } + + if (!api_sync_sem) { + if (ERR_OK != sys_sem_new(&api_sync_sem, 0)) { + ESP_LOGE(TAG, "esp netif api sync sem init fail"); + return ESP_FAIL; + } + } + + if (!api_lock_sem) { + if (ERR_OK != sys_sem_new(&api_lock_sem, 1)) { + ESP_LOGE(TAG, "esp netif api lock sem init fail"); + return ESP_FAIL; + } + } + + ESP_LOGD(TAG, "esp-netif has been successfully initialized"); + return ESP_OK; +} + +esp_err_t esp_netif_deinit(void) +{ + if (tcpip_initialized == true) { + /* deinit of LwIP not supported: + * do not deinit semaphores and states, + * so init could be called multiple times + * + tcpip_initialized = false; + sys_sem_free(&api_sync_sem); + sys_sem_free(&api_lock_sem); + */ + return ESP_ERR_NOT_SUPPORTED; + + } + return ESP_ERR_INVALID_STATE; +} + +esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config) +{ + // Create parent esp-netif object + esp_netif_t *esp_netif = calloc(1, sizeof(struct esp_netif_obj)); + if (!esp_netif) { + return NULL; + } + + // Create ip info + esp_netif_ip_info_t *ip_info = calloc(1, sizeof(esp_netif_ip_info_t)); + if (!ip_info) { + free(esp_netif); + return NULL; + } + esp_netif->ip_info = ip_info; + + // creating another ip info (to store old ip) + ip_info = calloc(1, sizeof(esp_netif_ip_info_t)); + if (!ip_info) { + free(esp_netif->ip_info); + free(esp_netif); + return NULL; + } + esp_netif->ip_info_old = ip_info; + + // Create underlying lwip netif + struct netif * lwip_netif = calloc(1, sizeof(struct netif)); + if (!lwip_netif) { + free(esp_netif->ip_info_old); + free(esp_netif->ip_info); + free(esp_netif); + return NULL; + } + + lwip_netif->state = esp_netif; + esp_netif->lwip_netif = lwip_netif; + + esp_netif_add_to_list(esp_netif); + + // Configure the created object with provided configuration + if (esp_netif_config) { + ESP_ERROR_CHECK(esp_netif_configure(esp_netif, esp_netif_config)); + } + + return esp_netif; +} + +void esp_netif_destroy(esp_netif_t *esp_netif) +{ + if (esp_netif) { + esp_netif_remove_from_list(esp_netif); + free(esp_netif->ip_info); + free(esp_netif->ip_info_old); + free(esp_netif->lwip_netif); + free(esp_netif->if_key); + free(esp_netif); + } +} + +esp_err_t esp_netif_attach(esp_netif_t *esp_netif, esp_netif_iodriver_handle driver_handle) +{ + esp_netif_driver_base_t *base_driver = driver_handle; + + esp_netif->driver_handle = driver_handle; + if (base_driver->post_attach) { + esp_err_t ret = base_driver->post_attach(esp_netif, driver_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Post-attach callback of driver(%p) failed with %d", driver_handle, ret); + return ESP_ERR_ESP_NETIF_DRIVER_ATACH_FAILED; + } + } + return ESP_OK; +} + +esp_err_t esp_netif_configure(esp_netif_t *esp_netif, const esp_netif_config_t *cfg) + +{ + if (cfg == NULL) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } +// Configure general esp-netif properties + if (cfg->base) { + memcpy(esp_netif->mac, cfg->base->mac, NETIF_MAX_HWADDR_LEN); + if (cfg->base->ip_info == NULL) { + ip4_addr_set_zero(&esp_netif->ip_info->ip); + ip4_addr_set_zero(&esp_netif->ip_info->gw); + ip4_addr_set_zero(&esp_netif->ip_info->netmask); + } else { + memcpy(esp_netif->ip_info, cfg->base->ip_info, sizeof(esp_netif_ip_info_t)); + } + memcpy(esp_netif->ip_info_old, esp_netif->ip_info, sizeof(esp_netif_ip_info_t)); + + // Setup main config parameters + esp_netif->lost_ip_event = cfg->base->lost_ip_event; + esp_netif->get_ip_event = cfg->base->get_ip_event; + esp_netif->flags = cfg->base->flags; + + if (cfg->base->if_key) { + esp_netif->if_key = strdup(cfg->base->if_key); + } + if (cfg->base->if_type) { + esp_netif->if_type = cfg->base->if_type; + } + if (cfg->base->route_prio) { + esp_netif->route_prio = cfg->base->route_prio; + } + } + +// Install network stack functions -- connects netif and L3 stack + if (cfg->stack) { + const esp_netif_netstack_config_t *esp_netif_stack_config = cfg->stack; + if (cfg->stack->base.type != ESP_NETIF_NETWORK_STACK_IS_LWIP) { + ESP_LOGE(TAG, "Failed to configure uknown network stack %d", cfg->stack->base.type); + return ESP_ERR_NOT_SUPPORTED; + } + if (esp_netif_stack_config->init_fn) { + esp_netif->lwip_init_fn = esp_netif_stack_config->init_fn; + } + if (esp_netif_stack_config->input_fn) { + esp_netif->lwip_input_fn = esp_netif_stack_config->input_fn; + } + } +// Install IO functions -- connects driver and netif + if (cfg->driver) { + const esp_netif_driver_ifconfig_t *esp_netif_driver_config = cfg->driver; + if (esp_netif_driver_config->handle) { + esp_netif->driver_handle = esp_netif_driver_config->handle; + } + if (esp_netif_driver_config->transmit) { + esp_netif->driver_transmit = esp_netif_driver_config->transmit; + } + if (esp_netif_driver_config->driver_free_rx_buffer) { + esp_netif->driver_free_rx_buffer = esp_netif_driver_config->driver_free_rx_buffer; + } + } + return ESP_OK; +} + +static esp_err_t esp_netif_reset_ip_info(esp_netif_t *esp_netif) +{ + ip4_addr_set_zero(&(esp_netif->ip_info->ip)); + ip4_addr_set_zero(&esp_netif->ip_info->gw); + ip4_addr_set_zero(&esp_netif->ip_info->netmask); + return ESP_OK; +} + +esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[]) +{ + if (esp_netif == NULL || esp_netif->lwip_netif == NULL) { + return ESP_ERR_ESP_NETIF_IF_NOT_READY; + } + memcpy(esp_netif->mac, mac, NETIF_MAX_HWADDR_LEN); + memcpy(esp_netif->lwip_netif->hwaddr, mac, NETIF_MAX_HWADDR_LEN); + return ESP_OK; +} + +esp_err_t esp_netif_start_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_start(msg->esp_netif); +} + +static void esp_netif_dhcps_cb(u8_t client_ip[4]) +{ + ESP_LOGI(TAG, "softAP assign IP to station,IP is: %d.%d.%d.%d", + client_ip[0], client_ip[1], client_ip[2], client_ip[3]); + ip_event_ap_staipassigned_t evt; + + memset(&evt, 0, sizeof(ip_event_ap_staipassigned_t)); + memcpy((char *)&evt.ip.addr, (char *)client_ip, sizeof(evt.ip.addr)); + int ret = esp_event_send_internal(IP_EVENT, IP_EVENT_AP_STAIPASSIGNED, &evt, sizeof(evt), 0); + if (ESP_OK != ret) { + ESP_LOGE(TAG, "dhcps cb: failed to post IP_EVENT_AP_STAIPASSIGNED (%x)", ret); + } +} + + +esp_err_t esp_netif_start(esp_netif_t *esp_netif) +{ + ESP_NETIF_IPC_CALL(esp_netif, NULL, esp_netif_start_api); + + ESP_LOGD(TAG, "%s %p", __func__, esp_netif); + + netif_add(esp_netif->lwip_netif, (struct ip4_addr*)&esp_netif->ip_info->ip, (struct ip4_addr*)&esp_netif->ip_info->netmask, (struct ip4_addr*)&esp_netif->ip_info->gw, esp_netif, esp_netif->lwip_init_fn, tcpip_input); + + if (esp_netif->flags&ESP_NETIF_FLAG_GARP) { +#if ESP_GRATUITOUS_ARP + netif_set_garp_flag(esp_netif->lwip_netif); +#else + ESP_LOGW(TAG,"CONFIG_LWIP_ESP_GRATUITOUS_ARP not enabled, but esp-netif configured woth ESP_NETIF_FLAG_GARP") +#endif + } + struct netif *p_netif = esp_netif->lwip_netif; + if (esp_netif->flags&ESP_NETIF_FLAG_AUTOUP) { + ESP_LOGD(TAG, "%s Setting the lwip netif%p UP", __func__, p_netif); + netif_set_up(p_netif); + } + if (esp_netif->flags&ESP_NETIF_DHCPS) { + if (esp_netif->dhcps_status != ESP_NETIF_DHCP_STARTED) { + if (p_netif != NULL && netif_is_up(p_netif)) { + esp_netif_ip_info_t *default_ip = esp_netif->ip_info; + ip4_addr_t lwip_ip; + memcpy(&lwip_ip, &default_ip->ip, sizeof(struct ip4_addr)); + dhcps_set_new_lease_cb(esp_netif_dhcps_cb); + dhcps_start(p_netif, lwip_ip); + esp_netif->dhcps_status = ESP_NETIF_DHCP_STARTED; + ESP_LOGD(TAG, "DHCP server started successfully"); + esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); + return ESP_OK; + } else { + ESP_LOGD(TAG, "DHCP server re init"); + esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT; + return ESP_OK; + } + } + ESP_LOGD(TAG, "DHCP server already started"); + return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED; + } + + esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); + + return ESP_OK; +} + +esp_err_t esp_netif_stop_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_stop(msg->esp_netif); +} + +esp_err_t esp_netif_stop(esp_netif_t *esp_netif) +{ + ESP_NETIF_IPC_CALL(esp_netif, NULL, esp_netif_stop_api); + + struct netif *lwip_netif = esp_netif->lwip_netif; + if (lwip_netif == NULL) { + return ESP_ERR_ESP_NETIF_IF_NOT_READY; + } + + if (!netif_is_up(lwip_netif)) { + netif_remove(lwip_netif); + return ESP_ERR_ESP_NETIF_IF_NOT_READY; + } + + if (esp_netif->flags&ESP_NETIF_DHCPS) { + dhcps_stop(lwip_netif); // TODO: dhcps checks status by its self + if (ESP_NETIF_DHCP_STOPPED != esp_netif->dhcps_status) { + esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT; + } + } else if (esp_netif->flags&ESP_NETIF_DHCPS) { + dhcp_release(lwip_netif); + dhcp_stop(lwip_netif); + dhcp_cleanup(lwip_netif); + + esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT; + + esp_netif_reset_ip_info(esp_netif); + } + + netif_set_down(lwip_netif); + netif_remove(lwip_netif); + esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);; + + return ESP_OK; +} + +void esp_netif_free_rx_buffer(void *h, void* buffer) +{ + esp_netif_t *esp_netif = h; + esp_netif->driver_free_rx_buffer(esp_netif->driver_handle, buffer); +} + +esp_err_t esp_netif_transmit(esp_netif_t *esp_netif, void* data, size_t len) +{ + return (esp_netif->driver_transmit)(esp_netif->driver_handle, data, len); +} + +esp_err_t esp_netif_receive(esp_netif_t *esp_netif, void *buffer, size_t len, void *eb) +{ + esp_netif->lwip_input_fn(esp_netif->lwip_netif, buffer, len, eb); + return ESP_OK; +} + + +static void esp_netif_api_cb(void *api_msg) +{ + esp_netif_api_msg_t *msg = (esp_netif_api_msg_t *)api_msg; + + if (!msg || !msg->api_fn) { + ESP_LOGD(TAG, "null msg/api_fn"); + return; + } + + msg->ret = msg->api_fn(msg); + ESP_LOGD(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret); + sys_sem_signal(&api_sync_sem); + +} + +static int esp_netif_ipc_check(esp_netif_api_msg_t *msg) +{ +#if ESP_NETIF_TRHEAD_SAFE + xTaskHandle local_task = xTaskGetCurrentTaskHandle(); + + if (local_task == g_lwip_task) { + return ESP_NETIF_IPC_LOCAL; + } + + sys_arch_sem_wait(&api_lock_sem, 0); + tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, msg, &api_sync_sem); + sys_sem_signal(&api_lock_sem); + + return ESP_NETIF_IPC_REMOTE; +#else + return ESP_NETIF_IPC_LOCAL; +#endif +} + +// +// DHCP: +// +static esp_err_t esp_netif_start_ip_lost_timer(esp_netif_t *esp_netif); + +static void esp_netif_dhcpc_cb(struct netif *netif) +{ + if (!netif) { + ESP_LOGD(TAG, "null netif=%p", netif); + return; + } + ESP_LOGD(TAG, "%s lwip-netif:%p", __func__, netif); + + esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif); + + esp_netif_ip_info_t *ip_info = esp_netif->ip_info; + esp_netif_ip_info_t *ip_info_old = esp_netif->ip_info_old; + + + if ( !ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), IP4_ADDR_ANY4) ) { + + //check whether IP is changed + if ( !ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), (&ip_info->ip)) || + !ip4_addr_cmp(ip_2_ip4(&netif->netmask), (&ip_info->netmask)) || + !ip4_addr_cmp(ip_2_ip4(&netif->gw), (&ip_info->gw)) ) { + ip_event_got_ip_t evt = { + .esp_netif = esp_netif, + .if_index = -1, // invalid index, handle used + .ip_changed = false, + }; + ip_event_t evt_id = esp_netif_get_event_id(esp_netif, ESP_NETIF_IP_EVENT_GOT_IP); + int ret; + + ip4_addr_set(&ip_info->ip, ip_2_ip4(&netif->ip_addr)); + ip4_addr_set(&ip_info->netmask, ip_2_ip4(&netif->netmask)); + ip4_addr_set(&ip_info->gw, ip_2_ip4(&netif->gw)); + + //notify event + if (memcmp(ip_info, ip_info_old, sizeof(esp_netif_ip_info_t))) { + evt.ip_changed = true; + } + + memcpy(&evt.ip_info, ip_info, sizeof(esp_netif_ip_info_t)); + memcpy(ip_info_old, ip_info, sizeof(esp_netif_ip_info_t)); + ESP_LOGD(TAG, "if%p ip changed=%d", esp_netif, evt.ip_changed); + ret = esp_event_send_internal(IP_EVENT, evt_id, &evt, sizeof(evt), 0); + if (ESP_OK != ret) { + ESP_LOGE(TAG, "dhcpc cb: failed to post got ip event (%x)", ret); + } + } else { + ESP_LOGD(TAG, "if%p ip unchanged", esp_netif); + } + } else { + if (!ip4_addr_cmp(&ip_info->ip, IP4_ADDR_ANY4)) { + esp_netif_start_ip_lost_timer(esp_netif); + } + } +} + +static void esp_netif_ip_lost_timer(void *arg) +{ + esp_netif_t *esp_netif = (esp_netif_t*)arg; + + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + esp_netif->timer_running = false; + + struct netif *netif = esp_netif->lwip_netif; + + // @TODO: check if netif type is sta + + if ( (!netif) || (netif && ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), IP4_ADDR_ANY4))) { + ip_event_got_ip_t evt = { + .esp_netif = esp_netif, + .if_index = -1, + }; + int ret; + + ESP_LOGD(TAG, "if%p ip lost tmr: raise ip lost event", esp_netif); + memset(&esp_netif->ip_info_old, 0, sizeof(esp_netif_ip_info_t)); + if (esp_netif->lost_ip_event) { + ret = esp_event_send_internal(IP_EVENT, esp_netif->lost_ip_event, + &evt, sizeof(evt), 0); + if (ESP_OK != ret) { + ESP_LOGE(TAG, "ip lost timer: failed to post lost ip event (%x)", ret); + } + } + } else { + ESP_LOGD(TAG, "if%p ip lost tmr: no need raise ip lost event", esp_netif); + } +} + + +static esp_err_t esp_netif_start_ip_lost_timer(esp_netif_t *esp_netif) +{ + esp_netif_ip_info_t *ip_info_old = (esp_netif_ip_info_t *)&esp_netif->ip_info; + struct netif *netif = esp_netif->lwip_netif; + + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (esp_netif->timer_running) { + ESP_LOGD(TAG, "if%p start ip lost tmr: already started", esp_netif); + return ESP_OK; + } + + if ( netif && (CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL > 0) && !ip4_addr_isany_val(ip_info_old->ip)) { + esp_netif->timer_running = true; + sys_timeout(CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL * 1000, esp_netif_ip_lost_timer, (void *)esp_netif); + ESP_LOGD(TAG, "if%p start ip lost tmr: interval=%d", esp_netif, CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL); + return ESP_OK; + } + + ESP_LOGD(TAG, "if%p start ip lost tmr: no need start because netif=%p interval=%d ip=%x", + esp_netif, netif, CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL, ip_info_old->ip.addr); + + return ESP_OK; +} + +static esp_err_t esp_netif_dhcpc_stop_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_dhcpc_stop(msg->esp_netif); +} + +esp_err_t esp_netif_dhcpc_stop(esp_netif_t *esp_netif) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + ESP_NETIF_IPC_CALL(esp_netif, NULL, esp_netif_dhcpc_stop_api); + + if (esp_netif == NULL) { + ESP_LOGE(TAG, "dhcp client stop called with NULL api"); + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) { + struct netif *p_netif = esp_netif->lwip_netif; + + if (p_netif != NULL) { + dhcp_stop(p_netif); + esp_netif_reset_ip_info(esp_netif); + esp_netif_start_ip_lost_timer(esp_netif); + } else { + ESP_LOGD(TAG, "dhcp client if not ready"); + return ESP_ERR_ESP_NETIF_IF_NOT_READY; + } + } else if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STOPPED) { + ESP_LOGD(TAG, "dhcp client already stoped"); + return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED; + } + + ESP_LOGD(TAG, "dhcp client stop successfully"); + esp_netif->dhcpc_status = ESP_NETIF_DHCP_STOPPED; + + LWIP_DHCP_IP_ADDR_ERASE(esp_netif); + + return ESP_OK; + +} + + +static esp_err_t esp_netif_dhcpc_start_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_dhcpc_start(msg->esp_netif); +} + +esp_err_t esp_netif_dhcpc_start(esp_netif_t *esp_netif) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (!esp_netif) { + return ESP_ERR_INVALID_ARG; + } + + ESP_NETIF_IPC_CALL(esp_netif, NULL, esp_netif_dhcpc_start_api); + + struct netif *p_netif = esp_netif->lwip_netif; + + esp_netif_reset_ip_info(esp_netif); + +#if LWIP_DNS + dns_clear_servers(true); +#endif + + if (p_netif != NULL) { + if (netif_is_up(p_netif)) { + ip_addr_set_zero(&p_netif->ip_addr); + ip_addr_set_zero(&p_netif->netmask); + ip_addr_set_zero(&p_netif->gw); + esp_netif_start_ip_lost_timer(esp_netif); + } else { + ESP_LOGD(TAG, "dhcp client re init"); + esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT; + return ESP_OK; + } + ESP_LOGD(TAG, "starting dhcp client"); + + if (dhcp_start(p_netif) != ERR_OK) { + ESP_LOGE(TAG, "dhcp client start failed"); + return ESP_ERR_ESP_NETIF_DHCPC_START_FAILED; + } + + dhcp_set_cb(p_netif, esp_netif_dhcpc_cb); + + esp_netif->dhcpc_status = ESP_NETIF_DHCP_STARTED; + return ESP_OK; + } else { + ESP_LOGD(TAG, "dhcp client re init"); + esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT; + return ESP_OK; + } +} + +esp_err_t esp_netif_dhcps_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) +{ + if (!esp_netif || (esp_netif->flags&ESP_NETIF_DHCPC)) { + return ESP_ERR_INVALID_ARG; + } + + *status = esp_netif->dhcps_status; + return ESP_OK; +} + +esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) +{ + if (!esp_netif || (esp_netif->flags&ESP_NETIF_DHCPS)) { + return ESP_ERR_INVALID_ARG; + } + + *status = esp_netif->dhcpc_status; + return ESP_OK; +} + +static esp_err_t esp_netif_dhcps_start_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_dhcps_start(msg->esp_netif); +} + +esp_err_t esp_netif_dhcps_start(esp_netif_t *esp_netif) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (!esp_netif || (!(esp_netif->flags&ESP_NETIF_DHCPS))) { + return ESP_ERR_INVALID_ARG; + } + + ESP_NETIF_IPC_CALL(esp_netif, NULL, esp_netif_dhcps_start_api); + + struct netif *p_netif = esp_netif->lwip_netif; + if (p_netif != NULL && netif_is_up(p_netif)) { + esp_netif_ip_info_t *default_ip = esp_netif->ip_info; + ip4_addr_t lwip_ip; + memcpy(&lwip_ip, &default_ip->ip, sizeof(struct ip4_addr)); + dhcps_set_new_lease_cb(esp_netif_dhcps_cb); + dhcps_start(p_netif, lwip_ip); + esp_netif->dhcps_status = ESP_NETIF_DHCP_STARTED; + ESP_LOGD(TAG, "DHCP server started successfully"); + return ESP_OK; + } else { + ESP_LOGD(TAG, "dhcp server re init"); + esp_netif->dhcps_status = ESP_NETIF_DHCP_INIT; + return ESP_OK; + } +} + +static esp_err_t esp_netif_dhcps_stop_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_dhcps_stop(msg->esp_netif); +} + +esp_err_t esp_netif_dhcps_stop(esp_netif_t *esp_netif) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (!esp_netif) { + return ESP_ERR_INVALID_ARG; + } + ESP_NETIF_IPC_CALL(esp_netif, NULL, esp_netif_dhcps_stop_api); + + struct netif *p_netif = esp_netif->lwip_netif; + if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STARTED) { + if (p_netif != NULL) { + dhcps_stop(p_netif); + } else { + ESP_LOGD(TAG, "dhcp server if not ready"); + return ESP_ERR_ESP_NETIF_IF_NOT_READY; + } + } else if (esp_netif->dhcps_status == ESP_NETIF_DHCP_STOPPED) { + ESP_LOGD(TAG, "dhcp server already stoped"); + return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED; + } + + ESP_LOGD(TAG, "dhcp server stop successfully"); + esp_netif->dhcps_status = ESP_NETIF_DHCP_STOPPED; + return ESP_OK; +} + +static esp_err_t esp_netif_set_hostname_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_set_hostname(msg->esp_netif, msg->data); +} + +esp_err_t esp_netif_set_hostname(esp_netif_t *esp_netif, const char *hostname) +{ + ESP_LOGD(TAG, "%s esp_netif:%p hostname %s", __func__, esp_netif, hostname); + + if (!esp_netif) { + return ESP_ERR_INVALID_ARG; + } + +#if LWIP_NETIF_HOSTNAME + ESP_NETIF_IPC_CALL(esp_netif, hostname, esp_netif_set_hostname_api); + + struct netif *p_netif = esp_netif->lwip_netif; + if (esp_netif->hostname) { + free(esp_netif->hostname); + } + esp_netif->hostname = strdup(hostname); + if (esp_netif->hostname == NULL) { + return ESP_ERR_NO_MEM; + } + + if (strlen(hostname) > ESP_NETIF_HOSTNAME_MAX_SIZE) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + if (p_netif != NULL) { + p_netif->hostname = esp_netif->hostname; + return ESP_OK; + } else { + return ESP_ERR_ESP_NETIF_IF_NOT_READY; + } +#else + return ESP_ERR_ESP_NETIF_IF_NOT_READY; +#endif +} + +esp_err_t esp_netif_get_hostname(esp_netif_t *esp_netif, const char **hostname) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (!esp_netif) { + return ESP_ERR_INVALID_ARG; + } + +#if LWIP_NETIF_HOSTNAME + struct netif *p_netif = esp_netif->lwip_netif; + + if (p_netif != NULL) { + *hostname = p_netif->hostname; + return ESP_OK; + } else { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } +#else + return ESP_ERR_ESP_NETIF_IF_NOT_READY; +#endif +} + +esp_err_t esp_netif_up_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_up(msg->esp_netif); +} + +esp_err_t esp_netif_up(esp_netif_t *esp_netif) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (!esp_netif) { + return ESP_ERR_INVALID_STATE; + } + ESP_NETIF_IPC_CALL(esp_netif, NULL, esp_netif_up_api); + + struct netif *lwip_netif = esp_netif->lwip_netif; + + /* use last obtained ip, or static ip */ + netif_set_addr(lwip_netif, (ip4_addr_t*)&esp_netif->ip_info->ip, (ip4_addr_t*)&esp_netif->ip_info->netmask, (ip4_addr_t*)&esp_netif->ip_info->gw); + netif_set_up(lwip_netif); + + esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); + + return ESP_OK; +} + +static esp_err_t esp_netif_down_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_down(msg->esp_netif); +} + +esp_err_t esp_netif_down(esp_netif_t *esp_netif) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (!esp_netif) { + return ESP_ERR_INVALID_STATE; + } + ESP_NETIF_IPC_CALL(esp_netif, NULL, &esp_netif_down_api); + + if (esp_netif->flags&ESP_NETIF_FLAG_AUTOUP) { + ESP_LOGE(TAG, "Interface if%p asked to go up, but configured to AUTO-UP flag (flags=%x)", esp_netif, esp_netif->flags); + return ESP_ERR_INVALID_STATE; + } + + struct netif *lwip_netif = esp_netif->lwip_netif; + + if (esp_netif->flags&ESP_NETIF_DHCPC && esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) { + dhcp_stop(esp_netif->lwip_netif); + + esp_netif->dhcpc_status = ESP_NETIF_DHCP_INIT; + + esp_netif_reset_ip_info(esp_netif); + } + + netif_set_addr(lwip_netif, IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); + netif_set_down(lwip_netif); + + if (esp_netif->flags&ESP_NETIF_DHCPC) { + esp_netif_start_ip_lost_timer(esp_netif); + } + + esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED); + + return ESP_OK; +} + +bool esp_netif_is_netif_up(esp_netif_t *esp_netif) +{ + ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (esp_netif != NULL && netif_is_up(esp_netif->lwip_netif)) { + return true; + } else { + return false; + } +} + +esp_err_t esp_netif_get_old_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (esp_netif == NULL || ip_info == NULL) { + return ESP_ERR_INVALID_ARG; + } + memcpy(ip_info, esp_netif->ip_info_old, sizeof(esp_netif_ip_info_t)); + return ESP_OK; +} + +esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (esp_netif == NULL || ip_info == NULL) { + return ESP_ERR_INVALID_ARG; + } + + struct netif *p_netif = esp_netif->lwip_netif; + + if (p_netif != NULL && netif_is_up(p_netif)) { + ip4_addr_set(&ip_info->ip, ip_2_ip4(&p_netif->ip_addr)); + ip4_addr_set(&ip_info->netmask, ip_2_ip4(&p_netif->netmask)); + ip4_addr_set(&ip_info->gw, ip_2_ip4(&p_netif->gw)); + + return ESP_OK; + } + + memcpy(ip_info, esp_netif->ip_info, sizeof(esp_netif_ip_info_t)); + + return ESP_OK; +} + + +bool esp_netif_is_valid_static_ip(esp_netif_ip_info_t *ip_info) +{ + if (!(ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask))) { + // let's assume valid ip_info is when none of ip and netmask is 'any' address (zeros) + return true; + } + return false; +} + +static esp_err_t esp_netif_set_ip_old_info_api(esp_netif_api_msg_t *msg) +{ + memcpy(msg->esp_netif->ip_info, msg->data, sizeof(esp_netif_ip_info_t)); + return ESP_OK; +} + +esp_err_t esp_netif_set_old_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_info_t *ip_info) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (esp_netif == NULL || ip_info == NULL) { + return ESP_ERR_INVALID_STATE; + } + ESP_NETIF_IPC_CALL(esp_netif, ip_info, esp_netif_set_ip_old_info_api); + return ESP_OK; +} + +static esp_err_t esp_netif_set_ip_info_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_set_ip_info(msg->esp_netif, msg->data); +} + +esp_err_t esp_netif_set_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_info_t *ip_info) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + if (esp_netif == NULL || ip_info == NULL) { + return ESP_ERR_INVALID_STATE; + } + ESP_NETIF_IPC_CALL(esp_netif, ip_info, esp_netif_set_ip_info_api); + + if (esp_netif->flags&ESP_NETIF_DHCPS) { + if (esp_netif->dhcps_status != ESP_NETIF_DHCP_STOPPED) { + return ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED; + } + } else if (esp_netif->flags&ESP_NETIF_DHCPC) { + if (esp_netif->dhcpc_status != ESP_NETIF_DHCP_STOPPED) { + return ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED; + } +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + dns_clear_servers(true); +#endif + } + + ip4_addr_copy(esp_netif->ip_info->ip, ip_info->ip); + ip4_addr_copy(esp_netif->ip_info->gw, ip_info->gw); + ip4_addr_copy(esp_netif->ip_info->netmask, ip_info->netmask); + + struct netif *p_netif = esp_netif->lwip_netif; + + if (p_netif != NULL && netif_is_up(p_netif)) { + netif_set_addr(p_netif, (ip4_addr_t*)&ip_info->ip, (ip4_addr_t*)&ip_info->netmask, (ip4_addr_t*)&ip_info->gw); + if (ESP_NETIF_FLAG_EVENT_IP_MODIFIED & esp_netif->flags) { + if (!(ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask) || ip4_addr_isany_val(ip_info->gw))) { + + ip_event_t evt_id = esp_netif->get_ip_event; + ip_event_got_ip_t evt = { .esp_netif = esp_netif, .if_index = -1, .ip_changed = false}; + int ret; + + if (memcmp(ip_info, &esp_netif->ip_info_old, sizeof(esp_netif_ip_info_t))) { + evt.ip_changed = true; + } + + memcpy(&evt.ip_info, ip_info, sizeof(esp_netif_ip_info_t)); + memcpy(&esp_netif->ip_info_old, ip_info, sizeof(esp_netif_ip_info_t)); + ret = esp_event_send_internal(IP_EVENT, evt_id, &evt, sizeof(evt), 0); + if (ESP_OK != ret) { + ESP_LOGE(TAG, "set ip info: failed to post got ip event (%x)", ret); + } + + ESP_LOGD(TAG, "if%p netif set static ip: ip changed=%d", esp_netif, evt.ip_changed); + + } + } + } + + return ESP_OK; +} + +static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg) +{ + esp_netif_dns_param_t *dns_param = (esp_netif_dns_param_t *)msg->data; + + return esp_netif_set_dns_info(msg->esp_netif, dns_param->dns_type, dns_param->dns_info); +} + +esp_err_t esp_netif_set_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + esp_netif_dns_param_t dns_param; + + dns_param.dns_type = type; + dns_param.dns_info = dns; + + ESP_NETIF_IPC_CALL(esp_netif, &dns_param, esp_netif_set_dns_info_api); + + if (esp_netif == NULL) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + if (!dns) { + ESP_LOGD(TAG, "set dns null dns"); + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + if (ip4_addr_isany_val(dns->ip.u_addr.ip4)) { + ESP_LOGD(TAG, "set dns invalid dns"); + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + ESP_LOGD(TAG, "set dns if=%p type=%d dns=%x", esp_netif, type, dns->ip.u_addr.ip4.addr); + + ip_addr_t *lwip_ip = (ip_addr_t*)&dns->ip; + lwip_ip->type = IPADDR_TYPE_V4; + + if (esp_netif->flags&ESP_NETIF_DHCPS) { + // if DHCP server configured to set DNS in dhcps API + if (type != ESP_NETIF_DNS_MAIN) { + ESP_LOGD(TAG, "set dns invalid type"); + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } else { + dhcps_dns_setserver(lwip_ip); + } + } else { + dns_setserver(type, lwip_ip); + } + + return ESP_OK; +} + +static esp_err_t esp_netif_get_dns_info_api(esp_netif_api_msg_t *msg) +{ + esp_netif_dns_param_t *dns_param = (esp_netif_dns_param_t *)msg->data; + + return esp_netif_get_dns_info(msg->esp_netif, dns_param->dns_type, dns_param->dns_info); +} + +esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns) +{ + ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); + + esp_netif_dns_param_t dns_param; + + dns_param.dns_type = type; + dns_param.dns_info = dns; + + ESP_NETIF_IPC_CALL(esp_netif, &dns_param, esp_netif_get_dns_info_api); + if (!dns) { + ESP_LOGD(TAG, "get dns null dns"); + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + if (esp_netif->flags&ESP_NETIF_DHCPS) { + ip4_addr_t dns_ip = dhcps_dns_getserver(); + memcpy(&dns->ip.u_addr.ip4, &dns_ip, sizeof(ip4_addr_t)); + } else { + const ip_addr_t* dns_ip = NULL; + dns_ip = dns_getserver(type); + if(dns_ip != NULL) { + memcpy(&dns->ip.u_addr, &dns_ip, sizeof(ip4_addr_t)); + } + } + + return ESP_OK; +} + +esp_err_t esp_netif_get_sta_list(const wifi_sta_list_t *wifi_sta_list, esp_netif_sta_list_t *netif_sta_list) +{ + ESP_LOGD(TAG, "%s entered", __func__); + + if ((wifi_sta_list == NULL) || (netif_sta_list == NULL)) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + memset(netif_sta_list, 0, sizeof(esp_netif_sta_list_t)); + netif_sta_list->num = wifi_sta_list->num; + for (int i = 0; i < wifi_sta_list->num; i++) { + memcpy(netif_sta_list->sta[i].mac, wifi_sta_list->sta[i].mac, 6); + dhcp_search_ip_on_mac(netif_sta_list->sta[i].mac, (ip4_addr_t*)&netif_sta_list->sta[i].ip); + } + + return ESP_OK; +} + + +static void esp_netif_nd6_cb(struct netif *p_netif, uint8_t ip_idex) +{ + ESP_LOGD(TAG, "%s lwip-netif:%p", __func__, p_netif); + if (!p_netif) { + ESP_LOGD(TAG, "null p_netif=%p", p_netif); + return; + } + + esp_netif_ip6_info_t ip6_info; + ip6_addr_t lwip_ip6_info; + //notify event + ip_event_got_ip6_t evt = { .esp_netif = p_netif->state, .if_index = -1 }; + + ip6_addr_set(&lwip_ip6_info, ip_2_ip6(&p_netif->ip6_addr[ip_idex])); +#if LWIP_IPV6_SCOPES + memcpy(&ip6_info.ip, &lwip_ip6_info, sizeof(esp_ip6_addr_t)); +#else + memcpy(&ip6_info.ip, &lwip_ip6_info, sizeof(ip6_addr_t)); + ip6_info.ip.zone = 0; // zero out zone, as not used in lwip +#endif /* LWIP_IPV6_SCOPES */ + + memcpy(&evt.ip6_info, &ip6_info, sizeof(esp_netif_ip6_info_t)); + int ret = esp_event_send_internal(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0); + if (ESP_OK != ret) { + ESP_LOGE(TAG, "nd6 cb: failed to post IP_EVENT_GOT_IP6 (%x)", ret); + } + +} + + +static esp_err_t esp_netif_create_ip6_linklocal_api(esp_netif_api_msg_t *msg) +{ + return esp_netif_create_ip6_linklocal(msg->esp_netif); +} + +esp_err_t esp_netif_create_ip6_linklocal(esp_netif_t *esp_netif) +{ + ESP_LOGD(TAG, "%s esp-netif:%p", __func__, esp_netif); + + ESP_NETIF_IPC_CALL(esp_netif, NULL, esp_netif_create_ip6_linklocal_api); + struct netif *p_netif = esp_netif->lwip_netif; + if (p_netif != NULL && netif_is_up(p_netif)) { + netif_create_ip6_linklocal_address(p_netif, 1); + nd6_set_cb(p_netif, esp_netif_nd6_cb); + return ESP_OK; + } else { + return ESP_FAIL; + } +} + +esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6) +{ + ESP_LOGD(TAG, "%s esp-netif:%p", __func__, esp_netif); + + if (esp_netif == NULL || if_ip6 == NULL) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + struct netif *p_netif = esp_netif->lwip_netif; + + if (p_netif != NULL && netif_is_up(p_netif) && ip6_addr_ispreferred(netif_ip6_addr_state(p_netif, 0))) { + memcpy(if_ip6, &p_netif->ip6_addr[0], sizeof(ip6_addr_t)); + } else { + return ESP_FAIL; + } + return ESP_OK; +} + +esp_netif_flags_t esp_netif_get_flags(esp_netif_t *esp_netif) +{ + return esp_netif->flags; +} + +char *esp_netif_get_ifkey(esp_netif_t *esp_netif) +{ + return esp_netif->if_key; +} + +esp_netif_type_t esp_netif_get_type(esp_netif_t *esp_netif) +{ + return esp_netif->if_type; +} + +esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) +{ + esp_netif_t *esp_netif = esp_netif_next(NULL); + do { + if (esp_netif && strcmp(if_key, esp_netif->if_key)==0) { + return esp_netif; + } + } while (NULL != (esp_netif = esp_netif_next(esp_netif))); + return NULL; +} + +uint32_t esp_netif_get_event_id(esp_netif_t *esp_netif, esp_netif_ip_event_type_t event_type) +{ + switch(event_type) { + case ESP_NETIF_IP_EVENT_GOT_IP: + return esp_netif->get_ip_event; + case ESP_NETIF_IP_EVENT_LOST_IP: + return esp_netif->lost_ip_event; + } + return 0; +} + +esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val, + uint32_t opt_len) +{ + void *opt_info = dhcps_option_info(opt_id, opt_len); + if (esp_netif == NULL) { + return ESP_ERR_ESP_NETIF_IF_NOT_READY; + } + + esp_netif_dhcp_status_t dhcps_status = esp_netif->dhcps_status; + if (opt_info == NULL || opt_val == NULL) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + if (opt_op == ESP_NETIF_OP_GET) { + if (dhcps_status == ESP_NETIF_DHCP_STOPPED) { + return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED; + } + + switch (opt_id) { + case IP_ADDRESS_LEASE_TIME: { + *(uint32_t *)opt_val = *(uint32_t *)opt_info; + break; + } + case REQUESTED_IP_ADDRESS: { + memcpy(opt_val, opt_info, opt_len); + break; + } + case ROUTER_SOLICITATION_ADDRESS: { + if ((*(uint8_t *)opt_info) & OFFER_ROUTER) { + *(uint8_t *)opt_val = 1; + } else { + *(uint8_t *)opt_val = 0; + } + break; + } + case DOMAIN_NAME_SERVER: { + if ((*(uint8_t *)opt_info) & OFFER_DNS) { + *(uint8_t *)opt_val = 1; + } else { + *(uint8_t *)opt_val = 0; + } + break; + } + default: + break; + } + } else if (opt_op == ESP_NETIF_OP_SET) { + if (dhcps_status == ESP_NETIF_DHCP_STARTED) { + return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED; + } + + switch (opt_id) { + case IP_ADDRESS_LEASE_TIME: { + if (*(uint32_t *)opt_val != 0) { + *(uint32_t *)opt_info = *(uint32_t *)opt_val; + } else { + *(uint32_t *)opt_info = DHCPS_LEASE_TIME_DEF; + } + break; + } + case REQUESTED_IP_ADDRESS: { + esp_netif_ip_info_t info; + uint32_t softap_ip = 0; + uint32_t start_ip = 0; + uint32_t end_ip = 0; + dhcps_lease_t *poll = opt_val; + + if (poll->enable) { + memset(&info, 0x00, sizeof(esp_netif_ip_info_t)); + esp_netif_get_ip_info(esp_netif, &info); + + softap_ip = htonl(info.ip.addr); + start_ip = htonl(poll->start_ip.addr); + end_ip = htonl(poll->end_ip.addr); + + /*config ip information can't contain local ip*/ + if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + /*config ip information must be in the same segment as the local ip*/ + softap_ip >>= 8; + if ((start_ip >> 8 != softap_ip) + || (end_ip >> 8 != softap_ip)) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + if (end_ip - start_ip > DHCPS_MAX_LEASE) { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + } + + memcpy(opt_info, opt_val, opt_len); + break; + } + case ROUTER_SOLICITATION_ADDRESS: { + if (*(uint8_t *)opt_val) { + *(uint8_t *)opt_info |= OFFER_ROUTER; + } else { + *(uint8_t *)opt_info &= ((~OFFER_ROUTER) & 0xFF); + } + break; + } + case DOMAIN_NAME_SERVER: { + if (*(uint8_t *)opt_val) { + *(uint8_t *)opt_info |= OFFER_DNS; + } else { + *(uint8_t *)opt_info &= ((~OFFER_DNS) & 0xFF); + } + break; + } + + default: + break; + } + dhcps_set_option_info(opt_id, opt_info, opt_len); + } else { + return ESP_ERR_ESP_NETIF_INVALID_PARAMS; + } + + return ESP_OK; +} + +esp_err_t esp_netif_dhcpc_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val, + uint32_t opt_len) +{ + // TODO: when dhcp request timeout,change the retry count + return ESP_ERR_NOT_SUPPORTED; +} + +int esp_netif_get_netif_index(esp_netif_t *esp_netif) +{ + if (esp_netif == NULL || esp_netif->lwip_netif == NULL) { + return -1; + } + return netif_get_index(esp_netif->lwip_netif); +} + +#endif /* CONFIG_TCPIP_LWIP */ diff --git a/components/esp_netif/lwip/esp_netif_lwip_defaults.c b/components/esp_netif/lwip/esp_netif_lwip_defaults.c new file mode 100644 index 000000000..6fce8067a --- /dev/null +++ b/components/esp_netif/lwip/esp_netif_lwip_defaults.c @@ -0,0 +1,44 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_netif.h" +#include "esp_netif_lwip_internal.h" + +#include "netif/wlanif.h" +#include "netif/ethernetif.h" + +// +// Purpose of this object is to define default network stack configuration +// of basic types of interfaces using lwip network stack +// + +static const struct esp_netif_netstack_config s_eth_netif_config = { + .base = { .type = ESP_NETIF_NETWORK_STACK_IS_LWIP }, + .init_fn = ethernetif_init, + .input_fn = ethernetif_input +}; +static const struct esp_netif_netstack_config s_wifi_netif_config_ap = { + .base = { .type = ESP_NETIF_NETWORK_STACK_IS_LWIP }, + .init_fn = wlanif_init_ap, + .input_fn = wlanif_input +}; +static const struct esp_netif_netstack_config s_wifi_netif_config_sta = { + .base = { .type = ESP_NETIF_NETWORK_STACK_IS_LWIP }, + .init_fn = wlanif_init_sta, + .input_fn = wlanif_input +}; + +const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_eth = &s_eth_netif_config; +const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta = &s_wifi_netif_config_sta; +const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap = &s_wifi_netif_config_ap; \ No newline at end of file diff --git a/components/esp_netif/lwip/esp_netif_lwip_internal.h b/components/esp_netif/lwip/esp_netif_lwip_internal.h new file mode 100644 index 000000000..181c3bf17 --- /dev/null +++ b/components/esp_netif/lwip/esp_netif_lwip_internal.h @@ -0,0 +1,70 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "esp_netif.h" +#include "lwip/netif.h" + +// LWIP netif specific network stack configuration +struct esp_netif_netstack_config { + esp_netif_netstack_base_config_t base; + err_t (*init_fn)(struct netif*); + void (*input_fn)(struct netif *netif, void *buffer, size_t len, void *eb); +}; + +struct esp_netif_api_msg_s; + +typedef int (*esp_netif_api_fn)(struct esp_netif_api_msg_s *msg); + +typedef struct esp_netif_api_msg_s { + int type; /**< The first field MUST be int */ + int ret; + esp_netif_api_fn api_fn; + esp_netif_t *esp_netif; + void *data; +} esp_netif_api_msg_t; + + +typedef struct esp_netif_dns_param_s { + esp_netif_dns_type_t dns_type; + esp_netif_dns_info_t *dns_info; +} esp_netif_dns_param_t; + +typedef struct esp_netif_ip_lost_timer_s { + bool timer_running; +} esp_netif_ip_lost_timer_t; + + +#define ESP_NETIF_TRHEAD_SAFE 1 +#define ESP_NETIF_IPC_LOCAL 0 +#define ESP_NETIF_IPC_REMOTE 1 + +#define ESP_NETIF_IPC_CALL(_if, _data, _fn) do {\ + esp_netif_api_msg_t msg;\ + if (tcpip_initialized == false) {\ + ESP_LOGE(TAG, "esp_netif is not initialized!");\ + abort();\ + }\ + memset(&msg, 0, sizeof(msg));\ + msg.esp_netif = (_if);\ + msg.data = (void*)(_data);\ + msg.api_fn = (_fn);\ + if (ESP_NETIF_IPC_REMOTE == esp_netif_ipc_check(&msg)) {\ + ESP_LOGD(TAG, "check: remote, if=%p fn=%p\n", (_if), (_fn));\ + return msg.ret;\ + } else {\ + ESP_LOGD(TAG, "check: local, if=%p fn=%p\n", (_if), (_fn));\ + }\ +} while(0) diff --git a/components/esp_netif/private_include/esp_netif_private.h b/components/esp_netif/private_include/esp_netif_private.h new file mode 100644 index 000000000..0519c397d --- /dev/null +++ b/components/esp_netif/private_include/esp_netif_private.h @@ -0,0 +1,114 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_NETIF_PRIVATE_H_ +#define _ESP_NETIF_PRIVATE_H_ + +#define ESP_NETIF_CALL_CHECK(info, api_call, ret) \ +do{\ + esp_err_t __err = (api_call);\ + if ((ret) != __err) {\ + ESP_LOGE(TAG, "%s %d %s ret=0x%X", __FUNCTION__, __LINE__, (info), __err);\ + return;\ + }\ +} while(0) + +/** + * @brief Cause the TCP/IP stack to start the ESP-NETIF instance interface + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + * - ESP_ERR_NO_MEM + */ +esp_err_t esp_netif_start(esp_netif_t *esp_netif); + +/** + * @brief Cause the TCP/IP stack to stop a network interface defined as ESP-NETIF instance + * + * Causes TCP/IP stack to clean up this interface. This includes stopping the DHCP server or client, if they are started. + * + * @note To stop an interface from application code, the media driver-specific API (esp_wifi_stop() or esp_eth_stop()) + * shall be called, the driver layer will then send a stop event and the event handler should call this API. + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS + * - ESP_ERR_ESP_NETIF_IF_NOT_READY + */ +esp_err_t esp_netif_stop(esp_netif_t *esp_netif); + +/** + * @brief Cause the TCP/IP stack to bring up an interface + * This function is called automatically by default called from event handlers/actions + * + * @note This function is not normally used with Wi-Fi AP interface. If the AP interface is started, it is up. + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_IF_NOT_READY + */ +esp_err_t esp_netif_up(esp_netif_t *esp_netif); + +/** + * @brief Cause the TCP/IP stack to shutdown an interface + * This function is called automatically by default called from event handlers/actions + * + * @note This function is not normally used with Wi-Fi AP interface. If the AP interface is stopped, it is down. + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK + * - ESP_ERR_ESP_NETIF_INVALID_PARAMS - parameter error + */ +esp_err_t esp_netif_down(esp_netif_t *esp_netif); + +/** + * @brief Returns true if underlying TCP/IP stack finds the ip_info as valid static address + * + * @param[in] ip_info + * @return true if address assumed to be valid static IP address + */ +bool esp_netif_is_valid_static_ip(esp_netif_ip_info_t *ip_info); + +/** + * @brief Adds created interface to the list of netifs + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK -- Success + * - ESP_ERR_NO_MEM -- Cannot be added due to memory allocation failure + */ +esp_err_t esp_netif_add_to_list(esp_netif_t* netif); + +/** + * @brief Removes interface to be destroyed from the list of netifs + * + * @param[in] esp_netif Handle to esp-netif instance + * + * @return + * - ESP_OK -- Success + * - ESP_ERR_NOT_FOUND -- This netif was not found in the netif list + */ +esp_err_t esp_netif_remove_from_list(esp_netif_t* netif); + +#endif //_ESP_NETIF_PRIVATE_H_ diff --git a/components/esp_netif/test/CMakeLists.txt b/components/esp_netif/test/CMakeLists.txt new file mode 100644 index 000000000..9dfde6842 --- /dev/null +++ b/components/esp_netif/test/CMakeLists.txt @@ -0,0 +1,5 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_PRIV_INCLUDEDIRS "../private_include" ".") +set(COMPONENT_PRIV_REQUIRES unity test_utils esp_netif) + +register_component() \ No newline at end of file diff --git a/components/esp_netif/test/component.mk b/components/esp_netif/test/component.mk new file mode 100644 index 000000000..22e49eddd --- /dev/null +++ b/components/esp_netif/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# +COMPONENT_PRIV_INCLUDEDIRS := ../private_include . +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive \ No newline at end of file diff --git a/components/esp_netif/test/test_esp_netif.c b/components/esp_netif/test/test_esp_netif.c new file mode 100644 index 000000000..3eedd10c3 --- /dev/null +++ b/components/esp_netif/test/test_esp_netif.c @@ -0,0 +1,56 @@ +#include "unity.h" +#include "esp_netif.h" +#include "esp_wifi.h" + +TEST_CASE("esp_netif: init and destroy", "[esp_netif][leaks=0]") +{ + esp_netif_config_t cfg = {}; + esp_netif_t *esp_netif = esp_netif_new(NULL); + + TEST_ASSERT_EQUAL(ESP_ERR_ESP_NETIF_INVALID_PARAMS, esp_netif_configure(esp_netif, NULL)); + TEST_ASSERT_EQUAL(ESP_OK, esp_netif_configure(esp_netif, &cfg)); + + esp_netif_destroy(esp_netif); +} + + +TEST_CASE("esp_netif: get from if_key", "[esp_netif][leaks=0]") +{ + // init default netif + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_WIFI_STA(); + esp_netif_t *esp_netif = esp_netif_new(&cfg); + TEST_ASSERT_NOT_NULL(esp_netif); + + // check it's accessible by key + TEST_ASSERT_EQUAL(esp_netif, esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")); + + // destroy it + esp_netif_destroy(esp_netif); + + // check it's also destroyed in list + TEST_ASSERT_EQUAL(NULL, esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")); + +} + + +TEST_CASE("esp_netif: create and delete multiple netifs", "[esp_netif][leaks=0]") +{ + const int nr_of_netifs = 10; + esp_netif_t *netifs[nr_of_netifs]; + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_WIFI_STA(); + + // create 10 wifi stations + for (int i=0; i CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM) #error "WiFi configuration check: WARNING, WIFI_RX_BA_WIN should not be larger than WIFI_DYNAMIC_RX_BUFFER_NUM!" @@ -124,10 +126,12 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) } } #endif +#if CONFIG_ESP_NETIF_USE_TCPIP_ADAPTER_COMPATIBLE_LAYER esp_err_t err = tcpip_adapter_set_default_wifi_handlers(); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to set default Wi-Fi event handlers (0x%x)", err); } +#endif esp_err_t result = esp_wifi_init_internal(config); if (result == ESP_OK) { esp_wifi_set_debug_log(); diff --git a/components/lwip/CMakeLists.txt b/components/lwip/CMakeLists.txt index 56187ca63..632a00e57 100644 --- a/components/lwip/CMakeLists.txt +++ b/components/lwip/CMakeLists.txt @@ -89,7 +89,6 @@ set(srcs "port/esp32/debug/lwip_debug.c" "port/esp32/freertos/sys_arch.c" "port/esp32/netif/dhcp_state.c" - "port/esp32/netif/nettestif.c" "port/esp32/netif/wlanif.c") if(CONFIG_LWIP_PPP_SUPPORT) @@ -134,7 +133,7 @@ idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "${include_dirs}" LDFRAGMENTS linker.lf REQUIRES vfs esp_wifi - PRIV_REQUIRES esp_eth tcpip_adapter nvs_flash) + PRIV_REQUIRES esp_eth esp_netif tcpip_adapter nvs_flash) # lots of LWIP source files evaluate macros that check address of stack variables target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-address) diff --git a/components/lwip/apps/dhcpserver/dhcpserver.c b/components/lwip/apps/dhcpserver/dhcpserver.c index 48adc3b98..5052b6741 100644 --- a/components/lwip/apps/dhcpserver/dhcpserver.c +++ b/components/lwip/apps/dhcpserver/dhcpserver.c @@ -20,7 +20,7 @@ #include "lwip/udp.h" #include "lwip/mem.h" #include "lwip/ip_addr.h" -#include "tcpip_adapter.h" +#include "esp_netif.h" #include "dhcpserver/dhcpserver.h" #include "dhcpserver/dhcpserver_options.h" @@ -81,7 +81,7 @@ typedef struct _list_node { static const u32_t magic_cookie = 0x63538263; -static struct udp_pcb *pcb_dhcps = NULL; +static struct netif *dhcps_netif = NULL; static ip4_addr_t broadcast_dhcps; static ip4_addr_t server_address; static ip4_addr_t dns_server = {0}; @@ -325,19 +325,19 @@ static u8_t *add_offer_options(u8_t *optptr) *optptr++ = ip4_addr4(&ipadd); if (dhcps_router_enabled(dhcps_offer)) { - tcpip_adapter_ip_info_t if_ip; - //bzero(&if_ip, sizeof(struct ip_info)); - memset(&if_ip , 0x00, sizeof(tcpip_adapter_ip_info_t)); + esp_netif_ip_info_t if_ip; + memset(&if_ip , 0x00, sizeof(esp_netif_ip_info_t)); + esp_netif_get_ip_info(dhcps_netif->state, &if_ip); - tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &if_ip); + ip4_addr_t* gw_ip = (ip4_addr_t*)&if_ip.gw; - if (!ip4_addr_isany_val(if_ip.gw)) { + if (!ip4_addr_isany_val(*gw_ip)) { *optptr++ = DHCP_OPTION_ROUTER; *optptr++ = 4; - *optptr++ = ip4_addr1(&if_ip.gw); - *optptr++ = ip4_addr2(&if_ip.gw); - *optptr++ = ip4_addr3(&if_ip.gw); - *optptr++ = ip4_addr4(&if_ip.gw); + *optptr++ = ip4_addr1(gw_ip); + *optptr++ = ip4_addr2(gw_ip); + *optptr++ = ip4_addr3(gw_ip); + *optptr++ = ip4_addr4(gw_ip); } } @@ -525,6 +525,7 @@ static void send_offer(struct dhcps_msg *m, u16_t len) ip_addr_t ip_temp = IPADDR4_INIT(0x0); ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps); + struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb; #if DHCPS_DEBUG SendOffer_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT); DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t); @@ -602,6 +603,7 @@ static void send_nak(struct dhcps_msg *m, u16_t len) ip_addr_t ip_temp = IPADDR4_INIT(0x0); ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps); + struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb; #if DHCPS_DEBUG SendNak_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT); DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t); @@ -678,6 +680,7 @@ static void send_ack(struct dhcps_msg *m, u16_t len) ip_addr_t ip_temp = IPADDR4_INIT(0x0); ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps); + struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb; SendAck_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT); #if DHCPS_DEBUG DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t); @@ -1135,19 +1138,20 @@ void dhcps_set_new_lease_cb(dhcps_cb_t cb) *******************************************************************************/ void dhcps_start(struct netif *netif, ip4_addr_t ip) { - struct netif *apnetif = netif; + dhcps_netif = netif; - if (apnetif->dhcps_pcb != NULL) { - udp_remove(apnetif->dhcps_pcb); + if (dhcps_netif->dhcps_pcb != NULL) { + udp_remove(dhcps_netif->dhcps_pcb); } - pcb_dhcps = udp_new(); + dhcps_netif->dhcps_pcb = udp_new(); + struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb; if (pcb_dhcps == NULL || ip4_addr_isany_val(ip)) { printf("dhcps_start(): could not obtain pcb\n"); } - apnetif->dhcps_pcb = pcb_dhcps; + dhcps_netif->dhcps_pcb = pcb_dhcps; IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255); @@ -1326,5 +1330,5 @@ dhcps_dns_getserver(void) { return dns_server; } -#endif +#endif // ESP_DHCP diff --git a/components/lwip/lwip b/components/lwip/lwip index f2bd195ee..c483f30ba 160000 --- a/components/lwip/lwip +++ b/components/lwip/lwip @@ -1 +1 @@ -Subproject commit f2bd195eed8f0d6e5cb784bccdba6c9b2e487e75 +Subproject commit c483f30ba22ac3c56c113f2466c39e7d6f60ab89 diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp32/include/lwipopts.h index 89e1b3276..19be43367 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp32/include/lwipopts.h @@ -231,7 +231,7 @@ #define LWIP_DHCP_IP_ADDR_RESTORE() dhcp_ip_addr_restore(netif) #define LWIP_DHCP_IP_ADDR_STORE() dhcp_ip_addr_store(netif) -#define LWIP_DHCP_IP_ADDR_ERASE() dhcp_ip_addr_erase(esp_netif[tcpip_if]) +#define LWIP_DHCP_IP_ADDR_ERASE(esp_netif) dhcp_ip_addr_erase(esp_netif) #endif diff --git a/components/lwip/port/esp32/include/netif/dhcp_state.h b/components/lwip/port/esp32/include/netif/dhcp_state.h index ffea11640..b03dabbe7 100644 --- a/components/lwip/port/esp32/include/netif/dhcp_state.h +++ b/components/lwip/port/esp32/include/netif/dhcp_state.h @@ -24,7 +24,7 @@ bool dhcp_ip_addr_restore(void *netif); void dhcp_ip_addr_store(void *netif); -void dhcp_ip_addr_erase(void *netif); +void dhcp_ip_addr_erase(void *esp_netif); #ifdef __cplusplus } diff --git a/components/lwip/port/esp32/include/netif/ethernetif.h b/components/lwip/port/esp32/include/netif/ethernetif.h index 134e8eb5f..9abd1e4ee 100644 --- a/components/lwip/port/esp32/include/netif/ethernetif.h +++ b/components/lwip/port/esp32/include/netif/ethernetif.h @@ -24,7 +24,7 @@ extern "C" { err_t ethernetif_init(struct netif *netif); -void ethernetif_input(struct netif *netif, void *buffer, u16_t len); +void ethernetif_input(struct netif *netif, void *buffer, size_t len, void *eb); void netif_reg_addr_change_cb(void* cb); diff --git a/components/lwip/port/esp32/include/netif/nettestif.h b/components/lwip/port/esp32/include/netif/nettestif.h deleted file mode 100644 index aa76ed807..000000000 --- a/components/lwip/port/esp32/include/netif/nettestif.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -#ifndef _NETTEST_LWIP_IF_H_ -#define _NETTEST_LWIP_IF_H_ - -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -err_t nettestif_init(struct netif *netif); - -void nettestif_input(void *buffer, u16_t len); - -#ifdef __cplusplus -} -#endif - -#endif /* _NETTEST_LWIP_IF_H_ */ \ No newline at end of file diff --git a/components/lwip/port/esp32/include/netif/wlanif.h b/components/lwip/port/esp32/include/netif/wlanif.h index 21fa91c34..d3e39e2ab 100644 --- a/components/lwip/port/esp32/include/netif/wlanif.h +++ b/components/lwip/port/esp32/include/netif/wlanif.h @@ -18,8 +18,6 @@ #include "esp_wifi.h" -#include "esp_private/wifi.h" - #include "lwip/err.h" #ifdef __cplusplus @@ -29,7 +27,8 @@ extern "C" { err_t wlanif_init_ap(struct netif *netif); err_t wlanif_init_sta(struct netif *netif); -void wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb); +void wlanif_input(struct netif *netif, void *buffer, size_t len, void* eb); +err_t wlanif_init(struct netif *netif); wifi_interface_t wifi_get_interface(void *dev); diff --git a/components/lwip/port/esp32/netif/dhcp_state.c b/components/lwip/port/esp32/netif/dhcp_state.c index 8e2e3d9f3..a442e12a0 100644 --- a/components/lwip/port/esp32/netif/dhcp_state.c +++ b/components/lwip/port/esp32/netif/dhcp_state.c @@ -19,17 +19,14 @@ #include "lwip/dhcp.h" #include "lwip/netif.h" #include "esp_interface.h" -#include "tcpip_adapter.h" +#include "esp_netif.h" +#include "esp_netif_net_stack.h" #include "netif/dhcp_state.h" #define DHCP_NAMESPACE "dhcp_state" -#define VALID_NETIF_ID(id) ((id < ESP_IF_MAX) && (id != ESP_IF_WIFI_AP)) -static uint32_t restored_ip_addr[TCPIP_ADAPTER_IF_MAX]; -static const char *interface_key[] = {"IF_STA", "IF_AP", "IF_ETH", "IF_TEST"}; - -_Static_assert(sizeof(interface_key) / sizeof(char*) == TCPIP_ADAPTER_IF_MAX, - "Number interface keys differs from number of interfaces"); +// DHCP_Client has to be enabled for this netif +#define VALID_NETIF_ID(netif) (ESP_NETIF_DHCPC&esp_netif_get_flags(netif)) bool dhcp_ip_addr_restore(void *netif) { @@ -37,13 +34,12 @@ bool dhcp_ip_addr_restore(void *netif) bool err = false; struct netif *net = (struct netif *)netif; struct dhcp *dhcp = netif_dhcp_data(net); - esp_interface_t netif_id = tcpip_adapter_get_esp_if(net); + esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif); - if(VALID_NETIF_ID(netif_id)) { + if(VALID_NETIF_ID(esp_netif)) { uint32_t *ip_addr = &dhcp->offered_ip_addr.addr; if (nvs_open(DHCP_NAMESPACE, NVS_READONLY, &nvs) == ESP_OK) { - if (nvs_get_u32(nvs, interface_key[netif_id], ip_addr) == ESP_OK) { - restored_ip_addr[netif_id] = *ip_addr; + if (nvs_get_u32(nvs, esp_netif_get_ifkey(esp_netif), ip_addr) == ESP_OK) { err = true; } nvs_close(nvs); @@ -58,28 +54,24 @@ void dhcp_ip_addr_store(void *netif) struct netif *net = (struct netif *)netif; struct dhcp *dhcp = netif_dhcp_data(net); uint32_t ip_addr = dhcp->offered_ip_addr.addr; - esp_interface_t netif_id = tcpip_adapter_get_esp_if(net); + esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif); - if(VALID_NETIF_ID(netif_id)) { - if (restored_ip_addr[netif_id] != ip_addr) { - if (nvs_open(DHCP_NAMESPACE, NVS_READWRITE, &nvs) == ESP_OK) { - nvs_set_u32(nvs, interface_key[netif_id], ip_addr); - nvs_commit(nvs); - nvs_close(nvs); - } + if(VALID_NETIF_ID(esp_netif)) { + if (nvs_open(DHCP_NAMESPACE, NVS_READWRITE, &nvs) == ESP_OK) { + nvs_set_u32(nvs,esp_netif_get_ifkey(esp_netif), ip_addr); + nvs_commit(nvs); + nvs_close(nvs); } } } -void dhcp_ip_addr_erase(void *netif) +void dhcp_ip_addr_erase(void *esp_netif) { nvs_handle_t nvs; - struct netif *net = (struct netif *)netif; - esp_interface_t netif_id = tcpip_adapter_get_esp_if(net); - if(VALID_NETIF_ID(netif_id)) { + if(VALID_NETIF_ID(esp_netif)) { if (nvs_open(DHCP_NAMESPACE, NVS_READWRITE, &nvs) == ESP_OK) { - nvs_erase_key(nvs, interface_key[netif_id]); + nvs_erase_key(nvs, esp_netif_get_ifkey(esp_netif)); nvs_commit(nvs); nvs_close(nvs); } diff --git a/components/lwip/port/esp32/netif/ethernetif.c b/components/lwip/port/esp32/netif/ethernetif.c index fb758b902..eac982380 100644 --- a/components/lwip/port/esp32/netif/ethernetif.c +++ b/components/lwip/port/esp32/netif/ethernetif.c @@ -49,7 +49,8 @@ #include #include "esp_eth.h" -#include "tcpip_adapter.h" +#include "esp_netif.h" +#include "esp_netif_net_stack.h" /* Define those to better describe your network interface. */ #define IFNAME0 'e' @@ -61,7 +62,7 @@ * @param buf memory alloc in L2 layer * @note this function is also the callback when invoke pbuf_free */ -static void ethernet_free_rx_buf_l2(void *buf) +static void ethernet_free_rx_buf_l2(struct netif *netif, void *buf) { free(buf); } @@ -105,17 +106,15 @@ static void ethernet_low_level_init(struct netif *netif) static err_t ethernet_low_level_output(struct netif *netif, struct pbuf *p) { struct pbuf *q = p; - esp_interface_t eth_if = tcpip_adapter_get_esp_if(netif); + esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif); esp_err_t ret = ESP_FAIL; - esp_eth_handle_t eth_handle = (esp_eth_handle_t)netif->state; - - if (eth_if != ESP_IF_ETH) { - LWIP_DEBUGF(NETIF_DEBUG, ("eth_if=%d netif=%p pbuf=%p len=%d\n", eth_if, netif, p, p->len)); + if (!esp_netif) { + LWIP_DEBUGF(NETIF_DEBUG, ("corresponding esp-netif is NULL: netif=%p pbuf=%p len=%d\n", netif, p, p->len)); return ERR_IF; } if (q->next == NULL) { - ret = esp_eth_transmit(eth_handle, q->payload, q->len); + ret = esp_netif_transmit(esp_netif, q->payload, q->len); } else { LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug")); q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM); @@ -129,7 +128,7 @@ static err_t ethernet_low_level_output(struct netif *netif, struct pbuf *p) } else { return ERR_MEM; } - ret = esp_eth_transmit(eth_handle, q->payload, q->len); + ret = esp_netif_transmit(esp_netif, q->payload, q->len); /* content in payload has been copied to DMA buffer, it's safe to free pbuf now */ pbuf_free(q); } @@ -152,13 +151,13 @@ static err_t ethernet_low_level_output(struct netif *netif, struct pbuf *p) * @param buffer ethernet buffer * @param len length of buffer */ -void ethernetif_input(struct netif *netif, void *buffer, uint16_t len) +void ethernetif_input(struct netif *netif, void *buffer, size_t len, void *eb) { struct pbuf *p; if (buffer == NULL || !netif_is_up(netif)) { if (buffer) { - ethernet_free_rx_buf_l2(buffer); + ethernet_free_rx_buf_l2(netif, buffer); } return; } @@ -166,7 +165,7 @@ void ethernetif_input(struct netif *netif, void *buffer, uint16_t len) /* acquire new pbuf, type: PBUF_REF */ p = pbuf_alloc(PBUF_RAW, len, PBUF_REF); if (p == NULL) { - ethernet_free_rx_buf_l2(buffer); + ethernet_free_rx_buf_l2(netif, buffer); return; } p->payload = buffer; @@ -194,7 +193,8 @@ void ethernetif_input(struct netif *netif, void *buffer, uint16_t len) err_t ethernetif_init(struct netif *netif) { LWIP_ASSERT("netif != NULL", (netif != NULL)); - esp_eth_handle_t eth_handle = (esp_eth_handle_t)netif->state; + /* Have to get the esp-netif handle from netif first and then driver==ethernet handle from there */ + esp_eth_handle_t eth_handle = esp_netif_get_io_driver(esp_netif_get_handle_from_netif_impl(netif)); /* Initialize interface hostname */ #if LWIP_NETIF_HOSTNAME #if ESP_LWIP @@ -207,6 +207,7 @@ err_t ethernetif_init(struct netif *netif) /* Initialize the snmp variables and counters inside the struct netif. */ eth_speed_t speed; + esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &speed); if (speed == ETH_SPEED_100M) { NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000); diff --git a/components/lwip/port/esp32/netif/nettestif.c b/components/lwip/port/esp32/netif/nettestif.c deleted file mode 100644 index 4422c2195..000000000 --- a/components/lwip/port/esp32/netif/nettestif.c +++ /dev/null @@ -1,105 +0,0 @@ - -#include "lwip/opt.h" - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/ethip6.h" -#include "netif/etharp.h" -#include "netif/wlanif.h" - -#include -#include - -#include "tcpip_adapter.h" - -static struct netif *g_last_netif = NULL; - - -err_t nettestif_output(struct netif *netif, struct pbuf *p) -{ - int i; - char *dat = p->payload; - - /* output the packet to stdout */ - printf("\nPacketOut:["); - for (i=0; ilen; i++) { - printf("%02x", *dat++); - } - printf("]\n"); - - return ERR_OK; -} - - -err_t nettestif_init(struct netif *netif) -{ - - g_last_netif = netif; - - netif->hostname = CONFIG_LWIP_LOCAL_HOSTNAME; - - /* - * Initialize the snmp variables and counters inside the struct netif. - * The last argument should be replaced with your link speed, in units - * of bits per second. - */ - NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100); - - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - netif->output = etharp_output; -#if LWIP_IPV6 - netif->output_ip6 = ethip6_output; -#endif /* LWIP_IPV6 */ - netif->linkoutput = nettestif_output; - /* set MAC hardware address length */ - netif->hwaddr_len = ETHARP_HWADDR_LEN; - - /* set MAC hardware address */ - - /* maximum transfer unit */ - netif->mtu = 1500; - - /* device capabilities */ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; - -#if ESP_LWIP -#if LWIP_IGMP - netif->flags |= NETIF_FLAG_IGMP; -#endif -#endif - return ERR_OK; - -} - -void nettestif_input(void *buffer, u16_t len) -{ - struct pbuf *p; - if (g_last_netif == NULL) { - printf("error!"); - return; - } - - printf("simul in: %d\n", len); - if (len==0) return; - - p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM); - p->l2_owner = NULL; - memcpy(p->payload, buffer, len); - - /* full packet send to tcpip_thread to process - * on success - the packet is processed and deallocated in tcpip stack - * on failure - log error and deallocate the packet - */ - if (g_last_netif->input(p, g_last_netif) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); - pbuf_free(p); - } - -} diff --git a/components/lwip/port/esp32/netif/wlanif.c b/components/lwip/port/esp32/netif/wlanif.c index 11e1fc857..e4df53a0a 100644 --- a/components/lwip/port/esp32/netif/wlanif.c +++ b/components/lwip/port/esp32/netif/wlanif.c @@ -50,8 +50,20 @@ #include #include -#include "tcpip_adapter.h" +#include "esp_netif.h" +#include "esp_netif_net_stack.h" +/** + * @brief Free resources allocated in L2 layer + * + * @param buf memory alloc in L2 layer + * @note this function is also the callback when invoke pbuf_free + */ +static void lwip_netif_wifi_free_rx_buffer(struct netif *netif, void *buf) +{ + esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif); + esp_netif_free_rx_buffer(esp_netif, buf); +} /** * In this function, the hardware should be initialized. @@ -82,7 +94,7 @@ low_level_init(struct netif *netif) #endif #if !ESP_L2_TO_L3_COPY - netif->l2_buffer_free_notify = esp_wifi_internal_free_rx_buffer; + netif->l2_buffer_free_notify = lwip_netif_wifi_free_rx_buffer; #endif } @@ -104,16 +116,21 @@ low_level_init(struct netif *netif) static err_t ESP_IRAM_ATTR low_level_output(struct netif *netif, struct pbuf *p) { - wifi_interface_t wifi_if = tcpip_adapter_get_esp_if(netif); - struct pbuf *q = p; - err_t ret; - - if (wifi_if >= ESP_IF_MAX) { + esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif); + if (esp_netif == NULL) { + return ERR_IF; + } + esp_netif_type_t type = esp_netif_get_type(esp_netif); + if (type != ESP_NETIF_TYPE_STA && type != ESP_NETIF_TYPE_AP) { return ERR_IF; } + struct pbuf *q = p; + err_t ret; + if(q->next == NULL) { - ret = esp_wifi_internal_tx(wifi_if, q->payload, q->len); + ret = esp_netif_transmit(esp_netif, q->payload, q->len); + } else { LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug")); q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM); @@ -123,7 +140,8 @@ low_level_output(struct netif *netif, struct pbuf *p) } else { return ERR_MEM; } - ret = esp_wifi_internal_tx(wifi_if, q->payload, q->len); + ret = esp_netif_transmit(esp_netif, q->payload, q->len); + pbuf_free(q); } @@ -140,13 +158,14 @@ low_level_output(struct netif *netif, struct pbuf *p) * @param netif the lwip network interface structure for this ethernetif */ void ESP_IRAM_ATTR -wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb) +wlanif_input(struct netif *netif, void *buffer, size_t len, void* eb) { + esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif); struct pbuf *p; if(!buffer || !netif_is_up(netif)) { if (eb) { - esp_wifi_internal_free_rx_buffer(eb); + esp_netif_free_rx_buffer(esp_netif, eb); } return; } @@ -154,16 +173,18 @@ wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb) #if (ESP_L2_TO_L3_COPY == 1) p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM); if (p == NULL) { - esp_wifi_internal_free_rx_buffer(eb); +// esp_wifi_internal_free_rx_buffer(eb); + esp_netif_free_rx_buffer(esp_netif, eb); return; } p->l2_owner = NULL; memcpy(p->payload, buffer, len); - esp_wifi_internal_free_rx_buffer(eb); + esp_netif_free_rx_buffer(esp_netif, eb); +// esp_wifi_internal_free_rx_buffer(eb); #else p = pbuf_alloc(PBUF_RAW, len, PBUF_REF); if (p == NULL){ - esp_wifi_internal_free_rx_buffer(eb); + esp_netif_free_rx_buffer(esp_netif, eb); return; } p->payload = buffer; diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 8ee6b5d91..31d0a96ce 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -4161,7 +4161,7 @@ static void event_handler(void* arg, esp_event_base_t event_base, action->data.sys_event.event_id = event_id; if (event_base == IP_EVENT && event_id == IP_EVENT_GOT_IP6) { ip_event_got_ip6_t* event = (ip_event_got_ip6_t*) event_data; - action->data.sys_event.interface = event->if_index; + action->data.sys_event.interface = tcpip_adapter_if_from_esp_netif(event->esp_netif); } if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) { diff --git a/components/tcpip_adapter/CMakeLists.txt b/components/tcpip_adapter/CMakeLists.txt index a63bcddde..6fb448e82 100644 --- a/components/tcpip_adapter/CMakeLists.txt +++ b/components/tcpip_adapter/CMakeLists.txt @@ -1,3 +1,3 @@ -idf_component_register(SRCS "event_handlers.c" "tcpip_adapter_lwip.c" +idf_component_register(SRCS "tcpip_adapter_compat.c" INCLUDE_DIRS include - REQUIRES lwip esp_eth) + REQUIRES esp_netif) diff --git a/components/tcpip_adapter/event_handlers.c b/components/tcpip_adapter/event_handlers.c deleted file mode 100644 index 146f87203..000000000 --- a/components/tcpip_adapter/event_handlers.c +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include "tcpip_adapter.h" -#include "esp_event.h" -#include "esp_wifi.h" -#include "esp_private/wifi.h" -#if CONFIG_ETH_ENABLED -#include "esp_eth.h" -#endif -#include "esp_err.h" -#include "esp_log.h" - -static const char *TAG = "tcpip_adapter"; - -#define API_CALL_CHECK(info, api_call, ret) \ -do{\ - esp_err_t __err = (api_call);\ - if ((ret) != __err) {\ - ESP_LOGE(TAG, "%s %d %s ret=0x%X", __FUNCTION__, __LINE__, (info), __err);\ - return;\ - }\ -} while(0) - -static void handle_ap_start(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_ap_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_sta_start(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_sta_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_sta_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_sta_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_sta_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data); -#if CONFIG_ETH_ENABLED -static void handle_eth_start(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_eth_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_eth_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_eth_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data); -static void handle_eth_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data); - -static void handle_eth_start(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - tcpip_adapter_ip_info_t eth_ip; - uint8_t eth_mac[6]; - esp_eth_handle_t eth_handle = *(esp_eth_handle_t*)data; - esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, eth_mac); - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, ð_ip); - tcpip_adapter_eth_start(eth_mac, ð_ip, eth_handle); -} - -static void handle_eth_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - tcpip_adapter_stop(TCPIP_ADAPTER_IF_ETH); -} - -static void handle_eth_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - tcpip_adapter_dhcp_status_t status; - - tcpip_adapter_up(TCPIP_ADAPTER_IF_ETH); - - tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_ETH, &status); - - if (status == TCPIP_ADAPTER_DHCP_INIT) { - tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_ETH); - } else if (status == TCPIP_ADAPTER_DHCP_STOPPED) { - tcpip_adapter_ip_info_t eth_ip; - - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, ð_ip); - - if (!(ip4_addr_isany_val(eth_ip.ip) || ip4_addr_isany_val(eth_ip.netmask))) { - ip_event_got_ip_t evt; - - //notify event - evt.if_index = TCPIP_ADAPTER_IF_ETH; - memcpy(&evt.ip_info, ð_ip, sizeof(tcpip_adapter_ip_info_t)); - API_CALL_CHECK("handle_eth_connected", esp_event_send_internal(IP_EVENT, IP_EVENT_ETH_GOT_IP, &evt, sizeof(evt), 0), ESP_OK); - } else { - ESP_LOGE(TAG, "invalid static ip"); - } - } -} - -static void handle_eth_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - tcpip_adapter_down(TCPIP_ADAPTER_IF_ETH); -} - -static void handle_eth_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - const ip_event_got_ip_t *event = (const ip_event_got_ip_t *) data; - ESP_LOGI(TAG, "eth ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR, - IP2STR(&event->ip_info.ip), - IP2STR(&event->ip_info.netmask), - IP2STR(&event->ip_info.gw)); -} -#endif - -static void handle_sta_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - API_CALL_CHECK("esp_wifi_internal_set_sta_ip", esp_wifi_internal_set_sta_ip(), ESP_OK); - - const ip_event_got_ip_t *event = (const ip_event_got_ip_t *) data; - ESP_LOGI(TAG, "sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR, - IP2STR(&event->ip_info.ip), - IP2STR(&event->ip_info.netmask), - IP2STR(&event->ip_info.gw)); -} - - -static void handle_ap_start(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - tcpip_adapter_ip_info_t ap_ip; - uint8_t ap_mac[6]; - - API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, (wifi_rxcb_t)tcpip_adapter_ap_input), ESP_OK); - API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_AP, ap_mac), ESP_OK); - - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ap_ip); - tcpip_adapter_ap_start(ap_mac, &ap_ip); -} - -static void handle_ap_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, NULL), ESP_OK); - - tcpip_adapter_stop(TCPIP_ADAPTER_IF_AP); -} - -static void handle_sta_start(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - tcpip_adapter_ip_info_t sta_ip; - uint8_t sta_mac[6]; - - API_CALL_CHECK("esp_wifi_mac_get", esp_wifi_get_mac(ESP_IF_WIFI_STA, sta_mac), ESP_OK); - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); - tcpip_adapter_sta_start(sta_mac, &sta_ip); -} - -static void handle_sta_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - tcpip_adapter_stop(TCPIP_ADAPTER_IF_STA); -} - -static void handle_sta_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - tcpip_adapter_dhcp_status_t status; - - API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, (wifi_rxcb_t)tcpip_adapter_sta_input), ESP_OK); - - tcpip_adapter_up(TCPIP_ADAPTER_IF_STA); - - tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status); - - if (status == TCPIP_ADAPTER_DHCP_INIT) { - tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); - } else if (status == TCPIP_ADAPTER_DHCP_STOPPED) { - tcpip_adapter_ip_info_t sta_ip; - tcpip_adapter_ip_info_t sta_old_ip; - - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); - tcpip_adapter_get_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_old_ip); - - if (!(ip4_addr_isany_val(sta_ip.ip) || ip4_addr_isany_val(sta_ip.netmask))) { - - ip_event_got_ip_t evt; - - evt.if_index = TCPIP_ADAPTER_IF_STA; - evt.ip_changed = false; - - if (memcmp(&sta_ip, &sta_old_ip, sizeof(sta_ip))) { - evt.ip_changed = true; - } - - memcpy(&evt.ip_info, &sta_ip, sizeof(tcpip_adapter_ip_info_t)); - tcpip_adapter_set_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip); - - API_CALL_CHECK("handle_sta_connected", esp_event_send_internal(IP_EVENT, IP_EVENT_STA_GOT_IP, &evt, sizeof(evt), 0), ESP_OK); - ESP_LOGD(TAG, "static ip: ip changed=%d", evt.ip_changed); - } else { - ESP_LOGE(TAG, "invalid static ip"); - } - } -} - -static void handle_sta_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data) -{ - tcpip_adapter_down(TCPIP_ADAPTER_IF_STA); - API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, NULL), ESP_OK); -} - - -esp_err_t tcpip_adapter_set_default_wifi_handlers(void) -{ - esp_err_t err; - err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_START, handle_sta_start, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_STOP, handle_sta_stop, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, handle_sta_connected, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, handle_sta_disconnected, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_START, handle_ap_start, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STOP, handle_ap_stop, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, handle_sta_got_ip, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_register_shutdown_handler((shutdown_handler_t)esp_wifi_stop); - if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { - goto fail; - } - - return ESP_OK; - -fail: - tcpip_adapter_clear_default_wifi_handlers(); - return err; -} - -esp_err_t tcpip_adapter_clear_default_wifi_handlers(void) -{ - esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_START, handle_sta_start); - esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_STOP, handle_sta_stop); - esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, handle_sta_connected); - esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, handle_sta_disconnected); - esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_AP_START, handle_ap_start); - esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_AP_STOP, handle_ap_stop); - esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, handle_sta_got_ip); - esp_unregister_shutdown_handler((shutdown_handler_t)esp_wifi_stop); - - return ESP_OK; -} - -#if CONFIG_ETH_ENABLED -esp_err_t tcpip_adapter_set_default_eth_handlers(void) -{ - esp_err_t err; - err = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, handle_eth_start, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_STOP, handle_eth_stop, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_CONNECTED, handle_eth_connected, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, handle_eth_disconnected, NULL); - if (err != ESP_OK) { - goto fail; - } - - err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, handle_eth_got_ip, NULL); - if (err != ESP_OK) { - goto fail; - } - - return ESP_OK; - -fail: - tcpip_adapter_clear_default_eth_handlers(); - return err; -} - -esp_err_t tcpip_adapter_clear_default_eth_handlers(void) -{ - esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_START, handle_eth_start); - esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_STOP, handle_eth_stop); - esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_CONNECTED, handle_eth_connected); - esp_event_handler_unregister(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, handle_eth_disconnected); - esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, handle_eth_got_ip); - return ESP_OK; -} -#endif diff --git a/components/tcpip_adapter/include/tcpip_adapter.h b/components/tcpip_adapter/include/tcpip_adapter.h index f880511f7..c27fffaea 100644 --- a/components/tcpip_adapter/include/tcpip_adapter.h +++ b/components/tcpip_adapter/include/tcpip_adapter.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,83 +15,25 @@ #ifndef _TCPIP_ADAPTER_H_ #define _TCPIP_ADAPTER_H_ -#include -#include "sys/queue.h" -#include "esp_wifi_types.h" -#include "sdkconfig.h" - -#if CONFIG_TCPIP_LWIP +#include "esp_netif.h" #include "lwip/ip_addr.h" #include "dhcpserver/dhcpserver.h" -typedef dhcps_lease_t tcpip_adapter_dhcps_lease_t; -#ifdef __cplusplus -extern "C" { -#endif +// +// Define compatible types if tcpip_adapter interface used +// +#define TCPIP_ADAPTER_DHCP_STARTED ESP_NETIF_DHCP_STARTED +#define TCPIP_ADAPTER_DHCP_STOPPED ESP_NETIF_DHCP_STOPPED +#define TCPIP_ADAPTER_DHCP_INIT ESP_NETIF_DHCP_INIT +#define TCPIP_ADAPTER_OP_SET ESP_NETIF_OP_SET +#define TCPIP_ADAPTER_OP_GET ESP_NETIF_OP_GET +#define TCPIP_ADAPTER_DOMAIN_NAME_SERVER ESP_NETIF_DOMAIN_NAME_SERVER +#define TCPIP_ADAPTER_ROUTER_SOLICITATION_ADDRESS ESP_NETIF_ROUTER_SOLICITATION_ADDRESS +#define TCPIP_ADAPTER_REQUESTED_IP_ADDRESS ESP_NETIF_REQUESTED_IP_ADDRESS +#define TCPIP_ADAPTER_IP_ADDRESS_LEASE_TIME ESP_NETIF_IP_ADDRESS_LEASE_TIME +#define TCPIP_ADAPTER_IP_REQUEST_RETRY_TIME ESP_NETIF_IP_REQUEST_RETRY_TIME -#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \ - ip4_addr2_16(ipaddr), \ - ip4_addr3_16(ipaddr), \ - ip4_addr4_16(ipaddr) - -#define IPSTR "%d.%d.%d.%d" - -#define IPV62STR(ipaddr) IP6_ADDR_BLOCK1(&(ipaddr)), \ - IP6_ADDR_BLOCK2(&(ipaddr)), \ - IP6_ADDR_BLOCK3(&(ipaddr)), \ - IP6_ADDR_BLOCK4(&(ipaddr)), \ - IP6_ADDR_BLOCK5(&(ipaddr)), \ - IP6_ADDR_BLOCK6(&(ipaddr)), \ - IP6_ADDR_BLOCK7(&(ipaddr)), \ - IP6_ADDR_BLOCK8(&(ipaddr)) - -#define IPV6STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" - -/** @brief IPV4 IP address information - */ -typedef struct { - ip4_addr_t ip; /**< Interface IPV4 address */ - ip4_addr_t netmask; /**< Interface IPV4 netmask */ - ip4_addr_t gw; /**< Interface IPV4 gateway address */ -} tcpip_adapter_ip_info_t; - -/** @brief IPV6 IP address information - */ -typedef struct { - ip6_addr_t ip; /**< Interface IPV6 address */ -} tcpip_adapter_ip6_info_t; - -/** @brief IP address info of station connected to WLAN AP - * - * @note See also wifi_sta_info_t (MAC layer information only) - */ -typedef struct { - uint8_t mac[6]; /**< Station MAC address */ - ip4_addr_t ip; /**< Station assigned IP address */ -} tcpip_adapter_sta_info_t; - -/** @brief WLAN AP: Connected stations list - * - * Used to retrieve IP address information about connected stations. - */ -typedef struct { - tcpip_adapter_sta_info_t sta[ESP_WIFI_MAX_CONN_NUM]; /**< Connected stations */ - int num; /**< Number of connected stations */ -} tcpip_adapter_sta_list_t; - -#endif - -#define ESP_ERR_TCPIP_ADAPTER_BASE 0x5000 -#define ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS ESP_ERR_TCPIP_ADAPTER_BASE + 0x01 -#define ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY ESP_ERR_TCPIP_ADAPTER_BASE + 0x02 -#define ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED ESP_ERR_TCPIP_ADAPTER_BASE + 0x03 -#define ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED ESP_ERR_TCPIP_ADAPTER_BASE + 0x04 -#define ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED ESP_ERR_TCPIP_ADAPTER_BASE + 0x05 -#define ESP_ERR_TCPIP_ADAPTER_NO_MEM ESP_ERR_TCPIP_ADAPTER_BASE + 0x06 -#define ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED ESP_ERR_TCPIP_ADAPTER_BASE + 0x07 - -/* @brief On-chip network interfaces */ typedef enum { TCPIP_ADAPTER_IF_STA = 0, /**< Wi-Fi STA (station) interface */ TCPIP_ADAPTER_IF_AP, /**< Wi-Fi soft-AP interface */ @@ -100,657 +42,123 @@ typedef enum { TCPIP_ADAPTER_IF_MAX } tcpip_adapter_if_t; -/** @brief Type of DNS server */ -typedef enum { - TCPIP_ADAPTER_DNS_MAIN= 0, /**< DNS main server address*/ - TCPIP_ADAPTER_DNS_BACKUP, /**< DNS backup server address (Wi-Fi STA and Ethernet only) */ - TCPIP_ADAPTER_DNS_FALLBACK, /**< DNS fallback server address (Wi-Fi STA and Ethernet only) */ - TCPIP_ADAPTER_DNS_MAX -} tcpip_adapter_dns_type_t; - -/** @brief DNS server info */ +/** @brief legacy ip_info type + */ typedef struct { - ip_addr_t ip; /**< IPV4 address of DNS server */ -} tcpip_adapter_dns_info_t; - -/** @brief Status of DHCP client or DHCP server */ -typedef enum { - TCPIP_ADAPTER_DHCP_INIT = 0, /**< DHCP client/server is in initial state (not yet started) */ - TCPIP_ADAPTER_DHCP_STARTED, /**< DHCP client/server has been started */ - TCPIP_ADAPTER_DHCP_STOPPED, /**< DHCP client/server has been stopped */ - TCPIP_ADAPTER_DHCP_STATUS_MAX -} tcpip_adapter_dhcp_status_t; - -/** @brief Mode for DHCP client or DHCP server option functions */ -typedef enum{ - TCPIP_ADAPTER_OP_START = 0, - TCPIP_ADAPTER_OP_SET, /**< Set option */ - TCPIP_ADAPTER_OP_GET, /**< Get option */ - TCPIP_ADAPTER_OP_MAX -} tcpip_adapter_dhcp_option_mode_t; - -/* Deprecated name for tcpip_adapter_dhcp_option_mode_t, to remove after ESP-IDF V4.0 */ -typedef tcpip_adapter_dhcp_option_mode_t tcpip_adapter_option_mode_t; - -/** @brief Supported options for DHCP client or DHCP server */ -typedef enum{ - TCPIP_ADAPTER_DOMAIN_NAME_SERVER = 6, /**< Domain name server */ - TCPIP_ADAPTER_ROUTER_SOLICITATION_ADDRESS = 32, /**< Solicitation router address */ - TCPIP_ADAPTER_REQUESTED_IP_ADDRESS = 50, /**< Request specific IP address */ - TCPIP_ADAPTER_IP_ADDRESS_LEASE_TIME = 51, /**< Request IP address lease time */ - TCPIP_ADAPTER_IP_REQUEST_RETRY_TIME = 52, /**< Request IP address retry counter */ -} tcpip_adapter_dhcp_option_id_t; - -/* Deprecated name for tcpip_adapter_dhcp_option_id_t, to remove after ESP-IDF V4.0 */ -typedef tcpip_adapter_dhcp_option_id_t tcpip_adapter_option_id_t; - -/** IP event declarations */ -typedef enum { - IP_EVENT_STA_GOT_IP, /*!< ESP32 station got IP from connected AP */ - IP_EVENT_STA_LOST_IP, /*!< ESP32 station lost IP and the IP is reset to 0 */ - IP_EVENT_AP_STAIPASSIGNED, /*!< ESP32 soft-AP assign an IP to a connected station */ - IP_EVENT_GOT_IP6, /*!< ESP32 station or ap or ethernet interface v6IP addr is preferred */ - IP_EVENT_ETH_GOT_IP, /*!< ESP32 ethernet got IP from connected AP */ -} ip_event_t; - -/** @brief IP event base declaration */ -ESP_EVENT_DECLARE_BASE(IP_EVENT); - -/** Event structure for IP_EVENT_STA_GOT_IP, IP_EVENT_ETH_GOT_IP events */ -typedef struct { - tcpip_adapter_if_t if_index; /*!< Interface for which the event is received */ - tcpip_adapter_ip_info_t ip_info; /*!< IP address, netmask, gatway IP address */ - bool ip_changed; /*!< Whether the assigned IP has changed or not */ -} ip_event_got_ip_t; - -/** Event structure for IP_EVENT_GOT_IP6 event */ -typedef struct { - tcpip_adapter_if_t if_index; /*!< Interface for which the event is received */ - tcpip_adapter_ip6_info_t ip6_info; /*!< IPv6 address of the interface */ -} ip_event_got_ip6_t; - -/** Event structure for IP_EVENT_AP_STAIPASSIGNED event */ -typedef struct { - ip4_addr_t ip; /*!< IP address which was assigned to the station */ -} ip_event_ap_staipassigned_t; + ip4_addr_t ip; /**< Interface IPV4 address */ + ip4_addr_t netmask; /**< Interface IPV4 netmask */ + ip4_addr_t gw; /**< Interface IPV4 gateway address */ +} tcpip_adapter_ip_info_t; +/** @brief legacy typedefs + */ +typedef esp_netif_dhcp_status_t tcpip_adapter_dhcp_status_t; +typedef dhcps_lease_t tcpip_adapter_dhcps_lease_t; +typedef esp_netif_dhcp_option_mode_t tcpip_adapter_dhcp_option_mode_t; +typedef esp_netif_dhcp_option_id_t tcpip_adapter_dhcp_option_id_t; +typedef esp_netif_dns_type_t tcpip_adapter_dns_type_t; +typedef esp_netif_dns_info_t tcpip_adapter_dns_info_t; +typedef esp_netif_sta_list_t tcpip_adapter_sta_list_t; +typedef esp_netif_sta_info_t tcpip_adapter_sta_info_t; /** - * @brief Initialize the underlying TCP/IP stack - * - * @note This function should be called exactly once from application code, when the application starts up. + * @brief tcpip adapter legacy init. It is used only to set the compatibility mode of esp-netif, which + * will enable backward compatibility of esp-netif. */ void tcpip_adapter_init(void); /** - * @brief Cause the TCP/IP stack to start the Ethernet interface with specified MAC and IP + * @brief Compatiblity mode: convert the esp-netif handle to tcpip_adapter legacy interface enum * - * @note This function should be called after the Ethernet MAC hardware is initialized. In the default configuration, application code does not need to call this function - it is called automatically by the default handler for the SYSTEM_EVENT_ETH_START event. + * @param esp_netif * - * @param[in] mac Set MAC address of this interface - * @param[in] ip_info Set IP address of this interface - * @param[in] args extra args passed to tcpip_adapter - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_NO_MEM + * @return corresponding interface if valid or known esp_netif provided, TCPIP_ADAPTER_IF_MAX otherwise */ -esp_err_t tcpip_adapter_eth_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info, void *args); +tcpip_adapter_if_t tcpip_adapter_if_from_esp_netif(esp_netif_t *esp_netif); /** - * @brief Cause the TCP/IP stack to start the Wi-Fi station interface with specified MAC and IP + * @brief Translates to esp_netif_get_ip_info * - * - * @note This function should be called after the Wi-Fi Station hardware is initialized. In the default configuration, application code does not need to call this function - it is called automatically by the default handler for the SYSTEM_EVENT_STA_START event. - * - * @param[in] mac Set MAC address of this interface - * @param[in] ip_info Set IP address of this interface - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_NO_MEM - */ -esp_err_t tcpip_adapter_sta_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info); - -/** - * @brief Cause the TCP/IP stack to start the Wi-Fi AP interface with specified MAC and IP - * - * @note This function should be called after the Wi-Fi AP hardware is initialized. In the default configuration, application code does not need to call this function - it is called automatically by the default handler for the SYSTEM_EVENT_AP_START event. - * - * DHCP server will be started automatically when this function is called. - * - * @param[in] mac Set MAC address of this interface - * @param[in] ip_info Set IP address of this interface - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_NO_MEM - */ -esp_err_t tcpip_adapter_ap_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info); - -/** - * @brief Cause the TCP/IP stack to stop a network interface - * - * Causes TCP/IP stack to clean up this interface. This includes stopping the DHCP server or client, if they are started. - * - * @note This API is called by the default Wi-Fi and Ethernet event handlers if the underlying network driver reports that the - * interface has stopped. - * - * @note To stop an interface from application code, call the network-specific API (esp_wifi_stop() or esp_eth_stop()). - * The driver layer will then send a stop event and the event handler should call this API. - * Otherwise, the driver and MAC layer will remain started. - * - * @param[in] tcpip_if Interface which will be stopped - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY - */ -esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if); - -/** - * @brief Cause the TCP/IP stack to bring up an interface - * - * @note This function is called automatically by the default event handlers for the Wi-Fi Station and Ethernet interfaces, - * in response to the SYSTEM_EVENT_STA_CONNECTED and SYSTEM_EVENT_ETH_CONNECTED events, respectively. - * - * @note This function is not normally used with Wi-Fi AP interface. If the AP interface is started, it is up. - * - * @param[in] tcpip_if Interface to bring up - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY - */ -esp_err_t tcpip_adapter_up(tcpip_adapter_if_t tcpip_if); - -/** - * @brief Cause the TCP/IP stack to shutdown an interface - * - * @note This function is called automatically by the default event handlers for the Wi-Fi Station and Ethernet interfaces, - * in response to the SYSTEM_EVENT_STA_DISCONNECTED and SYSTEM_EVENT_ETH_DISCONNECTED events, respectively. - * - * @note This function is not normally used with Wi-Fi AP interface. If the AP interface is stopped, it is down. - * - * @param[in] tcpip_if Interface to shutdown - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY - */ -esp_err_t tcpip_adapter_down(tcpip_adapter_if_t tcpip_if); - -/** - * @brief Get interface's IP address information - * - * If the interface is up, IP information is read directly from the TCP/IP stack. - * - * If the interface is down, IP information is read from a copy kept in the TCP/IP adapter - * library itself. - * - * @param[in] tcpip_if Interface to get IP information - * @param[out] ip_info If successful, IP information will be returned in this argument. - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS + * @param tcpip_if Interface type corresponding to appropriate instance of esp-netif + * @param ip_info See esp_netif_get_ip_info + * @return See esp_netif_get_ip_info */ esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info); /** - * @brief Set interface's IP address information + * @brief Translates to esp_netif_get_ip6_linklocal * - * This function is mainly used to set a static IP on an interface. - * - * If the interface is up, the new IP information is set directly in the TCP/IP stack. - * - * The copy of IP information kept in the TCP/IP adapter library is also updated (this - * copy is returned if the IP is queried while the interface is still down.) - * - * @note DHCP client/server must be stopped before setting new IP information. - * - * @note Calling this interface for the Wi-Fi STA or Ethernet interfaces may generate a - * SYSTEM_EVENT_STA_GOT_IP or SYSTEM_EVENT_ETH_GOT_IP event. - * - * @param[in] tcpip_if Interface to set IP information - * @param[in] ip_info IP information to set on the specified interface - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED If DHCP server or client is still running - */ -esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, const tcpip_adapter_ip_info_t *ip_info); - -/** - * @brief Set DNS Server information - * - * This function behaves differently for different interfaces: - * - * - For Wi-Fi Station interface and Ethernet interface, up to three types of DNS server can be set (in order of priority): - * - Main DNS Server (TCPIP_ADAPTER_DNS_MAIN) - * - Backup DNS Server (TCPIP_ADAPTER_DNS_BACKUP) - * - Fallback DNS Server (TCPIP_ADAPTER_DNS_FALLBACK) - * - * If DHCP client is enabled, main and backup DNS servers will be updated automatically from the DHCP lease if the relevant DHCP options are set. Fallback DNS Server is never updated from the DHCP lease and is designed to be set via this API. - * - * If DHCP client is disabled, all DNS server types can be set via this API only. - * - * - For Wi-Fi AP interface, the Main DNS Server setting is used by the DHCP server to provide a DNS Server option to DHCP clients (Wi-Fi stations). - * - The default Main DNS server is the IP of the Wi-Fi AP interface itself. - * - This function can override it by setting server type TCPIP_ADAPTER_DNS_MAIN. - * - Other DNS Server types are not supported for the Wi-Fi AP interface. - * - * @param[in] tcpip_if Interface to set DNS Server information - * @param[in] type Type of DNS Server to set: TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP, TCPIP_ADAPTER_DNS_FALLBACK - * @param[in] dns DNS Server address to set - * - * @return - * - ESP_OK on success - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS invalid params - */ -esp_err_t tcpip_adapter_set_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns); - -/** - * @brief Get DNS Server information - * - * Return the currently configured DNS Server address for the specified interface and Server type. - * - * This may be result of a previous call to tcpip_adapter_set_dns_info(). If the interface's DHCP client is enabled, - * the Main or Backup DNS Server may be set by the current DHCP lease. - * - * @param[in] tcpip_if Interface to get DNS Server information - * @param[in] type Type of DNS Server to get: TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP, TCPIP_ADAPTER_DNS_FALLBACK - * @param[out] dns DNS Server result is written here on success - * - * @return - * - ESP_OK on success - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS invalid params - */ -esp_err_t tcpip_adapter_get_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns); - -/** - * @brief Get interface's old IP information - * - * Returns an "old" IP address previously stored for the interface when the valid IP changed. - * - * If the IP lost timer has expired (meaning the interface was down for longer than the configured interval) - * then the old IP information will be zero. - * - * @param[in] tcpip_if Interface to get old IP information - * @param[out] ip_info If successful, IP information will be returned in this argument. - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - */ -esp_err_t tcpip_adapter_get_old_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info); - -/** - * @brief Set interface old IP information - * - * This function is called from the DHCP client for the Wi-Fi STA and Ethernet interfaces, before a new IP is set. It is also called from the default handlers for the SYSTEM_EVENT_STA_CONNECTED and SYSTEM_EVENT_ETH_CONNECTED events. - * - * Calling this function stores the previously configured IP, which can be used to determine if the IP changes in the future. - * - * If the interface is disconnected or down for too long, the "IP lost timer" will expire (after the configured interval) and set the old IP information to zero. - * - * @param[in] tcpip_if Interface to set old IP information - * @param[in] ip_info Store the old IP information for the specified interface - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - */ -esp_err_t tcpip_adapter_set_old_ip_info(tcpip_adapter_if_t tcpip_if, const tcpip_adapter_ip_info_t *ip_info); - - -/** - * @brief Create interface link-local IPv6 address - * - * Cause the TCP/IP stack to create a link-local IPv6 address for the specified interface. - * - * This function also registers a callback for the specified interface, so that if the link-local address becomes verified as the preferred address then a SYSTEM_EVENT_GOT_IP6 event will be sent. - * - * @param[in] tcpip_if Interface to create a link-local IPv6 address - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - */ -esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if); - -/** - * @brief Get interface link-local IPv6 address - * - * If the specified interface is up and a preferred link-local IPv6 address - * has been created for the interface, return a copy of it. - * - * @param[in] tcpip_if Interface to get link-local IPv6 address - * @param[out] if_ip6 IPv6 information will be returned in this argument if successful. - * - * @return - * - ESP_OK - * - ESP_FAIL If interface is down, does not have a link-local IPv6 address, or the link-local IPv6 address is not a preferred address. + * @param tcpip_if Interface type corresponding to appropriate instance of esp-netif + * @param if_ip6 See esp_netif_get_ip6_linklocal + * @return See esp_netif_get_ip6_linklocal */ esp_err_t tcpip_adapter_get_ip6_linklocal(tcpip_adapter_if_t tcpip_if, ip6_addr_t *if_ip6); -#if 0 -esp_err_t tcpip_adapter_get_mac(tcpip_adapter_if_t tcpip_if, uint8_t *mac); - -esp_err_t tcpip_adapter_set_mac(tcpip_adapter_if_t tcpip_if, uint8_t *mac); -#endif - /** - * @brief Get DHCP Server status - * - * @param[in] tcpip_if Interface to get status of DHCP server. - * @param[out] status If successful, the status of the DHCP server will be returned in this argument. - * - * @return - * - ESP_OK - */ -esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status); - -/** - * @brief Set or Get DHCP server option - * - * @param[in] opt_op TCPIP_ADAPTER_OP_SET to set an option, TCPIP_ADAPTER_OP_GET to get an option. - * @param[in] opt_id Option index to get or set, must be one of the supported enum values. - * @param[inout] opt_val Pointer to the option parameter. - * @param[in] opt_len Length of the option parameter. - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED - * - ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED - */ -esp_err_t tcpip_adapter_dhcps_option(tcpip_adapter_dhcp_option_mode_t opt_op, tcpip_adapter_dhcp_option_id_t opt_id, void *opt_val, uint32_t opt_len); - -/** - * @brief Start DHCP server - * - * @note Currently DHCP server is only supported on the Wi-Fi AP interface. - * - * @param[in] tcpip_if Interface to start DHCP server. Must be TCPIP_ADAPTER_IF_AP. - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED - */ -esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if); - -/** - * @brief Stop DHCP server - * - * @note Currently DHCP server is only supported on the Wi-Fi AP interface. - * - * @param[in] tcpip_if Interface to stop DHCP server. Must be TCPIP_ADAPTER_IF_AP. - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED - * - ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY - */ -esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if); - -/** - * @brief Get DHCP client status - * - * @param[in] tcpip_if Interface to get status of DHCP client - * @param[out] status If successful, the status of DHCP client will be returned in this argument. - * - * @return - * - ESP_OK + * @brief`Translates to esp_netif_dhcpc_get_status + * @param tcpip_if Interface type corresponding to appropriate instance of esp-netif + * @param status + * @return See esp_netif_dhcpc_get_status */ esp_err_t tcpip_adapter_dhcpc_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status); /** - * @brief Set or Get DHCP client's option - * - * @note This function is not yet implemented - * - * @param[in] opt_op TCPIP_ADAPTER_OP_SET to set an option, TCPIP_ADAPTER_OP_GET to get an option. - * @param[in] opt_id Option index to get or set, must be one of the supported enum values. - * @param[inout] opt_val Pointer to the option parameter. - * @param[in] opt_len Length of the option parameter. - * - * @return - * - ESP_ERR_NOT_SUPPORTED (not implemented) - */ -esp_err_t tcpip_adapter_dhcpc_option(tcpip_adapter_dhcp_option_mode_t opt_op, tcpip_adapter_dhcp_option_id_t opt_id, void *opt_val, uint32_t opt_len); - -/** - * @brief Start DHCP client - * - * @note DHCP Client is only supported for the Wi-Fi station and Ethernet interfaces. - * - * @note The default event handlers for the SYSTEM_EVENT_STA_CONNECTED and SYSTEM_EVENT_ETH_CONNECTED events call this function. - * - * @param[in] tcpip_if Interface to start the DHCP client - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED - * - ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED - */ -esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if); - -/** - * @brief Stop DHCP client - * - * @note DHCP Client is only supported for the Wi-Fi station and Ethernet interfaces. - * - * @note Calling tcpip_adapter_stop() or tcpip_adapter_down() will also stop the DHCP Client if it is running. - * - * @param[in] tcpip_if Interface to stop the DHCP client - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED - * - ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY - */ -esp_err_t tcpip_adapter_dhcpc_stop(tcpip_adapter_if_t tcpip_if); - -/** - * @brief Receive an Ethernet frame from the Ethernet interface - * - * This function will automatically be installed by esp_eth_init(). The Ethernet driver layer will then call this function to forward frames to the TCP/IP stack. - * - * @note Application code does not usually need to use this function directly. - * - * @param[in] buffer Received data - * @param[in] len Length of the data frame - * @param[in] eb Pointer to internal Wi-Fi buffer (ignored for Ethernet) - * - * @return - * - ESP_OK - */ -esp_err_t tcpip_adapter_eth_input(void *buffer, uint16_t len, void *eb); - -/** - * @brief Receive an 802.11 data frame from the Wi-Fi Station interface - * - * This function should be installed by calling esp_wifi_reg_rxcb(). The Wi-Fi driver layer will then call this function to forward frames to the TCP/IP stack. - * - * @note Installation happens automatically in the default handler for the SYSTEM_EVENT_STA_CONNECTED event. - * - * @note Application code does not usually need to call this function directly. - * - * @param[in] buffer Received data - * @param[in] len Length of the data frame - * @param[in] eb Pointer to internal Wi-Fi buffer - * - * @return - * - ESP_OK - */ -esp_err_t tcpip_adapter_sta_input(void *buffer, uint16_t len, void *eb); - -/** - * @brief Receive an 802.11 data frame from the Wi-Fi AP interface - * - * This function should be installed by calling esp_wifi_reg_rxcb(). The Wi-Fi driver layer will then call this function to forward frames to the TCP/IP stack. - * - * @note Installation happens automatically in the default handler for the SYSTEM_EVENT_AP_START event. - * - * @note Application code does not usually need to call this function directly. - * - * @param[in] buffer Received data - * @param[in] len Length of the data frame - * @param[in] eb Pointer to internal Wi-Fi buffer - * - * @return - * - ESP_OK - */ -esp_err_t tcpip_adapter_ap_input(void *buffer, uint16_t len, void *eb); - -/** - * @brief Get network interface index - * - * Get network interface from TCP/IP implementation-specific interface pointer. - * - * @param[in] dev Implementation-specific TCP/IP stack interface pointer. - * - * @return - * - ESP_IF_WIFI_STA - * - ESP_IF_WIFI_AP - * - ESP_IF_ETH - * - ESP_IF_MAX - invalid parameter - */ -esp_interface_t tcpip_adapter_get_esp_if(void *dev); - -/** - * @brief Get IP information for stations connected to the Wi-Fi AP interface - * - * @param[in] wifi_sta_list Wi-Fi station info list, returned from esp_wifi_ap_get_sta_list() - * @param[out] tcpip_sta_list IP layer station info list, corresponding to MAC addresses provided in wifi_sta_list - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_NO_MEM - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - */ -esp_err_t tcpip_adapter_get_sta_list(const wifi_sta_list_t *wifi_sta_list, tcpip_adapter_sta_list_t *tcpip_sta_list); - -#define TCPIP_HOSTNAME_MAX_SIZE 32 -/** - * @brief Set the hostname of an interface - * - * @param[in] tcpip_if Interface to set the hostname - * @param[in] hostname New hostname for the interface. Maximum length 32 bytes. - * - * @return - * - ESP_OK - success - * - ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY - interface status error - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - parameter error - */ -esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname); - -/** - * @brief Get interface hostname. - * - * @param[in] tcpip_if Interface to get the hostname - * @param[out] hostname Returns a pointer to the hostname. May be NULL if no hostname is set. If set non-NULL, pointer remains valid (and string may change if the hostname changes). - * - * @return - * - ESP_OK - success - * - ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY - interface status error - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - parameter error - */ -esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char **hostname); - -/** - * @brief Get the TCP/IP stack-specific interface that is assigned to a given interface - * - * @note For lwIP, this returns a pointer to a netif structure. - * - * @param[in] tcpip_if Interface to get the implementation-specific interface - * @param[out] netif Pointer to the implementation-specific interface - * - * @return - * - ESP_OK - success - * - ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY - interface status error - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - parameter error - */ -esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif); - -/** - * @brief Test if supplied interface is up or down - * - * @param[in] tcpip_if Interface to test up/down status - * - * @return - * - true - Interface is up - * - false - Interface is down + * @brief Translates to esp_netif_is_netif_up + * @param tcpip_if Interface type corresponding to appropriate instance of esp-netif + * @return see esp_netif_is_netif_up */ bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if); /** - * @brief Cause the TCP/IP stack to start the test interface with specified MAC and IP. - * Test interface is used to exercise network stack with injected packets from SW. - * - * @param[in] mac Set MAC address of this interface - * @param[in] ip_info Set IP address of this interface - * - * @return - * - ESP_OK - * - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS - * - ESP_ERR_NO_MEM + * @brief Translates to esp_netif_get_netif + * @param tcpip_if Interface type corresponding to appropriate instance of esp-netif + * @param netif + * @return see esp_netif_get_netif */ -esp_err_t tcpip_adapter_test_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info); +esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif); /** - * @brief Install default event handlers for Ethernet interface - * @return - * - ESP_OK on success - * - one of the errors from esp_event on failure + * @brief Translates to esp_netif_create_ip6_linklocal + * @param tcpip_if Interface type corresponding to appropriate instance of esp-netif + * @return see esp_netif_create_ip6_linklocal + */ +esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if); + +/** + * @brief Compatible version of setting ethernet default handlers + * @note Compatible version of wifi handlers are provided in a separate header, + * as this used to be called privately from wifi_init() + * @return ESP_OK on success */ esp_err_t tcpip_adapter_set_default_eth_handlers(void); /** - * @brief Uninstall default event handlers for Ethernet interface - * @return - * - ESP_OK on success - * - one of the errors from esp_event on failure + * @brief Compatible version of network stack input function. Translates to esp_netif_receive() + * @param buffer + * @param len + * @param eb + * @return see esp_netif_receive */ -esp_err_t tcpip_adapter_clear_default_eth_handlers(void); +esp_err_t tcpip_adapter_eth_input(void *buffer, uint16_t len, void *eb); /** - * @brief Install default event handlers for Wi-Fi interfaces (station and AP) - * @return - * - ESP_OK on success - * - one of the errors from esp_event on failure - */ -esp_err_t tcpip_adapter_set_default_wifi_handlers(void); - -/** - * @brief Uninstall default event handlers for Wi-Fi interfaces (station and AP) - * @return - * - ESP_OK on success - * - one of the errors from esp_event on failure + * @brief Compatible version of former tcpip_adapter API to clear default WIFI handlers + * @return ESP_OK on success */ esp_err_t tcpip_adapter_clear_default_wifi_handlers(void); -/** - * @brief Search nefit index through netif interface - * @param[in] tcpip_if Interface to search for netif index - * @return - * - netif_index on success - * - -1 if an invalid parameter is supplied - */ +esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if); +esp_err_t tcpip_adapter_dhcpc_stop(tcpip_adapter_if_t tcpip_if); +esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if); +esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if); + +esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status); +esp_err_t tcpip_adapter_dhcps_option(tcpip_adapter_dhcp_option_mode_t opt_op, tcpip_adapter_dhcp_option_id_t opt_id, void *opt_val, uint32_t opt_len); +esp_err_t tcpip_adapter_dhcpc_option(tcpip_adapter_dhcp_option_mode_t opt_op, tcpip_adapter_dhcp_option_id_t opt_id, void *opt_val, uint32_t opt_len); +esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, const tcpip_adapter_ip_info_t *ip_info); +esp_err_t tcpip_adapter_get_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns); +esp_err_t tcpip_adapter_set_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns); int tcpip_adapter_get_netif_index(tcpip_adapter_if_t tcpip_if); +esp_err_t tcpip_adapter_get_sta_list(const wifi_sta_list_t *wifi_sta_list, tcpip_adapter_sta_list_t *tcpip_sta_list); -#ifdef __cplusplus -} -#endif - -#endif /* _TCPIP_ADAPTER_H_ */ +#endif //_TCPIP_ADAPTER_H_ diff --git a/components/tcpip_adapter/include/tcpip_adapter_compatible/tcpip_adapter_compat.h b/components/tcpip_adapter/include/tcpip_adapter_compatible/tcpip_adapter_compat.h new file mode 100644 index 000000000..45d5d6ac1 --- /dev/null +++ b/components/tcpip_adapter/include/tcpip_adapter_compatible/tcpip_adapter_compat.h @@ -0,0 +1,40 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _TCPIP_ADAPTER_COMPAT_H_ +#define _TCPIP_ADAPTER_COMPAT_H_ + +/** + * @brief This function is called from wifi_init to assure backward compatibility mode + * of tcpip_adapter. In case of legacy use, default instances of ap and sta + * are created and handlers are registered + * + * @note This api is given in a separate header, which is included internally (from wifi driver) + * rather then user initialization code. + * + * @return ESP_OK on success + */ +esp_err_t tcpip_adapter_set_default_wifi_handlers(void); + +/** + * @brief This function is called from ethernet driver init code to facilitate + * autostart fo the driver in backward compatible tcpip_adapter way + * + * @param[in] h Handle to the ethernet driver + * + * @return ESP_OK on success + */ +esp_err_t tcpip_adapter_start_eth(void* h); + +#endif //_TCPIP_ADAPTER_COMPAT_H_ diff --git a/components/tcpip_adapter/include/tcpip_adapter_internal.h b/components/tcpip_adapter/include/tcpip_adapter_internal.h deleted file mode 100644 index 2b9879b4a..000000000 --- a/components/tcpip_adapter/include/tcpip_adapter_internal.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#include "tcpip_adapter.h" -#include "sys/queue.h" - -struct tcpip_adapter_api_msg_s; - -typedef int (*tcpip_adapter_api_fn)(struct tcpip_adapter_api_msg_s *msg); - -typedef struct tcpip_adapter_api_msg_s { - int type; /**< The first field MUST be int */ - int ret; - tcpip_adapter_api_fn api_fn; - tcpip_adapter_if_t tcpip_if; - tcpip_adapter_ip_info_t *ip_info; - uint8_t *mac; - void *data; -} tcpip_adapter_api_msg_t; - -typedef struct tcpip_adapter_dns_param_s { - tcpip_adapter_dns_type_t dns_type; - tcpip_adapter_dns_info_t *dns_info; -} tcpip_adapter_dns_param_t; - -typedef struct tcpip_adapter_ip_lost_timer_s { - bool timer_running; -} tcpip_adapter_ip_lost_timer_t; - - -#define TCPIP_ADAPTER_TRHEAD_SAFE 1 -#define TCPIP_ADAPTER_IPC_LOCAL 0 -#define TCPIP_ADAPTER_IPC_REMOTE 1 - -#define TCPIP_ADAPTER_IPC_CALL(_if, _mac, _ip, _data, _fn) do {\ - tcpip_adapter_api_msg_t msg;\ - if (tcpip_inited == false) {\ - ESP_LOGE(TAG, "tcpip_adapter is not initialized!");\ - abort();\ - }\ - memset(&msg, 0, sizeof(msg));\ - msg.tcpip_if = (_if);\ - msg.mac = (uint8_t*)(_mac);\ - msg.ip_info = (tcpip_adapter_ip_info_t*)(_ip);\ - msg.data = (void*)(_data);\ - msg.api_fn = (_fn);\ - if (TCPIP_ADAPTER_IPC_REMOTE == tcpip_adapter_ipc_check(&msg)) {\ - ESP_LOGV(TAG, "check: remote, if=%d fn=%p\n", (_if), (_fn));\ - return msg.ret;\ - } else {\ - ESP_LOGV(TAG, "check: local, if=%d fn=%p\n", (_if), (_fn));\ - }\ -} while(0) diff --git a/components/tcpip_adapter/sdkconfig.rename b/components/tcpip_adapter/sdkconfig.rename deleted file mode 100644 index 72405c056..000000000 --- a/components/tcpip_adapter/sdkconfig.rename +++ /dev/null @@ -1,5 +0,0 @@ -# sdkconfig replacement configurations for deprecated options formatted as -# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION - -CONFIG_IP_LOST_TIMER_INTERVAL CONFIG_NETIF_IP_LOST_TIMER_INTERVAL -CONFIG_USE_TCPIP_STACK_LIB CONFIG_NETIF_USE_TCPIP_STACK_LIB diff --git a/components/tcpip_adapter/tcpip_adapter_compat.c b/components/tcpip_adapter/tcpip_adapter_compat.c new file mode 100644 index 000000000..cef9c8826 --- /dev/null +++ b/components/tcpip_adapter/tcpip_adapter_compat.c @@ -0,0 +1,274 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "esp_netif.h" +#include "tcpip_adapter_compatible/tcpip_adapter_compat.h" +#include "esp_private/wifi.h" +#include "esp_log.h" +#include "esp_netif_net_stack.h" +#include "tcpip_adapter.h" +#include "esp_eth.h" + +extern void _esp_wifi_set_default_ap_netif(esp_netif_t* esp_netif); +extern void _esp_wifi_set_default_sta_netif(esp_netif_t* esp_netif); +extern esp_err_t _esp_wifi_set_default_wifi_handlers(void); +extern esp_err_t esp_eth_set_default_handlers(void *esp_netif); +extern esp_err_t esp_wifi_clear_default_wifi_handlers(void); + +// +// Purpose of this module is to provide backward compatible version of esp-netif +// with legacy tcpip_adapter interface +// + +static const char* TAG = "tcpip_adapter_compat"; + +static esp_netif_t *s_esp_netifs[TCPIP_ADAPTER_IF_MAX] = { NULL }; +static const char* s_netif_keyif[TCPIP_ADAPTER_IF_MAX] = { + "WIFI_STA_DEF", + "WIFI_AP_DEF", + "ETH_DEF", +}; + +static bool s_tcpip_adapter_compat = false; + +void wifi_start(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data); + +static void wifi_create_and_start_ap(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data) +{ + if (s_esp_netifs[TCPIP_ADAPTER_IF_AP] == NULL) { + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_WIFI_AP(); + esp_netif_t *ap_netif = esp_netif_new(&cfg); + + _esp_wifi_set_default_ap_netif(ap_netif); + s_esp_netifs[TCPIP_ADAPTER_IF_AP] = ap_netif; + } +} + +static void wifi_create_and_start_sta(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data) +{ + if (s_esp_netifs[TCPIP_ADAPTER_IF_STA] == NULL) { + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_WIFI_STA(); + esp_netif_t *sta_netif = esp_netif_new(&cfg); + + _esp_wifi_set_default_sta_netif(sta_netif); + s_esp_netifs[TCPIP_ADAPTER_IF_STA] = sta_netif; + } +} + +static inline esp_netif_t * netif_from_if(tcpip_adapter_if_t interface) +{ + if (interface < TCPIP_ADAPTER_IF_MAX) { + if (s_esp_netifs[interface] == NULL) { + s_esp_netifs[interface] = esp_netif_get_handle_from_ifkey(s_netif_keyif[interface]); + if (s_esp_netifs[interface] == NULL && s_tcpip_adapter_compat) { + // if not found in compat mode -> create it + if (interface == TCPIP_ADAPTER_IF_STA) { + wifi_create_and_start_sta(NULL, 0, 0, NULL); + s_esp_netifs[interface] = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); + } else if (interface == TCPIP_ADAPTER_IF_AP) { + wifi_create_and_start_ap(NULL, 0, 0, NULL); + s_esp_netifs[interface] = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); + } + } + } + return s_esp_netifs[interface]; + } + return NULL; +} + +void tcpip_adapter_init(void) +{ + s_tcpip_adapter_compat = true; + esp_err_t err; + if (ESP_OK != (err = esp_netif_init())) { + ESP_LOGE(TAG, "ESP-NETIF initialization failed with %d in tcpip_adapter compatibility mode", err); + } +} + +static void tcpip_adapter_eth_start(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data) +{ + esp_eth_handle_t eth_handle = *(esp_eth_handle_t*)data; + esp_netif_attach(esp_netif, eth_handle); +} + +esp_err_t tcpip_adapter_set_default_eth_handlers(void) +{ + if (s_tcpip_adapter_compat) { + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); + esp_netif_t *eth_netif = esp_netif_new(&cfg); + + s_esp_netifs[TCPIP_ADAPTER_IF_ETH] = eth_netif; + // provide a separate "after driver start" hook to attach + esp_err_t ret = esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, tcpip_adapter_eth_start, eth_netif); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to register "); + return ret; + } + + return esp_eth_set_default_handlers(eth_netif); + } + return ESP_OK; + +} + +esp_err_t tcpip_adapter_eth_input(void *buffer, uint16_t len, void *eb) +{ + return esp_netif_receive(netif_from_if(TCPIP_ADAPTER_IF_ETH), buffer, len, eb); +} + +esp_err_t tcpip_adapter_start_eth(void* eth_driver) +{ +#if CONFIG_ESP_NETIF_USE_TCPIP_ADAPTER_COMPATIBLE_LAYER + if (s_tcpip_adapter_compat) { + esp_netif_t *esp_netif = netif_from_if(TCPIP_ADAPTER_IF_ETH); + esp_netif_attach(esp_netif, eth_driver); + } + return ESP_OK; +#else + ESP_LOGE(TAG, "%s: tcpip adapter compatibility layer is disabled", __func__); + return ESP_ERR_INVALID_STATE; +#endif +} + +esp_err_t tcpip_adapter_set_default_wifi_handlers(void) +{ +#if CONFIG_ESP_NETIF_USE_TCPIP_ADAPTER_COMPATIBLE_LAYER + if (s_tcpip_adapter_compat) { + // create instances and register default handlers only on start event + esp_err_t err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_START, wifi_create_and_start_sta, NULL); + if (err != ESP_OK) { + return err; + } + err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_START, wifi_create_and_start_ap, NULL); + if (err != ESP_OK) { + return err; + } + _esp_wifi_set_default_wifi_handlers(); + } + return ESP_OK; +#else + ESP_LOGE(TAG, "%s: tcpip adapter compatibility layer is disabled", __func__); + return ESP_ERR_INVALID_STATE; +#endif +} + +esp_err_t tcpip_adapter_clear_default_wifi_handlers(void) +{ + return esp_wifi_clear_default_wifi_handlers(); +} + +tcpip_adapter_if_t tcpip_adapter_if_from_esp_netif(esp_netif_t *esp_netif) +{ + for (int i=0; i -#include - -#include "tcpip_adapter_internal.h" -#if CONFIG_TCPIP_LWIP - -#include "lwip/inet.h" -#include "lwip/tcpip.h" -#include "lwip/dhcp.h" -#include "lwip/ip_addr.h" -#include "lwip/ip6_addr.h" -#include "lwip/nd6.h" -#include "lwip/priv/tcpip_priv.h" -#include "lwip/netif.h" -#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ -#include "lwip/dns.h" -#include "lwip/netif.h" -#endif -#include "netif/wlanif.h" -#ifdef CONFIG_ETH_ENABLED -#include "netif/ethernetif.h" -#endif -#include "netif/nettestif.h" - -#include "dhcpserver/dhcpserver.h" -#include "dhcpserver/dhcpserver_options.h" - -#include "esp_event.h" -#include "esp_log.h" - -static struct netif *esp_netif[TCPIP_ADAPTER_IF_MAX]; -static tcpip_adapter_ip_info_t esp_ip[TCPIP_ADAPTER_IF_MAX]; -static tcpip_adapter_ip_info_t esp_ip_old[TCPIP_ADAPTER_IF_MAX]; -static tcpip_adapter_ip6_info_t esp_ip6[TCPIP_ADAPTER_IF_MAX]; -static netif_init_fn esp_netif_init_fn[TCPIP_ADAPTER_IF_MAX]; -static tcpip_adapter_ip_lost_timer_t esp_ip_lost_timer[TCPIP_ADAPTER_IF_MAX]; - -static tcpip_adapter_dhcp_status_t dhcps_status = TCPIP_ADAPTER_DHCP_INIT; -static tcpip_adapter_dhcp_status_t dhcpc_status[TCPIP_ADAPTER_IF_MAX] = {TCPIP_ADAPTER_DHCP_INIT}; -static esp_err_t tcpip_adapter_start_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_stop_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_up_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_down_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_set_ip_info_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_set_dns_info_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_get_dns_info_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_create_ip6_linklocal_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_dhcps_start_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_dhcps_stop_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_dhcpc_start_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_dhcpc_stop_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_set_hostname_api(tcpip_adapter_api_msg_t *msg); -static esp_err_t tcpip_adapter_reset_ip_info(tcpip_adapter_if_t tcpip_if); -static esp_err_t tcpip_adapter_start_ip_lost_timer(tcpip_adapter_if_t tcpip_if); -static void tcpip_adapter_ip_lost_timer(void *arg); -static sys_sem_t api_sync_sem = NULL; -static bool tcpip_inited = false; -static sys_sem_t api_lock_sem = NULL; -extern sys_thread_t g_lwip_task; -static const char *TAG = "tcpip_adapter"; - -ESP_EVENT_DEFINE_BASE(IP_EVENT); - -static void tcpip_adapter_api_cb(void *api_msg) -{ - tcpip_adapter_api_msg_t *msg = (tcpip_adapter_api_msg_t *)api_msg; - - if (!msg || !msg->api_fn) { - ESP_LOGD(TAG, "null msg/api_fn"); - return; - } - - msg->ret = msg->api_fn(msg); - ESP_LOGV(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret); - sys_sem_signal(&api_sync_sem); - - return; -} - -static void tcpip_adapter_dhcps_cb(u8_t client_ip[4]) -{ - int ret; - - ESP_LOGI(TAG, "softAP assign IP to station,IP is: %d.%d.%d.%d", - client_ip[0], client_ip[1], client_ip[2], client_ip[3]); - ip_event_ap_staipassigned_t evt; - - memset(&evt, 0, sizeof(ip_event_ap_staipassigned_t)); - memcpy((char *)&evt.ip.addr, (char *)client_ip, sizeof(evt.ip.addr)); - ret = esp_event_send_internal(IP_EVENT, IP_EVENT_AP_STAIPASSIGNED, &evt, sizeof(evt), 0); - if (ESP_OK != ret) { - ESP_LOGE(TAG, "dhcps cb: failed to post IP_EVENT_AP_STAIPASSIGNED (%x)", ret); - } -} - -void tcpip_adapter_init(void) -{ - int ret; - - if (tcpip_inited == false) { - tcpip_inited = true; - - tcpip_init(NULL, NULL); - - memset(esp_ip, 0, sizeof(tcpip_adapter_ip_info_t)*TCPIP_ADAPTER_IF_MAX); - memset(esp_ip_old, 0, sizeof(tcpip_adapter_ip_info_t)*TCPIP_ADAPTER_IF_MAX); - - IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].ip, 192, 168 , 4, 1); - IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].gw, 192, 168 , 4, 1); - IP4_ADDR(&esp_ip[TCPIP_ADAPTER_IF_AP].netmask, 255, 255 , 255, 0); - ret = sys_sem_new(&api_sync_sem, 0); - if (ERR_OK != ret) { - ESP_LOGE(TAG, "tcpip adatper api sync sem init fail"); - } - - ret = sys_sem_new(&api_lock_sem, 1); - if (ERR_OK != ret) { - ESP_LOGE(TAG, "tcpip adatper api lock sem init fail"); - } - } -} - -static inline netif_init_fn tcpip_if_to_netif_init_fn(tcpip_adapter_if_t tcpip_if) -{ - if (tcpip_if < TCPIP_ADAPTER_IF_MAX) { - return esp_netif_init_fn[tcpip_if]; - } else { - return NULL; - } -} - -static int tcpip_adapter_ipc_check(tcpip_adapter_api_msg_t *msg) -{ -#if TCPIP_ADAPTER_TRHEAD_SAFE - xTaskHandle local_task = xTaskGetCurrentTaskHandle(); - - if (local_task == g_lwip_task) { - return TCPIP_ADAPTER_IPC_LOCAL; - } - - sys_arch_sem_wait(&api_lock_sem, 0); - tcpip_send_msg_wait_sem((tcpip_callback_fn)tcpip_adapter_api_cb, msg, &api_sync_sem); - sys_sem_signal(&api_lock_sem); - - return TCPIP_ADAPTER_IPC_REMOTE; -#else - return TCPIP_ADAPTER_IPC_LOCAL; -#endif -} - -static esp_err_t tcpip_adapter_update_default_netif(void) -{ - if (esp_netif[TCPIP_ADAPTER_IF_STA] != NULL && netif_is_up(esp_netif[TCPIP_ADAPTER_IF_STA])) { - netif_set_default(esp_netif[TCPIP_ADAPTER_IF_STA]); - } else if (esp_netif[TCPIP_ADAPTER_IF_ETH] != NULL && netif_is_up(esp_netif[TCPIP_ADAPTER_IF_ETH])) { - netif_set_default(esp_netif[TCPIP_ADAPTER_IF_ETH]); - } else if (esp_netif[TCPIP_ADAPTER_IF_AP] != NULL && netif_is_up(esp_netif[TCPIP_ADAPTER_IF_AP])) { - netif_set_default(esp_netif[TCPIP_ADAPTER_IF_AP]); - } else if(esp_netif[TCPIP_ADAPTER_IF_TEST] != NULL && netif_is_up(esp_netif[TCPIP_ADAPTER_IF_TEST])) { - netif_set_default(esp_netif[TCPIP_ADAPTER_IF_TEST]); - } - - return ESP_OK; -} - -static esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, tcpip_adapter_ip_info_t *ip_info, void *args) -{ - netif_init_fn netif_init; - - TCPIP_ADAPTER_IPC_CALL(tcpip_if, mac, ip_info, args, tcpip_adapter_start_api); - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || mac == NULL || ip_info == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (esp_netif[tcpip_if] == NULL || !netif_is_up(esp_netif[tcpip_if])) { - if (esp_netif[tcpip_if] == NULL) { - esp_netif[tcpip_if] = calloc(1, sizeof(*esp_netif[tcpip_if])); - } - - if (esp_netif[tcpip_if] == NULL) { - return ESP_ERR_NO_MEM; - } - memcpy(esp_netif[tcpip_if]->hwaddr, mac, NETIF_MAX_HWADDR_LEN); - - netif_init = tcpip_if_to_netif_init_fn(tcpip_if); - assert(netif_init != NULL); - netif_add(esp_netif[tcpip_if], &ip_info->ip, &ip_info->netmask, &ip_info->gw, args, netif_init, tcpip_input); - -#if ESP_GRATUITOUS_ARP - if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) { - netif_set_garp_flag(esp_netif[tcpip_if]); - } -#endif - - } - - if (tcpip_if == TCPIP_ADAPTER_IF_AP) { - netif_set_up(esp_netif[tcpip_if]); - - if (dhcps_status == TCPIP_ADAPTER_DHCP_INIT) { - dhcps_set_new_lease_cb(tcpip_adapter_dhcps_cb); - - dhcps_start(esp_netif[tcpip_if], ip_info->ip); - - ESP_LOGD(TAG, "dhcp server start:(ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR ")", - IP2STR(&ip_info->ip), IP2STR(&ip_info->netmask), IP2STR(&ip_info->gw)); - - dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; - } - } else if (tcpip_if == TCPIP_ADAPTER_IF_TEST) { - netif_set_up(esp_netif[tcpip_if]); - } - - tcpip_adapter_update_default_netif(); - - return ESP_OK; -} - -esp_err_t tcpip_adapter_eth_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info, void *args) -{ -#ifdef CONFIG_ETH_ENABLED - esp_netif_init_fn[TCPIP_ADAPTER_IF_ETH] = ethernetif_init; - return tcpip_adapter_start(TCPIP_ADAPTER_IF_ETH, mac, ip_info, args); -#else - return ESP_ERR_NOT_SUPPORTED; -#endif -} - -esp_err_t tcpip_adapter_sta_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info) -{ - esp_netif_init_fn[TCPIP_ADAPTER_IF_STA] = wlanif_init_sta; - return tcpip_adapter_start(TCPIP_ADAPTER_IF_STA, mac, ip_info, NULL); -} - -esp_err_t tcpip_adapter_test_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info) -{ - esp_netif_init_fn[TCPIP_ADAPTER_IF_TEST] = nettestif_init; - return tcpip_adapter_start(TCPIP_ADAPTER_IF_TEST, mac, ip_info, NULL); -} - - -esp_err_t tcpip_adapter_ap_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info) -{ - esp_netif_init_fn[TCPIP_ADAPTER_IF_AP] = wlanif_init_ap; - return tcpip_adapter_start(TCPIP_ADAPTER_IF_AP, mac, ip_info, NULL); -} - -static esp_err_t tcpip_adapter_start_api(tcpip_adapter_api_msg_t *msg) -{ - return tcpip_adapter_start(msg->tcpip_if, msg->mac, msg->ip_info, msg->data); -} - -esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if) -{ - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_stop_api); - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (esp_netif[tcpip_if] == NULL) { - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; - } - - if (!netif_is_up(esp_netif[tcpip_if])) { - netif_remove(esp_netif[tcpip_if]); - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; - } - - if (tcpip_if == TCPIP_ADAPTER_IF_AP) { - dhcps_stop(esp_netif[tcpip_if]); // TODO: dhcps checks status by its self - if (TCPIP_ADAPTER_DHCP_STOPPED != dhcps_status) { - dhcps_status = TCPIP_ADAPTER_DHCP_INIT; - } - } else if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) { - dhcp_release(esp_netif[tcpip_if]); - dhcp_stop(esp_netif[tcpip_if]); - dhcp_cleanup(esp_netif[tcpip_if]); - - dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; - - tcpip_adapter_reset_ip_info(tcpip_if); - } - - netif_set_down(esp_netif[tcpip_if]); - netif_remove(esp_netif[tcpip_if]); - tcpip_adapter_update_default_netif(); - - return ESP_OK; -} - -static esp_err_t tcpip_adapter_stop_api(tcpip_adapter_api_msg_t *msg) -{ - msg->ret = tcpip_adapter_stop(msg->tcpip_if); - return msg->ret; -} - -esp_err_t tcpip_adapter_up(tcpip_adapter_if_t tcpip_if) -{ - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_up_api); - - if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH ) { - if (esp_netif[tcpip_if] == NULL) { - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; - } - - /* use last obtained ip, or static ip */ - netif_set_addr(esp_netif[tcpip_if], &esp_ip[tcpip_if].ip, &esp_ip[tcpip_if].netmask, &esp_ip[tcpip_if].gw); - netif_set_up(esp_netif[tcpip_if]); - } - - tcpip_adapter_update_default_netif(); - - return ESP_OK; -} - -static esp_err_t tcpip_adapter_up_api(tcpip_adapter_api_msg_t *msg) -{ - msg->ret = tcpip_adapter_up(msg->tcpip_if); - return msg->ret; -} - -esp_err_t tcpip_adapter_down(tcpip_adapter_if_t tcpip_if) -{ - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_down_api); - - if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH ) { - if (esp_netif[tcpip_if] == NULL) { - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; - } - - if (dhcpc_status[tcpip_if] == TCPIP_ADAPTER_DHCP_STARTED) { - dhcp_stop(esp_netif[tcpip_if]); - - dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; - - tcpip_adapter_reset_ip_info(tcpip_if); - } - - netif_set_addr(esp_netif[tcpip_if], IP4_ADDR_ANY4, IP4_ADDR_ANY4, IP4_ADDR_ANY4); - netif_set_down(esp_netif[tcpip_if]); - tcpip_adapter_start_ip_lost_timer(tcpip_if); - } - - tcpip_adapter_update_default_netif(); - - return ESP_OK; -} - -static esp_err_t tcpip_adapter_down_api(tcpip_adapter_api_msg_t *msg) -{ - return tcpip_adapter_down(msg->tcpip_if); -} - -esp_err_t tcpip_adapter_set_old_ip_info_api(tcpip_adapter_api_msg_t *msg) -{ - memcpy(&esp_ip_old[msg->tcpip_if], msg->ip_info, sizeof(tcpip_adapter_ip_info_t)); - return ESP_OK; -} - -esp_err_t tcpip_adapter_set_old_ip_info(tcpip_adapter_if_t tcpip_if, const tcpip_adapter_ip_info_t *ip_info) -{ - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, ip_info, 0, tcpip_adapter_set_old_ip_info_api); - - return ESP_OK; -} - -esp_err_t tcpip_adapter_get_old_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) -{ - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - memcpy(ip_info, &esp_ip_old[tcpip_if], sizeof(tcpip_adapter_ip_info_t)); - return ESP_OK; -} - -esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) -{ - struct netif *p_netif; - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - p_netif = esp_netif[tcpip_if]; - - if (p_netif != NULL && netif_is_up(p_netif)) { - ip4_addr_set(&ip_info->ip, ip_2_ip4(&p_netif->ip_addr)); - ip4_addr_set(&ip_info->netmask, ip_2_ip4(&p_netif->netmask)); - ip4_addr_set(&ip_info->gw, ip_2_ip4(&p_netif->gw)); - - return ESP_OK; - } - - ip4_addr_copy(ip_info->ip, esp_ip[tcpip_if].ip); - ip4_addr_copy(ip_info->gw, esp_ip[tcpip_if].gw); - ip4_addr_copy(ip_info->netmask, esp_ip[tcpip_if].netmask); - - return ESP_OK; -} - -esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, const tcpip_adapter_ip_info_t *ip_info) -{ - struct netif *p_netif; - tcpip_adapter_dhcp_status_t status; - - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, ip_info, 0, tcpip_adapter_set_ip_info_api); - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || ip_info == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (tcpip_if == TCPIP_ADAPTER_IF_AP) { - tcpip_adapter_dhcps_get_status(tcpip_if, &status); - - if (status != TCPIP_ADAPTER_DHCP_STOPPED) { - return ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED; - } - } else if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH ) { - tcpip_adapter_dhcpc_get_status(tcpip_if, &status); - - if (status != TCPIP_ADAPTER_DHCP_STOPPED) { - return ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED; - } -#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ - dns_clear_servers(true); -#endif - } - - ip4_addr_copy(esp_ip[tcpip_if].ip, ip_info->ip); - ip4_addr_copy(esp_ip[tcpip_if].gw, ip_info->gw); - ip4_addr_copy(esp_ip[tcpip_if].netmask, ip_info->netmask); - - p_netif = esp_netif[tcpip_if]; - - if (p_netif != NULL && netif_is_up(p_netif)) { - netif_set_addr(p_netif, &ip_info->ip, &ip_info->netmask, &ip_info->gw); - if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) { - if (!(ip4_addr_isany_val(ip_info->ip) || ip4_addr_isany_val(ip_info->netmask) || ip4_addr_isany_val(ip_info->gw))) { - - ip_event_t evt_id = IP_EVENT_STA_GOT_IP; - ip_event_got_ip_t evt; - int ret; - - memset(&evt, 0, sizeof(ip_event_got_ip_t)); - evt.if_index = tcpip_if; - evt.ip_changed = false; - - if (memcmp(ip_info, &esp_ip_old[tcpip_if], sizeof(tcpip_adapter_ip_info_t))) { - evt.ip_changed = true; - } - - if (tcpip_if == TCPIP_ADAPTER_IF_ETH) { - evt_id = IP_EVENT_ETH_GOT_IP; - } - - memcpy(&evt.ip_info, ip_info, sizeof(tcpip_adapter_ip_info_t)); - memcpy(&esp_ip_old[tcpip_if], ip_info, sizeof(tcpip_adapter_ip_info_t)); - ret = esp_event_send_internal(IP_EVENT, evt_id, &evt, sizeof(evt), 0); - if (ESP_OK != ret) { - ESP_LOGE(TAG, "set ip info: failed to post got ip event (%x)", ret); - } - - ESP_LOGD(TAG, "if%d tcpip adapter set static ip: ip changed=%d", tcpip_if, evt.ip_changed); - } - } - } - - return ESP_OK; -} - -static esp_err_t tcpip_adapter_set_ip_info_api(tcpip_adapter_api_msg_t *msg) -{ - return tcpip_adapter_set_ip_info(msg->tcpip_if, msg->ip_info); -} - -static void tcpip_adapter_nd6_cb(struct netif *p_netif, uint8_t ip_idex) -{ - tcpip_adapter_ip6_info_t *ip6_info; - int ret; - - ip_event_got_ip6_t evt; - memset(&evt, 0, sizeof(ip_event_got_ip6_t)); - //notify event - - if (!p_netif) { - ESP_LOGD(TAG, "null p_netif=%p", p_netif); - return; - } - - if (p_netif == esp_netif[TCPIP_ADAPTER_IF_STA]) { - ip6_info = &esp_ip6[TCPIP_ADAPTER_IF_STA]; - evt.if_index = TCPIP_ADAPTER_IF_STA; - } else if (p_netif == esp_netif[TCPIP_ADAPTER_IF_AP]) { - ip6_info = &esp_ip6[TCPIP_ADAPTER_IF_AP]; - evt.if_index = TCPIP_ADAPTER_IF_AP; - } else if (p_netif == esp_netif[TCPIP_ADAPTER_IF_ETH]) { - ip6_info = &esp_ip6[TCPIP_ADAPTER_IF_ETH]; - evt.if_index = TCPIP_ADAPTER_IF_ETH; - } else { - return; - } - - ip6_addr_set(&ip6_info->ip, ip_2_ip6(&p_netif->ip6_addr[ip_idex])); - - memcpy(&evt.ip6_info, ip6_info, sizeof(tcpip_adapter_ip6_info_t)); - ret = esp_event_send_internal(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0); - if (ESP_OK != ret) { - ESP_LOGE(TAG, "nd6 cb: failed to post IP_EVENT_GOT_IP6 (%x)", ret); - } -} - -esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if) -{ - struct netif *p_netif; - - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_create_ip6_linklocal_api); - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - p_netif = esp_netif[tcpip_if]; - if (p_netif != NULL && netif_is_up(p_netif)) { - netif_create_ip6_linklocal_address(p_netif, 1); - nd6_set_cb(p_netif, tcpip_adapter_nd6_cb); - - return ESP_OK; - } else { - return ESP_FAIL; - } -} - -static esp_err_t tcpip_adapter_create_ip6_linklocal_api(tcpip_adapter_api_msg_t *msg) -{ - return tcpip_adapter_create_ip6_linklocal(msg->tcpip_if); -} - -esp_err_t tcpip_adapter_get_ip6_linklocal(tcpip_adapter_if_t tcpip_if, ip6_addr_t *if_ip6) -{ - struct netif *p_netif; - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || if_ip6 == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - p_netif = esp_netif[tcpip_if]; - if (p_netif != NULL && netif_is_up(p_netif) && ip6_addr_ispreferred(netif_ip6_addr_state(p_netif, 0))) { - memcpy(if_ip6, &p_netif->ip6_addr[0], sizeof(ip6_addr_t)); - } else { - return ESP_FAIL; - } - return ESP_OK; -} - -#if 0 -esp_err_t tcpip_adapter_get_mac(tcpip_adapter_if_t tcpip_if, uint8_t mac[6]) -{ - struct netif *p_netif; - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || mac == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - p_netif = esp_netif[tcpip_if]; - - if (p_netif != NULL) { - memcpy(mac, p_netif->hwaddr, NETIF_MAX_HWADDR_LEN); - - return ESP_OK; - } - - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; -} - -esp_err_t tcpip_adapter_set_mac(tcpip_adapter_if_t tcpip_if, uint8_t mac[6]) -{ - struct netif *p_netif; - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || mac == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - p_netif = esp_netif[tcpip_if]; - - if (p_netif != NULL) { - memcpy(p_netif->hwaddr, mac, NETIF_MAX_HWADDR_LEN); - - return ESP_OK; - } - - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; -} -#endif - -esp_err_t tcpip_adapter_dhcps_option(tcpip_adapter_dhcp_option_mode_t opt_op, tcpip_adapter_dhcp_option_id_t opt_id, void *opt_val, uint32_t opt_len) -{ - void *opt_info = dhcps_option_info(opt_id, opt_len); - - if (opt_info == NULL || opt_val == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (opt_op == TCPIP_ADAPTER_OP_GET) { - if (dhcps_status == TCPIP_ADAPTER_DHCP_STOPPED) { - return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED; - } - - switch (opt_id) { - case IP_ADDRESS_LEASE_TIME: { - *(uint32_t *)opt_val = *(uint32_t *)opt_info; - break; - } - case REQUESTED_IP_ADDRESS: { - memcpy(opt_val, opt_info, opt_len); - break; - } - case ROUTER_SOLICITATION_ADDRESS: { - if ((*(uint8_t *)opt_info) & OFFER_ROUTER) { - *(uint8_t *)opt_val = 1; - } else { - *(uint8_t *)opt_val = 0; - } - break; - } - case DOMAIN_NAME_SERVER: { - if ((*(uint8_t *)opt_info) & OFFER_DNS) { - *(uint8_t *)opt_val = 1; - } else { - *(uint8_t *)opt_val = 0; - } - break; - } - default: - break; - } - } else if (opt_op == TCPIP_ADAPTER_OP_SET) { - if (dhcps_status == TCPIP_ADAPTER_DHCP_STARTED) { - return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; - } - - switch (opt_id) { - case IP_ADDRESS_LEASE_TIME: { - if (*(uint32_t *)opt_val != 0) { - *(uint32_t *)opt_info = *(uint32_t *)opt_val; - } else { - *(uint32_t *)opt_info = DHCPS_LEASE_TIME_DEF; - } - break; - } - case REQUESTED_IP_ADDRESS: { - tcpip_adapter_ip_info_t info; - uint32_t softap_ip = 0; - uint32_t start_ip = 0; - uint32_t end_ip = 0; - dhcps_lease_t *poll = opt_val; - - if (poll->enable) { - memset(&info, 0x00, sizeof(tcpip_adapter_ip_info_t)); - tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &info); - softap_ip = htonl(info.ip.addr); - start_ip = htonl(poll->start_ip.addr); - end_ip = htonl(poll->end_ip.addr); - - /*config ip information can't contain local ip*/ - if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - /*config ip information must be in the same segment as the local ip*/ - softap_ip >>= 8; - if ((start_ip >> 8 != softap_ip) - || (end_ip >> 8 != softap_ip)) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (end_ip - start_ip > DHCPS_MAX_LEASE) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - } - - memcpy(opt_info, opt_val, opt_len); - break; - } - case ROUTER_SOLICITATION_ADDRESS: { - if (*(uint8_t *)opt_val) { - *(uint8_t *)opt_info |= OFFER_ROUTER; - } else { - *(uint8_t *)opt_info &= ((~OFFER_ROUTER) & 0xFF); - } - break; - } - case DOMAIN_NAME_SERVER: { - if (*(uint8_t *)opt_val) { - *(uint8_t *)opt_info |= OFFER_DNS; - } else { - *(uint8_t *)opt_info &= ((~OFFER_DNS) & 0xFF); - } - break; - } - - default: - break; - } - dhcps_set_option_info(opt_id, opt_info, opt_len); - } else { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - return ESP_OK; -} - -esp_err_t tcpip_adapter_set_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns) -{ - tcpip_adapter_dns_param_t dns_param; - - dns_param.dns_type = type; - dns_param.dns_info = dns; - - TCPIP_ADAPTER_IPC_CALL(tcpip_if, type, 0, &dns_param, tcpip_adapter_set_dns_info_api); - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - ESP_LOGD(TAG, "set dns invalid if=%d", tcpip_if); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (!dns) { - ESP_LOGD(TAG, "set dns null dns"); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (type >= TCPIP_ADAPTER_DNS_MAX) { - ESP_LOGD(TAG, "set dns invalid type=%d", type); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (ip4_addr_isany_val(dns->ip.u_addr.ip4)) { - ESP_LOGD(TAG, "set dns invalid dns"); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - ESP_LOGD(TAG, "set dns if=%d type=%d dns=%x", tcpip_if, type, dns->ip.u_addr.ip4.addr); - dns->ip.type = IPADDR_TYPE_V4; - - if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) { - dns_setserver(type, &(dns->ip)); - } else { - if (type != TCPIP_ADAPTER_DNS_MAIN) { - ESP_LOGD(TAG, "set dns invalid type"); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } else { - dhcps_dns_setserver(&(dns->ip)); - } - } - - return ESP_OK; -} - -static esp_err_t tcpip_adapter_set_dns_info_api(tcpip_adapter_api_msg_t *msg) -{ - tcpip_adapter_dns_param_t *dns_param = (tcpip_adapter_dns_param_t *)msg->data; - - return tcpip_adapter_set_dns_info(msg->tcpip_if, dns_param->dns_type, dns_param->dns_info); -} - -esp_err_t tcpip_adapter_get_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns) -{ - tcpip_adapter_dns_param_t dns_param; - - dns_param.dns_type = type; - dns_param.dns_info = dns; - const ip_addr_t* dns_ip = NULL; - - - TCPIP_ADAPTER_IPC_CALL(tcpip_if, type, 0, &dns_param, tcpip_adapter_get_dns_info_api); - if (!dns) { - ESP_LOGD(TAG, "get dns null dns"); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (type >= TCPIP_ADAPTER_DNS_MAX) { - ESP_LOGD(TAG, "get dns invalid type=%d", type); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - ESP_LOGD(TAG, "get dns invalid tcpip_if=%d", tcpip_if); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) { - dns_ip = dns_getserver(type); - if(dns_ip != NULL){ - dns->ip = *dns_ip; - } - } else { - dns->ip.u_addr.ip4 = dhcps_dns_getserver(); - } - - return ESP_OK; -} - -static esp_err_t tcpip_adapter_get_dns_info_api(tcpip_adapter_api_msg_t *msg) -{ - tcpip_adapter_dns_param_t *dns_param = (tcpip_adapter_dns_param_t *)msg->data; - - return tcpip_adapter_get_dns_info(msg->tcpip_if, dns_param->dns_type, dns_param->dns_info); -} - -esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status) -{ - *status = dhcps_status; - - return ESP_OK; -} - -esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if) -{ - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_dhcps_start_api); - - /* only support ap now */ - if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - ESP_LOGD(TAG, "dhcp server invalid if=%d", tcpip_if); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (dhcps_status != TCPIP_ADAPTER_DHCP_STARTED) { - struct netif *p_netif = esp_netif[tcpip_if]; - - if (p_netif != NULL && netif_is_up(p_netif)) { - tcpip_adapter_ip_info_t default_ip; - tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &default_ip); - dhcps_start(p_netif, default_ip.ip); - dhcps_status = TCPIP_ADAPTER_DHCP_STARTED; - ESP_LOGD(TAG, "dhcp server start successfully"); - return ESP_OK; - } else { - ESP_LOGD(TAG, "dhcp server re init"); - dhcps_status = TCPIP_ADAPTER_DHCP_INIT; - return ESP_OK; - } - } - - ESP_LOGD(TAG, "dhcp server already start"); - return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; -} - -static esp_err_t tcpip_adapter_dhcps_start_api(tcpip_adapter_api_msg_t *msg) -{ - return tcpip_adapter_dhcps_start(msg->tcpip_if); -} - - -esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if) -{ - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_dhcps_stop_api); - - /* only support ap now */ - if (tcpip_if != TCPIP_ADAPTER_IF_AP || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - ESP_LOGD(TAG, "dhcp server invalid if=%d", tcpip_if); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (dhcps_status == TCPIP_ADAPTER_DHCP_STARTED) { - struct netif *p_netif = esp_netif[tcpip_if]; - - if (p_netif != NULL) { - dhcps_stop(p_netif); - } else { - ESP_LOGD(TAG, "dhcp server if not ready"); - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; - } - } else if (dhcps_status == TCPIP_ADAPTER_DHCP_STOPPED) { - ESP_LOGD(TAG, "dhcp server already stoped"); - return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED; - } - - ESP_LOGD(TAG, "dhcp server stop successfully"); - dhcps_status = TCPIP_ADAPTER_DHCP_STOPPED; - return ESP_OK; -} - -static esp_err_t tcpip_adapter_dhcps_stop_api(tcpip_adapter_api_msg_t *msg) -{ - return tcpip_adapter_dhcps_stop(msg->tcpip_if); -} - -esp_err_t tcpip_adapter_dhcpc_option(tcpip_adapter_dhcp_option_mode_t opt_op, tcpip_adapter_dhcp_option_id_t opt_id, void *opt_val, uint32_t opt_len) -{ - // TODO: when dhcp request timeout,change the retry count - return ESP_ERR_NOT_SUPPORTED; -} - -static void tcpip_adapter_dhcpc_cb(struct netif *netif) -{ - tcpip_adapter_ip_info_t *ip_info_old = NULL; - tcpip_adapter_ip_info_t *ip_info = NULL; - tcpip_adapter_if_t tcpip_if; - - if (!netif) { - ESP_LOGD(TAG, "null netif=%p", netif); - return; - } - - if ( netif == esp_netif[TCPIP_ADAPTER_IF_STA] ) { - tcpip_if = TCPIP_ADAPTER_IF_STA; - } else if (netif == esp_netif[TCPIP_ADAPTER_IF_ETH] ) { - tcpip_if = TCPIP_ADAPTER_IF_ETH; - } else { - ESP_LOGD(TAG, "err netif=%p", netif); - return; - } - - ESP_LOGD(TAG, "if%d dhcpc cb", tcpip_if); - ip_info = &esp_ip[tcpip_if]; - ip_info_old = &esp_ip_old[tcpip_if]; - - if ( !ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), IP4_ADDR_ANY4) ) { - - //check whether IP is changed - if ( !ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), (&ip_info->ip)) || - !ip4_addr_cmp(ip_2_ip4(&netif->netmask), (&ip_info->netmask)) || - !ip4_addr_cmp(ip_2_ip4(&netif->gw), (&ip_info->gw)) ) { - ip_event_got_ip_t evt; - ip_event_t evt_id; - int ret; - - memset(&evt, 0, sizeof(ip_event_got_ip_t)); - - ip4_addr_set(&ip_info->ip, ip_2_ip4(&netif->ip_addr)); - ip4_addr_set(&ip_info->netmask, ip_2_ip4(&netif->netmask)); - ip4_addr_set(&ip_info->gw, ip_2_ip4(&netif->gw)); - - //notify event - evt.if_index = tcpip_if; - if (tcpip_if == TCPIP_ADAPTER_IF_ETH) { - evt_id = IP_EVENT_ETH_GOT_IP; - evt.ip_changed = true; - } else { - evt_id = IP_EVENT_STA_GOT_IP; - evt.ip_changed = false; - } - - if (memcmp(ip_info, ip_info_old, sizeof(tcpip_adapter_ip_info_t))) { - evt.ip_changed = true; - } - - memcpy(&evt.ip_info, ip_info, sizeof(tcpip_adapter_ip_info_t)); - memcpy(ip_info_old, ip_info, sizeof(tcpip_adapter_ip_info_t)); - ESP_LOGD(TAG, "if%d ip changed=%d", tcpip_if, evt.ip_changed); - ret = esp_event_send_internal(IP_EVENT, evt_id, &evt, sizeof(evt), 0); - if (ESP_OK != ret) { - ESP_LOGE(TAG, "dhcpc cb: failed to post got ip event (%x)", ret); - } - } else { - ESP_LOGD(TAG, "if%d ip unchanged", tcpip_if); - } - } else { - if (!ip4_addr_cmp(&ip_info->ip, IP4_ADDR_ANY4)) { - tcpip_adapter_start_ip_lost_timer(tcpip_if); - } - } - - return; -} - -static esp_err_t tcpip_adapter_start_ip_lost_timer(tcpip_adapter_if_t tcpip_if) -{ - tcpip_adapter_ip_info_t *ip_info_old = &esp_ip_old[tcpip_if]; - struct netif *netif = esp_netif[tcpip_if]; - - ESP_LOGD(TAG, "if%d start ip lost tmr: enter", tcpip_if); - if (tcpip_if != TCPIP_ADAPTER_IF_STA) { - ESP_LOGD(TAG, "if%d start ip lost tmr: only sta support ip lost timer", tcpip_if); - return ESP_OK; - } - - if (esp_ip_lost_timer[tcpip_if].timer_running) { - ESP_LOGD(TAG, "if%d start ip lost tmr: already started", tcpip_if); - return ESP_OK; - } - - if ( netif && (CONFIG_NETIF_IP_LOST_TIMER_INTERVAL > 0) && !ip4_addr_isany_val(ip_info_old->ip)) { - esp_ip_lost_timer[tcpip_if].timer_running = true; - sys_timeout(CONFIG_NETIF_IP_LOST_TIMER_INTERVAL * 1000, tcpip_adapter_ip_lost_timer, (void *)tcpip_if); - ESP_LOGD(TAG, "if%d start ip lost tmr: interval=%d", tcpip_if, CONFIG_NETIF_IP_LOST_TIMER_INTERVAL); - return ESP_OK; - } - - ESP_LOGD(TAG, "if%d start ip lost tmr: no need start because netif=%p interval=%d ip=%x", - tcpip_if, netif, CONFIG_NETIF_IP_LOST_TIMER_INTERVAL, ip_info_old->ip.addr); - - return ESP_OK; -} - -static void tcpip_adapter_ip_lost_timer(void *arg) -{ - tcpip_adapter_if_t tcpip_if = (tcpip_adapter_if_t)arg; - - ESP_LOGD(TAG, "if%d ip lost tmr: enter", tcpip_if); - esp_ip_lost_timer[tcpip_if].timer_running = false; - - if (tcpip_if == TCPIP_ADAPTER_IF_STA) { - struct netif *netif = esp_netif[tcpip_if]; - - if ( (!netif) || (netif && ip4_addr_cmp(ip_2_ip4(&netif->ip_addr), IP4_ADDR_ANY4))) { - ip_event_got_ip_t evt; - int ret; - memset(&evt, 0, sizeof(ip_event_got_ip_t)); - - ESP_LOGD(TAG, "if%d ip lost tmr: raise ip lost event", tcpip_if); - evt.if_index = tcpip_if; - memset(&esp_ip_old[tcpip_if], 0, sizeof(tcpip_adapter_ip_info_t)); - ret = esp_event_send_internal(IP_EVENT, IP_EVENT_STA_LOST_IP, &evt, sizeof(evt), 0); - if (ESP_OK != ret) { - ESP_LOGE(TAG, "ip lost timer: failed to post lost ip event (%x)", ret); - } - } else { - ESP_LOGD(TAG, "if%d ip lost tmr: no need raise ip lost event", tcpip_if); - } - } else { - ESP_LOGD(TAG, "if%d ip lost tmr: not station", tcpip_if); - } -} - -esp_err_t tcpip_adapter_dhcpc_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status) -{ - *status = dhcpc_status[tcpip_if]; - - return ESP_OK; -} - -esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if) -{ - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_dhcpc_start_api); - - if ((tcpip_if != TCPIP_ADAPTER_IF_STA && tcpip_if != TCPIP_ADAPTER_IF_ETH) || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - ESP_LOGD(TAG, "dhcp client invalid if=%d", tcpip_if); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (dhcpc_status[tcpip_if] != TCPIP_ADAPTER_DHCP_STARTED) { - struct netif *p_netif = esp_netif[tcpip_if]; - - tcpip_adapter_reset_ip_info(tcpip_if); -#if LWIP_DNS - dns_clear_servers(true); -#endif - - if (p_netif != NULL) { - if (netif_is_up(p_netif)) { - ESP_LOGD(TAG, "dhcp client init ip/mask/gw to all-0"); - ip_addr_set_zero(&p_netif->ip_addr); - ip_addr_set_zero(&p_netif->netmask); - ip_addr_set_zero(&p_netif->gw); - tcpip_adapter_start_ip_lost_timer(tcpip_if); - } else { - ESP_LOGD(TAG, "dhcp client re init"); - dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; - return ESP_OK; - } - - if (dhcp_start(p_netif) != ERR_OK) { - ESP_LOGD(TAG, "dhcp client start failed"); - return ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED; - } - - dhcp_set_cb(p_netif, tcpip_adapter_dhcpc_cb); - - ESP_LOGD(TAG, "dhcp client start successfully"); - dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_STARTED; - return ESP_OK; - } else { - ESP_LOGD(TAG, "dhcp client re init"); - dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_INIT; - return ESP_OK; - } - } - - ESP_LOGD(TAG, "dhcp client already started"); - return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED; -} - -static esp_err_t tcpip_adapter_dhcpc_start_api(tcpip_adapter_api_msg_t *msg) -{ - return tcpip_adapter_dhcpc_start(msg->tcpip_if); -} - -esp_err_t tcpip_adapter_dhcpc_stop(tcpip_adapter_if_t tcpip_if) -{ - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, 0, tcpip_adapter_dhcpc_stop_api); - - if ((tcpip_if != TCPIP_ADAPTER_IF_STA && tcpip_if != TCPIP_ADAPTER_IF_ETH) || tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - ESP_LOGD(TAG, "dhcp client invalid if=%d", tcpip_if); - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (dhcpc_status[tcpip_if] == TCPIP_ADAPTER_DHCP_STARTED) { - struct netif *p_netif = esp_netif[tcpip_if]; - - if (p_netif != NULL) { - dhcp_stop(p_netif); - tcpip_adapter_reset_ip_info(tcpip_if); - tcpip_adapter_start_ip_lost_timer(tcpip_if); - } else { - ESP_LOGD(TAG, "dhcp client if not ready"); - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; - } - } else if (dhcpc_status[tcpip_if] == TCPIP_ADAPTER_DHCP_STOPPED) { - ESP_LOGD(TAG, "dhcp client already stoped"); - return ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED; - } - - ESP_LOGD(TAG, "dhcp client stop successfully"); - dhcpc_status[tcpip_if] = TCPIP_ADAPTER_DHCP_STOPPED; - - LWIP_DHCP_IP_ADDR_ERASE(); - - return ESP_OK; -} - -static esp_err_t tcpip_adapter_dhcpc_stop_api(tcpip_adapter_api_msg_t *msg) -{ - return tcpip_adapter_dhcpc_stop(msg->tcpip_if); -} - -esp_err_t tcpip_adapter_eth_input(void *buffer, uint16_t len, void *eb) -{ -#ifdef CONFIG_ETH_ENABLED - ethernetif_input(esp_netif[TCPIP_ADAPTER_IF_ETH], buffer, len); - return ESP_OK; -#else - return ESP_ERR_NOT_SUPPORTED; -#endif -} - -esp_err_t tcpip_adapter_sta_input(void *buffer, uint16_t len, void *eb) -{ - wlanif_input(esp_netif[TCPIP_ADAPTER_IF_STA], buffer, len, eb); - return ESP_OK; -} - -esp_err_t tcpip_adapter_ap_input(void *buffer, uint16_t len, void *eb) -{ - wlanif_input(esp_netif[TCPIP_ADAPTER_IF_AP], buffer, len, eb); - return ESP_OK; -} - -#if 0 -bool tcpip_dep_output(wifi_interface_t wifi_if, void *buffer, uint16_t len) -{ - - return true; -} -#endif - -esp_interface_t tcpip_adapter_get_esp_if(void *dev) -{ - struct netif *p_netif = (struct netif *)dev; - - if (p_netif == esp_netif[TCPIP_ADAPTER_IF_STA]) { - return ESP_IF_WIFI_STA; - } else if (p_netif == esp_netif[TCPIP_ADAPTER_IF_AP]) { - return ESP_IF_WIFI_AP; - } else if (p_netif == esp_netif[TCPIP_ADAPTER_IF_ETH]) { - return ESP_IF_ETH; - } - - return ESP_IF_MAX; -} - -esp_err_t tcpip_adapter_get_sta_list(const wifi_sta_list_t *wifi_sta_list, tcpip_adapter_sta_list_t *tcpip_sta_list) -{ - int i; - - if ((wifi_sta_list == NULL) || (tcpip_sta_list == NULL)) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - memset(tcpip_sta_list, 0, sizeof(tcpip_adapter_sta_list_t)); - tcpip_sta_list->num = wifi_sta_list->num; - for (i = 0; i < wifi_sta_list->num; i++) { - memcpy(tcpip_sta_list->sta[i].mac, wifi_sta_list->sta[i].mac, 6); - dhcp_search_ip_on_mac(tcpip_sta_list->sta[i].mac, &tcpip_sta_list->sta[i].ip); - } - - return ESP_OK; -} - -esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname) -{ -#if LWIP_NETIF_HOSTNAME - TCPIP_ADAPTER_IPC_CALL(tcpip_if, 0, 0, hostname, tcpip_adapter_set_hostname_api); - struct netif *p_netif; - static char hostinfo[TCPIP_ADAPTER_IF_MAX][TCPIP_HOSTNAME_MAX_SIZE + 1]; - - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || hostname == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - if (strlen(hostname) > TCPIP_HOSTNAME_MAX_SIZE) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - p_netif = esp_netif[tcpip_if]; - if (p_netif != NULL) { - memset(hostinfo[tcpip_if], 0, sizeof(hostinfo[tcpip_if])); - strlcpy(hostinfo[tcpip_if], hostname, sizeof(hostinfo[tcpip_if])); - p_netif->hostname = hostinfo[tcpip_if]; - return ESP_OK; - } else { - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; - } -#else - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; -#endif -} - -static esp_err_t tcpip_adapter_set_hostname_api(tcpip_adapter_api_msg_t *msg) -{ - const char *hostname = (char *) msg->data; - - return tcpip_adapter_set_hostname(msg->tcpip_if, hostname); -} - -esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char **hostname) -{ -#if LWIP_NETIF_HOSTNAME - struct netif *p_netif = NULL; - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || hostname == NULL) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - p_netif = esp_netif[tcpip_if]; - if (p_netif != NULL) { - *hostname = p_netif->hostname; - return ESP_OK; - } else { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } -#else - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; -#endif -} - -static esp_err_t tcpip_adapter_reset_ip_info(tcpip_adapter_if_t tcpip_if) -{ - ip4_addr_set_zero(&esp_ip[tcpip_if].ip); - ip4_addr_set_zero(&esp_ip[tcpip_if].gw); - ip4_addr_set_zero(&esp_ip[tcpip_if].netmask); - return ESP_OK; -} - -esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void **netif) -{ - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) { - return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS; - } - - *netif = esp_netif[tcpip_if]; - - if (*netif == NULL) { - return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY; - } - return ESP_OK; -} - -bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if) -{ - if (esp_netif[tcpip_if] != NULL && netif_is_up(esp_netif[tcpip_if])) { - return true; - } else { - return false; - } -} - -int tcpip_adapter_get_netif_index(tcpip_adapter_if_t tcpip_if) -{ - if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || esp_netif[tcpip_if] == NULL) { - return -1; - } - return netif_get_index(esp_netif[tcpip_if]); -} - -#endif /* CONFIG_TCPIP_LWIP */ diff --git a/components/wifi_provisioning/src/handlers.c b/components/wifi_provisioning/src/handlers.c index a53c9d6e4..66f138a27 100644 --- a/components/wifi_provisioning/src/handlers.c +++ b/components/wifi_provisioning/src/handlers.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include "wifi_provisioning/wifi_config.h" #include "wifi_provisioning/wifi_scan.h" @@ -64,10 +64,10 @@ static esp_err_t get_status_handler(wifi_prov_config_get_data_t *resp_data, wifi ESP_LOGD(TAG, "Got state : connected"); /* IP Addr assigned to STA */ - tcpip_adapter_ip_info_t ip_info; - tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info); - char *ip_addr = ip4addr_ntoa(&ip_info.ip); - strcpy(resp_data->conn_info.ip_addr, ip_addr); + esp_netif_ip_info_t ip_info; + esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip_info); + esp_ip4addr_ntoa(&ip_info.ip, resp_data->conn_info.ip_addr, sizeof(resp_data->conn_info.ip_addr)); + /* AP information to which STA is connected */ wifi_ap_record_t ap_info; diff --git a/examples/system/network_tests/main/CMakeLists.txt b/examples/system/network_tests/main/CMakeLists.txt index f379bf03a..db11fd053 100644 --- a/examples/system/network_tests/main/CMakeLists.txt +++ b/examples/system/network_tests/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "net_suite.c" +idf_component_register(SRCS "net_suite.c" "lwip_test_netif.c" INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/system/network_tests/main/lwip_test_netif.c b/examples/system/network_tests/main/lwip_test_netif.c new file mode 100644 index 000000000..0efbbbf2e --- /dev/null +++ b/examples/system/network_tests/main/lwip_test_netif.c @@ -0,0 +1,125 @@ +/* Net-suite test code: lwip netif API for creating test interface + + 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 "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/ethip6.h" +#include "netif/etharp.h" +#include "netif/wlanif.h" + +#include "esp_netif.h" + +#include +#include + +static struct netif *g_last_netif = NULL; + +// LWIP netif specific defines +struct esp_netif_netstack_config { + esp_netif_netstack_base_config_t base; + err_t (*init_fn)(struct netif*); + void (*input_fn)(struct netif *netif, void *buffer, size_t len, void *eb); +}; + +err_t testnetif_init(struct netif *netif); + +void testnetif_input(struct netif *netif, void *buffer, size_t len, void *eb); + +const struct esp_netif_netstack_config _g_test_netif_stack_config = { { ESP_NETIF_NETWORK_STACK_IS_LWIP }, testnetif_init, testnetif_input}; + + +err_t testnetif_output(struct netif *netif, struct pbuf *p) +{ + int i; + char *dat = p->payload; + + /* output the packet to stdout */ + printf("\nPacketOut:["); + for (i=0; ilen; i++) { + printf("%02x", *dat++); + } + printf("]\n"); + + return ERR_OK; +} + + +err_t testnetif_init(struct netif *netif) +{ + + g_last_netif = netif; + + netif->hostname = CONFIG_LWIP_LOCAL_HOSTNAME; + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100); + + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = testnetif_output; + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + +#if ESP_LWIP + #if LWIP_IGMP + netif->flags |= NETIF_FLAG_IGMP; +#endif +#endif + return ERR_OK; + +} + +void testnetif_input(struct netif *netif, void *buffer, size_t len, void *eb) +{ + struct pbuf *p; + if (g_last_netif == NULL) { + printf("error!"); + return; + } + + printf("simul in: %d\n", len); + if (len==0) return; + + p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM); + p->l2_owner = NULL; + memcpy(p->payload, buffer, len); + + /* full packet send to tcpip_thread to process + * on success - the packet is processed and deallocated in tcpip stack + * on failure - log error and deallocate the packet + */ + if (g_last_netif->input(p, g_last_netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + } + +} diff --git a/examples/system/network_tests/main/net_suite.c b/examples/system/network_tests/main/net_suite.c index d474dda5a..09bb03723 100644 --- a/examples/system/network_tests/main/net_suite.c +++ b/examples/system/network_tests/main/net_suite.c @@ -25,7 +25,8 @@ #include "lwip/debug.h" #include "lwip/stats.h" #include "lwip/tcp.h" -void nettestif_input(void *buffer, u16_t len); + +extern const struct esp_netif_netstack_config _g_test_netif_stack_config; /* these data configures ARP cache so the test IPs are knows */ static char arp1[] = { @@ -135,21 +136,39 @@ void app_main(void) { char packet[128]; - tcpip_adapter_ip_info_t ip_info; + // Netif configs + // + esp_netif_ip_info_t ip_info; + uint8_t mac[] = { 0,0,0,0,0,1}; + esp_netif_inherent_config_t netif_common_config = { + .flags = ESP_NETIF_FLAG_AUTOUP, + .ip_info = (esp_netif_ip_info_t*)&ip_info, + }; + esp_netif_set_ip4_addr(&ip_info.ip, 10, 0 , 0, 1); + esp_netif_set_ip4_addr(&ip_info.gw, 10, 0 , 0, 1); + esp_netif_set_ip4_addr(&ip_info.netmask, 255, 255 , 255, 0); - uint8_t ap_mac[6] = { 0,0,0,0,0,1}; - IP4_ADDR(&ip_info.ip, 10, 0 , 0, 1); - IP4_ADDR(&ip_info.gw, 10, 0 , 0, 1); - IP4_ADDR(&ip_info.netmask, 255, 255 , 255, 0); + esp_netif_config_t config = { + .base = &netif_common_config, + .stack = &_g_test_netif_stack_config, + .driver = NULL + }; - tcpip_adapter_init(); + // Netif creation and configure + // + esp_netif_init(); + esp_netif_t* netif = esp_netif_new(&config); + assert(netif); - tcpip_adapter_test_start(ap_mac, &ip_info); + // Start the netif in a manual way, no need for events + // + esp_netif_set_mac(netif, mac); + esp_netif_action_start(netif, NULL, 0, NULL); // initializes TCP endpoint on DUT per https://github.com/intel/net-test-suites#21-endpoints test_tcp_init(); // Inject ARP packet to let the network stack know about IP/MAC of the counterpart - nettestif_input(arp1, sizeof(arp1)); + esp_netif_receive(netif, arp1, sizeof(arp1), NULL); // Initialize VFS & UART so we can use std::cout/cin setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); @@ -173,7 +192,8 @@ void app_main(void) size = process_line(line, packet); - nettestif_input(packet, size); + esp_netif_receive(netif, packet, size, NULL); + linenoiseFree(line); }