Merge branch 'feat/ot_make_esp_netif_glue_optional' into 'master'

feat(openthread): make esp_netif glue optional

See merge request espressif/esp-idf!46986
This commit is contained in:
Shu Chen
2026-04-22 09:09:18 +00:00
12 changed files with 131 additions and 33 deletions
+11 -2
View File
@@ -249,7 +249,7 @@ menu "OpenThread"
config OPENTHREAD_BORDER_ROUTER config OPENTHREAD_BORDER_ROUTER
bool "Enable Border Router" bool "Enable Border Router"
depends on OPENTHREAD_FTD depends on OPENTHREAD_FTD && OPENTHREAD_PLATFORM_NETIF
default n default n
help help
Select this option to enable border router features in OpenThread. Select this option to enable border router features in OpenThread.
@@ -299,7 +299,7 @@ menu "OpenThread"
config OPENTHREAD_DNS64_CLIENT config OPENTHREAD_DNS64_CLIENT
bool "Enable DNS64 Client" bool "Enable DNS64 Client"
depends on LWIP_IPV4 depends on LWIP_IPV4 && OPENTHREAD_PLATFORM_NETIF
select LWIP_HOOK_DNS_EXTERNAL_RESOLVE_SELECT_CUSTOM select LWIP_HOOK_DNS_EXTERNAL_RESOLVE_SELECT_CUSTOM
default n default n
help help
@@ -508,6 +508,15 @@ menu "OpenThread"
failure. failure.
endmenu endmenu
config OPENTHREAD_PLATFORM_NETIF
bool "Enable esp_netif/lwIP glue"
depends on OPENTHREAD_FTD || OPENTHREAD_MTD
default y
help
Enable the default ESP-IDF OpenThread integration which creates an
OpenThread esp_netif, attaches the esp_netif glue, and enables
lwIP-specific DNS/netif handling.
endmenu endmenu
menu "Thread Log" menu "Thread Log"
@@ -454,6 +454,21 @@
#endif #endif
#define OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_MARGIN CONFIG_OPENTHREAD_PARENT_SEARCH_RSS_MARGIN #define OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_MARGIN CONFIG_OPENTHREAD_PARENT_SEARCH_RSS_MARGIN
/**
* @def OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
*
* Define to 1 to enable platform NETIF support.
*
*/
#ifdef OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
#error `OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE` is redefined.
#endif
#ifdef CONFIG_OPENTHREAD_PLATFORM_NETIF
#ifndef OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
#define OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE 1
#endif
#endif
/*----The following options set fixed default values but can be overridden by the user header file.----*/ /*----The following options set fixed default values but can be overridden by the user header file.----*/
#if CONFIG_OPENTHREAD_BORDER_ROUTER #if CONFIG_OPENTHREAD_BORDER_ROUTER
@@ -703,16 +718,6 @@
#define OPENTHREAD_CONFIG_COAP_API_ENABLE 1 #define OPENTHREAD_CONFIG_COAP_API_ENABLE 1
#endif #endif
/**
* @def OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
*
* Define to 1 to enable platform NETIF support.
*
*/
#ifndef OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
#define OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE 1
#endif
/** /**
* @def OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE * @def OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
* *
@@ -245,6 +245,21 @@
#endif #endif
#define OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT #define OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT
/**
* @def OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
*
* Define to 1 to enable platform NETIF support.
*
*/
#ifdef OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
#error `OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE` is redefined.
#endif
#ifdef CONFIG_OPENTHREAD_PLATFORM_NETIF
#ifndef OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
#define OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE 1
#endif
#endif
/*----The following options set fixed default values but can be overridden by the user header file.----*/ /*----The following options set fixed default values but can be overridden by the user header file.----*/
/** /**
@@ -257,16 +272,6 @@
#define OPENTHREAD_CONFIG_COAP_API_ENABLE 1 #define OPENTHREAD_CONFIG_COAP_API_ENABLE 1
#endif #endif
/**
* @def OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
*
* Define to 1 to enable platform NETIF support.
*
*/
#ifndef OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
#define OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE 1
#endif
/** /**
* @def OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT * @def OPENTHREAD_CONFIG_PLATFORM_ASSERT_MANAGEMENT
* *
+3 -2
View File
@@ -182,6 +182,7 @@ esp_err_t esp_openthread_mainloop_exit(void)
esp_err_t esp_openthread_launch_mainloop(void) esp_err_t esp_openthread_launch_mainloop(void)
{ {
ESP_LOGI(OT_PLAT_LOG_TAG, "OpenThread enter mainloop");
esp_openthread_mainloop_context_t mainloop; esp_openthread_mainloop_context_t mainloop;
otInstance *instance = esp_openthread_get_instance(); otInstance *instance = esp_openthread_get_instance();
esp_err_t error = ESP_OK; esp_err_t error = ESP_OK;
@@ -253,7 +254,7 @@ static void ot_task_worker(void *aContext)
// Initialize the OpenThread stack // Initialize the OpenThread stack
ESP_ERROR_CHECK(esp_openthread_init(&(config->platform_config))); ESP_ERROR_CHECK(esp_openthread_init(&(config->platform_config)));
#if CONFIG_OPENTHREAD_FTD || CONFIG_OPENTHREAD_MTD #if CONFIG_OPENTHREAD_PLATFORM_NETIF
esp_netif_t *openthread_netif = esp_netif_new(&(config->netif_config)); esp_netif_t *openthread_netif = esp_netif_new(&(config->netif_config));
assert(openthread_netif != NULL); assert(openthread_netif != NULL);
ESP_ERROR_CHECK(esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(&(config->platform_config)))); ESP_ERROR_CHECK(esp_netif_attach(openthread_netif, esp_openthread_netif_glue_init(&(config->platform_config))));
@@ -285,7 +286,7 @@ static void ot_task_worker(void *aContext)
esp_openthread_cli_console_command_unregister(); esp_openthread_cli_console_command_unregister();
#endif // CONFIG_OPENTHREAD_CLI #endif // CONFIG_OPENTHREAD_CLI
#if CONFIG_OPENTHREAD_FTD || CONFIG_OPENTHREAD_MTD #if CONFIG_OPENTHREAD_PLATFORM_NETIF
// Clean up // Clean up
esp_openthread_netif_glue_deinit(); esp_openthread_netif_glue_deinit();
esp_netif_destroy(openthread_netif); esp_netif_destroy(openthread_netif);
@@ -46,8 +46,6 @@ static esp_openthread_netif_glue_t s_openthread_netif_glue = {
.event_fd = -1, .event_fd = -1,
}; };
ESP_EVENT_DEFINE_BASE(OPENTHREAD_EVENT);
static QueueHandle_t s_packet_queue; static QueueHandle_t s_packet_queue;
static esp_netif_t *s_openthread_netif; static esp_netif_t *s_openthread_netif;
static const char *netif_glue_workflow = "netif_glue"; static const char *netif_glue_workflow = "netif_glue";
@@ -21,6 +21,8 @@
#define TAG "OT_STATE" #define TAG "OT_STATE"
ESP_EVENT_DEFINE_BASE(OPENTHREAD_EVENT);
#if CONFIG_OPENTHREAD_BORDER_ROUTER #if CONFIG_OPENTHREAD_BORDER_ROUTER
static void handle_ot_border_router_state_changed(otInstance* instance) static void handle_ot_border_router_state_changed(otInstance* instance)
{ {
+6
View File
@@ -107,6 +107,12 @@ if(NOT CONFIG_OPENTHREAD_DNS64_CLIENT)
"src/esp_openthread_dns64.c") "src/esp_openthread_dns64.c")
endif() endif()
if(NOT CONFIG_OPENTHREAD_PLATFORM_NETIF)
list(APPEND exclude_srcs
"src/esp_openthread_lwip_netif.c"
"src/esp_openthread_netif_glue.c")
endif()
if(NOT CONFIG_FREERTOS_USE_TICKLESS_IDLE) if(NOT CONFIG_FREERTOS_USE_TICKLESS_IDLE)
list(APPEND exclude_srcs list(APPEND exclude_srcs
"src/port/esp_openthread_sleep.c") "src/port/esp_openthread_sleep.c")
+6 -5
View File
@@ -188,7 +188,7 @@ def getDataset(dut: IdfDut) -> str:
def init_thread(dut: IdfDut) -> None: def init_thread(dut: IdfDut) -> None:
dut.expect('OpenThread attached to netif', timeout=10) dut.expect('OpenThread enter mainloop', timeout=10)
wait(dut, 3) wait(dut, 3)
reset_thread(dut) reset_thread(dut)
@@ -201,16 +201,16 @@ def stop_thread(dut: IdfDut) -> None:
def reset_thread(dut: IdfDut) -> None: def reset_thread(dut: IdfDut) -> None:
execute_command(dut, 'factoryreset') execute_command(dut, 'factoryreset')
dut.expect('OpenThread attached to netif', timeout=20) dut.expect('OpenThread enter mainloop', timeout=20)
wait(dut, 3) wait(dut, 3)
clean_buffer(dut) clean_buffer(dut)
def hardreset_dut(dut: IdfDut) -> None: def hardreset_dut(dut: IdfDut) -> None:
dut.serial.hard_reset() dut.serial.hard_reset()
dut.expect('OpenThread attached to netif', timeout=20) dut.expect('OpenThread enter mainloop', timeout=20)
execute_command(dut, 'factoryreset') execute_command(dut, 'factoryreset')
dut.expect('OpenThread attached to netif', timeout=20) dut.expect('OpenThread enter mainloop', timeout=20)
# get the mleid address of the thread # get the mleid address of the thread
@@ -474,7 +474,8 @@ def check_ipmaddr(dut: IdfDut) -> bool:
def thread_is_joined_group(dut: IdfDut) -> bool: def thread_is_joined_group(dut: IdfDut) -> bool:
command = 'mcast join ' + thread_ipv6_group should_use_mcast = dut.app.sdkconfig.get('OPENTHREAD_PLATFORM_NETIF') is True
command = ('mcast join ' if should_use_mcast else 'ipmaddr add ') + thread_ipv6_group
execute_command(dut, command) execute_command(dut, command)
dut.expect('Done', timeout=5) dut.expect('Done', timeout=5)
order = 0 order = 0
@@ -53,7 +53,9 @@ void app_main(void)
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(esp_event_loop_create_default());
#if CONFIG_OPENTHREAD_PLATFORM_NETIF
ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_netif_init());
#endif
ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config));
#if CONFIG_OPENTHREAD_CLI #if CONFIG_OPENTHREAD_CLI
@@ -62,7 +64,9 @@ void app_main(void)
#endif #endif
static esp_openthread_config_t config = { static esp_openthread_config_t config = {
#if CONFIG_OPENTHREAD_PLATFORM_NETIF
.netif_config = ESP_NETIF_DEFAULT_OPENTHREAD(), .netif_config = ESP_NETIF_DEFAULT_OPENTHREAD(),
#endif
.platform_config = { .platform_config = {
.radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(),
.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),
@@ -0,0 +1,2 @@
CONFIG_OPENTHREAD_PLATFORM_NETIF=n
CONFIG_OPENTHREAD_CLI_ESP_EXTENSION=n
@@ -12,7 +12,12 @@ menu "Config for OpenThread Examples"
menu "External Console Commands" menu "External Console Commands"
config OPENTHREAD_IPERF_CMD_ENABLE config OPENTHREAD_IPERF_CMD_ENABLE
bool "Enable iperf command" bool "Enable iperf command"
depends on OPENTHREAD_FTD || OPENTHREAD_MTD # TODO: Make this option depend on LWIP_ENABLE in the future.
# Currently, LWIP_ENABLE cannot be set to `n` because the OpenThread component makes MbedTLS a hard
# dependency.
# This is a known limitation of the ESP-IDF (<6) build system (component requirements are expanded
# before configuration is loaded).
depends on OPENTHREAD_PLATFORM_NETIF
default y default y
help help
If enabled, iperf will be registered and available as a console command. If enabled, iperf will be registered and available as a console command.
+61 -1
View File
@@ -121,6 +121,16 @@ PORT_MAPPING = {'ESPPORT1': 'esp32h2', 'ESPPORT2': 'esp32s3', 'ESPPORT3': 'esp32
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2-s3', id='c6-h2-s3',
), ),
pytest.param(
'rcp_uart|cli_disable_platform_netif|br',
3,
f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32c6|esp32h2|esp32s3',
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2_disable_platform_netif-s3',
),
pytest.param( pytest.param(
'rcp_spi|cli|br_spi', 'rcp_spi|cli|br_spi',
3, 3,
@@ -211,6 +221,16 @@ def formBasicWiFiThreadNetwork(br: IdfDut, cli: IdfDut) -> None:
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2-s3', id='c6-h2-s3',
), ),
pytest.param(
'rcp_uart|cli_disable_platform_netif|br',
3,
f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32c6|esp32h2|esp32s3',
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2_disable_platform_netif-s3',
),
], ],
indirect=True, indirect=True,
) )
@@ -267,6 +287,16 @@ def test_Bidirectional_IPv6_connectivity(Init_interface: bool, dut: tuple[IdfDut
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2-s3', id='c6-h2-s3',
), ),
pytest.param(
'rcp_uart|cli_disable_platform_netif|br',
3,
f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32c6|esp32h2|esp32s3',
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2_disable_platform_netif-s3',
),
], ],
indirect=True, indirect=True,
) )
@@ -319,6 +349,16 @@ def test_multicast_forwarding_A(Init_interface: bool, dut: tuple[IdfDut, IdfDut,
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2-s3', id='c6-h2-s3',
), ),
pytest.param(
'rcp_uart|cli_disable_platform_netif|br',
3,
f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32c6|esp32h2|esp32s3',
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2_disable_platform_netif-s3',
),
], ],
indirect=True, indirect=True,
) )
@@ -372,6 +412,16 @@ def test_multicast_forwarding_B(Init_interface: bool, dut: tuple[IdfDut, IdfDut,
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2-s3', id='c6-h2-s3',
), ),
pytest.param(
'rcp_uart|cli_disable_platform_netif|br',
3,
f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32c6|esp32h2|esp32s3',
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2_disable_platform_netif-s3',
),
], ],
indirect=True, indirect=True,
) )
@@ -432,6 +482,16 @@ def test_service_discovery_of_Thread_device(
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2-s3', id='c6-h2-s3',
), ),
pytest.param(
'rcp_uart|cli_disable_platform_netif|br',
3,
f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_cli")}'
f'|{os.path.join(os.path.dirname(__file__), "ot_br")}',
'esp32c6|esp32h2|esp32s3',
f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}',
id='c6-h2_disable_platform_netif-s3',
),
], ],
indirect=True, indirect=True,
) )
@@ -719,7 +779,7 @@ def test_ot_sleepy_device(dut: tuple[IdfDut, IdfDut]) -> None:
finally: finally:
logging.info('Cleaning up...') logging.info('Cleaning up...')
ocf.execute_command(leader, 'factoryreset') ocf.execute_command(leader, 'factoryreset')
leader.expect('OpenThread attached to netif', timeout=20) leader.expect('OpenThread enter mainloop', timeout=20)
ocf.hardreset_dut(sleepy_device) ocf.hardreset_dut(sleepy_device)
time.sleep(3) time.sleep(3)