esp-netif: Support non-lwip mode, add test

It is required to define a mandatory dependency on lwip, so we
introduced esp_netif_stack component and made it require lwip, instead
of directly depending on lwip.
This enables building w-out lwip and support other TCP/IP stacks.
This commit is contained in:
David Cermak 2022-09-26 13:22:20 +02:00 committed by David Čermák
parent 678d7aadd9
commit 38dec0be48
16 changed files with 107 additions and 35 deletions

View File

@ -92,6 +92,7 @@
/components/esp_lcd/ @esp-idf-codeowners/peripherals /components/esp_lcd/ @esp-idf-codeowners/peripherals
/components/esp_local_ctrl/ @esp-idf-codeowners/app-utilities /components/esp_local_ctrl/ @esp-idf-codeowners/app-utilities
/components/esp_netif/ @esp-idf-codeowners/network /components/esp_netif/ @esp-idf-codeowners/network
/components/esp_netif_stack/ @esp-idf-codeowners/network
/components/esp_partition/ @esp-idf-codeowners/storage /components/esp_partition/ @esp-idf-codeowners/storage
/components/esp_phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154 /components/esp_phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
/components/esp_pm/ @esp-idf-codeowners/power-management @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi /components/esp_pm/ @esp-idf-codeowners/power-management @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi

View File

@ -6,48 +6,52 @@ if(${target} STREQUAL "linux")
return() return()
endif() endif()
set(srcs_lwip
"lwip/esp_netif_lwip.c"
"lwip/esp_netif_lwip_defaults.c"
"lwip/netif/wlanif.c"
"lwip/netif/ethernetif.c"
"lwip/netif/esp_pbuf_ref.c")
set(srcs set(srcs
"esp_netif_handlers.c" "esp_netif_handlers.c"
"esp_netif_objects.c" "esp_netif_objects.c"
"esp_netif_defaults.c" "esp_netif_defaults.c")
"lwip/esp_netif_lwip.c"
"lwip/esp_netif_lwip_defaults.c"
"lwip/netif/wlanif.c"
"lwip/netif/ethernetif.c"
"lwip/netif/esp_pbuf_ref.c" )
set(include_dirs "include") set(include_dirs "include")
set(priv_include_dirs "lwip" "private_include") set(priv_include_dirs "private_include")
if(CONFIG_PPP_SUPPORT) if(CONFIG_PPP_SUPPORT)
list(APPEND srcs list(APPEND srcs_lwip lwip/esp_netif_lwip_ppp.c)
"lwip/esp_netif_lwip_ppp.c")
endif() endif()
if(CONFIG_LWIP_NETIF_LOOPBACK)
list(APPEND srcs
"loopback/esp_netif_loopback.c")
endif()
if(CONFIG_ESP_NETIF_L2_TAP) if(CONFIG_ESP_NETIF_L2_TAP)
list(APPEND srcs list(APPEND srcs vfs_l2tap/esp_vfs_l2tap.c)
"vfs_l2tap/esp_vfs_l2tap.c")
endif() endif()
if(CONFIG_ESP_NETIF_BRIDGE_EN) if(CONFIG_ESP_NETIF_BRIDGE_EN)
list(APPEND srcs list(APPEND srcs_lwip lwip/esp_netif_br_glue.c)
"lwip/esp_netif_br_glue.c") endif()
if(CONFIG_ESP_NETIF_LOOPBACK)
list(APPEND srcs loopback/esp_netif_loopback.c)
elseif(CONFIG_ESP_NETIF_TCPIP_LWIP)
list(APPEND srcs ${srcs_lwip})
list(APPEND priv_include_dirs lwip)
endif() endif()
idf_component_register(SRCS "${srcs}" idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}" INCLUDE_DIRS "${include_dirs}"
PRIV_INCLUDE_DIRS "${priv_include_dirs}" PRIV_INCLUDE_DIRS "${priv_include_dirs}"
REQUIRES esp_event REQUIRES esp_event
PRIV_REQUIRES lwip PRIV_REQUIRES esp_netif_stack
LDFRAGMENTS linker.lf) LDFRAGMENTS linker.lf)
if(CONFIG_ESP_NETIF_L2_TAP OR CONFIG_ESP_NETIF_BRIDGE_EN) if(CONFIG_ESP_NETIF_L2_TAP OR CONFIG_ESP_NETIF_BRIDGE_EN)
idf_component_optional_requires(PRIVATE esp_eth vfs) idf_component_optional_requires(PRIVATE esp_eth vfs)
endif() endif()
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")

