diff --git a/components/esp_netif/include/esp_netif.h b/components/esp_netif/include/esp_netif.h index e44c5ba168..3646352e75 100644 --- a/components/esp_netif/include/esp_netif.h +++ b/components/esp_netif/include/esp_netif.h @@ -832,6 +832,17 @@ esp_err_t esp_netif_get_ip6_global(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip */ int esp_netif_get_all_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[]); +/** + * @brief Get all preferred IPv6 addresses of the specified interface + * + * @param[in] esp_netif Handle to esp-netif instance + * @param[out] if_ip6 Array of IPv6 addresses will be copied to the argument + * + * @return + * number of returned IPv6 addresses + */ +int esp_netif_get_all_preferred_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[]); + /** * @brief Cause the TCP/IP stack to add an IPv6 address to the interface * diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c index cedd7807c9..230a56e25d 100644 --- a/components/esp_netif/lwip/esp_netif_lwip.c +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -2203,6 +2203,30 @@ int esp_netif_get_all_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[]) } return addr_count; } + +int esp_netif_get_all_preferred_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[]) +{ + ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif); + + if (esp_netif == NULL || if_ip6 == NULL) { + return 0; + } + + int addr_count = 0; + struct netif *p_netif = esp_netif->lwip_netif; + + if (p_netif != NULL && netif_is_up(p_netif)) { + for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { + // Only return the IPs which are: + // 1. the state is preferred + // 2. not the IP6_ADDR_ANY(all bits are `0`) + if (ip6_addr_ispreferred(netif_ip6_addr_state(p_netif, i)) && !ip_addr_cmp(&p_netif->ip6_addr[i], IP6_ADDR_ANY)) { + memcpy(&if_ip6[addr_count++], &p_netif->ip6_addr[i], sizeof(ip6_addr_t)); + } + } + } + return addr_count; +} #endif esp_netif_flags_t esp_netif_get_flags(esp_netif_t *esp_netif) diff --git a/components/ieee802154/driver/esp_ieee802154_ack.c b/components/ieee802154/driver/esp_ieee802154_ack.c index 2c96bdf99b..cb21dd72a0 100644 --- a/components/ieee802154/driver/esp_ieee802154_ack.c +++ b/components/ieee802154/driver/esp_ieee802154_ack.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,9 +17,11 @@ static ieee802154_pending_table_t ieee802154_pending_table; -#define BIT_SET(mask, pos) ((mask) |= (1UL << (pos))) -#define BIT_CLR(mask, pos) ((mask) &= ~(1UL << (pos))) -#define BIT_IST(mask, pos) ((mask) & (1UL << (pos))) +#define GET_MASK_ITEM_FROM_TABLE(mask, pos) (mask[(pos) / IEEE802154_PENDING_TABLE_MASK_BITS]) + +#define BIT_SET(mask, pos) (GET_MASK_ITEM_FROM_TABLE(mask, pos) |= (1UL << (pos % IEEE802154_PENDING_TABLE_MASK_BITS))) +#define BIT_CLR(mask, pos) (GET_MASK_ITEM_FROM_TABLE(mask, pos) &= ~(1UL << (pos % IEEE802154_PENDING_TABLE_MASK_BITS))) +#define BIT_IST(mask, pos) (GET_MASK_ITEM_FROM_TABLE(mask, pos) & (1UL << (pos % IEEE802154_PENDING_TABLE_MASK_BITS))) static IRAM_ATTR bool ieee802154_addr_in_pending_table(const uint8_t *addr, bool is_short) { @@ -114,9 +116,9 @@ void ieee802154_reset_pending_table(bool is_short) { // Consider this function may be called in ISR, only clear the mask bits for finishing the process quickly. if (is_short) { - ieee802154_pending_table.short_addr_mask = 0; + memset(ieee802154_pending_table.short_addr_mask, 0, IEEE802154_PENDING_TABLE_MASK_SIZE); } else { - ieee802154_pending_table.ext_addr_mask = 0; + memset(ieee802154_pending_table.ext_addr_mask, 0, IEEE802154_PENDING_TABLE_MASK_SIZE); } } diff --git a/components/ieee802154/private_include/esp_ieee802154_ack.h b/components/ieee802154/private_include/esp_ieee802154_ack.h index 1b44f608b5..2910a561b4 100644 --- a/components/ieee802154/private_include/esp_ieee802154_ack.h +++ b/components/ieee802154/private_include/esp_ieee802154_ack.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +8,7 @@ #include #include +#include "sdkconfig.h" #include "esp_err.h" #include "esp_ieee802154_frame.h" @@ -18,11 +19,14 @@ extern "C" { /** * @brief The radio pending table, which is utilized to determine whether the received frame should be responded to with pending bit enabled. */ + +#define IEEE802154_PENDING_TABLE_MASK_BITS (8) +#define IEEE802154_PENDING_TABLE_MASK_SIZE (((CONFIG_IEEE802154_PENDING_TABLE_SIZE - 1) / IEEE802154_PENDING_TABLE_MASK_BITS) + 1) typedef struct { uint8_t short_addr[CONFIG_IEEE802154_PENDING_TABLE_SIZE][IEEE802154_FRAME_SHORT_ADDR_SIZE]; /*!< Short address table */ uint8_t ext_addr[CONFIG_IEEE802154_PENDING_TABLE_SIZE][IEEE802154_FRAME_EXT_ADDR_SIZE]; /*!< Extend address table */ - uint32_t short_addr_mask; /*!< The mask which the index of short address table is used */ - uint32_t ext_addr_mask; /*!< The mask which the index of extended address table is used */ + uint8_t short_addr_mask[IEEE802154_PENDING_TABLE_MASK_SIZE]; /*!< The mask which the index of short address table is used */ + uint8_t ext_addr_mask[IEEE802154_PENDING_TABLE_MASK_SIZE]; /*!< The mask which the index of extended address table is used */ } ieee802154_pending_table_t; /** diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 56da539f4d..4c88a19594 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -883,6 +883,27 @@ menu "LWIP" default 0x1 if LWIP_TCPIP_TASK_AFFINITY_CPU1 + config LWIP_IPV6_ND6_NUM_PREFIXES + int "Max number of entries in IPv6 on-link prefixes cache" + depends on LWIP_IPV6 + default 5 + help + Maximum number of entries in IPv6 on-link prefixes cache + + config LWIP_IPV6_ND6_NUM_ROUTERS + int "Max number of entries in IPv6 default routers cache" + depends on LWIP_IPV6 + default 3 + help + Maximum number of entries in IPv6 default routers cache + + config LWIP_IPV6_ND6_NUM_DESTINATIONS + int "Max number of entries in IPv6 destinations cache" + depends on LWIP_IPV6 + default 10 + help + Maximum number of entries in IPv6 destinations cache + menuconfig LWIP_PPP_SUPPORT bool "Enable PPP support" default n diff --git a/components/lwip/port/include/lwipopts.h b/components/lwip/port/include/lwipopts.h index db4ef60bcf..a959ba1cc3 100644 --- a/components/lwip/port/include/lwipopts.h +++ b/components/lwip/port/include/lwipopts.h @@ -1297,6 +1297,20 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min) */ #define LWIP_ND6_NUM_NEIGHBORS CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS +/** + * LWIP_ND6_NUM_PREFIXES: Maximum number of entries in IPv6 on-link prefixes cache + */ +#define LWIP_ND6_NUM_PREFIXES CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES + +/** + * LWIP_ND6_NUM_ROUTERS: Maximum number of entries in IPv6 default routers cache + */ +#define LWIP_ND6_NUM_ROUTERS CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS + +/** + * LWIP_ND6_NUM_DESTINATIONS: Maximum number of entries in IPv6 destinations cache + */ +#define LWIP_ND6_NUM_DESTINATIONS CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS /* --------------------------------------- ---------- Hook options --------------- diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index d32ad89398..66119f65aa 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -83,6 +83,7 @@ if(CONFIG_OPENTHREAD_ENABLED) "openthread/src/core/api/nat64_api.cpp" "openthread/src/core/api/netdata_api.cpp" "openthread/src/core/api/netdiag_api.cpp" + "openthread/src/core/api/network_time_api.cpp" "openthread/src/core/api/random_crypto_api.cpp" "openthread/src/core/api/tcp_api.cpp" "openthread/src/core/api/udp_api.cpp" @@ -122,6 +123,7 @@ if(CONFIG_OPENTHREAD_ENABLED) "openthread/src/core/thread/network_diagnostic.cpp" "openthread/src/core/thread/panid_query_server.cpp" "openthread/src/core/thread/thread_netif.cpp" + "openthread/src/core/thread/time_sync_service.cpp" "openthread/src/core/thread/tmf.cpp" "openthread/src/core/thread/topology.cpp" "openthread/src/core/utils/child_supervision.cpp") 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 8a954c86d3..c06dcf526a 100644 --- a/components/openthread/private_include/openthread-core-esp32x-radio-config.h +++ b/components/openthread/private_include/openthread-core-esp32x-radio-config.h @@ -242,3 +242,13 @@ #ifndef OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT #define OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT CONFIG_OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT #endif + +/** + * @def OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + * + * Define as 1 to enable the time synchronization service feature. + * + */ +#if CONFIG_OPENTHREAD_TIME_SYNC +#define OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1 +#endif diff --git a/components/openthread/src/port/esp_openthread_radio_spinel.cpp b/components/openthread/src/port/esp_openthread_radio_spinel.cpp index 4cbe63a845..b851c5608b 100644 --- a/components/openthread/src/port/esp_openthread_radio_spinel.cpp +++ b/components/openthread/src/port/esp_openthread_radio_spinel.cpp @@ -22,6 +22,7 @@ #include "lib/spinel/spinel.h" #include "openthread/platform/diag.h" #include "openthread/platform/radio.h" +#include "openthread/platform/time.h" #include "platform/exit_code.h" #include "spinel_driver.hpp" @@ -442,3 +443,8 @@ void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aEnable) s_radio.SetRxOnWhenIdle(aEnable); } #endif + +uint16_t otPlatTimeGetXtalAccuracy(void) +{ + return CONFIG_OPENTHREAD_XTAL_ACCURACY; +} diff --git a/examples/openthread/ot_br/main/esp_ot_br.c b/examples/openthread/ot_br/main/esp_ot_br.c index bf887803a9..206f0de977 100644 --- a/examples/openthread/ot_br/main/esp_ot_br.c +++ b/examples/openthread/ot_br/main/esp_ot_br.c @@ -48,6 +48,16 @@ #include "ot_led_strip.h" #endif +#if CONFIG_OPENTHREAD_BR_AUTO_START +#include "example_common_private.h" +#include "protocol_examples_common.h" +#endif + +#if !CONFIG_OPENTHREAD_BR_AUTO_START && CONFIG_EXAMPLE_CONNECT_ETHERNET +// TZ-1109: Add a menchanism for connecting ETH manually. +#error Currently we do not support a manual way to connect ETH, if you want to use ETH, please enable OPENTHREAD_BR_AUTO_START. +#endif + #define TAG "esp_ot_br" #if CONFIG_EXTERNAL_COEX_ENABLE @@ -93,47 +103,62 @@ static void ot_task_worker(void *aContext) void ot_br_init(void *ctx) { -#if CONFIG_EXAMPLE_CONNECT_WIFI +#if CONFIG_OPENTHREAD_CLI_WIFI + ESP_ERROR_CHECK(esp_ot_wifi_config_init()); +#endif #if CONFIG_OPENTHREAD_BR_AUTO_START - ESP_ERROR_CHECK(example_connect()); - ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_MAX_MODEM)); -#if CONFIG_ESP_COEX_SW_COEXIST_ENABLE && CONFIG_OPENTHREAD_RADIO_NATIVE - ESP_ERROR_CHECK(esp_coex_wifi_i154_enable()); +#if CONFIG_EXAMPLE_CONNECT_WIFI || CONFIG_EXAMPLE_CONNECT_ETHERNET + bool wifi_or_ethernet_connected = false; #else +#error No backbone netif! +#endif +#if CONFIG_EXAMPLE_CONNECT_WIFI + char wifi_ssid[32] = ""; + char wifi_password[64] = ""; + if (esp_ot_wifi_config_get_ssid(wifi_ssid) == ESP_OK) { + ESP_LOGI(TAG, "use the Wi-Fi config from NVS"); + esp_ot_wifi_config_get_password(wifi_password); + } else { + ESP_LOGI(TAG, "use the Wi-Fi config from Kconfig"); + strcpy(wifi_ssid, CONFIG_EXAMPLE_WIFI_SSID); + strcpy(wifi_password, CONFIG_EXAMPLE_WIFI_PASSWORD); + } + if (esp_ot_wifi_connect(wifi_ssid, wifi_password) == ESP_OK) { + wifi_or_ethernet_connected = true; + } else { + ESP_LOGE(TAG, "Fail to connect to Wi-Fi, please try again manually"); + } +#endif +#if CONFIG_EXAMPLE_CONNECT_ETHERNET + ESP_ERROR_CHECK(example_ethernet_connect()); + wifi_or_ethernet_connected = true; +#endif +#endif // CONFIG_OPENTHREAD_BR_AUTO_START #if CONFIG_EXTERNAL_COEX_ENABLE ot_br_external_coexist_init(); #endif // CONFIG_EXTERNAL_COEX_ENABLE - -#endif - esp_openthread_set_backbone_netif(get_example_netif()); -#else - esp_ot_wifi_netif_init(); - esp_openthread_set_backbone_netif(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")); -#endif // CONFIG_OPENTHREAD_BR_AUTO_START -#elif CONFIG_EXAMPLE_CONNECT_ETHERNET - ESP_ERROR_CHECK(example_connect()); - esp_openthread_set_backbone_netif(get_example_netif()); -#else - ESP_LOGE(TAG, "ESP-Openthread has not set backbone netif"); -#endif // CONFIG_EXAMPLE_CONNECT_WIFI - ESP_ERROR_CHECK(mdns_init()); ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-br")); - // Initialize border routing features esp_openthread_lock_acquire(portMAX_DELAY); #if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); #endif - #if CONFIG_OPENTHREAD_BR_AUTO_START - ESP_ERROR_CHECK(esp_openthread_border_router_init()); - otOperationalDatasetTlvs dataset; - otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); - ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL)); + if (wifi_or_ethernet_connected) { + esp_openthread_set_backbone_netif(get_example_netif()); + ESP_ERROR_CHECK(esp_openthread_border_router_init()); +#if CONFIG_EXAMPLE_CONNECT_WIFI + esp_ot_wifi_border_router_init_flag_set(true); +#endif + otOperationalDatasetTlvs dataset; + otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); + ESP_ERROR_CHECK(esp_openthread_auto_start((error == OT_ERROR_NONE) ? &dataset : NULL)); + } else { + ESP_LOGE(TAG, "Auto-start mode failed, please try to start manually"); + } #endif // CONFIG_OPENTHREAD_BR_AUTO_START - esp_openthread_lock_release(); vTaskDelete(NULL); } diff --git a/examples/openthread/ot_br/main/idf_component.yml b/examples/openthread/ot_br/main/idf_component.yml index 519cf7f89d..bf43f391cb 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.1.0" + version: "~1.2.0" espressif/mdns: "^1.0.3" ## Required IDF version idf: diff --git a/examples/openthread/ot_cli/main/idf_component.yml b/examples/openthread/ot_cli/main/idf_component.yml index 3f1f6778d2..06b75f0c81 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.1.0" + version: "~1.2.0" idf: version: ">=4.1.0" ot_led: