Merge branch 'feat/call_meshcop_mdns_publish_in_idf_v5.4' into 'release/v5.4'

Handle MeshCoP mDNS service in state change callback, update OpenThread upstream (v5.4)

See merge request espressif/esp-idf!40083
This commit is contained in:
Shu Chen
2025-07-01 02:52:59 +00:00
16 changed files with 314 additions and 83 deletions

View File

@@ -44,6 +44,13 @@ menu "OpenThread"
default y default y
help help
Select this option to enable Command-Line Interface in OpenThread. Select this option to enable Command-Line Interface in OpenThread.
config OPENTHREAD_CONSOLE_COMMAND_PREFIX
string "The prefix of the openthread CLI command registered on the esp console"
default "ot"
help
A prefix string used before a Thread CLI command, allowing the ESP console to identify
it and delegate the remaining command to the OpenThread callback for processing.
endmenu endmenu
menu "Thread Core Features" menu "Thread Core Features"
@@ -130,6 +137,14 @@ menu "OpenThread"
default 12390 default 12390
help help
Configure the port number of TREL service. Configure the port number of TREL service.
config OPENTHREAD_TREL_BUFFER_SIZE
int "The receive buffer size of openthread trel"
depends on OPENTHREAD_RADIO_TREL
range 10 255
default 50
help
Configure the receive buffer size of TREL service.
endmenu endmenu
menu "Thread 15.4 Radio Link" menu "Thread 15.4 Radio Link"

View File