View File

@ -5,7 +5,6 @@
*/ */
#include "esp_netif.h" #include "esp_netif.h"
#include "lwip/esp_netif_net_stack.h"
// //
// Purpose of this module is to provide // Purpose of this module is to provide
@ -31,4 +30,6 @@ const esp_netif_inherent_config_t _g_esp_netif_inherent_ap_config = ESP_NETIF_IN
const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config = ESP_NETIF_INHERENT_DEFAULT_ETH(); const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
#ifdef CONFIG_PPP_SUPPORT
const esp_netif_inherent_config_t _g_esp_netif_inherent_ppp_config = ESP_NETIF_INHERENT_DEFAULT_PPP(); const esp_netif_inherent_config_t _g_esp_netif_inherent_ppp_config = ESP_NETIF_INHERENT_DEFAULT_PPP();
#endif

View File

@ -17,8 +17,8 @@ extern "C" {
// Macros to assemble master configs with partial configs from netif, stack and driver // Macros to assemble master configs with partial configs from netif, stack and driver
// //
#ifdef CONFIG_LWIP_ESP_GRATUITOUS_ARP
// If GARP enabled in menuconfig (default), make it also a default config for common netifs // If GARP enabled in menuconfig (default), make it also a default config for common netifs
#ifdef CONFIG_LWIP_ESP_GRATUITOUS_ARP
#define ESP_NETIF_DEFAULT_ARP_FLAGS (ESP_NETIF_FLAG_GARP) #define ESP_NETIF_DEFAULT_ARP_FLAGS (ESP_NETIF_FLAG_GARP)
#else #else
#define ESP_NETIF_DEFAULT_ARP_FLAGS (0) #define ESP_NETIF_DEFAULT_ARP_FLAGS (0)
@ -65,6 +65,7 @@ extern "C" {
.bridge_info = NULL \ .bridge_info = NULL \
} }
#ifdef CONFIG_PPP_SUPPORT
#define ESP_NETIF_INHERENT_DEFAULT_PPP() \ #define ESP_NETIF_INHERENT_DEFAULT_PPP() \
{ \ { \
.flags = ESP_NETIF_FLAG_IS_PPP, \ .flags = ESP_NETIF_FLAG_IS_PPP, \
@ -77,6 +78,7 @@ extern "C" {
.route_prio = 20, \ .route_prio = 20, \
.bridge_info = NULL \ .bridge_info = NULL \
} }
#endif /* CONFIG_PPP_SUPPORT */
@ -126,6 +128,7 @@ extern "C" {
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA, \ .stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA, \
} }
#ifdef CONFIG_PPP_SUPPORT
/** /**
* @brief Default configuration reference of PPP client * @brief Default configuration reference of PPP client
*/ */
@ -135,6 +138,7 @@ extern "C" {
.driver = NULL, \ .driver = NULL, \
.stack = ESP_NETIF_NETSTACK_DEFAULT_PPP, \ .stack = ESP_NETIF_NETSTACK_DEFAULT_PPP, \
} }
#endif /* CONFIG_PPP_SUPPORT */
/** /**
* @brief Default base config (esp-netif inherent) of WIFI STA * @brief Default base config (esp-netif inherent) of WIFI STA
@ -153,10 +157,12 @@ extern "C" {
*/ */
#define ESP_NETIF_BASE_DEFAULT_ETH &_g_esp_netif_inherent_eth_config #define ESP_NETIF_BASE_DEFAULT_ETH &_g_esp_netif_inherent_eth_config
#ifdef CONFIG_PPP_SUPPORT
/** /**
* @brief Default base config (esp-netif inherent) of ppp interface * @brief Default base config (esp-netif inherent) of ppp interface
*/ */
#define ESP_NETIF_BASE_DEFAULT_PPP &_g_esp_netif_inherent_ppp_config #define ESP_NETIF_BASE_DEFAULT_PPP &_g_esp_netif_inherent_ppp_config
#endif
#define ESP_NETIF_NETSTACK_DEFAULT_ETH _g_esp_netif_netstack_default_eth #define ESP_NETIF_NETSTACK_DEFAULT_ETH _g_esp_netif_netstack_default_eth
@ -165,7 +171,9 @@ extern "C" {
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
#define ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP _g_esp_netif_netstack_default_wifi_ap #define ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP _g_esp_netif_netstack_default_wifi_ap
#endif #endif
#ifdef CONFIG_PPP_SUPPORT
#define ESP_NETIF_NETSTACK_DEFAULT_PPP _g_esp_netif_netstack_default_ppp #define ESP_NETIF_NETSTACK_DEFAULT_PPP _g_esp_netif_netstack_default_ppp
#endif
// //
// Include default network stacks configs // Include default network stacks configs
@ -179,8 +187,9 @@ extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap; extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap;
#endif #endif
#ifdef CONFIG_PPP_SUPPORT
extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_ppp; extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_ppp;
#endif
// //
// Include default common configs inherent to esp-netif // Include default common configs inherent to esp-netif
// - These inherent configs are defined in esp_netif_defaults.c and describe // - These inherent configs are defined in esp_netif_defaults.c and describe
@ -191,8 +200,9 @@ 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_ap_config;
#endif #endif
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config; extern const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config;
#ifdef CONFIG_PPP_SUPPORT
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_ppp_config; extern const esp_netif_inherent_config_t _g_esp_netif_inherent_ppp_config;
#endif
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
extern const esp_netif_ip_info_t _g_esp_netif_soft_ap_ip; extern const esp_netif_ip_info_t _g_esp_netif_soft_ap_ip;
#endif #endif

View File

@ -0,0 +1 @@
idf_component_register(REQUIRES lwip)

View File

@ -0,0 +1,20 @@
# ESP-NETIF stack component
This component is a direct dependency of ESP-NETIF and it defines a required dependency on lwIP.
## Purpose
Purpose of this component is to pull specific TCP/IP stack (lwIP) into the list of dependencies when using component ESP-NETIF.
By means of `esp_netif_stack` component, we can define these two
dependency scenarios:
1) Defines a required dependency on lwIP via this component (default)
2) In case a non-lwip build is required.
## Configure ESP-NETIF for building without lwIP
In order to use ESP-NETIF without lwIP (e.g. when using custom TCP/IP stack), follow these steps
* unselect `CONFIG_ESP_NETIF_TCPIP_LWIP` in `esp_netif` component configuration
* add a component `esp_netif_stack` to your private component paths
* register an empty component `idf_component_register()` in the component's CMakeLists.txt

