diff --git a/components/openthread/Kconfig b/components/openthread/Kconfig index c291ede131..558f093f6c 100644 --- a/components/openthread/Kconfig +++ b/components/openthread/Kconfig @@ -266,6 +266,14 @@ menu "OpenThread" default 1024 range 512 8192 + config OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT + int "Maximum backoffs times before declaring a channel access failure." + depends on OPENTHREAD_ENABLED || OPENTHREAD_SPINEL_ONLY + default 4 + help + The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access + failure. + config OPENTHREAD_MLE_MAX_CHILDREN int "The size of max MLE children entries" depends on OPENTHREAD_ENABLED diff --git a/components/openthread/include/esp_openthread_netif_glue.h b/components/openthread/include/esp_openthread_netif_glue.h index 404e9f1f5c..3d70c8a7f7 100644 --- a/components/openthread/include/esp_openthread_netif_glue.h +++ b/components/openthread/include/esp_openthread_netif_glue.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,7 +16,7 @@ extern "C" { #endif /** -* @brief Default configuration reference of OT esp-netif +* @brief Default configuration reference of OpenThread esp-netif */ #define ESP_NETIF_INHERENT_DEFAULT_OPENTHREAD() \ { \ @@ -67,6 +67,15 @@ void esp_openthread_netif_glue_deinit(void); */ esp_netif_t *esp_openthread_get_netif(void); +/** + * @brief This function register a handler for meshcop-e service publish event and remove event. + * + * @param[in] handler The handler. + * @param[in] for_publish The usage of handler, true for publish event and false for remove event. + * + */ +void esp_openthread_register_meshcop_e_handler(esp_event_handler_t handler, bool for_publish); + #ifdef __cplusplus } #endif diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index 28595d3fa0..0309594019 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -44,6 +44,8 @@ typedef enum { OPENTHREAD_EVENT_TREL_REMOVE_IP6, /*!< OpenThread stack removed TREL IPv6 address */ OPENTHREAD_EVENT_TREL_MULTICAST_GROUP_JOIN, /*!< OpenThread stack joined TREL IPv6 multicast group */ OPENTHREAD_EVENT_SET_DNS_SERVER, /*!< OpenThread stack set DNS server >*/ + OPENTHREAD_EVENT_PUBLISH_MESHCOP_E, /*!< OpenThread stack start to publish meshcop-e service >*/ + OPENTHREAD_EVENT_REMOVE_MESHCOP_E, /*!< OpenThread stack start to remove meshcop-e service >*/ } esp_openthread_event_t; /** diff --git a/components/openthread/include/esp_radio_spinel.h b/components/openthread/include/esp_radio_spinel.h index b3acb66496..d9b08529e6 100644 --- a/components/openthread/include/esp_radio_spinel.h +++ b/components/openthread/include/esp_radio_spinel.h @@ -6,6 +6,7 @@ #pragma once +#include "sdkconfig.h" #include #include "esp_err.h" #include "esp_ieee802154_types.h" @@ -56,11 +57,11 @@ typedef struct void (*transmit_started)(const uint8_t *frame); /* Callback for Transmit Started.*/ void (*switchover_done)(bool success); /* Callback for Switchover Done.*/ -#if OPENTHREAD_CONFIG_DIAG_ENABLE +#if CONFIG_OPENTHREAD_DIAG void (*diag_receive_done)(const uint8_t *frame, esp_ieee802154_frame_info_t *frame_info); /* Callback for Receive Done (diag).*/ void (*diag_transmit_done)(const uint8_t *frame, esp_ieee802154_frame_info_t *frame_info); /* Callback for Transmit Done (diag).*/ void (*diag_transmit_failed)(esp_ieee802154_tx_error_t error); /* Callback for Transmit Failed (diag).*/ -#endif // OPENTHREAD_CONFIG_DIAG_ENABLE +#endif // CONFIG_OPENTHREAD_DIAG } esp_radio_spinel_callbacks_t; /* ESP Radio Spinel Callbacks.*/ /** diff --git a/components/openthread/lib b/components/openthread/lib index fcee30db4b..a0f6a77960 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit fcee30db4b7342de4df9105bdd049a09d2d63187 +Subproject commit a0f6a77960b36ebe357cc4bee280034f8c7120f1 diff --git a/components/openthread/openthread b/components/openthread/openthread index 456c448284..be7d36e4ff 160000 --- a/components/openthread/openthread +++ b/components/openthread/openthread @@ -1 +1 @@ -Subproject commit 456c448284486abe2a9118a9fdaa468fe2383fcd +Subproject commit be7d36e4ff9cf7df6dfce54e58a31163c87b93f7 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 6043159bf3..bf61bc9094 100644 --- a/components/openthread/private_include/openthread-core-esp32x-ftd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-ftd-config.h @@ -620,4 +620,20 @@ #define OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY CONFIG_OPENTHREAD_ADDRESS_QUERY_MAX_RETRY_DELAY #endif +/** + * @def OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT + * + * The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access failure. + * + * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006, default value is 4. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT +#define OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT +#endif + +#ifndef OPENTHREAD_CONFIG_THREAD_VERSION +#define OPENTHREAD_CONFIG_THREAD_VERSION OT_THREAD_VERSION_1_4 +#endif + #define OPENTHREAD_FTD 1 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 a008afcca6..40ac95b9eb 100644 --- a/components/openthread/private_include/openthread-core-esp32x-mtd-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-mtd-config.h @@ -217,7 +217,7 @@ #endif // CONFIG_OPENTHREAD_MACFILTER_ENABLE #if CONFIG_OPENTHREAD_JOINER -#define OPENTHREAD_CONFIG_JOINER_ENABLE 0 +#define OPENTHREAD_CONFIG_JOINER_ENABLE 1 #endif #if CONFIG_OPENTHREAD_DIAG @@ -304,4 +304,16 @@ #define OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY CONFIG_OPENTHREAD_ADDRESS_QUERY_MAX_RETRY_DELAY #endif +/** + * @def OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT + * + * The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access failure. + * + * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006, default value is 4. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT +#define OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT +#endif + #define OPENTHREAD_MTD 1 diff --git a/components/openthread/private_include/openthread-core-esp32x-radio-config.h b/components/openthread/private_include/openthread-core-esp32x-radio-config.h index 2f34b61ef1..cd8ad15909 100644 --- a/components/openthread/private_include/openthread-core-esp32x-radio-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-radio-config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -230,3 +230,15 @@ #define OPENTHREAD_ENABLE_NCP_VENDOR_HOOK 1 #endif #endif //CONFIG_OPENTHREAD_NCP_VENDOR_HOOK + +/** + * @def OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT + * + * The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access failure. + * + * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006, default value is 4. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT +#define OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT +#endif diff --git a/components/openthread/private_include/openthread-core-esp32x-spinel-config.h b/components/openthread/private_include/openthread-core-esp32x-spinel-config.h index ab6da83d84..68d5b8240a 100644 --- a/components/openthread/private_include/openthread-core-esp32x-spinel-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-spinel-config.h @@ -46,3 +46,15 @@ * */ #define OPENTHREAD_CONFIG_PLATFORM_RADIO_SPINEL_RX_FRAME_BUFFER_SIZE CONFIG_OPENTHREAD_SPINEL_RX_FRAME_BUFFER_SIZE + +/** + * @def OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT + * + * The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access failure. + * + * Equivalent to macMaxCSMABackoffs in IEEE 802.15.4-2006, default value is 4. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT +#define OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT +#endif diff --git a/components/openthread/src/esp_openthread_netif_glue.c b/components/openthread/src/esp_openthread_netif_glue.c index 608a3218fa..8e0ff03085 100644 --- a/components/openthread/src/esp_openthread_netif_glue.c +++ b/components/openthread/src/esp_openthread_netif_glue.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -203,6 +203,33 @@ exit: return error; } +static esp_event_handler_t meshcop_e_publish_handler = NULL; +static void esp_openthread_meshcop_e_publish_handler(void *args, esp_event_base_t base, int32_t event_id, void *data) +{ + if (meshcop_e_publish_handler) { + meshcop_e_publish_handler(args, base, event_id, data); + } +} + +static esp_event_handler_t meshcop_e_remove_handler = NULL; +static void esp_openthread_meshcop_e_remove_handler(void *args, esp_event_base_t base, int32_t event_id, void *data) +{ + if (meshcop_e_remove_handler) { + meshcop_e_remove_handler(args, base, event_id, data); + } +} + +void esp_openthread_register_meshcop_e_handler(esp_event_handler_t handler, bool for_publish) +{ + if (for_publish) { + meshcop_e_publish_handler = handler; + } else if (!for_publish) { + meshcop_e_remove_handler = handler; + } else { + ESP_ERROR_CHECK(ESP_FAIL); + } +} + static esp_err_t register_openthread_event_handlers(esp_netif_t *esp_netif) { ESP_RETURN_ON_ERROR( @@ -229,6 +256,12 @@ static esp_err_t register_openthread_event_handlers(esp_netif_t *esp_netif) ESP_RETURN_ON_ERROR(esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_MULTICAST_GROUP_LEAVE, esp_netif_action_leave_ip6_multicast_group, esp_netif), OT_PLAT_LOG_TAG, "OpenThread interface leave ip6 multicast group event register failed"); + ESP_RETURN_ON_ERROR(esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_PUBLISH_MESHCOP_E, + esp_openthread_meshcop_e_publish_handler, NULL), + OT_PLAT_LOG_TAG, "OpenThread publish meshcop-e service event register failed"); + ESP_RETURN_ON_ERROR(esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_REMOVE_MESHCOP_E, + esp_openthread_meshcop_e_remove_handler, NULL), + OT_PLAT_LOG_TAG, "OpenThread remove meshcop-e service event register failed"); return ESP_OK; } @@ -244,6 +277,8 @@ static void unregister_openthread_event_handlers(void) esp_netif_action_join_ip6_multicast_group); esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_MULTICAST_GROUP_LEAVE, esp_netif_action_leave_ip6_multicast_group); + esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_PUBLISH_MESHCOP_E, esp_openthread_meshcop_e_publish_handler); + esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_REMOVE_MESHCOP_E, esp_openthread_meshcop_e_remove_handler); } static esp_err_t openthread_netif_post_attach(esp_netif_t *esp_netif, void *args) diff --git a/components/openthread/src/spinel/esp_radio_spinel.cpp b/components/openthread/src/spinel/esp_radio_spinel.cpp index c9895ff00a..2b7bcfdf16 100644 --- a/components/openthread/src/spinel/esp_radio_spinel.cpp +++ b/components/openthread/src/spinel/esp_radio_spinel.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "sdkconfig.h" #include "esp_check.h" #include "esp_log.h" #include "platform/exit_code.h" @@ -123,7 +124,7 @@ void SwitchoverDone(otInstance *aInstance, bool aSuccess) s_esp_radio_spinel_callbacks[idx].switchover_done(aSuccess); } -#if OPENTHREAD_CONFIG_DIAG_ENABLE +#if CONFIG_OPENTHREAD_DIAG void DiagReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError) { esp_radio_spinel_idx_t idx = get_index_from_instance(aInstance); @@ -172,7 +173,7 @@ void DiagTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otError aErro } } } -#endif // OPENTHREAD_CONFIG_DIAG_ENABLE +#endif // CONFIG_OPENTHREAD_DIAG void esp_radio_spinel_set_callbacks(const esp_radio_spinel_callbacks_t aCallbacks, esp_radio_spinel_idx_t idx) @@ -184,10 +185,10 @@ void esp_radio_spinel_set_callbacks(const esp_radio_spinel_callbacks_t aCallback Callbacks.mEnergyScanDone = EnergyScanDone; Callbacks.mTxStarted = TxStarted; Callbacks.mSwitchoverDone = SwitchoverDone; -#if OPENTHREAD_CONFIG_DIAG_ENABLE +#if CONFIG_OPENTHREAD_DIAG Callbacks.mDiagReceiveDone = DiagReceiveDone; Callbacks.mDiagTransmitDone = DiagTransmitDone; -#endif // OPENTHREAD_CONFIG_DIAG_ENABLE +#endif // CONFIG_OPENTHREAD_DIAG s_radio[idx].SetCallbacks(Callbacks); } @@ -268,6 +269,7 @@ esp_err_t esp_radio_spinel_transmit(uint8_t *frame, uint8_t channel, bool cca, e s_transmit_frame.mLength = frame[0]; s_transmit_frame.mPsdu = frame + 1; s_transmit_frame.mInfo.mTxInfo.mCsmaCaEnabled = cca; + s_transmit_frame.mInfo.mTxInfo.mMaxCsmaBackoffs = CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT; s_transmit_frame.mChannel = channel; s_transmit_frame.mInfo.mTxInfo.mRxChannelAfterTxDone = channel; return (s_radio[idx].Transmit(s_transmit_frame) == OT_ERROR_NONE) ? ESP_OK : ESP_FAIL; diff --git a/components/vfs/test/test_vfs_eventfd.c b/components/vfs/test/test_vfs_eventfd.c index 906bdecd1c..d250b7c33b 100644 --- a/components/vfs/test/test_vfs_eventfd.c +++ b/components/vfs/test/test_vfs_eventfd.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -349,3 +349,51 @@ TEST_CASE("eventfd multiple selects", "[vfs][eventfd]") TEST_ASSERT_EQUAL(0, close(fd)); TEST_ESP_OK(esp_vfs_eventfd_unregister()); } + +typedef struct { + QueueHandle_t queue; + int fd; +} select_block_task_args_t; + +static void select_block_task(void *arg) +{ + select_block_task_args_t *select_arg = (select_block_task_args_t *)arg; + int fd = select_arg->fd; + fd_set read_fds; + + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + + int val = select(fd + 1, &read_fds, NULL, NULL, NULL); + assert(val == 1); + bool is_selected = true; + xQueueSend(select_arg->queue, &is_selected, 0); + vTaskDelete(NULL); +} + +TEST_CASE("eventfd select block", "[vfs][eventfd]") +{ + esp_vfs_eventfd_config_t config = ESP_VFS_EVENTD_CONFIG_DEFAULT(); + TEST_ESP_OK(esp_vfs_eventfd_register(&config)); + + select_block_task_args_t args; + args.fd = eventfd(0, 0); + TEST_ASSERT_GREATER_OR_EQUAL(0, args.fd); + args.queue = xQueueCreate(1, sizeof(bool)); + + int fd_write = eventfd(0, 0); + TEST_ASSERT_GREATER_OR_EQUAL(0, fd_write); + + xTaskCreate(select_block_task, "select_block_task", 2048, &args, 5, NULL); + + bool is_selected = false; + uint64_t val = 1; + TEST_ASSERT_EQUAL(sizeof(val), write(fd_write, &val, sizeof(val))); + TEST_ASSERT(!xQueueReceive(args.queue, &is_selected, pdMS_TO_TICKS(2000))); + TEST_ASSERT_EQUAL(sizeof(val), write(args.fd, &val, sizeof(val))); + TEST_ASSERT(xQueueReceive(args.queue, &is_selected, pdMS_TO_TICKS(1000))); + TEST_ASSERT_EQUAL(true, is_selected); + TEST_ASSERT_EQUAL(0, close(args.fd)); + TEST_ASSERT_EQUAL(0, close(fd_write)); + TEST_ESP_OK(esp_vfs_eventfd_unregister()); +} diff --git a/examples/openthread/ot_br/CMakeLists.txt b/examples/openthread/ot_br/CMakeLists.txt index 509229d9b0..6bb56e3002 100644 --- a/examples/openthread/ot_br/CMakeLists.txt +++ b/examples/openthread/ot_br/CMakeLists.txt @@ -4,8 +4,7 @@ cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common - $ENV{IDF_PATH}/examples/common_components/iperf) +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(esp_ot_br) diff --git a/examples/openthread/ot_br/main/idf_component.yml b/examples/openthread/ot_br/main/idf_component.yml index 0b743288fd..b6a0a80c2f 100644 --- a/examples/openthread/ot_br/main/idf_component.yml +++ b/examples/openthread/ot_br/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: espressif/esp_ot_cli_extension: - version: "~1.0.0" + version: "~1.1.0" espressif/mdns: "^1.0.3" ## Required IDF version idf: diff --git a/examples/openthread/ot_cli/CMakeLists.txt b/examples/openthread/ot_cli/CMakeLists.txt index d677a901c9..b12d49bfa3 100644 --- a/examples/openthread/ot_cli/CMakeLists.txt +++ b/examples/openthread/ot_cli/CMakeLists.txt @@ -2,7 +2,5 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/iperf) - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(esp_ot_cli) diff --git a/examples/openthread/ot_cli/main/idf_component.yml b/examples/openthread/ot_cli/main/idf_component.yml index 722ae188c6..3f1f6778d2 100644 --- a/examples/openthread/ot_cli/main/idf_component.yml +++ b/examples/openthread/ot_cli/main/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File dependencies: espressif/esp_ot_cli_extension: - version: "~1.0.0" + version: "~1.1.0" idf: version: ">=4.1.0" ot_led: diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index 486b82b30a..9f7caf1829 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -1,8 +1,10 @@ # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 # !/usr/bin/env python3 +import copy import os.path import re +import secrets import subprocess import threading import time @@ -16,7 +18,7 @@ from pytest_embedded_idf.dut import IdfDut # This file contains the test scripts for Thread: # Case 1: Thread network formation and attaching -# A Thread Border Router forms a Thread network, Thread devices attache to it, then test ping connection between them. +# A Thread Border Router forms a Thread network, Thread devices attach to it, then test ping connection between them. # Case 2: Bidirectional IPv6 connectivity # Test IPv6 ping connection between Thread device and Linux Host (via Thread Border Router). @@ -27,10 +29,10 @@ from pytest_embedded_idf.dut import IdfDut # Case 4: Multicast forwarding from Thread to Wi-Fi network # Linux Host joins the multicast group, test group communication from Thread to Wi-Fi network. -# Case 5: discover Serice published by Thread device +# Case 5: discover Service published by Thread device # Thread device publishes the service, Linux Host discovers the service on Wi-Fi network. -# Case 6: discover Serice published by W-Fi device +# Case 6: discover Service published by W-Fi device # Linux Host device publishes the service on Wi-Fi network, Thread device discovers the service. # Case 7: ICMP communication via NAT64 @@ -627,3 +629,64 @@ def test_basic_startup(dut: Tuple[IdfDut, IdfDut]) -> None: finally: ocf.execute_command(br, 'factoryreset') time.sleep(3) + + +# Case 12: Curl a website via DNS and NAT64 +# @pytest.mark.openthread_bbr is not supported on release 5.1, skip this check + + +# Case 13: Meshcop discovery of Border Router +@pytest.mark.supported_targets +@pytest.mark.esp32c6 +@pytest.mark.openthread_br +@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.parametrize( + 'config, count, app_path, target', [ + ('rcp|br', 2, + f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', + 'esp32c6|esp32s3'), + ], + indirect=True, +) +def test_br_meshcop(Init_interface:bool, Init_avahi:bool, dut: Tuple[IdfDut, IdfDut]) -> None: + br = dut[1] + assert Init_interface + assert Init_avahi + dut[0].serial.stop_redirect_thread() + + result = None + output_bytes = b'' + try: + ocf.init_thread(br) + br_wifi_para = copy.copy(default_br_wifi_para) + ipv4_address = ocf.joinWiFiNetwork(br, br_wifi_para)[0] + br_thread_para = copy.copy(default_br_ot_para) + networkname = 'OTCI-' + str(secrets.token_hex(1)) + br_thread_para.setnetworkname(networkname) + ocf.joinThreadNetwork(br, br_thread_para) + ocf.wait(br, 10) + assert ocf.is_joined_wifi_network(br) + command = 'timeout 3 avahi-browse -r _meshcop._udp' + try: + result = subprocess.run(command, capture_output=True, check=True, shell=True) + if result: + output_bytes = result.stdout + except subprocess.CalledProcessError as e: + output_bytes = e.stdout + finally: + print('out_bytes: ', output_bytes) + output_str = str(output_bytes) + print('out_str: ', output_str) + + assert 'hostname = [esp-ot-br.local]' in str(output_str) + assert ('address = [' + ipv4_address + ']') in str(output_str) + assert 'dn=DefaultDomain' in str(output_str) + assert 'tv=1.4.0' in str(output_str) + assert ('nn=' + networkname) in str(output_str) + assert 'mn=BorderRouter' in str(output_str) + assert 'vn=OpenThread' in str(output_str) + assert 'rv=1' in str(output_str) + finally: + ocf.execute_command(br, 'factoryreset') + time.sleep(3)