diff --git a/components/ieee802154/lib b/components/ieee802154/lib index 46396c46bd..efbc05d641 160000 --- a/components/ieee802154/lib +++ b/components/ieee802154/lib @@ -1 +1 @@ -Subproject commit 46396c46bd3c4d459b194e0e9273ff004158b993 +Subproject commit efbc05d641040253567e825dae53731da595c7b5 diff --git a/components/lwip/port/esp32/hooks/lwip_default_hooks.c b/components/lwip/port/esp32/hooks/lwip_default_hooks.c index 8e317def40..87f684a4f1 100644 --- a/components/lwip/port/esp32/hooks/lwip_default_hooks.c +++ b/components/lwip/port/esp32/hooks/lwip_default_hooks.c @@ -40,7 +40,7 @@ int __weak lwip_hook_netconn_external_resolve(const char *name, ip_addr_t *addr, #endif #ifdef CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT -const ip6_addr_t *lwip_hook_nd6_get_gw(struct netif *netif, const ip6_addr_t *dest) +const ip6_addr_t *__weak lwip_hook_nd6_get_gw(struct netif *netif, const ip6_addr_t *dest) { LWIP_UNUSED_ARG(netif); LWIP_UNUSED_ARG(dest); diff --git a/components/lwip/port/esp32/netif/openthreadif.c b/components/lwip/port/esp32/netif/openthreadif.c index fdfce6572f..3ca4d57e2c 100644 --- a/components/lwip/port/esp32/netif/openthreadif.c +++ b/components/lwip/port/esp32/netif/openthreadif.c @@ -11,23 +11,20 @@ // See the License for the specific language governing permissions and // limitations under the License - #include #include "esp_netif.h" #include "esp_netif_net_stack.h" #include "lwip/netif.h" +#include "lwip/pbuf.h" #include "netif/openthreadif.h" +#include "openthread/error.h" #include "openthread/ip6.h" #include "openthread/link.h" +#include "openthread/message.h" #define OPENTHREAD_IP6_MTU 1280 -static void openthread_free_rx_buf_l2(struct netif *netif, void *buf) -{ - free(buf); -} - static err_t openthread_output_ip6(struct netif *netif, struct pbuf *p, const struct ip6_addr *peer_addr) { struct pbuf *q = p; @@ -69,24 +66,26 @@ void openthread_netif_input(void *h, void *buffer, size_t len, void *eb) { struct netif *netif = h; struct pbuf *p; + otMessage *message = (otMessage *)buffer; if (unlikely(buffer == NULL || !netif_is_up(netif))) { - if (buffer) { - openthread_free_rx_buf_l2(netif, buffer); - } return; } - /* acquire new pbuf, type: PBUF_REF */ - p = pbuf_alloc(PBUF_RAW, len, PBUF_REF); + /* Allocate LINK buffer in case it's forwarded to WiFi/ETH */ + p = pbuf_alloc(PBUF_LINK, len, PBUF_POOL); if (p == NULL) { - openthread_free_rx_buf_l2(netif, buffer); + LWIP_DEBUGF(NETIF_DEBUG, ("Failed to allocate input pbuf for OpenThread netif\n")); return; } - p->payload = buffer; + + if (unlikely(otMessageRead(message, 0, p->payload, len) != OT_ERROR_NONE)) { + LWIP_DEBUGF(NETIF_DEBUG, ("Failed to read OpenThread message\n")); + } + #if ESP_LWIP - p->l2_owner = netif; - p->l2_buf = buffer; + p->l2_owner = NULL; + p->l2_buf = NULL; #endif /* full packet send to tcpip_thread to process */ if (unlikely(netif->input(p, netif) != ERR_OK)) { @@ -106,7 +105,7 @@ err_t openthread_netif_init(struct netif *netif) netif->flags = NETIF_FLAG_BROADCAST; netif->output = NULL; netif->output_ip6 = openthread_output_ip6; - netif->l2_buffer_free_notify = openthread_free_rx_buf_l2; + netif->l2_buffer_free_notify = NULL; netif_set_link_up(netif); return ERR_OK; diff --git a/components/openthread/CMakeLists.txt b/components/openthread/CMakeLists.txt index e10d0300bd..c32211eadc 100644 --- a/components/openthread/CMakeLists.txt +++ b/components/openthread/CMakeLists.txt @@ -4,7 +4,6 @@ if(CONFIG_OPENTHREAD_ENABLED) "openthread/include") set(private_include_dirs - "openthread/include/openthread" "openthread/src" "openthread/src/core" "openthread/src/lib/hdlc" @@ -38,11 +37,15 @@ if(CONFIG_OPENTHREAD_ENABLED) endif() set(exclude_srcs - "openthread/examples/apps/cli/main.cpp" + "openthread/examples/apps/cli/main.c" "openthread/examples/platforms/utils/logging_rtt.c" "openthread/examples/platforms/utils/soft_source_match_table.c" "openthread/src/core/common/extension_example.cpp") + set_source_files_properties("openthread/src/core/net/srp_server.cpp" + PROPERTIES COMPILE_FLAGS + -Wno-maybe-uninitialized) + if(CONFIG_OPENTHREAD_FTD) set(device_type "OPENTHREAD_FTD=1") elseif(CONFIG_OPENTHREAD_MTD) diff --git a/components/openthread/component.mk b/components/openthread/component.mk index 6c872950c8..c49b004d42 100644 --- a/components/openthread/component.mk +++ b/components/openthread/component.mk @@ -34,6 +34,10 @@ COMPONENT_SRCDIRS := \ openthread/src/lib/spinel \ port +ifdef CONFIG_OPENTHREAD_BORDER_ROUTER +COMPONENT_SRCDIRS += openthread/src/core/border_router +endif + COMPONENT_OBJEXCLUDE := \ openthread/examples/apps/cli/main.o \ openthread/src/core/common/extension_example.o \ @@ -54,7 +58,8 @@ OPENTHREAD_PACKAGE_VERSION := $(IDF_VERSION_FOR_OPENTHREAD_PACKAGE)-$(OPENTHREAD COMMON_FLAGS := \ -DOPENTHREAD_CONFIG_FILE=\ \ - -DPACKAGE_VERSION=\"OPENTHREAD_PACKAGE_VERSION\" + -DPACKAGE_VERSION=\"OPENTHREAD_PACKAGE_VERSION\" \ + -Wno-maybe-uninitialized ifdef CONFIG_OPENTHREAD_FTD COMMON_FLAGS += -DOPENTHREAD_FTD=1 diff --git a/components/openthread/include/esp_openthread_border_router.h b/components/openthread/include/esp_openthread_border_router.h index aef20df628..b7df61d09a 100644 --- a/components/openthread/include/esp_openthread_border_router.h +++ b/components/openthread/include/esp_openthread_border_router.h @@ -17,6 +17,7 @@ #include "esp_netif.h" #include "esp_netif_types.h" #include "esp_openthread.h" +#include "openthread/instance.h" #ifdef __cplusplus extern "C" { @@ -33,10 +34,23 @@ extern "C" { * @return * - ESP_OK on success * - ESP_ERR_NOT_SUPPORTED if feature not supported + * - ESP_ERR_INVALID_STATE if already initialized + * - ESP_FIAL on other failures * */ esp_err_t esp_openthread_border_router_init(esp_netif_t *backbone_netif); +/** + * @brief Deinitializes the border router features of OpenThread. + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if not initialized + * - ESP_FIAL on other failures + * + */ +esp_err_t esp_openthread_border_router_deinit(void); + /** * @brief Gets the backbone interface of OpenThread border router. * diff --git a/components/openthread/include/openthread-core-esp32x-config.h b/components/openthread/include/openthread-core-esp32x-config.h index db046c73dc..254672aa88 100644 --- a/components/openthread/include/openthread-core-esp32x-config.h +++ b/components/openthread/include/openthread-core-esp32x-config.h @@ -105,6 +105,7 @@ */ #define OPENTHREAD_CONFIG_COAP_API_ENABLE 1 + /** * @def OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE * @@ -115,6 +116,16 @@ #define OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE + * + * Enable the external heap. + * + */ +#ifndef OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE +#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1 +#endif + #if CONFIG_OPENTHREAD_BORDER_ROUTER /** @@ -137,6 +148,16 @@ #define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + * + * Define to 1 to enable Border Routing support. + * + */ +#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +#define OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 1 +#endif + /** * @def OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE * @@ -147,6 +168,26 @@ #define OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_ECDSA_ENABLE + * + * Define to 1 to enable ECDSA support. + * + */ +#ifndef OPENTHREAD_CONFIG_ECDSA_ENABLE +#define OPENTHREAD_CONFIG_ECDSA_ENABLE 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_SRP_SERVER_ENABLE + * + * Define to 1 to enable SRP Server support. + * + */ +#ifndef OPENTHREAD_CONFIG_SRP_SERVER_ENABLE +#define OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 1 +#endif + #endif // CONFIG_OPENTHREAD_BORDER_ROUTER /** diff --git a/components/openthread/lib b/components/openthread/lib index d84f8967f8..105f3610d2 160000 --- a/components/openthread/lib +++ b/components/openthread/lib @@ -1 +1 @@ -Subproject commit d84f8967f8ce14490e19433b85c8c363d424f4c1 +Subproject commit 105f3610d2258d7a7dd1c72f5f1adea89077c6cc diff --git a/components/openthread/openthread b/components/openthread/openthread index d16edaa5ef..a662c32eb0 160000 --- a/components/openthread/openthread +++ b/components/openthread/openthread @@ -1 +1 @@ -Subproject commit d16edaa5ef73e9139ac9c9d3b71981bf21a5de17 +Subproject commit a662c32eb074cc624bf344f810f65f8637a89552 diff --git a/examples/openthread/ot_br/README.md b/examples/openthread/ot_br/README.md index a85d8438f3..2bc7a64d4e 100644 --- a/examples/openthread/ot_br/README.md +++ b/examples/openthread/ot_br/README.md @@ -146,3 +146,80 @@ I(552749) OPENTHREAD:[INFO]-UTIL----: Starting Child Supervision ``` The device has now joined the same Thread network based on the key set by the commissioner. + +## Bidirectional IPv6 connectivity + +The border router will automatically publish the prefix and the route table rule to the WiFi network via ICMPv6 router advertisment packages. + +### Host configuration + +The automatically configure your host's route table rules you need to set these sysctl options: + +Please relace `wlan0` with the real name of your WiFi network interface. +``` +sudo sysctl -w net/ipv6/conf/wlan0/accept_ra=2 +sudo sysctl -w net/ipv6/conf/wlan0/accept_ra_rt_info_max_plen=128 +``` + +For mobile devices, the route table rules will be automatically configured after iOS 14 and Android 8.1. + + +### Testing IPv6 connecitivity + +Now in the joining device, check the IP addresses: + +``` +> ipaddr +fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5 +fdde:ad00:beef:0:0:ff:fe00:c402 +fdde:ad00:beef:0:ad4a:9a9a:3cd6:e423 +fe80:0:0:0:f011:2951:569e:9c4a +``` + +You'll notice an IPv6 global prefix with only on address assigned under it. This is the routable address of this Thread node. +You can ping this address on your host: + +``` bash +$ ping fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5 +PING fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5(fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5) 56 data bytes +64 bytes from fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5: icmp_seq=1 ttl=63 time=459 ms +64 bytes from fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5: icmp_seq=2 ttl=63 time=109 ms +64 bytes from fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5: icmp_seq=3 ttl=63 time=119 ms +64 bytes from fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5: icmp_seq=4 ttl=63 time=117 ms +``` + +## Service discovery + +The newly introduced service registration protocol([SRP](https://datatracker.ietf.org/doc/html/draft-ietf-dnssd-srp-10)) allows devices in the Thread network to register a service. The border router will forward the service to the WiFi network via mDNS. + +Now we'll publish the service `my-service._test._udp` with hostname `test0` and port 12345 + +``` +> srp client host name test0 +Done +> srp client host address fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5 +Done +> srp client service add my-service _test._udp 12345 +Done +> srp client autostart enable +Done +``` + +This service will also become visible on the WiFi network: + +```bash +$ avahi-browse -r _test._udp -t + ++ enp1s0 IPv6 my-service _test._udp local += enp1s0 IPv6 my-service _test._udp local + hostname = [test0.local] + address = [fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5] + port = [12345] + txt = [] ++ enp1s0 IPv4 my-service _test._udp local += enp1s0 IPv4 my-service _test._udp local + hostname = [test0.local] + address = [fde6:75ff:def4:3bc3:9e9e:3ef:4245:28b5] + port = [12345] + txt = [] +``` diff --git a/examples/openthread/ot_br/main/esp_ot_br.c b/examples/openthread/ot_br/main/esp_ot_br.c index 6d98c9909d..a892e1dd7d 100644 --- a/examples/openthread/ot_br/main/esp_ot_br.c +++ b/examples/openthread/ot_br/main/esp_ot_br.c @@ -30,6 +30,7 @@ #include "esp_ot_config.h" #include "esp_vfs_eventfd.h" #include "esp_wifi.h" +#include "mdns.h" #include "nvs_flash.h" #include "protocol_examples_common.h" #include "sdkconfig.h" @@ -109,18 +110,19 @@ static void create_config_network(otInstance *instance) abort(); } dataset.mComponents.mIsExtendedPanIdPresent = true; - if (hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_MASTERKEY, dataset.mMasterKey.m8, - sizeof(dataset.mMasterKey.m8)) != sizeof(dataset.mMasterKey.m8)) { + if (hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_MASTERKEY, dataset.mNetworkKey.m8, + sizeof(dataset.mNetworkKey.m8)) != sizeof(dataset.mNetworkKey.m8)) { ESP_LOGE(TAG, "Cannot convert OpenThread master key. Please double-check your config."); abort(); } - dataset.mComponents.mIsMasterKeyPresent = true; + dataset.mComponents.mIsNetworkKeyPresent = true; if (hex_string_to_binary(CONFIG_OPENTHREAD_NETWORK_PSKC, dataset.mPskc.m8, sizeof(dataset.mPskc.m8)) != sizeof(dataset.mPskc.m8)) { ESP_LOGE(TAG, "Cannot convert OpenThread pre-shared commissioner key. Please double-check your config."); abort(); } dataset.mComponents.mIsPskcPresent = true; + dataset.mComponents.mIsMeshLocalPrefixPresent = false; if (otDatasetSetActive(instance, &dataset) != OT_ERROR_NONE) { ESP_LOGE(TAG, "Failed to set OpenThread active dataset."); abort(); @@ -188,5 +190,7 @@ void app_main(void) ESP_ERROR_CHECK(esp_event_loop_create_default()); ESP_ERROR_CHECK(example_connect()); ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); + ESP_ERROR_CHECK(mdns_init()); + ESP_ERROR_CHECK(mdns_hostname_set("esp-ot-br")); xTaskCreate(ot_task_worker, "ot_br_main", 20480, xTaskGetCurrentTaskHandle(), 5, NULL); } diff --git a/examples/openthread/ot_br/sdkconfig.defaults b/examples/openthread/ot_br/sdkconfig.defaults index 535bec0057..0393543019 100644 --- a/examples/openthread/ot_br/sdkconfig.defaults +++ b/examples/openthread/ot_br/sdkconfig.defaults @@ -36,6 +36,16 @@ CONFIG_OPENTHREAD_BORDER_ROUTER=y # # lwIP # +CONFIG_LWIP_IPV6_FORWARD=y CONFIG_LWIP_IPV6_NUM_ADDRESSES=8 CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_NETIF_STATUS_CALLBACK=y +CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y +CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y # end of lwIP + +# +# mDNS +# +CONFIG_MDNS_STRICT_MODE=y +# end of mDNS