View File

@ -8,6 +8,8 @@ The purpose of ESP-NETIF library is twofold:
ESP-IDF currently implements ESP-NETIF for the lwIP TCP/IP stack only. However, the adapter itself is TCP/IP implementation agnostic and different implementations are possible. ESP-IDF currently implements ESP-NETIF for the lwIP TCP/IP stack only. However, the adapter itself is TCP/IP implementation agnostic and different implementations are possible.
It is also possible to use a custom TCP/IP stack with ESP-IDF, provided it implements BSD API. For more information on building ESP-IDF without lwIP, please refer to :idf_file:`components/esp_netif_stack/README.md`.
Some ESP-NETIF API functions are intended to be called by application code, for example to get/set interface IP addresses, configure DHCP. Other functions are intended for internal ESP-IDF use by the network driver layer. Some ESP-NETIF API functions are intended to be called by application code, for example to get/set interface IP addresses, configure DHCP. Other functions are intended for internal ESP-IDF use by the network driver layer.
In many cases, applications do not need to call ESP-NETIF APIs directly as they are called from the default network event handlers. In many cases, applications do not need to call ESP-NETIF APIs directly as they are called from the default network event handlers.

View File

@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <sys/time.h> #include <sys/time.h>
#include <netdb.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/event_groups.h" #include "freertos/event_groups.h"

