From 181ed29c3a413e761d48bcab3634fd82e519c142 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Fri, 9 Jun 2023 12:17:32 +0800 Subject: [PATCH] feat(openthread): Add event post for thread role changed and integrate all the thread state change callbacks --- components/openthread/CMakeLists.txt | 1 + .../openthread/include/esp_openthread_dns64.h | 2 + .../openthread/include/esp_openthread_types.h | 14 +++ .../esp_openthread_netif_glue_priv.h | 11 +- .../private_include/esp_openthread_state.h | 31 +++++ components/openthread/src/esp_openthread.cpp | 5 + .../openthread/src/esp_openthread_dns64.c | 26 +---- .../src/esp_openthread_netif_glue.c | 30 +---- .../src/port/esp_openthread_state.c | 109 ++++++++++++++++++ 9 files changed, 166 insertions(+), 63 deletions(-) create mode 100644 components/openthread/private_include/esp_openthread_state.h create mode 100644 components/openthread/src/port/esp_openthread_state.c diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index 176823e11f..26c3d5706a 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -58,6 +58,7 @@ if(CONFIG_OPENTHREAD_ENABLED) "openthread/examples/apps/ncp") list(APPEND exclude_srcs + "src/port/esp_openthread_state.c" "openthread/examples/apps/ncp/main.c" "openthread/src/core/api/backbone_router_api.cpp" "openthread/src/core/api/child_supervision_api.cpp" diff --git a/components/openthread/include/esp_openthread_dns64.h b/components/openthread/include/esp_openthread_dns64.h index 8c8bb15795..22809b8560 100644 --- a/components/openthread/include/esp_openthread_dns64.h +++ b/components/openthread/include/esp_openthread_dns64.h @@ -12,6 +12,8 @@ #ifdef __cplusplus extern "C" { #endif +// The network data change callback sets the dns server address of index 0, while the CLI sets the dns server address of index 1. +#define OPENTHREAD_DNS_SERVER_INDEX 0 /** * @brief This function initiizes the dns64 client. diff --git a/components/openthread/include/esp_openthread_types.h b/components/openthread/include/esp_openthread_types.h index 5923814fb4..936dd6d542 100644 --- a/components/openthread/include/esp_openthread_types.h +++ b/components/openthread/include/esp_openthread_types.h @@ -14,8 +14,10 @@ #include "driver/gpio.h" #include "driver/spi_master.h" #include "driver/spi_slave.h" +#include "driver/uart.h" #include "hal/gpio_types.h" #include "hal/uart_types.h" +#include "openthread/thread.h" #ifdef __cplusplus extern "C" { @@ -28,6 +30,9 @@ extern "C" { typedef enum { OPENTHREAD_EVENT_START, /*!< OpenThread stack start */ OPENTHREAD_EVENT_STOP, /*!< OpenThread stack stop */ + OPENTHREAD_EVENT_DETACHED, /*!< OpenThread detached */ + OPENTHREAD_EVENT_ATTACHED, /*!< OpenThread attached */ + OPENTHREAD_EVENT_ROLE_CHANGED, /*!< OpenThread role changed */ OPENTHREAD_EVENT_IF_UP, /*!< OpenThread network interface up */ OPENTHREAD_EVENT_IF_DOWN, /*!< OpenThread network interface down */ OPENTHREAD_EVENT_GOT_IP6, /*!< OpenThread stack added IPv6 address */ @@ -46,6 +51,15 @@ typedef enum { */ ESP_EVENT_DECLARE_BASE(OPENTHREAD_EVENT); +/** + * @brief OpenThread role changed event data + * + */ +typedef struct { + otDeviceRole previous_role; /*!< Previous Thread role */ + otDeviceRole current_role; /*!< Current Thread role */ +} esp_openthread_role_changed_event_t; + /** * This structure represents a context for a select() based mainloop. * diff --git a/components/openthread/private_include/esp_openthread_netif_glue_priv.h b/components/openthread/private_include/esp_openthread_netif_glue_priv.h index 47e5134638..d5a9d1c072 100644 --- a/components/openthread/private_include/esp_openthread_netif_glue_priv.h +++ b/components/openthread/private_include/esp_openthread_netif_glue_priv.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,15 +14,6 @@ extern "C" { #endif -/** - * @brief The state handler to be called when OpenThread state changes - * - * @param[in] changed_flags The changed Openthread states - * @param[in] ctx A pointer to application-specific context - * - */ -void esp_openthread_netif_glue_state_callback(otChangedFlags changed_flags, void *ctx); - /** * @brief This function updates the netif fds and timeouts to the main loop. * diff --git a/components/openthread/private_include/esp_openthread_state.h b/components/openthread/private_include/esp_openthread_state.h new file mode 100644 index 0000000000..e2ee350805 --- /dev/null +++ b/components/openthread/private_include/esp_openthread_state.h @@ -0,0 +1,31 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief This function initiizes OpenThread state event post. + * + * @pram[in] instance The OpenThread instance + * + * @return + * - ESP_OK on success + * - ESP_FAIL if OpenThread state changed callback fails to be registered + * + */ +esp_err_t esp_openthread_state_event_init(otInstance *instance); + +#ifdef __cplusplus +} +#endif diff --git a/components/openthread/src/esp_openthread.cpp b/components/openthread/src/esp_openthread.cpp index bcb88437b2..38f3511528 100644 --- a/components/openthread/src/esp_openthread.cpp +++ b/components/openthread/src/esp_openthread.cpp @@ -11,6 +11,7 @@ #include "esp_openthread_dns64.h" #include "esp_openthread_lock.h" #include "esp_openthread_platform.h" +#include "esp_openthread_state.h" #include "esp_openthread_task_queue.h" #include "esp_openthread_types.h" #include "freertos/FreeRTOS.h" @@ -64,6 +65,10 @@ esp_err_t esp_openthread_init(const esp_openthread_platform_config_t *config) #if CONFIG_OPENTHREAD_DNS64_CLIENT ESP_RETURN_ON_ERROR(esp_openthread_dns64_client_init(), OT_PLAT_LOG_TAG, "Failed to initialize OpenThread dns64 client"); +#endif +#if !CONFIG_OPENTHREAD_RADIO + ESP_RETURN_ON_ERROR(esp_openthread_state_event_init(esp_openthread_get_instance()), OT_PLAT_LOG_TAG, + "Failed to initialize OpenThread state event"); #endif esp_openthread_lock_release(); diff --git a/components/openthread/src/esp_openthread_dns64.c b/components/openthread/src/esp_openthread_dns64.c index cdece8334a..77be398886 100644 --- a/components/openthread/src/esp_openthread_dns64.c +++ b/components/openthread/src/esp_openthread_dns64.c @@ -5,6 +5,7 @@ */ #include "esp_openthread_dns64.h" +#include "esp_openthread_state.h" #include "esp_check.h" #include "esp_event.h" @@ -16,34 +17,9 @@ #include "lwip/dns.h" #define TAG "OT_DNS64" -// The network data change callback sets the dns server address of index 0, while the CLI sets the dns server address of index 1. -#define OPENTHREAD_DNS_SERVER_INDEX 0 - -static void esp_openthread_netdata_change_callback(otChangedFlags changed_flags, void *ctx) -{ - if (OT_CHANGED_THREAD_NETDATA & changed_flags) { - ip_addr_t dns_server_addr = *IP_ADDR_ANY; - if (esp_openthread_get_nat64_prefix(&dns_server_addr.u_addr.ip6) == ESP_OK) { - dns_server_addr.type = IPADDR_TYPE_V6; - dns_server_addr.u_addr.ip6.addr[3] = ipaddr_addr(CONFIG_OPENTHREAD_DNS_SERVER_ADDR); - const ip_addr_t *dnsserver = dns_getserver(OPENTHREAD_DNS_SERVER_INDEX); - if (memcmp(dnsserver, &dns_server_addr, sizeof(ip_addr_t)) != 0) { - ESP_LOGI(TAG, "Set dns server address: %s", ipaddr_ntoa(&dns_server_addr)); - dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, &dns_server_addr); - if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_SET_DNS_SERVER, NULL, 0, 0) != ESP_OK) { - ESP_LOGE(TAG, "Failed to post OpenThread set DNS server event"); - } - } - } - } -} esp_err_t esp_openthread_dns64_client_init(void) { - otInstance *instance = esp_openthread_get_instance(); - ESP_RETURN_ON_FALSE(otSetStateChangedCallback(instance, esp_openthread_netdata_change_callback, NULL) == - OT_ERROR_NONE, - ESP_FAIL, TAG, "Failed to install network data change callback"); dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, NULL); return ESP_OK; } diff --git a/components/openthread/src/esp_openthread_netif_glue.c b/components/openthread/src/esp_openthread_netif_glue.c index 9be2b6b947..608a3218fa 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-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,7 @@ #include "esp_openthread_lock.h" #include "esp_openthread_netif_glue_priv.h" #include "esp_openthread_platform.h" +#include "esp_openthread_state.h" #include "esp_openthread_types.h" #include "esp_vfs_eventfd.h" #include "sdkconfig.h" @@ -170,30 +171,6 @@ static esp_err_t process_thread_transmit(otInstance *instance) return error; } -void esp_openthread_netif_glue_state_callback(otChangedFlags changed_flags, void *ctx) -{ - otInstance *instance = esp_openthread_get_instance(); - esp_err_t err = ESP_OK; - - if (s_packet_queue != NULL && (OT_CHANGED_THREAD_NETIF_STATE & changed_flags)) { - if (otLinkIsEnabled(instance)) { - ESP_LOGI(OT_PLAT_LOG_TAG, "netif up"); - if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_UP, NULL, 0, 0) != ESP_OK) { - ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to post OpenThread if up event"); - } - } else { - ESP_LOGI(OT_PLAT_LOG_TAG, "netif down"); - if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_DOWN, NULL, 0, 0) != ESP_OK) { - ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to post OpenThread if down event"); - } - } - } - - if (err != ESP_OK) { - ESP_LOGE(OT_PLAT_LOG_TAG, "Failed to configure netif state"); - } -} - static esp_err_t openthread_netif_transmit(void *handle, void *buffer, size_t len) { esp_err_t error = ESP_OK; @@ -298,9 +275,6 @@ void *esp_openthread_netif_glue_init(const esp_openthread_platform_config_t *con if (instance == NULL || s_packet_queue || s_openthread_netif_glue.event_fd >= 0) { return NULL; } - ESP_RETURN_ON_FALSE(otSetStateChangedCallback(instance, esp_openthread_netif_glue_state_callback, NULL) == - OT_ERROR_NONE, - NULL, OT_PLAT_LOG_TAG, "Failed to install netif glue state callback"); s_packet_queue = xQueueCreate(config->port_config.netif_queue_size, sizeof(otMessage *)); if (s_packet_queue == NULL) { diff --git a/components/openthread/src/port/esp_openthread_state.c b/components/openthread/src/port/esp_openthread_state.c new file mode 100644 index 0000000000..6dbe101670 --- /dev/null +++ b/components/openthread/src/port/esp_openthread_state.c @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define TAG "OT_STATE" + +static void handle_ot_netif_state_change(otInstance* instance) +{ + if (otLinkIsEnabled(instance)) { + ESP_LOGI(TAG, "netif up"); + if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_UP, NULL, 0, 0) != ESP_OK) { + ESP_LOGE(TAG, "Failed to post OpenThread if up event"); + } + } else { + ESP_LOGI(TAG, "netif down"); + if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_DOWN, NULL, 0, 0) != ESP_OK) { + ESP_LOGE(TAG, "Failed to post OpenThread if down event"); + } + } +} + +static void handle_ot_netdata_change(void) +{ +#if CONFIG_OPENTHREAD_DNS64_CLIENT + ip_addr_t dns_server_addr = *IP_ADDR_ANY; + if (esp_openthread_get_nat64_prefix(&dns_server_addr.u_addr.ip6) == ESP_OK) { + dns_server_addr.type = IPADDR_TYPE_V6; + dns_server_addr.u_addr.ip6.addr[3] = ipaddr_addr(CONFIG_OPENTHREAD_DNS_SERVER_ADDR); + const ip_addr_t* dnsserver = dns_getserver(OPENTHREAD_DNS_SERVER_INDEX); + if (memcmp(dnsserver, &dns_server_addr, sizeof(ip_addr_t)) != 0) { + ESP_LOGI(TAG, "Set dns server address: %s", ipaddr_ntoa(&dns_server_addr)); + dns_setserver(OPENTHREAD_DNS_SERVER_INDEX, &dns_server_addr); + if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_SET_DNS_SERVER, NULL, 0, 0) != ESP_OK) { + ESP_LOGE(TAG, "Failed to post OpenThread set DNS server event"); + } + } + } +#endif +} + +static void handle_ot_role_change(otInstance* instance) +{ + static otDeviceRole s_previous_role = OT_DEVICE_ROLE_DISABLED; + otDeviceRole role = otThreadGetDeviceRole(instance); + esp_err_t ret = ESP_OK; + esp_openthread_role_changed_event_t event_data; + event_data.current_role = role; + event_data.previous_role = s_previous_role; + if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_ROLE_CHANGED, &event_data, sizeof(event_data), 0) != ESP_OK) { + ESP_LOGE(TAG, "Failed to post OPENTHREAD_EVENT_ROLE_CHANGED"); + } + if (role == OT_DEVICE_ROLE_CHILD || role == OT_DEVICE_ROLE_ROUTER || role == OT_DEVICE_ROLE_LEADER) { + if (s_previous_role == OT_DEVICE_ROLE_DETACHED || s_previous_role == OT_DEVICE_ROLE_DISABLED) { + otOperationalDataset dataset; + ESP_GOTO_ON_FALSE(otDatasetGetActive(instance, &dataset) == OT_ERROR_NONE, ESP_FAIL, exit, TAG, + "Failed to get the active dataset"); + ESP_GOTO_ON_ERROR(esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_ATTACHED, &dataset, sizeof(dataset), 0), + exit, TAG, "Failed to post OPENTHREAD_EVENT_ATTACHED. Err: %s", esp_err_to_name(ret)); + } + } else if (role == OT_DEVICE_ROLE_DETACHED) { + if (s_previous_role != OT_DEVICE_ROLE_DISABLED) { + ESP_GOTO_ON_ERROR( + esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_DETACHED, &s_previous_role, sizeof(s_previous_role), 0), + exit, TAG, "Failed to post OPENTHREAD_EVENT_DETACHED. Err: %s", esp_err_to_name(ret)); + } + } +exit: + s_previous_role = role; +} + +static void ot_state_change_callback(otChangedFlags changed_flags, void* ctx) +{ + OT_UNUSED_VARIABLE(ctx); + otInstance* instance = esp_openthread_get_instance(); + if (!instance) { + return; + } + + if (changed_flags & OT_CHANGED_THREAD_ROLE) { + handle_ot_role_change(instance); + } + + if (changed_flags & OT_CHANGED_THREAD_NETDATA) { + handle_ot_netdata_change(); + } + + if (changed_flags & OT_CHANGED_THREAD_NETIF_STATE) { + handle_ot_netif_state_change(instance); + } +} + +esp_err_t esp_openthread_state_event_init(otInstance* instance) +{ + ESP_RETURN_ON_FALSE(otSetStateChangedCallback(instance, ot_state_change_callback, NULL) == OT_ERROR_NONE, + ESP_FAIL, TAG, "Failed to install state change callback"); + return ESP_OK; +}