Explorar el Código

openthread: support 1.3 border routing features

- Support ICMPv6 auto config
- Support SRP service delegation
- Publish _meshcop._mdns service
Jiacheng Guo hace 4 años
padre
commit
a74bbde9c5

+ 1 - 1
components/ieee802154/lib

@@ -1 +1 @@
-Subproject commit 46396c46bd3c4d459b194e0e9273ff004158b993
+Subproject commit efbc05d641040253567e825dae53731da595c7b5

+ 1 - 1
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);

+ 15 - 16
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 <string.h>
 
 #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;

+ 5 - 2
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)

+ 6 - 1
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=\<openthread-core-esp32x-config.h\>             \
-    -DPACKAGE_VERSION=\"OPENTHREAD_PACKAGE_VERSION\"
+    -DPACKAGE_VERSION=\"OPENTHREAD_PACKAGE_VERSION\"                         \
+    -Wno-maybe-uninitialized
 
 ifdef CONFIG_OPENTHREAD_FTD
     COMMON_FLAGS += -DOPENTHREAD_FTD=1

+ 14 - 0
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.
  *

+ 41 - 0
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
 
 /**

+ 1 - 1
components/openthread/lib

@@ -1 +1 @@
-Subproject commit d84f8967f8ce14490e19433b85c8c363d424f4c1
+Subproject commit 105f3610d2258d7a7dd1c72f5f1adea89077c6cc

+ 1 - 1
components/openthread/openthread

@@ -1 +1 @@
-Subproject commit d16edaa5ef73e9139ac9c9d3b71981bf21a5de17
+Subproject commit a662c32eb074cc624bf344f810f65f8637a89552

+ 77 - 0
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 = []
+```

+ 7 - 3
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);
 }

+ 10 - 0
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