View File

@ -46,10 +46,12 @@ static void test_wifi_init_custom(void)
s_init_wifi_netif(&esp_netif_config); s_init_wifi_netif(&esp_netif_config);
} }
#ifdef CONFIG_PPP_SUPPORT
{ {
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_PPP(); esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_PPP();
s_init_wifi_netif(&esp_netif_config); s_init_wifi_netif(&esp_netif_config);
} }
#endif
} }
static void test_common_init_field(void) static void test_common_init_field(void)

View File

@ -45,10 +45,12 @@ static void test_wifi_init_custom(void)
s_init_wifi_netif(esp_netif_config); s_init_wifi_netif(esp_netif_config);
} }
#ifdef CONFIG_PPP_SUPPORT
{ {
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_PPP(); esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_PPP();
s_init_wifi_netif(esp_netif_config); s_init_wifi_netif(esp_netif_config);
} }
#endif
} }
static void test_common_init_field(void) static void test_common_init_field(void)

View File

@ -0,0 +1 @@
CONFIG_LWIP_PPP_SUPPORT=y

View File

@ -6,30 +6,48 @@ cmake_minimum_required(VERSION 3.16)
set(driver_components esp_eth esp_wifi openthread) set(driver_components esp_eth esp_wifi openthread)
# General rules for all these tests
# * No optional dependencies
# * Forbidden dependencies are only driver components
set(forbidden_deps ${driver_components})
set(optional_deps)
# Check manually if the ESP_NETIF is configured in sdkconfig # Check manually if the ESP_NETIF is configured in sdkconfig
# Note that we cannot use Kconfig values at this stage, and therefore we have to parse
# the sdkconfig manually for the relevant "config" (CONFIG_TESTAPP_COMPONENT_...),
# in case the sdkconfig doesn't exist (clean build), we choose the default.
message(STATUS "Checking if sdkconfig contains CONFIG_TESTAPP_COMPONENT related config:") message(STATUS "Checking if sdkconfig contains CONFIG_TESTAPP_COMPONENT related config:")
set(config_file "${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig") set(config_file "${CMAKE_CURRENT_SOURCE_DIR}/sdkconfig")
if(EXISTS ${config_file}) if(EXISTS ${config_file})
# If the config file exists, check for the non-default settings - LWIP # If the config file exists, check for the non-default settings - LWIP or ESP-NETIF-without-LWIP
# otherwise (file missing or defalut settings) go with ESP_NETIF # otherwise (file missing or defalut settings) go with ESP_NETIF
file(READ ${config_file} config_file_content) file(READ ${config_file} config_file_content)
string(FIND "${config_file_content}" "CONFIG_TESTAPP_COMPONENT_LWIP=y" match) string(FIND "${config_file_content}" "CONFIG_TESTAPP_COMPONENT_LWIP=y" match_lwip)
if(NOT ${match} EQUAL -1) string(FIND "${config_file_content}" "CONFIG_TESTAPP_COMPONENT_ESP_NETIF_WITHOUT_LWIP=y" match_netif_no_lwip)
set(CONFIG_IS_LWIP 1) if(NOT ${match_lwip} EQUAL -1)
set(CHECK_DEPS_FOR_LWIP 1)
elseif(NOT ${match_netif_no_lwip} EQUAL -1)
set(CHECK_DEPS_FOR_ESP_NETIF_WITHOUT_LWIP 1)
endif() endif()
endif() endif()
if(CONFIG_IS_LWIP) if(CHECK_DEPS_FOR)
message(STATUS "CONFIG_TESTAPP_COMPONENT_ESP_LWIP") message(STATUS "CONFIG_TESTAPP_COMPONENT_LWIP")
set(component_under_test lwip) set(component_under_test lwip)
set(expected_build_components lwip) set(expected_build_components lwip)
elseif(CHECK_DEPS_FOR_ESP_NETIF_WITHOUT_LWIP)
message(STATUS "CONFIG_TESTAPP_COMPONENT_ESP_NETIF_WITHOUT_LWIP")
set(component_under_test esp_netif)
set(expected_build_components esp_netif)
list(APPEND optional_deps mbedtls)
list(APPEND forbidden_deps lwip) # lwip mustn't be pulled in, in "esp-netif without lwip" setup
list(APPEND EXTRA_COMPONENT_DIRS "esp_netif_stack")
else() else()
message(STATUS "CONFIG_TESTAPP_COMPONENT_ESP_NETIF") message(STATUS "CONFIG_TESTAPP_COMPONENT_ESP_NETIF")
set(component_under_test esp_netif) set(component_under_test esp_netif)
set(expected_build_components esp_netif lwip) set(expected_build_components esp_netif lwip)
endif() endif()
set(COMPONENTS ${component_under_test} main) set(COMPONENTS ${component_under_test} main ${optional_deps})
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
@ -45,8 +63,8 @@ foreach(comp ${build_components})
message(STATUS "${comp}") message(STATUS "${comp}")
endforeach() endforeach()
# Check for all driver components, these shall not be included # Check for all the components, these shall not be included
foreach(comp ${driver_components}) foreach(comp ${forbidden_deps})
if(${comp} IN_LIST build_components) if(${comp} IN_LIST build_components)
message(FATAL_ERROR "Component ${comp} shall not be included when building only ${component_under_test}") message(FATAL_ERROR "Component ${comp} shall not be included when building only ${component_under_test}")
else() else()