@@ -76,6 +76,14 @@ esp_netif_t *esp_openthread_get_backbone_netif(void);
*/ */
esp_err_t esp_openthread_set_meshcop_instance_name(const char *instance_name); esp_err_t esp_openthread_set_meshcop_instance_name(const char *instance_name);
/**
* @brief Gets the meshcop(e) instance name.
*
* @return The instance name.
*
*/
const char* esp_openthread_get_meshcop_instance_name(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -13,6 +13,14 @@ extern "C" {
/** /**
* @brief This function initializes the OpenThread command line interface(CLI). * @brief This function initializes the OpenThread command line interface(CLI).
* *
* @note There are two ways to initialize the OpenThread CLI:
* 1. By creating a dedicated task via `esp_openthread_cli_create_task`
*
* 2. By registering a console command with the ESP console via
* `esp_openthread_cli_console_command_register`
* If using this approach, the user must initialize the interface used
* by the console and also initialize esp_console manually. Additionally,
* the `host_connection_mode` should be set to `HOST_CONNECTION_MODE_NONE`.
*/ */
void esp_openthread_cli_init(void); void esp_openthread_cli_init(void);
@@ -34,11 +42,27 @@ esp_err_t esp_openthread_cli_input(const char *line);
/** /**
* @brief This function launches an exclusive loop for the OpenThread CLI. * @brief This function launches an exclusive loop for the OpenThread CLI.
* *
* @param[in] priority The priority of the created task.
*
*/ */
void esp_openthread_cli_create_task(void); void esp_openthread_cli_create_task(void);
/**
* @brief This function registers an ESP Console command for the OpenThread CLI.
*
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM if allocation has failed
*/
esp_err_t esp_openthread_cli_console_command_register(void);
/**
* @brief This function deregisters the ESP Console command for the OpenThread CLI.
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if command is not registered
*/
esp_err_t esp_openthread_cli_console_command_unregister(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_openthread.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Publishes the OpenThread meshcop service in mDNS
*
* @param[in] instance_name Instance name of meshcop mDNS service
*
* @return
* - ESP_OK success
* - ESP_ERR_NO_MEM memory error
* - ESP_FAIL failed to add service
*
*/
esp_err_t esp_openthread_publish_meshcop_mdns(const char *instance_name);
/**
* @brief Removes the OpenThread meshcop service in mDNS
*
* @return
* - ESP_OK success
* - ESP_ERR_NO_MEM memory error
* - ESP_FAIL failed to remove service
*
*/
esp_err_t esp_openthread_remove_meshcop_mdns(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,15 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdatomic.h>
typedef struct {
uint8_t head;
uint8_t tail;
atomic_uint_fast8_t used;
} esp_openthread_circular_queue_info_t;

View File

@@ -84,6 +84,27 @@ void esp_openthread_set_coex_config(esp_ieee802154_coex_config_t config);
* *
*/ */
esp_ieee802154_coex_config_t esp_openthread_get_coex_config(void); esp_ieee802154_coex_config_t esp_openthread_get_coex_config(void);
/**
* @brief This function updates the TREL fds and timeouts to the main loop.
*
* @param[inout] mainloop The main loop context.
*
*/
void esp_openthread_trel_update(esp_openthread_mainloop_context_t *mainloop);
/**
* @brief This function performs the OpenThread TREL process.
*
* @param[in] instance The OpenThread instance.
* @param[in] mainloop The main loop context.
*
* @return
* - ESP_OK on success
* - ESP_FAIL on failure
*
*/
esp_err_t esp_openthread_trel_process(otInstance *aInstance, const esp_openthread_mainloop_context_t *mainloop);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -10,6 +10,11 @@
#include <esp_openthread.h> #include <esp_openthread.h>
#include <esp_openthread_types.h> #include <esp_openthread_types.h>
#define ESP_OPENTHREAD_BORDER_ROUTER_FLAG_OF_INTEREST \
(OT_CHANGED_THREAD_ROLE | OT_CHANGED_THREAD_EXT_PANID | OT_CHANGED_THREAD_NETWORK_NAME | \
OT_CHANGED_ACTIVE_DATASET | OT_CHANGED_THREAD_PARTITION_ID | OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE | \
OT_CHANGED_PSKC)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@@ -5,4 +5,4 @@ supplier: 'Organization: Espressif Systems (Shanghai) CO LTD'
originator: 'Organization: Google LLC' originator: 'Organization: Google LLC'
description: OpenThread released by Google is an open-source implementation of the Thread networking description: OpenThread released by Google is an open-source implementation of the Thread networking
url: https://github.com/espressif/openthread url: https://github.com/espressif/openthread
hash: ec2b0d487356d2955346457a6515201039140037 hash: b945928d722177cd9caeab2e1025499628c101ef

View File

@@ -1,14 +1,13 @@
/* /*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include "esp_openthread_cli.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "sdkconfig.h"
#include "openthread/cli.h" #include "openthread/cli.h"
#include "esp_check.h" #include "esp_check.h"
@@ -16,6 +15,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "esp_openthread.h" #include "esp_openthread.h"
#include "esp_openthread_common_macro.h" #include "esp_openthread_common_macro.h"
#include "esp_openthread_cli.h"
#include "esp_openthread_task_queue.h" #include "esp_openthread_task_queue.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
@@ -63,6 +63,40 @@ esp_err_t esp_openthread_cli_input(const char *line)
return esp_openthread_task_queue_post(line_handle_task, line_copy); return esp_openthread_task_queue_post(line_handle_task, line_copy);
} }
static int ot_cli_console_callback(int argc, char **argv)
{
char cli_cmd[OT_CLI_MAX_LINE_LENGTH] = {0};
strncpy(cli_cmd, argv[1], sizeof(cli_cmd) - strlen(cli_cmd) - 1);
for (int i = 2; i < argc; i++) {
strncat(cli_cmd, " ", sizeof(cli_cmd) - strlen(cli_cmd) - 1);
strncat(cli_cmd, argv[i], sizeof(cli_cmd) - strlen(cli_cmd) - 1);
}
s_cli_task = xTaskGetCurrentTaskHandle();
if (esp_openthread_cli_input(cli_cmd) == ESP_OK) {
xTaskNotifyWait(0, 0, NULL, portMAX_DELAY);
} else {
printf("Openthread task is busy, failed to run command: %s\n", cli_cmd);
}
s_cli_task = NULL;
return 0;
}
esp_err_t esp_openthread_cli_console_command_register(void)
{
esp_console_cmd_t cmd = {
.command = CONFIG_OPENTHREAD_CONSOLE_COMMAND_PREFIX,
.help = "Execute `"CONFIG_OPENTHREAD_CONSOLE_COMMAND_PREFIX" ...` to run openthread cli",
.hint = NULL,
.func = ot_cli_console_callback,
};
return esp_console_cmd_register(&cmd);
}
esp_err_t esp_openthread_cli_console_command_unregister(void)
{
return esp_console_cmd_deregister(CONFIG_OPENTHREAD_CONSOLE_COMMAND_PREFIX);
}
static void ot_cli_loop(void *context) static void ot_cli_loop(void *context)
{ {
int ret = 0; int ret = 0;

View File

@@ -4,7 +4,6 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <stdatomic.h>
#include "esp_openthread_radio.h" #include "esp_openthread_radio.h"
#include "esp_err.h" #include "esp_err.h"
@@ -13,6 +12,7 @@
#include "esp_ieee802154.h" #include "esp_ieee802154.h"
#include "esp_ieee802154_types.h" #include "esp_ieee802154_types.h"
#include "esp_mac.h" #include "esp_mac.h"
#include "esp_openthread_common.h"
#include "esp_openthread_common_macro.h" #include "esp_openthread_common_macro.h"
#include "esp_openthread_platform.h" #include "esp_openthread_platform.h"
#include "esp_openthread_types.h" #include "esp_openthread_types.h"
@@ -52,12 +52,6 @@ typedef struct {
uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE]; uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
} esp_openthread_radio_tx_psdu; } esp_openthread_radio_tx_psdu;
typedef struct {
uint8_t head;
uint8_t tail;
atomic_uint_fast8_t used;
} esp_openthread_circular_queue_info_t;
static otRadioFrame s_transmit_frame; static otRadioFrame s_transmit_frame;
static esp_openthread_radio_tx_psdu s_transmit_psdu; static esp_openthread_radio_tx_psdu s_transmit_psdu;

View File

@@ -10,7 +10,9 @@
#include <esp_check.h> #include <esp_check.h>
#include <esp_event.h> #include <esp_event.h>
#include <esp_log.h> #include <esp_log.h>
#include <esp_openthread_border_router.h>
#include <esp_openthread_dns64.h> #include <esp_openthread_dns64.h>
#include <esp_openthread_meshcop_mdns.h>
#include <esp_openthread_netif_glue_priv.h> #include <esp_openthread_netif_glue_priv.h>
#include <esp_openthread_radio.h> #include <esp_openthread_radio.h>
#include <esp_openthread_state.h> #include <esp_openthread_state.h>
@@ -19,6 +21,19 @@
#define TAG "OT_STATE" #define TAG "OT_STATE"
#if CONFIG_OPENTHREAD_BORDER_ROUTER
static void handle_ot_border_router_state_changed(otInstance* instance)
{
otDeviceRole role = otThreadGetDeviceRole(esp_openthread_get_instance());
if (role == OT_DEVICE_ROLE_CHILD || role == OT_DEVICE_ROLE_ROUTER || role == OT_DEVICE_ROLE_LEADER) {
esp_openthread_publish_meshcop_mdns(esp_openthread_get_meshcop_instance_name());
} else {
esp_openthread_remove_meshcop_mdns();
}
}
#endif
static void handle_ot_netif_state_change(otInstance* instance) static void handle_ot_netif_state_change(otInstance* instance)
{ {
if (otIp6IsEnabled(instance)) { if (otIp6IsEnabled(instance)) {
@@ -123,6 +138,12 @@ static void ot_state_change_callback(otChangedFlags changed_flags, void* ctx)
return; return;
} }
#if CONFIG_OPENTHREAD_BORDER_ROUTER
if (changed_flags & ESP_OPENTHREAD_BORDER_ROUTER_FLAG_OF_INTEREST) {
handle_ot_border_router_state_changed(instance);
}
#endif
if (changed_flags & OT_CHANGED_THREAD_ROLE) { if (changed_flags & OT_CHANGED_THREAD_ROLE) {
handle_ot_role_change(instance); handle_ot_role_change(instance);
} }

View File

@@ -18,10 +18,12 @@
#include "esp_netif_ip_addr.h" #include "esp_netif_ip_addr.h"
#include "esp_openthread.h" #include "esp_openthread.h"
#include "esp_openthread_border_router.h" #include "esp_openthread_border_router.h"
#include "esp_openthread_common.h"
#include "esp_openthread_common_macro.h" #include "esp_openthread_common_macro.h"
#include "esp_openthread_lock.h" #include "esp_openthread_lock.h"
#include "esp_openthread_platform.h"
#include "esp_openthread_radio.h" #include "esp_openthread_radio.h"
#include "esp_openthread_task_queue.h" #include "esp_vfs_eventfd.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "lwip/tcpip.h" #include "lwip/tcpip.h"
#include "lwip/udp.h" #include "lwip/udp.h"
@@ -54,6 +56,10 @@ typedef struct {
static ot_trel_t s_ot_trel = {CONFIG_OPENTHREAD_TREL_PORT, NULL}; static ot_trel_t s_ot_trel = {CONFIG_OPENTHREAD_TREL_PORT, NULL};
static bool s_is_service_registered = false; static bool s_is_service_registered = false;
static ot_trel_recv_task_t s_trel_receive_buffer[CONFIG_OPENTHREAD_TREL_BUFFER_SIZE];
static esp_openthread_circular_queue_info_t s_recv_queue = {.head = 0, .tail = 0, .used = 0};
static const char *s_trel_workflow = "trel";
static int s_trel_event_fd = -1;
static void trel_browse_notifier(mdns_result_t *result) static void trel_browse_notifier(mdns_result_t *result)
{ {
@@ -89,55 +95,27 @@ static void trel_browse_notifier(mdns_result_t *result)
} }
} }
static void trel_recv_task(void *ctx)
{
esp_err_t ret = ESP_OK;
OT_UNUSED_VARIABLE(ret);
ot_trel_recv_task_t *task_ctx = (ot_trel_recv_task_t *)ctx;
struct pbuf *recv_buf = task_ctx->p;
uint8_t *data_buf = (uint8_t *)recv_buf->payload;
uint8_t *data_buf_to_free = NULL;
uint16_t length = recv_buf->len;
if (recv_buf->next != NULL) {
data_buf = (uint8_t *)malloc(recv_buf->tot_len);
ESP_GOTO_ON_FALSE(data_buf, ESP_ERR_NO_MEM, exit, OT_PLAT_LOG_TAG, "Failed to allocate data buf when receiving Thread TREL message");
length = recv_buf->tot_len;
data_buf_to_free = data_buf;
pbuf_copy_partial(recv_buf, data_buf, recv_buf->tot_len, 0);
}
otPlatTrelHandleReceived(esp_openthread_get_instance(), data_buf, length, task_ctx->source_addr);
exit:
if (recv_buf) {
pbuf_free(recv_buf);
}
free(data_buf_to_free);
free(task_ctx->source_addr);
free(task_ctx);
}
// TZ-1704
static void handle_trel_udp_recv(void *ctx, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, uint16_t port) static void handle_trel_udp_recv(void *ctx, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, uint16_t port)
{ {
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
otSockAddr *source_addr = NULL;
uint64_t event_trel_rx = 1;
ESP_LOGD(OT_PLAT_LOG_TAG, "Receive from %s:%d", ip6addr_ntoa(&(addr->u_addr.ip6)), port); ESP_LOGD(OT_PLAT_LOG_TAG, "Receive from %s:%d", ip6addr_ntoa(&(addr->u_addr.ip6)), port);
ESP_GOTO_ON_FALSE(atomic_load(&s_recv_queue.used) < CONFIG_OPENTHREAD_TREL_BUFFER_SIZE, ESP_ERR_NO_MEM, exit, OT_PLAT_LOG_TAG, "trel receive buffer full!");
source_addr = (otSockAddr *)malloc(sizeof(otSockAddr));
ESP_GOTO_ON_FALSE(source_addr, ESP_ERR_NO_MEM, exit, OT_PLAT_LOG_TAG, "Failed to allocate buf for Thread TREL");
ot_trel_recv_task_t *task_ctx = (ot_trel_recv_task_t *)malloc(sizeof(ot_trel_recv_task_t)); memset(source_addr, 0, sizeof(otSockAddr));
ESP_GOTO_ON_FALSE(task_ctx, ESP_ERR_NO_MEM, exit, OT_PLAT_LOG_TAG, "Failed to allocate buf for Thread TREL"); source_addr->mPort = port;
task_ctx->p = p; memcpy(&source_addr->mAddress.mFields.m32, addr->u_addr.ip6.addr, sizeof(addr->u_addr.ip6.addr));
task_ctx->source_addr = (otSockAddr *)malloc(sizeof(otSockAddr)); s_trel_receive_buffer[s_recv_queue.tail].source_addr = source_addr;
ESP_GOTO_ON_FALSE(task_ctx->source_addr, ESP_ERR_NO_MEM, exit, OT_PLAT_LOG_TAG, "Failed to allocate buf for Thread TREL"); s_trel_receive_buffer[s_recv_queue.tail].p = p;
memset(task_ctx->source_addr, 0, sizeof(otSockAddr)); s_recv_queue.tail = (s_recv_queue.tail + 1) % CONFIG_OPENTHREAD_TREL_BUFFER_SIZE;
task_ctx->source_addr->mPort = port; atomic_fetch_add(&s_recv_queue.used, 1);
memcpy(&task_ctx->source_addr->mAddress.mFields.m32, addr->u_addr.ip6.addr, sizeof(addr->u_addr.ip6.addr)); assert(write(s_trel_event_fd, &event_trel_rx, sizeof(event_trel_rx)) == sizeof(event_trel_rx));
ESP_GOTO_ON_ERROR(esp_openthread_task_queue_post(trel_recv_task, task_ctx), exit, OT_PLAT_LOG_TAG, "Failed to receive OpenThread TREL message");
exit: exit:
if (ret != ESP_OK) { if (ret != ESP_OK) {
free(task_ctx->source_addr);
free(task_ctx);
if (p) { if (p) {
pbuf_free(p); pbuf_free(p);
} }
@@ -146,25 +124,76 @@ exit:
static esp_err_t ot_new_trel(void *ctx) static esp_err_t ot_new_trel(void *ctx)
{ {
ot_trel_t *task = (ot_trel_t *)ctx; s_ot_trel.trel_pcb = udp_new();
ESP_RETURN_ON_FALSE(s_ot_trel.trel_pcb != NULL, ESP_ERR_NO_MEM, OT_PLAT_LOG_TAG, "Failed to create a new UDP pcb");
udp_bind(s_ot_trel.trel_pcb, IP6_ADDR_ANY, s_ot_trel.port);
udp_recv(s_ot_trel.trel_pcb, handle_trel_udp_recv, NULL);
return ESP_OK;
}
void esp_openthread_trel_update(esp_openthread_mainloop_context_t *mainloop)
{
FD_SET(s_trel_event_fd, &mainloop->read_fds);
if (s_trel_event_fd > mainloop->max_fd) {
mainloop->max_fd = s_trel_event_fd;
}
}
esp_err_t esp_openthread_trel_process(otInstance *aInstance, const esp_openthread_mainloop_context_t *mainloop)
{
uint64_t event_read = 0;
assert(read(s_trel_event_fd, &event_read, sizeof(event_read)) == sizeof(event_read));
struct pbuf *recv_buf = NULL;
uint8_t *data_buf = NULL;
uint16_t length = 0;
otSockAddr *source_addr = NULL;
while (atomic_load(&s_recv_queue.used)) {
if (s_trel_receive_buffer[s_recv_queue.head].p != NULL) {
uint8_t *data_buf_to_free = NULL;
bool should_handle = true;
recv_buf = s_trel_receive_buffer[s_recv_queue.head].p;
data_buf = (uint8_t *)recv_buf->payload;
length = recv_buf->len;
source_addr = s_trel_receive_buffer[s_recv_queue.head].source_addr;
if (recv_buf->next != NULL) {
data_buf = (uint8_t *)malloc(recv_buf->tot_len);
if (data_buf) {
pbuf_copy_partial(recv_buf, data_buf, recv_buf->tot_len, 0);
} else {
should_handle = false;
}
length = recv_buf->tot_len;
data_buf_to_free = data_buf;
}
if (should_handle) {
otPlatTrelHandleReceived(aInstance, data_buf, length, source_addr);
}
pbuf_free(recv_buf);
free(data_buf_to_free);
free(source_addr);
s_recv_queue.head = (s_recv_queue.head + 1) % CONFIG_OPENTHREAD_TREL_BUFFER_SIZE;
atomic_fetch_sub(&s_recv_queue.used, 1);
}
}
task->trel_pcb = udp_new();
ESP_RETURN_ON_FALSE(task->trel_pcb != NULL, ESP_ERR_NO_MEM, OT_PLAT_LOG_TAG, "Failed to create a new UDP pcb");
udp_bind(task->trel_pcb, IP6_ADDR_ANY, task->port);
udp_recv(task->trel_pcb, handle_trel_udp_recv, NULL);
return ESP_OK; return ESP_OK;
} }
void otPlatTrelEnable(otInstance *aInstance, uint16_t *aUdpPort) void otPlatTrelEnable(otInstance *aInstance, uint16_t *aUdpPort)
{ {
ESP_RETURN_ON_FALSE(s_trel_event_fd == -1, , OT_PLAT_LOG_TAG, "ot trel has been initialized.");
s_trel_event_fd = eventfd(0, 0);
assert(s_trel_event_fd >= 0);
*aUdpPort = s_ot_trel.port; *aUdpPort = s_ot_trel.port;
esp_openthread_task_switching_lock_release(); esp_openthread_task_switching_lock_release();
esp_err_t err = esp_netif_tcpip_exec(ot_new_trel, &s_ot_trel); ESP_ERROR_CHECK(esp_netif_tcpip_exec(ot_new_trel, NULL));
if (err != ESP_OK) {
ESP_LOGE(OT_PLAT_LOG_TAG, "Fail to create trel udp");
}
mdns_browse_new(TREL_MDNS_TYPE, TREL_MDNS_PROTO, trel_browse_notifier); mdns_browse_new(TREL_MDNS_TYPE, TREL_MDNS_PROTO, trel_browse_notifier);
esp_openthread_task_switching_lock_acquire(portMAX_DELAY); esp_openthread_task_switching_lock_acquire(portMAX_DELAY);
ESP_ERROR_CHECK(esp_openthread_platform_workflow_register(&esp_openthread_trel_update, &esp_openthread_trel_process, s_trel_workflow));
} }
static esp_err_t trel_send_task(void *ctx) static esp_err_t trel_send_task(void *ctx)
@@ -263,23 +292,41 @@ void otPlatTrelResetCounters(otInstance *aInstance)
memset(&s_trel_counters, 0, sizeof(otPlatTrelCounters)); memset(&s_trel_counters, 0, sizeof(otPlatTrelCounters));
} }
static void trel_disable_task(void *ctx) static esp_err_t trel_disable_task(void *ctx)
{ {
struct udp_pcb *pcb = (struct udp_pcb *)ctx; if (ctx) {
udp_remove(pcb); struct udp_pcb *pcb = (struct udp_pcb *)ctx;
udp_remove(pcb);
}
return ESP_OK;
}
static void free_all_buffer(void)
{
while (atomic_load(&s_recv_queue.used)) {
if (s_trel_receive_buffer[s_recv_queue.head].p != NULL) {
pbuf_free(s_trel_receive_buffer[s_recv_queue.head].p);
free(s_trel_receive_buffer[s_recv_queue.head].source_addr);
s_recv_queue.head = (s_recv_queue.head + 1) % CONFIG_OPENTHREAD_TREL_BUFFER_SIZE;
atomic_fetch_sub(&s_recv_queue.used, 1);
}
}
} }
void otPlatTrelDisable(otInstance *aInstance) void otPlatTrelDisable(otInstance *aInstance)
{ {
ESP_RETURN_ON_FALSE(s_trel_event_fd >= 0, , OT_PLAT_LOG_TAG, "ot trel is not initialized.");
esp_openthread_task_switching_lock_release(); esp_openthread_task_switching_lock_release();
if (s_ot_trel.trel_pcb) { esp_netif_tcpip_exec(trel_disable_task, s_ot_trel.trel_pcb);
tcpip_callback(trel_disable_task, s_ot_trel.trel_pcb); s_ot_trel.trel_pcb = NULL;
}
mdns_service_remove(TREL_MDNS_TYPE, TREL_MDNS_PROTO); mdns_service_remove(TREL_MDNS_TYPE, TREL_MDNS_PROTO);
s_is_service_registered = false; s_is_service_registered = false;
mdns_browse_delete(TREL_MDNS_TYPE, TREL_MDNS_PROTO); mdns_browse_delete(TREL_MDNS_TYPE, TREL_MDNS_PROTO);
esp_openthread_task_switching_lock_acquire(portMAX_DELAY); esp_openthread_task_switching_lock_acquire(portMAX_DELAY);
s_ot_trel.trel_pcb = NULL; esp_openthread_platform_workflow_unregister(s_trel_workflow);
free_all_buffer();
close(s_trel_event_fd);
s_trel_event_fd = -1;
} }
const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *aInstance) const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *aInstance)

View File

@@ -199,15 +199,20 @@ void app_main(void)
// * netif // * netif
// * task queue // * task queue
// * border router // * border router
esp_vfs_eventfd_config_t eventfd_config = { size_t max_eventfd = 3;
#if CONFIG_OPENTHREAD_RADIO_NATIVE || CONFIG_OPENTHREAD_RADIO_SPINEL_SPI #if CONFIG_OPENTHREAD_RADIO_NATIVE || CONFIG_OPENTHREAD_RADIO_SPINEL_SPI
// * radio driver (A native radio device needs a eventfd for radio driver.) // * radio driver (A native radio device needs a eventfd for radio driver.)
// * SpiSpinelInterface (The Spi Spinel Interface needs a eventfd.) // * SpiSpinelInterface (The Spi Spinel Interface needs a eventfd.)
// The above will not exist at the same time. // The above will not exist at the same time.
.max_fds = 4, max_eventfd++;
#else
.max_fds = 3,
#endif #endif
#if CONFIG_OPENTHREAD_RADIO_TREL
// * TREL reception (The Thread Radio Encapsulation Link needs a eventfd for reception.)
max_eventfd++;
#endif
esp_vfs_eventfd_config_t eventfd_config = {
.max_fds = max_eventfd,
}; };
ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config));
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());

View File

@@ -125,8 +125,9 @@ void app_main(void)
// Used eventfds: // Used eventfds:
// * netif // * netif
// * ot task queue // * ot task queue
// * ot trel
esp_vfs_eventfd_config_t eventfd_config = { esp_vfs_eventfd_config_t eventfd_config = {
.max_fds = 2, .max_fds = 3,
}; };
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());