Просмотр исходного кода

Merge branch 'openthread/thread_state' into 'master'

openthread: Add event post for OpenThread role changed

See merge request espressif/esp-idf!24141
Shu Chen 2 лет назад
Родитель
Сommit
28a6aeb303

+ 1 - 0
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"

+ 2 - 0
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.

+ 14 - 1
components/openthread/include/esp_openthread_types.h

@@ -14,9 +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 "driver/uart.h"
+#include "openthread/thread.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -29,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 */
@@ -47,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.
  *

+ 1 - 10
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.
  *

+ 31 - 0
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 <esp_err.h>
+#include <esp_openthread.h>
+#include <esp_openthread_types.h>
+
+#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

+ 5 - 0
components/openthread/src/esp_openthread.cpp

@@ -12,6 +12,7 @@
 #include "esp_openthread_lock.h"
 #include "esp_openthread_platform.h"
 #include "esp_openthread_sleep.h"
+#include "esp_openthread_state.h"
 #include "esp_openthread_task_queue.h"
 #include "esp_openthread_types.h"
 #include "freertos/FreeRTOS.h"
@@ -69,6 +70,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();
 

+ 1 - 25
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;
 }

+ 2 - 28
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) {

+ 109 - 0
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 <esp_check.h>
+#include <esp_event.h>
+#include <esp_log.h>
+#include <esp_openthread_dns64.h>
+#include <esp_openthread_netif_glue_priv.h>
+#include <esp_openthread_state.h>
+#include <lwip/dns.h>
+
+#include <openthread/thread.h>
+
+#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;
+}