View File

@ -5,6 +5,8 @@
This test application checks the list of components included into the build when: This test application checks the list of components included into the build when:
* `esp_netif` component is added to the build. * `esp_netif` component is added to the build.
- with default network stack, i.e. `lwip`
- without lwip using empty `esp-netif-stack` component
* `lwip` component is added to the build. * `lwip` component is added to the build.
The test checks that driver components are not included in the build The test checks that driver components are not included in the build
@ -17,12 +19,12 @@ The test checks that driver components are not included in the build
# Troubleshooting # Troubleshooting
If you get a build error in this example, please check there's no dependency from the tested component (either `esp_netif` or `lwip`) to any defined driver component. If you get a build error in this example, please check there's no dependency from the tested component (either `esp_netif` or `lwip`) to any defined component listed in `${forbidden_deps}`, that must not be included.
Please open the project `CMakeLists.txt` to view the expected dependencies and driver's components that must not be included in the list: Please open the project `CMakeLists.txt` to view the expected dependencies and driver's components that must not be included in the list:
* CMake variable `driver_components` contains list of driver's components * CMake variable `forbidden_deps` contains list of components that must not be included.
* CMake variable `expected_build_components` contains list expected dependecies * CMake variable `expected_build_components` contains list expected dependencies
Note that this project creates `component_deps.dot`, a simpified dependecy graph that could be used to display and troubleshoot component dependencies. Note that this project creates `component_deps.dot`, a simplified dependency graph that could be used to display and troubleshoot component dependencies.
Note that this test is executed for one target only in CI (ESP32), but shall work correctly for all IDF supported targets. Note that this test is executed for one target only in CI (ESP32), but shall work correctly for all IDF supported targets.

View File

@ -0,0 +1 @@
idf_component_register()

View File

@ -11,6 +11,10 @@ menu "TestApp Configuration"
config TESTAPP_COMPONENT_LWIP config TESTAPP_COMPONENT_LWIP
bool "lwip" bool "lwip"
config TESTAPP_COMPONENT_ESP_NETIF_WITHOUT_LWIP
bool "esp_netif without lwip"
depends on ESP_NETIF_LOOPBACK
endchoice endchoice
endmenu endmenu

View File

@ -0,0 +1,2 @@
CONFIG_TESTAPP_COMPONENT_ESP_NETIF_WITHOUT_LWIP=y
CONFIG_ESP_NETIF_LOOPBACK=y