feat(openthread): Add event post for thread role changed and integrate all the thread state change callbacks

This commit is contained in:
WanqQixiang 2023-06-09 12:17:32 +08:00
parent 0298e6f257
commit 58b99731f5
9 changed files with 166 additions and 64 deletions

View File

@ -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"

View File

@ -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.

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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

View File

@ -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();

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;
}