diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index 12a5066d16..8e0d219e66 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -249,7 +249,7 @@ menu "OpenThread" config OPENTHREAD_BORDER_ROUTER bool "Enable Border Router" - depends on OPENTHREAD_FTD + depends on OPENTHREAD_FTD && OPENTHREAD_PLATFORM_NETIF default n help Select this option to enable border router features in OpenThread. @@ -299,7 +299,7 @@ menu "OpenThread" config OPENTHREAD_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 default n help @@ -508,6 +508,15 @@ menu "OpenThread" failure. 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 menu "Thread Log" diff --git a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h index 82d474aff8..32a3a33795 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -454,6 +454,21 @@ #endif #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.----*/ #if CONFIG_OPENTHREAD_BORDER_ROUTER @@ -703,16 +718,6 @@ #define OPENTHREAD_CONFIG_COAP_API_ENABLE 1 #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 * diff --git a/components/openthread/private_include/openthread-core-esp32x-mtd-config.h b/components/openthread/private_include/openthread-core-esp32x-mtd-config.h index f631a157d5..1d3997c7e1 100644 --- a/components/openthread/private_include/openthread-core-esp32x-mtd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-mtd-config.h @@ -245,6 +245,21 @@ #endif #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.----*/ /** @@ -257,16 +272,6 @@ #define OPENTHREAD_CONFIG_COAP_API_ENABLE 1 #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 * diff --git a/components/openthread/src/esp_openthread.cpp b/components/openthread/src/esp_openthread.cpp index 311617f6a0..3ca5d46527 100644 --- a/components/openthread/src/esp_openthread.cpp +++ b/components/openthread/src/esp_openthread.cpp @@ -182,6 +182,7 @@ esp_err_t esp_openthread_mainloop_exit(void) esp_err_t esp_openthread_launch_mainloop(void) { + ESP_LOGI(OT_PLAT_LOG_TAG, "OpenThread enter mainloop"); esp_openthread_mainloop_context_t mainloop; otInstance *instance = esp_openthread_get_instance(); esp_err_t error = ESP_OK; @@ -253,7 +254,7 @@ static void ot_task_worker(void *aContext) // Initialize the OpenThread stack 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)); assert(openthread_netif != NULL); 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(); #endif // CONFIG_OPENTHREAD_CLI -#if CONFIG_OPENTHREAD_FTD || CONFIG_OPENTHREAD_MTD +#if CONFIG_OPENTHREAD_PLATFORM_NETIF // Clean up esp_openthread_netif_glue_deinit(); esp_netif_destroy(openthread_netif); diff --git a/components/openthread/src/esp_openthread_netif_glue.c b/components/openthread/src/esp_openthread_netif_glue.c index 35dd8db149..fc371d4849 100644 --- a/components/openthread/src/esp_openthread_netif_glue.c +++ b/components/openthread/src/esp_openthread_netif_glue.c @@ -46,8 +46,6 @@ static esp_openthread_netif_glue_t s_openthread_netif_glue = { .event_fd = -1, }; -ESP_EVENT_DEFINE_BASE(OPENTHREAD_EVENT); - static QueueHandle_t s_packet_queue; static esp_netif_t *s_openthread_netif; static const char *netif_glue_workflow = "netif_glue"; diff --git a/components/openthread/src/port/esp_openthread_state.c b/components/openthread/src/port/esp_openthread_state.c index c3724773bd..d106d39778 100644 --- a/components/openthread/src/port/esp_openthread_state.c +++ b/components/openthread/src/port/esp_openthread_state.c @@ -21,6 +21,8 @@ #define TAG "OT_STATE" +ESP_EVENT_DEFINE_BASE(OPENTHREAD_EVENT); + #if CONFIG_OPENTHREAD_BORDER_ROUTER static void handle_ot_border_router_state_changed(otInstance* instance) { diff --git a/components/openthread/srcs_ftd_mtd.cmake b/components/openthread/srcs_ftd_mtd.cmake index 4d6c2fab63..bae3a44fa8 100644 --- a/components/openthread/srcs_ftd_mtd.cmake +++ b/components/openthread/srcs_ftd_mtd.cmake @@ -107,6 +107,12 @@ if(NOT CONFIG_OPENTHREAD_DNS64_CLIENT) "src/esp_openthread_dns64.c") 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) list(APPEND exclude_srcs "src/port/esp_openthread_sleep.c") diff --git a/examples/openthread/ot_ci_function.py b/examples/openthread/ot_ci_function.py index 09c9c523f7..5ec70fc14b 100644 --- a/examples/openthread/ot_ci_function.py +++ b/examples/openthread/ot_ci_function.py @@ -188,7 +188,7 @@ def getDataset(dut: IdfDut) -> str: def init_thread(dut: IdfDut) -> None: - dut.expect('OpenThread attached to netif', timeout=10) + dut.expect('OpenThread enter mainloop', timeout=10) wait(dut, 3) reset_thread(dut) @@ -201,16 +201,16 @@ def stop_thread(dut: IdfDut) -> None: def reset_thread(dut: IdfDut) -> None: execute_command(dut, 'factoryreset') - dut.expect('OpenThread attached to netif', timeout=20) + dut.expect('OpenThread enter mainloop', timeout=20) wait(dut, 3) clean_buffer(dut) def hardreset_dut(dut: IdfDut) -> None: dut.serial.hard_reset() - dut.expect('OpenThread attached to netif', timeout=20) + dut.expect('OpenThread enter mainloop', timeout=20) 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 @@ -474,7 +474,8 @@ def check_ipmaddr(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) dut.expect('Done', timeout=5) order = 0 diff --git a/examples/openthread/ot_cli/main/esp_ot_cli.c b/examples/openthread/ot_cli/main/esp_ot_cli.c index 44a7d1abe8..0d49da7ef5 100644 --- a/examples/openthread/ot_cli/main/esp_ot_cli.c +++ b/examples/openthread/ot_cli/main/esp_ot_cli.c @@ -53,7 +53,9 @@ void app_main(void) ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); +#if CONFIG_OPENTHREAD_PLATFORM_NETIF ESP_ERROR_CHECK(esp_netif_init()); +#endif ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); #if CONFIG_OPENTHREAD_CLI @@ -62,7 +64,9 @@ void app_main(void) #endif static esp_openthread_config_t config = { +#if CONFIG_OPENTHREAD_PLATFORM_NETIF .netif_config = ESP_NETIF_DEFAULT_OPENTHREAD(), +#endif .platform_config = { .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), diff --git a/examples/openthread/ot_cli/sdkconfig.ci.cli_disable_platform_netif b/examples/openthread/ot_cli/sdkconfig.ci.cli_disable_platform_netif new file mode 100644 index 0000000000..6d7624ee6c --- /dev/null +++ b/examples/openthread/ot_cli/sdkconfig.ci.cli_disable_platform_netif @@ -0,0 +1,2 @@ +CONFIG_OPENTHREAD_PLATFORM_NETIF=n +CONFIG_OPENTHREAD_CLI_ESP_EXTENSION=n diff --git a/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild b/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild index 0bca5c2987..6123273f4a 100644 --- a/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild +++ b/examples/openthread/ot_common_components/ot_examples_common/Kconfig.projbuild @@ -12,7 +12,12 @@ menu "Config for OpenThread Examples" menu "External Console Commands" config OPENTHREAD_IPERF_CMD_ENABLE 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 help If enabled, iperf will be registered and available as a console command. diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index c2ac697f11..607fd28288 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -121,6 +121,16 @@ PORT_MAPPING = {'ESPPORT1': 'esp32h2', 'ESPPORT2': 'esp32s3', 'ESPPORT3': 'esp32 f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', 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( 'rcp_spi|cli|br_spi', 3, @@ -211,6 +221,16 @@ def formBasicWiFiThreadNetwork(br: IdfDut, cli: IdfDut) -> None: f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', 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, ) @@ -267,6 +287,16 @@ def test_Bidirectional_IPv6_connectivity(Init_interface: bool, dut: tuple[IdfDut f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', 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, ) @@ -319,6 +349,16 @@ def test_multicast_forwarding_A(Init_interface: bool, dut: tuple[IdfDut, IdfDut, f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', 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, ) @@ -372,6 +412,16 @@ def test_multicast_forwarding_B(Init_interface: bool, dut: tuple[IdfDut, IdfDut, f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', 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, ) @@ -432,6 +482,16 @@ def test_service_discovery_of_Thread_device( f'{ESPPORT3}|{ESPPORT1}|{ESPPORT2}', 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, ) @@ -719,7 +779,7 @@ def test_ot_sleepy_device(dut: tuple[IdfDut, IdfDut]) -> None: finally: logging.info('Cleaning up...') 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) time.sleep(3)