mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
[netdata] adding NetworkData::Publisher (#6768)
This commit implements a new feature "Network Data Publisher" which provides mechanisms to limit the number of similar entries (service and/or prefix) in the Thread Network Data by monitoring the Network Data and managing if or when to add or remove entries. This feature is enabled using `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE` config, or `NETDATA_PUBLISHER` in autoconf, or `OT_NETDATA_PUBLISHER` cmake option. This commit adds support for publishing DNS/SRP anycast/unicast service, on-mesh prefix, and external route prefix entries. When there is a request to publish an entry, the `Publisher` monitors the Network Data and counts the number of similar entries. If there are fewer entries than a desired target number, the entry is added after a short random delay. If there are too many similar entries, `Publisher` starts the process of removing its own entry (again after some random wait time). When removing entries, certain entries are preferred over others (e.g., an entry from a router over one from an end-device or if they are from the same type of node, the one with smaller RLOC16). If `Publisher` determines that its own entry is a preferred one, it adds an extra wait time before removing its entry. This gives higher chance for a non-preferred entry from another device to be removed before removing a preferred entry which helps towards quicker convergence of the process to the desired number of entries. On-mesh prefix and external route entries have a "preference" field. When publishing such an entry, a matching entry in the network data is counted only if its preference is same or higher than the entry's preference. This ensures that a device with a higher preference entry publishes its entry even when there are many lower preference similar entries in the network data (potentially causing a lower preference entry to be removed). This commit also adds `test_netdata_publisher.py` to verify the behavior of the `Publisher`.
This commit is contained in:
committed by
GitHub
parent
71bc37bbc3
commit
2e625bfe39
@@ -190,6 +190,7 @@ LOCAL_SRC_FILES := \
|
||||
src/core/api/message_api.cpp \
|
||||
src/core/api/multi_radio_api.cpp \
|
||||
src/core/api/netdata_api.cpp \
|
||||
src/core/api/netdata_publisher_api.cpp \
|
||||
src/core/api/netdiag_api.cpp \
|
||||
src/core/api/network_time_api.cpp \
|
||||
src/core/api/ping_sender_api.cpp \
|
||||
@@ -322,6 +323,7 @@ LOCAL_SRC_FILES := \
|
||||
src/core/thread/network_data_leader_ftd.cpp \
|
||||
src/core/thread/network_data_local.cpp \
|
||||
src/core/thread/network_data_notifier.cpp \
|
||||
src/core/thread/network_data_publisher.cpp \
|
||||
src/core/thread/network_data_service.cpp \
|
||||
src/core/thread/network_data_tlvs.cpp \
|
||||
src/core/thread/network_data_types.cpp \
|
||||
|
||||
@@ -269,6 +269,11 @@ if(OT_NEIGHBOR_DISCOVERY_AGENT)
|
||||
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE=1")
|
||||
endif()
|
||||
|
||||
option(OT_NETDATA_PUBLISHER "enable Thread Network Data publisher")
|
||||
if(OT_NETDATA_PUBLISHER)
|
||||
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE=1")
|
||||
endif()
|
||||
|
||||
option(OT_PING_SENDER "enable ping sender support" ${OT_APP_CLI})
|
||||
if(OT_PING_SENDER)
|
||||
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_PING_SENDER_ENABLE=1")
|
||||
|
||||
@@ -60,6 +60,7 @@ LINK_RAW ?= 1
|
||||
MAC_FILTER ?= 1
|
||||
MTD_NETDIAG ?= 1
|
||||
NEIGHBOR_DISCOVERY_AGENT ?= 1
|
||||
NETDATA_PUBLISHER ?= 1
|
||||
PING_SENDER ?= 1
|
||||
REFERENCE_DEVICE ?= 1
|
||||
SERVICE ?= 1
|
||||
|
||||
@@ -48,6 +48,7 @@ This page lists the available common switches with description. Unless stated ot
|
||||
| MLR | OT_MLR | Enables Multicast Listener Registration feature for Thread 1.2. |
|
||||
| MTD_NETDIAG | OT_MTD_NETDIAG | Enables the TMF network diagnostics on MTDs. |
|
||||
| MULTIPLE_INSTANCE | OT_MULTIPLE_INSTANCE | Enables multiple OpenThread instances. |
|
||||
| NETDATA_PUBLISHER | OT_NETDATA_PUBLISHER | Enables support for Thread Network Data publisher. |
|
||||
| PING_SENDER | OT_PING_SENDER | Enables support for ping sender. |
|
||||
| OTNS | OT_OTNS | Enables support for [OpenThread Network Simulator](https://github.com/openthread/ot-ns). Enable this switch if you are building OpenThread for OpenThread Network Simulator. |
|
||||
| PLATFORM_UDP | OT_PLATFORM_UDP | Enables platform UDP support. |
|
||||
|
||||
@@ -70,6 +70,7 @@ MLR ?= 0
|
||||
MTD_NETDIAG ?= 0
|
||||
MULTIPLE_INSTANCE ?= 0
|
||||
NEIGHBOR_DISCOVERY_AGENT ?= 0
|
||||
NETDATA_PUBLISHER ?= 0
|
||||
OTNS ?= 0
|
||||
PING_SENDER ?= 1
|
||||
PLATFORM_UDP ?= 0
|
||||
@@ -265,6 +266,10 @@ ifeq ($(NEIGHBOR_DISCOVERY_AGENT),1)
|
||||
COMMONCFLAGS += -DOPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE=1
|
||||
endif
|
||||
|
||||
ifeq ($(NETDATA_PUBLISHER),1)
|
||||
COMMONCFLAGS += -DOPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE=1
|
||||
endif
|
||||
|
||||
ifeq ($(PING_SENDER),1)
|
||||
COMMONCFLAGS += -DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1
|
||||
endif
|
||||
|
||||
@@ -71,6 +71,7 @@ openthread_headers = \
|
||||
openthread/multi_radio.h \
|
||||
openthread/ncp.h \
|
||||
openthread/netdata.h \
|
||||
openthread/netdata_publisher.h \
|
||||
openthread/netdiag.h \
|
||||
openthread/network_time.h \
|
||||
openthread/ping_sender.h \
|
||||
|
||||
@@ -92,6 +92,7 @@ source_set("openthread") {
|
||||
"multi_radio.h",
|
||||
"ncp.h",
|
||||
"netdata.h",
|
||||
"netdata_publisher.h",
|
||||
"netdiag.h",
|
||||
"network_time.h",
|
||||
"ping_sender.h",
|
||||
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (146)
|
||||
#define OPENTHREAD_API_VERSION (147)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (c) 2021, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file defines the OpenThread Network Data Publisher API.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_NETDATA_PUBLISHER_H_
|
||||
#define OPENTHREAD_NETDATA_PUBLISHER_H_
|
||||
|
||||
#include <openthread/netdata.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup api-thread-general
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* The Network Data Publisher provides mechanisms to limit the number of similar Service and/or Prefix (on-mesh prefix
|
||||
* or external route) entries in the Thread Network Data by monitoring the Network Data and managing if or when to add
|
||||
* or remove entries.
|
||||
*
|
||||
* All the functions in this module require `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE` to be enabled.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This enumeration represents the events reported from the Publisher callbacks.
|
||||
*
|
||||
*/
|
||||
typedef enum otNetDataPublisherEvent
|
||||
{
|
||||
OT_NETDATA_PUBLISHER_EVENT_ENTRY_ADDED = 0, ///< Published entry is added to the Thread Network Data.
|
||||
OT_NETDATA_PUBLISHER_EVENT_ENTRY_REMOVED = 1, ///< Published entry is removed from the Thread Network Data.
|
||||
} otNetDataPublisherEvent;
|
||||
|
||||
/**
|
||||
* This function pointer type defines the callback used to notify when a "DNS/SRP Service" entry is added to or removed
|
||||
* from the Thread Network Data.
|
||||
*
|
||||
* On remove the callback is invoked independent of whether the entry is removed by `Publisher` (e.g., when there are
|
||||
* too many similar entries already present in the Network Data) or through an explicit call to unpublish the entry
|
||||
* (i.e., a call to `otNetDataUnpublishDnsSrpService()`).
|
||||
*
|
||||
* @param[in] aEvent Indicates the event (whether the entry was added or removed).
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
typedef void (*otNetDataDnsSrpServicePublisherCallback)(otNetDataPublisherEvent aEvent, void *aContext);
|
||||
|
||||
/**
|
||||
* This function pointer type defines the callback used to notify when a prefix (on-mesh or external route) entry is
|
||||
* added to or removed from the Thread Network Data.
|
||||
*
|
||||
* On remove the callback is invoked independent of whether the entry is removed by `Publisher` (e.g., when there are
|
||||
* too many similar entries already present in the Network Data) or through an explicit call to unpublish the entry.
|
||||
*
|
||||
* @param[in] aEvent Indicates the event (whether the entry was added or removed).
|
||||
* @param[in] aPrefix A pointer to the prefix entry.
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
typedef void (*otNetDataPrefixPublisherCallback)(otNetDataPublisherEvent aEvent,
|
||||
const otIp6Prefix * aPrefix,
|
||||
void * aContext);
|
||||
|
||||
/**
|
||||
* This function requests "DNS/SRP Service Anycast Address" to be published in the Thread Network Data.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` to be enabled.
|
||||
*
|
||||
* A call to this function will remove and replace any previous "DNS/SRP Service" entry that was being published (from
|
||||
* earlier call to any of `otNetDataPublishDnsSrpService{Type}()` functions).
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aSequenceNUmber The sequence number of DNS/SRP Anycast Service.
|
||||
*
|
||||
*/
|
||||
void otNetDataPublishDnsSrpServiceAnycast(otInstance *aInstance, uint8_t aSequenceNUmber);
|
||||
|
||||
/**
|
||||
* This function requests "DNS/SRP Service Unicast Address" to be published in the Thread Network Data.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` to be enabled.
|
||||
*
|
||||
* A call to this function will remove and replace any previous "DNS/SRP Service" entry that was being published (from
|
||||
* earlier call to any of `otNetDataPublishDnsSrpService{Type}()` functions).
|
||||
*
|
||||
* This function publishes the "DNS/SRP Service Unicast Address" by including the address and port info in the Service
|
||||
* TLV data.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aAddress The DNS/SRP server address to publish (MUST NOT be NULL).
|
||||
* @param[in] aPort The SRP server port number to publish.
|
||||
*
|
||||
*/
|
||||
void otNetDataPublishDnsSrpServiceUnicast(otInstance *aInstance, const otIp6Address *aAddress, uint16_t aPort);
|
||||
|
||||
/**
|
||||
* This function requests "DNS/SRP Service Unicast Address" to be published in the Thread Network Data.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` to be enabled.
|
||||
*
|
||||
* A call to this function will remove and replace any previous "DNS/SRP Service" entry that was being published (from
|
||||
* earlier call to any of `otNetDataPublishDnsSrpService{Type}()` functions).
|
||||
*
|
||||
* Unlike `otNetDataPublishDnsSrpServiceUnicast()` which requires the published address to be given and includes the
|
||||
* info in the Service TLV data, this function uses the device's mesh-local EID and includes the info in the Server TLV
|
||||
* data.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aPort The SRP server port number to publish.
|
||||
*
|
||||
*/
|
||||
void otNetDataPublishDnsSrpServiceUnicastMeshLocalEid(otInstance *aInstance, uint16_t aPort);
|
||||
|
||||
/**
|
||||
* This function indicates whether or not currently the "DNS/SRP Service" entry is added to the Thread Network Data.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @retval TRUE The published DNS/SRP Service entry is added to the Thread Network Data.
|
||||
* @retval FLASE The entry is not added to Thread Network Data or there is no entry to publish.
|
||||
*
|
||||
*/
|
||||
bool otNetDataIsDnsSrpServiceAdded(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This function sets a callback for notifying when a published "DNS/SRP Service" is actually added to or removed from
|
||||
* the Thread Network Data.
|
||||
*
|
||||
* A subsequent call to this function replaces any previously set callback function.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCallback The callback function pointer (can be NULL if not needed).
|
||||
* @param[in] aContext A pointer to application-specific context (used when @p aCallback is invoked).
|
||||
*
|
||||
*/
|
||||
void otNetDataSetDnsSrpServicePublisherCallback(otInstance * aInstance,
|
||||
otNetDataDnsSrpServicePublisherCallback aCallback,
|
||||
void * aContext);
|
||||
|
||||
/**
|
||||
* This function unpublishes any previously added "DNS/SRP (Anycast or Unicast) Service" entry from the Thread Network
|
||||
* Data.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
*/
|
||||
void otNetDataUnpublishDnsSrpService(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This function requests an on-mesh prefix to be published in the Thread Network Data.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE` to be enabled.
|
||||
*
|
||||
* Only stable entries can be published (i.e.,`aConfig.mStable` MUST be TRUE).
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aConfig The on-mesh prefix config to publish (MUST NOT be NULL).
|
||||
*
|
||||
* @retval OT_ERROR_NONE The on-mesh prefix is published successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
|
||||
* @retval OT_ERROR_ALREADY An entry with the same prefix is already in the published list.
|
||||
* @retval OT_ERROR_NO_BUFS Could not allocate an entry for the new request. Publisher supports a limited number
|
||||
* of entries (shared between on-mesh prefix and external route) determined by config
|
||||
* `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.
|
||||
*
|
||||
*
|
||||
*/
|
||||
otError otNetDataPublishOnMeshPrefix(otInstance *aInstance, const otBorderRouterConfig *aConfig);
|
||||
|
||||
/**
|
||||
* This function requests an external route prefix to be published in the Thread Network Data.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE` to be enabled.
|
||||
*
|
||||
* Only stable entries can be published (i.e.,`aConfig.mStable` MUST be TRUE).
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aConfig The external route config to publish (MUST NOT be NULL).
|
||||
*
|
||||
* @retval OT_ERROR_NONE The external route is published successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
|
||||
* @retval OT_ERROR_ALREADY An entry with the same prefix is already in the published list.
|
||||
* @retval OT_ERROR_NO_BUFS Could not allocate an entry for the new request. Publisher supports a limited number
|
||||
* of entries (shared between on-mesh prefix and external route) determined by config
|
||||
* `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.
|
||||
*/
|
||||
otError otNetDataPublishExternalRoute(otInstance *aInstance, const otExternalRouteConfig *aConfig);
|
||||
|
||||
/**
|
||||
* This function indicates whether or not currently a published prefix entry (on-mesh or external route) is added to
|
||||
* the Thread Network Data.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aPrefix A pointer to the prefix (MUST NOT be NULL).
|
||||
*
|
||||
* @retval TRUE The published prefix entry is added to the Thread Network Data.
|
||||
* @retval FLASE The entry is not added to Thread Network Data or there is no entry to publish.
|
||||
*
|
||||
*/
|
||||
bool otNetDataIsPrefixAdded(otInstance *aInstance, const otIp6Prefix *aPrefix);
|
||||
|
||||
/**
|
||||
* This function sets a callback for notifying when a published prefix entry is actually added to or removed from
|
||||
* the Thread Network Data.
|
||||
*
|
||||
* A subsequent call to this function replaces any previously set callback function.
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCallback The callback function pointer (can be NULL if not needed).
|
||||
* @param[in] aContext A pointer to application-specific context (used when @p aCallback is invoked).
|
||||
*
|
||||
*/
|
||||
void otNetDataSetPrefixPublisherCallback(otInstance * aInstance,
|
||||
otNetDataPrefixPublisherCallback aCallback,
|
||||
void * aContext);
|
||||
|
||||
/**
|
||||
* This function unpublishes a previously published prefix (on-mesh or external route).
|
||||
*
|
||||
* This function requires the feature `OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aPrefix The prefix to unpublish (MUST NOT be NULL).
|
||||
*
|
||||
* @retval OT_ERROR_NONE The prefix was unpublished successfully.
|
||||
* @retval OT_ERROR_NOT_FOUND Could not find the prefix in the published list.
|
||||
*
|
||||
*/
|
||||
otError otNetDataUnpublishPrefix(otInstance *aInstance, const otIp6Prefix *aPrefix);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_NETDATA_PUBLISHER_H_
|
||||
@@ -69,6 +69,7 @@ do_scan_build()
|
||||
"-DOPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_MPL_DYNAMIC_INTERVAL_ENABLE"
|
||||
"-DOPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT=1"
|
||||
"-DOPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
|
||||
"-DOPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE=1"
|
||||
|
||||
@@ -136,6 +136,7 @@ size_nrf52840_version()
|
||||
"-DOT_MAC_FILTER=ON"
|
||||
"-DOT_MESSAGE_USE_HEAP=ON"
|
||||
"-DOT_MTD_NETDIAG=ON"
|
||||
"-DOT_NETDATA_PUBLISHER=ON"
|
||||
"-DOT_PING_SENDER=ON"
|
||||
"-DOT_SERVICE=ON"
|
||||
"-DOT_SLAAC=ON"
|
||||
|
||||
@@ -89,6 +89,7 @@ readonly OT_POSIX_SIM_COMMON_OPTIONS=(
|
||||
"-DOT_MAC_FILTER=ON"
|
||||
"-DOT_MTD_NETDIAG=ON"
|
||||
"-DOT_NEIGHBOR_DISCOVERY_AGENT=ON"
|
||||
"-DOT_NETDATA_PUBLISHER=ON"
|
||||
"-DOT_PING_SENDER=ON"
|
||||
"-DOT_REFERENCE_DEVICE=ON"
|
||||
"-DOT_SERVICE=ON"
|
||||
|
||||
@@ -108,6 +108,7 @@ readonly OT_CLANG_TIDY_BUILD_OPTS=(
|
||||
'-DOT_LINK_METRICS_SUBJECT=ON'
|
||||
'-DOT_MAC_FILTER=ON'
|
||||
'-DOT_MTD_NETDIAG=ON'
|
||||
'-DOT_NETDATA_PUBLISHER=ON'
|
||||
'-DOT_PING_SENDER=ON'
|
||||
'-DOT_REFERENCE_DEVICE=ON'
|
||||
'-DOT_SERVICE=ON'
|
||||
|
||||
+11
-9
@@ -55,17 +55,18 @@ build_simulation()
|
||||
{
|
||||
local version="$1"
|
||||
local options=(
|
||||
"-DOT_MESSAGE_USE_HEAP=ON"
|
||||
"-DOT_THREAD_VERSION=${version}"
|
||||
"-DBUILD_TESTING=ON"
|
||||
"-DOT_REFERENCE_DEVICE=ON"
|
||||
"-DOT_SRP_SERVER=ON"
|
||||
"-DOT_SRP_CLIENT=ON"
|
||||
"-DOT_SERVICE=ON"
|
||||
"-DOT_ECDSA=ON"
|
||||
"-DOT_PING_SENDER=ON"
|
||||
"-DOT_DNSSD_SERVER=ON"
|
||||
"-DOT_DNS_CLIENT=ON"
|
||||
"-DOT_DNSSD_SERVER=ON"
|
||||
"-DOT_ECDSA=ON"
|
||||
"-DOT_MESSAGE_USE_HEAP=ON"
|
||||
"-DOT_NETDATA_PUBLISHER=ON"
|
||||
"-DOT_PING_SENDER=ON"
|
||||
"-DOT_REFERENCE_DEVICE=ON"
|
||||
"-DOT_SERVICE=ON"
|
||||
"-DOT_SRP_CLIENT=ON"
|
||||
"-DOT_SRP_SERVER=ON"
|
||||
"-DOT_THREAD_VERSION=${version}"
|
||||
)
|
||||
|
||||
if [[ ${FULL_LOGS} == 1 ]]; then
|
||||
@@ -269,6 +270,7 @@ do_build_otbr_docker()
|
||||
"-DOT_DNS_CLIENT=ON"
|
||||
"-DOT_DUA=ON"
|
||||
"-DOT_MLR=ON"
|
||||
"-DOT_NETDATA_PUBLISHER=ON"
|
||||
"-DOT_SLAAC=ON"
|
||||
"-DOT_SRP_CLIENT=ON"
|
||||
"-DOT_TREL=OFF"
|
||||
|
||||
+2
-1
@@ -2168,11 +2168,12 @@ Get the external route list in the local Network Data.
|
||||
Done
|
||||
```
|
||||
|
||||
### route add \<prefix\> [s][prf]
|
||||
### route add \<prefix\> [sn][prf]
|
||||
|
||||
Add a valid external route to the Network Data.
|
||||
|
||||
- s: Stable flag
|
||||
- n: NAT64 flag
|
||||
- prf: Default Router Preference, which may be: 'high', 'med', or 'low'.
|
||||
|
||||
```bash
|
||||
|
||||
@@ -142,9 +142,11 @@ After the device successfully attaches to a Thread network, the device will retr
|
||||
## Command List
|
||||
|
||||
- [help](#help)
|
||||
- [publish](#publish)
|
||||
- [register](#register)
|
||||
- [show](#show)
|
||||
- [steeringdata](#steeringdata-check-eui64discerner)
|
||||
- [unpublish](#unpublish)
|
||||
|
||||
## Command Details
|
||||
|
||||
@@ -157,9 +159,75 @@ Print netdata help menu.
|
||||
```bash
|
||||
> netdata help
|
||||
help
|
||||
publish
|
||||
register
|
||||
show
|
||||
steeringdata
|
||||
unpublish
|
||||
Done
|
||||
```
|
||||
|
||||
### publish
|
||||
|
||||
The Network Data Publisher provides mechanisms to limit the number of similar Service and/or Prefix (on-mesh prefix or external route) entries in the Thread Network Data by monitoring the Network Data and managing if or when to add or remove entries.
|
||||
|
||||
The Publisher requires `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE`.
|
||||
|
||||
### publish dnssrp
|
||||
|
||||
Publish DNS/SRP service entry.
|
||||
|
||||
This command requires `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE`.
|
||||
|
||||
The following formats are available: :
|
||||
|
||||
- `netdata publish dnssrp anycast <seq-num>` to publish "DNS/SRP Service Anycast Address" with a given sequence number.
|
||||
- `netdata publish dnssrp unicast <address> <port>` to publish "DNS/SRP Service Unicast Address" with given address and port number info. The address/port info is included in Service TLV data.
|
||||
- `netdata publish dnssrp unicast <port>` to publish "DNS/SRP Service Unicast Address" with given port number and the device's mesh-local EID for the address. The address and port info is included in Server TLV data.
|
||||
|
||||
A new call to `netdata publish dnssrp [anycast|unicast] [...]` command will remove and replace any previous "DNS/SRP Service" entry that was being published (from earlier `netdata publish dnssrp [...]` commands).
|
||||
|
||||
```bash
|
||||
> netdata publish dnssrp anycast 1
|
||||
Done
|
||||
|
||||
> netdata publish dnssrp unicast fd00::1234 51525
|
||||
Done
|
||||
|
||||
> netdata publish dnssrp unicast 50152
|
||||
Done
|
||||
```
|
||||
|
||||
### publish prefix \<prefix\> [padcrosnD][prf]
|
||||
|
||||
Publish an on-mesh prefix entry.
|
||||
|
||||
- p: Preferred flag
|
||||
- a: Stateless IPv6 Address Autoconfiguration flag
|
||||
- d: DHCPv6 IPv6 Address Configuration flag
|
||||
- c: DHCPv6 Other Configuration flag
|
||||
- r: Default Route flag
|
||||
- o: On Mesh flag
|
||||
- s: Stable flag
|
||||
- n: Nd Dns flag
|
||||
- D: Domain Prefix flag (only available for Thread 1.2).
|
||||
- prf: Preference, which may be 'high', 'med', or 'low'.
|
||||
|
||||
```bash
|
||||
> netdata publish prefix fd00:1234:5678::/64 paos med
|
||||
Done
|
||||
```
|
||||
|
||||
### publish route \<prefix\> [sn][prf]
|
||||
|
||||
Publish an external route entry.
|
||||
|
||||
- s: Stable flag
|
||||
- n: NAT64 flag
|
||||
- prf: Preference, which may be: 'high', 'med', or 'low'.
|
||||
|
||||
```bash
|
||||
> netdata publish route fd00:1234:5678::/64 s high
|
||||
Done
|
||||
```
|
||||
|
||||
@@ -212,3 +280,29 @@ Done
|
||||
> netdata steeringdata check 0xdef/12
|
||||
Error 23: NotFound
|
||||
```
|
||||
|
||||
### unpublish
|
||||
|
||||
This command unpublishes a previously published Network Data entry.
|
||||
|
||||
This command requires `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE`.
|
||||
|
||||
### unpublish dnssrp
|
||||
|
||||
Unpublishes DNS/SRP Service entry (available when `OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE` is enabled):
|
||||
|
||||
- `netdata unpublish dnssrp` to unpublish "DNS/SRP Service" entry (anycast or unciast).
|
||||
|
||||
```bash
|
||||
> netdata unpublish dnssrp
|
||||
Done
|
||||
```
|
||||
|
||||
### unpublish \<prefix\>
|
||||
|
||||
Unpublishes a previously published on-mesh prefix or external route entry.
|
||||
|
||||
```bash
|
||||
> netdata unpublish fd00:1234:5678::/64
|
||||
Done
|
||||
```
|
||||
|
||||
+45
-27
@@ -3302,29 +3302,28 @@ void Interpreter::HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx)
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
otError Interpreter::ProcessPrefixAdd(Arg aArgs[])
|
||||
otError Interpreter::ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otBorderRouterConfig config;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
memset(&config, 0, sizeof(otBorderRouterConfig));
|
||||
memset(&aConfig, 0, sizeof(otBorderRouterConfig));
|
||||
|
||||
SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(config.mPrefix));
|
||||
SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(aConfig.mPrefix));
|
||||
aArgs++;
|
||||
|
||||
for (; !aArgs->IsEmpty(); aArgs++)
|
||||
{
|
||||
if (*aArgs == "high")
|
||||
{
|
||||
config.mPreference = OT_ROUTE_PREFERENCE_HIGH;
|
||||
aConfig.mPreference = OT_ROUTE_PREFERENCE_HIGH;
|
||||
}
|
||||
else if (*aArgs == "med")
|
||||
{
|
||||
config.mPreference = OT_ROUTE_PREFERENCE_MED;
|
||||
aConfig.mPreference = OT_ROUTE_PREFERENCE_MED;
|
||||
}
|
||||
else if (*aArgs == "low")
|
||||
{
|
||||
config.mPreference = OT_ROUTE_PREFERENCE_LOW;
|
||||
aConfig.mPreference = OT_ROUTE_PREFERENCE_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3333,40 +3332,40 @@ otError Interpreter::ProcessPrefixAdd(Arg aArgs[])
|
||||
switch (*arg)
|
||||
{
|
||||
case 'p':
|
||||
config.mPreferred = true;
|
||||
aConfig.mPreferred = true;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
config.mSlaac = true;
|
||||
aConfig.mSlaac = true;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
config.mDhcp = true;
|
||||
aConfig.mDhcp = true;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
config.mConfigure = true;
|
||||
aConfig.mConfigure = true;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
config.mDefaultRoute = true;
|
||||
aConfig.mDefaultRoute = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
config.mOnMesh = true;
|
||||
aConfig.mOnMesh = true;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
config.mStable = true;
|
||||
aConfig.mStable = true;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
config.mNdDns = true;
|
||||
aConfig.mNdDns = true;
|
||||
break;
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
case 'D':
|
||||
config.mDp = true;
|
||||
aConfig.mDp = true;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -3376,6 +3375,16 @@ otError Interpreter::ProcessPrefixAdd(Arg aArgs[])
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Interpreter::ProcessPrefixAdd(Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otBorderRouterConfig config;
|
||||
|
||||
SuccessOrExit(error = ParsePrefix(aArgs, config));
|
||||
error = otBorderRouterAddOnMeshPrefix(mInstance, &config);
|
||||
|
||||
exit:
|
||||
@@ -3526,37 +3535,36 @@ otError Interpreter::ProcessRloc16(Arg aArgs[])
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
otError Interpreter::ProcessRouteAdd(Arg aArgs[])
|
||||
otError Interpreter::ParseRoute(Arg aArgs[], otExternalRouteConfig &aConfig)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otExternalRouteConfig config;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
memset(&config, 0, sizeof(otExternalRouteConfig));
|
||||
memset(&aConfig, 0, sizeof(otExternalRouteConfig));
|
||||
|
||||
SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(config.mPrefix));
|
||||
SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(aConfig.mPrefix));
|
||||
aArgs++;
|
||||
|
||||
for (; !aArgs->IsEmpty(); aArgs++)
|
||||
{
|
||||
if (*aArgs == "s")
|
||||
{
|
||||
config.mStable = true;
|
||||
aConfig.mStable = true;
|
||||
}
|
||||
else if (*aArgs == "n")
|
||||
{
|
||||
config.mNat64 = true;
|
||||
aConfig.mNat64 = true;
|
||||
}
|
||||
else if (*aArgs == "high")
|
||||
{
|
||||
config.mPreference = OT_ROUTE_PREFERENCE_HIGH;
|
||||
aConfig.mPreference = OT_ROUTE_PREFERENCE_HIGH;
|
||||
}
|
||||
else if (*aArgs == "med")
|
||||
{
|
||||
config.mPreference = OT_ROUTE_PREFERENCE_MED;
|
||||
aConfig.mPreference = OT_ROUTE_PREFERENCE_MED;
|
||||
}
|
||||
else if (*aArgs == "low")
|
||||
{
|
||||
config.mPreference = OT_ROUTE_PREFERENCE_LOW;
|
||||
aConfig.mPreference = OT_ROUTE_PREFERENCE_LOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3564,6 +3572,16 @@ otError Interpreter::ProcessRouteAdd(Arg aArgs[])
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Interpreter::ProcessRouteAdd(Arg aArgs[])
|
||||
{
|
||||
otError error;
|
||||
otExternalRouteConfig config;
|
||||
|
||||
SuccessOrExit(error = ParseRoute(aArgs, config));
|
||||
error = otBorderRouterAddRoute(mInstance, &config);
|
||||
|
||||
exit:
|
||||
|
||||
@@ -412,6 +412,10 @@ private:
|
||||
otError ParsePingInterval(const Arg &aArg, uint32_t &aInterval);
|
||||
#endif
|
||||
static otError ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscerner);
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
static otError ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig);
|
||||
static otError ParseRoute(Arg aArgs[], otExternalRouteConfig &aConfig);
|
||||
#endif
|
||||
|
||||
otError ProcessUserCommands(Arg aArgs[]);
|
||||
otError ProcessHelp(Arg aArgs[]);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "cli_network_data.hpp"
|
||||
|
||||
#include <openthread/border_router.h>
|
||||
#include <openthread/netdata_publisher.h>
|
||||
#include <openthread/server.h>
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
@@ -215,6 +216,100 @@ otError NetworkData::ProcessHelp(Arg aArgs[])
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
otError NetworkData::ProcessPublish(Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
if (aArgs[0] == "dnssrp")
|
||||
{
|
||||
if (aArgs[1] == "anycast")
|
||||
{
|
||||
uint8_t sequenceNumber;
|
||||
|
||||
SuccessOrExit(error = aArgs[2].ParseAsUint8(sequenceNumber));
|
||||
otNetDataPublishDnsSrpServiceAnycast(mInterpreter.mInstance, sequenceNumber);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (aArgs[1] == "unicast")
|
||||
{
|
||||
otIp6Address address;
|
||||
uint16_t port;
|
||||
|
||||
if (aArgs[3].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = aArgs[2].ParseAsUint16(port));
|
||||
otNetDataPublishDnsSrpServiceUnicastMeshLocalEid(mInterpreter.mInstance, port);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
SuccessOrExit(error = aArgs[2].ParseAsIp6Address(address));
|
||||
SuccessOrExit(error = aArgs[3].ParseAsUint16(port));
|
||||
otNetDataPublishDnsSrpServiceUnicast(mInterpreter.mInstance, &address, port);
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
if (aArgs[0] == "prefix")
|
||||
{
|
||||
otBorderRouterConfig config;
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParsePrefix(aArgs + 1, config));
|
||||
error = otNetDataPublishOnMeshPrefix(mInterpreter.mInstance, &config);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (aArgs[0] == "route")
|
||||
{
|
||||
otExternalRouteConfig config;
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseRoute(aArgs + 1, config));
|
||||
error = otNetDataPublishExternalRoute(mInterpreter.mInstance, &config);
|
||||
ExitNow();
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
|
||||
error = OT_ERROR_INVALID_ARGS;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NetworkData::ProcessUnpublish(Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
if (aArgs[0] == "dnssrp")
|
||||
{
|
||||
otNetDataUnpublishDnsSrpService(mInterpreter.mInstance);
|
||||
ExitNow();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
{
|
||||
otIp6Prefix prefix;
|
||||
|
||||
if (aArgs[0].ParseAsIp6Prefix(prefix) == OT_ERROR_NONE)
|
||||
{
|
||||
error = otNetDataUnpublishPrefix(mInterpreter.mInstance, &prefix);
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
error = OT_ERROR_INVALID_ARGS;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
otError NetworkData::ProcessRegister(Arg aArgs[])
|
||||
{
|
||||
|
||||
@@ -103,6 +103,10 @@ private:
|
||||
};
|
||||
|
||||
otError ProcessHelp(Arg aArgs[]);
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
otError ProcessPublish(Arg aArgs[]);
|
||||
otError ProcessUnpublish(Arg aArgs[]);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
otError ProcessRegister(Arg aArgs[]);
|
||||
#endif
|
||||
@@ -118,11 +122,16 @@ private:
|
||||
|
||||
static constexpr Command sCommands[] = {
|
||||
{"help", &NetworkData::ProcessHelp},
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
{"publish", &NetworkData::ProcessPublish},
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
{"register", &NetworkData::ProcessRegister},
|
||||
#endif
|
||||
{"show", &NetworkData::ProcessShow},
|
||||
{"steeringdata", &NetworkData::ProcessSteeringData},
|
||||
{"show", &NetworkData::ProcessShow}, {"steeringdata", &NetworkData::ProcessSteeringData},
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
{"unpublish", &NetworkData::ProcessUnpublish},
|
||||
#endif
|
||||
};
|
||||
|
||||
static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
|
||||
|
||||
@@ -327,6 +327,7 @@ openthread_core_files = [
|
||||
"api/message_api.cpp",
|
||||
"api/multi_radio_api.cpp",
|
||||
"api/netdata_api.cpp",
|
||||
"api/netdata_publisher_api.cpp",
|
||||
"api/netdiag_api.cpp",
|
||||
"api/network_time_api.cpp",
|
||||
"api/ping_sender_api.cpp",
|
||||
@@ -597,6 +598,8 @@ openthread_core_files = [
|
||||
"thread/network_data_local.hpp",
|
||||
"thread/network_data_notifier.cpp",
|
||||
"thread/network_data_notifier.hpp",
|
||||
"thread/network_data_publisher.cpp",
|
||||
"thread/network_data_publisher.hpp",
|
||||
"thread/network_data_service.cpp",
|
||||
"thread/network_data_service.hpp",
|
||||
"thread/network_data_tlvs.cpp",
|
||||
@@ -714,6 +717,7 @@ source_set("libopenthread_core_config") {
|
||||
"config/logging.h",
|
||||
"config/mac.h",
|
||||
"config/mle.h",
|
||||
"config/netdata_publisher.h",
|
||||
"config/openthread-core-config-check.h",
|
||||
"config/openthread-core-default-config.h",
|
||||
"config/parent_search.h",
|
||||
|
||||
@@ -63,6 +63,7 @@ set(COMMON_SOURCES
|
||||
api/message_api.cpp
|
||||
api/multi_radio_api.cpp
|
||||
api/netdata_api.cpp
|
||||
api/netdata_publisher_api.cpp
|
||||
api/netdiag_api.cpp
|
||||
api/network_time_api.cpp
|
||||
api/ping_sender_api.cpp
|
||||
@@ -195,6 +196,7 @@ set(COMMON_SOURCES
|
||||
thread/network_data_leader_ftd.cpp
|
||||
thread/network_data_local.cpp
|
||||
thread/network_data_notifier.cpp
|
||||
thread/network_data_publisher.cpp
|
||||
thread/network_data_service.cpp
|
||||
thread/network_data_tlvs.cpp
|
||||
thread/network_data_types.cpp
|
||||
|
||||
@@ -140,6 +140,7 @@ SOURCES_COMMON = \
|
||||
api/message_api.cpp \
|
||||
api/multi_radio_api.cpp \
|
||||
api/netdata_api.cpp \
|
||||
api/netdata_publisher_api.cpp \
|
||||
api/netdiag_api.cpp \
|
||||
api/network_time_api.cpp \
|
||||
api/ping_sender_api.cpp \
|
||||
@@ -272,6 +273,7 @@ SOURCES_COMMON = \
|
||||
thread/network_data_leader_ftd.cpp \
|
||||
thread/network_data_local.cpp \
|
||||
thread/network_data_notifier.cpp \
|
||||
thread/network_data_publisher.cpp \
|
||||
thread/network_data_service.cpp \
|
||||
thread/network_data_tlvs.cpp \
|
||||
thread/network_data_types.cpp \
|
||||
@@ -435,6 +437,7 @@ HEADERS_COMMON = \
|
||||
config/logging.h \
|
||||
config/mac.h \
|
||||
config/mle.h \
|
||||
config/netdata_publisher.h \
|
||||
config/openthread-core-config-check.h \
|
||||
config/openthread-core-default-config.h \
|
||||
config/parent_search.h \
|
||||
@@ -538,6 +541,7 @@ HEADERS_COMMON = \
|
||||
thread/network_data_leader_ftd.hpp \
|
||||
thread/network_data_local.hpp \
|
||||
thread/network_data_notifier.hpp \
|
||||
thread/network_data_publisher.hpp \
|
||||
thread/network_data_service.hpp \
|
||||
thread/network_data_tlvs.hpp \
|
||||
thread/network_data_types.hpp \
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2021, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the OpenThread Network Data Publisher API.
|
||||
*/
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
|
||||
#include <openthread/netdata_publisher.h>
|
||||
|
||||
#include "common/instance.hpp"
|
||||
#include "common/locator_getters.hpp"
|
||||
|
||||
using namespace ot;
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
void otNetDataPublishDnsSrpServiceAnycast(otInstance *aInstance, uint8_t aSequenceNumber)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
instance.Get<NetworkData::Publisher>().PublishDnsSrpServiceAnycast(aSequenceNumber);
|
||||
}
|
||||
|
||||
void otNetDataPublishDnsSrpServiceUnicast(otInstance *aInstance, const otIp6Address *aAddress, uint16_t aPort)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
instance.Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(*static_cast<const Ip6::Address *>(aAddress),
|
||||
aPort);
|
||||
}
|
||||
|
||||
void otNetDataPublishDnsSrpServiceUnicastMeshLocalEid(otInstance *aInstance, uint16_t aPort)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
instance.Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(aPort);
|
||||
}
|
||||
|
||||
bool otNetDataIsDnsSrpServiceAdded(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkData::Publisher>().IsDnsSrpServiceAdded();
|
||||
}
|
||||
|
||||
void otNetDataSetDnsSrpServicePublisherCallback(otInstance * aInstance,
|
||||
otNetDataDnsSrpServicePublisherCallback aCallback,
|
||||
void * aContext)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
instance.Get<NetworkData::Publisher>().SetDnsSrpServiceCallback(aCallback, aContext);
|
||||
}
|
||||
|
||||
void otNetDataUnpublishDnsSrpService(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
instance.Get<NetworkData::Publisher>().UnpublishDnsSrpService();
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
|
||||
otError otNetDataPublishOnMeshPrefix(otInstance *aInstance, const otBorderRouterConfig *aConfig)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkData::Publisher>().PublishOnMeshPrefix(
|
||||
*static_cast<const NetworkData::OnMeshPrefixConfig *>(aConfig));
|
||||
}
|
||||
|
||||
otError otNetDataPublishExternalRoute(otInstance *aInstance, const otExternalRouteConfig *aConfig)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkData::Publisher>().PublishExternalRoute(
|
||||
*static_cast<const NetworkData::ExternalRouteConfig *>(aConfig));
|
||||
}
|
||||
|
||||
bool otNetDataIsPrefixAdded(otInstance *aInstance, const otIp6Prefix *aPrefix)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkData::Publisher>().IsPrefixAdded(*static_cast<const Ip6::Prefix *>(aPrefix));
|
||||
}
|
||||
|
||||
void otNetDataSetPrefixPublisherCallback(otInstance * aInstance,
|
||||
otNetDataPrefixPublisherCallback aCallback,
|
||||
void * aContext)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkData::Publisher>().SetPrefixCallback(aCallback, aContext);
|
||||
}
|
||||
|
||||
otError otNetDataUnpublishPrefix(otInstance *aInstance, const otIp6Prefix *aPrefix)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<NetworkData::Publisher>().UnpublishPrefix(*static_cast<const Ip6::Prefix *>(aPrefix));
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
@@ -187,6 +187,8 @@ Error Local::AddService(bool aForce)
|
||||
serverData.SetMlrTimeout(mMlrTimeout);
|
||||
|
||||
SuccessOrExit(error = Get<NetworkData::Service::Manager>().Add<NetworkData::Service::BackboneRouter>(serverData));
|
||||
Get<NetworkData::Notifier>().HandleServerDataUpdated();
|
||||
|
||||
mIsServiceAdded = true;
|
||||
|
||||
exit:
|
||||
@@ -199,6 +201,7 @@ void Local::RemoveService(void)
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Get<NetworkData::Service::Manager>().Remove<NetworkData::Service::BackboneRouter>());
|
||||
Get<NetworkData::Notifier>().HandleServerDataUpdated();
|
||||
mIsServiceAdded = false;
|
||||
|
||||
exit:
|
||||
|
||||
@@ -640,6 +640,13 @@ template <> inline NetworkData::Notifier &Instance::Get(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
template <> inline NetworkData::Publisher &Instance::Get(void)
|
||||
{
|
||||
return mThreadNetif.mNetworkDataPublisher;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <> inline NetworkData::Service::Manager &Instance::Get(void)
|
||||
{
|
||||
return mThreadNetif.mNetworkDataServiceManager;
|
||||
|
||||
@@ -183,12 +183,15 @@ void Notifier::EmitEvents(void)
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
Get<BorderRouter::RoutingManager>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
|
||||
Get<Srp::Server>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
|
||||
Get<Srp::Client>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
// The `NetworkData::Publisher` is notified last (e.g., after SRP
|
||||
// client) to allow other modules to request changes to what is
|
||||
// being published (if needed).
|
||||
Get<NetworkData::Publisher>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
|
||||
for (ExternalCallback &callback : mExternalCallbacks)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2021, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes compile-time configurations for Network Data Publisher.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_NETDATA_PUBLISHER_H_
|
||||
#define CONFIG_NETDATA_PUBLISHER_H_
|
||||
|
||||
#include "config/srp_server.h"
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
*
|
||||
* Define to 1 to enable Network Data Publisher.
|
||||
*
|
||||
* Network Data Publisher provides mechanisms to limit the number of similar Service and/or Prefix (on-mesh prefix
|
||||
* or external route) entries in the Thread Network Data by monitoring the Network Data and managing if or when to add
|
||||
* or remove entries.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_ADD
|
||||
*
|
||||
* Specifies the maximum value (in milliseconds) of the random delay used before adding an entry in the Thread Network
|
||||
* Data.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_ADD
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_ADD 3500
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_REMOVE
|
||||
*
|
||||
* Specifies the maximum value (in milliseconds) of the random wait time used before removing an entry from the Thread
|
||||
* Network Data.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_REMOVE
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_REMOVE 15000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_EXTRA_DELAY_TIME_TO_REMOVE_PREFERRED
|
||||
*
|
||||
* Specifies the extra wait time (in milliseconds) used when removing a preferred entry.
|
||||
*
|
||||
* When removing entries, certain entries are preferred over others. How the preference is determined depends on the
|
||||
* entry type (e.g., (for DNS/SRP service entries associated with smaller RLOC16 or smaller IPv6 address are preferred).
|
||||
* If the `Publisher` determines that its own entry is a preferred one, it adds the above extra wait time in addition
|
||||
* to the random wait selected based on `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_REMOVE` before removing
|
||||
* its entry. This gives higher chance for a non-preferred entry from another device to be removed before removing a
|
||||
* preferred entry which helps towards quicker convergence of the process to the desired number of entries.
|
||||
*
|
||||
* It is recommended that `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_EXTRA_DELAY_TIME_TO_REMOVE_PREFERRED` to be set to a
|
||||
* value larger than `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_REMOVE` to ensure that non-preferred entries
|
||||
* are removed first.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_EXTRA_DELAY_TIME_TO_REMOVE_PREFERRED
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_EXTRA_DELAY_TIME_TO_REMOVE_PREFERRED 16000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_ANYCAST_DNS_SRP_SERVICE_ENTRIES
|
||||
*
|
||||
* Specifies the desired number of "DNS/SRP Service Anycast Address" entries in the Thread Network Data.
|
||||
*
|
||||
* Publisher attempts to limit the number of such entries to this value.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_ANYCAST_DNS_SRP_SERVICE_ENTRIES
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_ANYCAST_DNS_SRP_SERVICE_ENTRIES 8
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_UNICAST_DNS_SRP_SERVICE_ENTRIES
|
||||
*
|
||||
* Specifies the desired number of "DNS/SRP Service Anycast Address" entries in the Thread Network Data.
|
||||
*
|
||||
* Publisher attempts to limit the number of such entries to this value.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_UNICAST_DNS_SRP_SERVICE_ENTRIES
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_UNICAST_DNS_SRP_SERVICE_ENTRIES 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_ON_MESH_PREFIX_ENTRIES
|
||||
*
|
||||
* Specifies the desired number of matching On-mesh Prefix entries in the Thread Network Data.
|
||||
*
|
||||
* Publisher attempts to limit the number of matching entries to this value.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_ON_MESH_PREFIX_ENTRIES
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_ON_MESH_PREFIX_ENTRIES 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_EXTERNAL_ROUTE_ENTRIES
|
||||
*
|
||||
* Specifies the desired number of matching External Route entries in the Thread Network Data.
|
||||
*
|
||||
* Publisher attempts to limit the number of matching entries to this value.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_EXTERNAL_ROUTE_ENTRIES
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_EXTERNAL_ROUTE_ENTRIES 10
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES
|
||||
*
|
||||
* Specifies maximum number of prefix (on-mesh prefix or external route) entries supported by Publisher.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES 3
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_NETDATA_PUBLISHER_H_
|
||||
+50
-58
@@ -41,7 +41,6 @@
|
||||
#include "common/new.hpp"
|
||||
#include "common/random.hpp"
|
||||
#include "net/dns_types.hpp"
|
||||
#include "thread/network_data_service.hpp"
|
||||
#include "thread/thread_netif.hpp"
|
||||
|
||||
namespace ot {
|
||||
@@ -87,7 +86,8 @@ Server::Server(Instance &aInstance)
|
||||
, mLeaseTimer(aInstance, HandleLeaseTimer)
|
||||
, mOutstandingUpdatesTimer(aInstance, HandleOutstandingUpdatesTimer)
|
||||
, mServiceUpdateId(Random::NonCrypto::GetUint32())
|
||||
, mEnabled(false)
|
||||
, mPort(kUdpPortMin)
|
||||
, mState(kStateDisabled)
|
||||
, mHasRegisteredAnyService(false)
|
||||
{
|
||||
IgnoreError(SetDomain(kDefaultDomain));
|
||||
@@ -101,17 +101,27 @@ void Server::SetServiceHandler(otSrpServerServiceUpdateHandler aServiceHandler,
|
||||
|
||||
void Server::SetEnabled(bool aEnabled)
|
||||
{
|
||||
VerifyOrExit(mEnabled != aEnabled);
|
||||
|
||||
mEnabled = aEnabled;
|
||||
|
||||
if (!mEnabled)
|
||||
if (aEnabled)
|
||||
{
|
||||
Stop();
|
||||
VerifyOrExit(mState == kStateDisabled);
|
||||
mState = kStateStopped;
|
||||
|
||||
// Select a port and then publish "DNS/SRP Unicast Address
|
||||
// Service" in Thread Network Data using the device's
|
||||
// mesh-local EID as the address. Then wait for callback
|
||||
// `HandleNetDataPublisherEntryChange()` from to `Publisher` to
|
||||
// start server operation when entry is published (i.e., added
|
||||
// to the Network Data).
|
||||
|
||||
SelectPort();
|
||||
Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(mPort);
|
||||
}
|
||||
else if (Get<Mle::MleRouter>().IsAttached())
|
||||
else
|
||||
{
|
||||
Start();
|
||||
VerifyOrExit(mState != kStateDisabled);
|
||||
Get<NetworkData::Publisher>().UnpublishDnsSrpService();
|
||||
Stop();
|
||||
mState = kStateDisabled;
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -174,7 +184,7 @@ Error Server::SetDomain(const char *aDomain)
|
||||
Error error = kErrorNone;
|
||||
uint16_t length;
|
||||
|
||||
VerifyOrExit(!mEnabled, error = kErrorInvalidState);
|
||||
VerifyOrExit(mState == kStateDisabled, error = kErrorInvalidState);
|
||||
|
||||
length = StringLength(aDomain, Dns::Name::kMaxNameSize);
|
||||
VerifyOrExit((length > 0) && (length < Dns::Name::kMaxNameSize), error = kErrorInvalidArgs);
|
||||
@@ -407,12 +417,9 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
void Server::Start(void)
|
||||
void Server::SelectPort(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t port = kUdpPortMin;
|
||||
|
||||
VerifyOrExit(!IsRunning());
|
||||
mPort = kUdpPortMin;
|
||||
|
||||
#if OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
|
||||
{
|
||||
@@ -420,35 +427,44 @@ void Server::Start(void)
|
||||
|
||||
if (Get<Settings>().Read(info) == kErrorNone)
|
||||
{
|
||||
port = info.GetPort() + 1;
|
||||
if (port < kUdpPortMin || port > kUdpPortMax)
|
||||
mPort = info.GetPort() + 1;
|
||||
if (mPort < kUdpPortMin || mPort > kUdpPortMax)
|
||||
{
|
||||
port = kUdpPortMin;
|
||||
mPort = kUdpPortMin;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SuccessOrExit(error = mSocket.Open(HandleUdpReceive, this));
|
||||
SuccessOrExit(error = mSocket.Bind(port, OT_NETIF_THREAD));
|
||||
SuccessOrExit(error = PublishServerData());
|
||||
otLogInfoSrp("[server] selected port %u", mPort);
|
||||
}
|
||||
|
||||
otLogInfoSrp("[server] start listening on port %hu", mSocket.GetSockName().mPort);
|
||||
void Server::Start(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(mState == kStateStopped);
|
||||
|
||||
mState = kStateRunning;
|
||||
|
||||
SuccessOrExit(error = mSocket.Open(HandleUdpReceive, this));
|
||||
SuccessOrExit(error = mSocket.Bind(mPort, OT_NETIF_THREAD));
|
||||
|
||||
otLogInfoSrp("[server] start listening on port %u", mPort);
|
||||
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
otLogCritSrp("[server] failed to start: %s", ErrorToString(error));
|
||||
// Cleanup any resources we may have allocated.
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void Server::Stop(void)
|
||||
{
|
||||
VerifyOrExit(IsRunning());
|
||||
VerifyOrExit(mState == kStateRunning);
|
||||
|
||||
UnpublishServerData();
|
||||
mState = kStateStopped;
|
||||
|
||||
while (!mHosts.IsEmpty())
|
||||
{
|
||||
@@ -465,7 +481,7 @@ void Server::Stop(void)
|
||||
mLeaseTimer.Stop();
|
||||
mOutstandingUpdatesTimer.Stop();
|
||||
|
||||
otLogInfoSrp("[server] stop listening on %hu", mSocket.GetSockName().mPort);
|
||||
otLogInfoSrp("[server] stop listening on %u", mPort);
|
||||
IgnoreError(mSocket.Close());
|
||||
mHasRegisteredAnyService = false;
|
||||
|
||||
@@ -473,41 +489,17 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Server::HandleNotifierEvents(Events aEvents)
|
||||
void Server::HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent)
|
||||
{
|
||||
VerifyOrExit(mEnabled);
|
||||
VerifyOrExit(aEvents.Contains(kEventThreadRoleChanged));
|
||||
|
||||
if (Get<Mle::MleRouter>().IsAttached())
|
||||
switch (aEvent)
|
||||
{
|
||||
case NetworkData::Publisher::kEventEntryAdded:
|
||||
Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
case NetworkData::Publisher::kEventEntryRemoved:
|
||||
Stop();
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error Server::PublishServerData(void)
|
||||
{
|
||||
NetworkData::Service::DnsSrpUnicast::ServerData serverData(Get<Mle::Mle>().GetMeshLocal64(),
|
||||
mSocket.GetSockName().GetPort());
|
||||
|
||||
OT_ASSERT(mSocket.IsBound());
|
||||
|
||||
return Get<NetworkData::Service::Manager>().Add<NetworkData::Service::DnsSrpUnicast>(serverData);
|
||||
}
|
||||
|
||||
void Server::UnpublishServerData(void)
|
||||
{
|
||||
Error error = Get<NetworkData::Service::Manager>().Remove<NetworkData::Service::DnsSrpUnicast>();
|
||||
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
otLogWarnSrp("[server] failed to unpublish SRP service: %s", ErrorToString(error));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,10 @@
|
||||
#error "OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
|
||||
#endif
|
||||
|
||||
#if !OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
#error "OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
|
||||
#endif
|
||||
|
||||
#if !OPENTHREAD_CONFIG_ECDSA_ENABLE
|
||||
#error "OPENTHREAD_CONFIG_ECDSA_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
|
||||
#endif
|
||||
@@ -61,6 +65,7 @@
|
||||
#include "net/ip6.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
#include "net/udp6.hpp"
|
||||
#include "thread/network_data_publisher.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Srp {
|
||||
@@ -71,7 +76,7 @@ namespace Srp {
|
||||
*/
|
||||
class Server : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
friend class ot::Notifier;
|
||||
friend class NetworkData::Publisher;
|
||||
friend class UpdateMetadata;
|
||||
friend class Service;
|
||||
friend class Host;
|
||||
@@ -593,7 +598,7 @@ public:
|
||||
* @returns A boolean that indicates whether the server is running.
|
||||
*
|
||||
*/
|
||||
bool IsRunning(void) const { return mSocket.IsBound(); }
|
||||
bool IsRunning(void) const { return (mState == kStateRunning); }
|
||||
|
||||
/**
|
||||
* This method enables/disables the SRP server.
|
||||
@@ -655,6 +660,13 @@ private:
|
||||
static constexpr uint32_t kDefaultMaxKeyLease = 3600u * 24 * 14; // 14 days (in seconds).
|
||||
static constexpr uint32_t kDefaultEventsHandlerTimeout = OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT;
|
||||
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateDisabled,
|
||||
kStateRunning,
|
||||
kStateStopped,
|
||||
};
|
||||
|
||||
// This class includes metadata for processing a SRP update (register, deregister)
|
||||
// and sending DNS response to the client.
|
||||
class UpdateMetadata : public InstanceLocator, public LinkedListEntry<UpdateMetadata>
|
||||
@@ -688,11 +700,10 @@ private:
|
||||
UpdateMetadata * mNext;
|
||||
};
|
||||
|
||||
void Start(void);
|
||||
void Stop(void);
|
||||
void HandleNotifierEvents(Events aEvents);
|
||||
Error PublishServerData(void);
|
||||
void UnpublishServerData(void);
|
||||
void Start(void);
|
||||
void Stop(void);
|
||||
void SelectPort(void);
|
||||
void HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent);
|
||||
|
||||
ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; }
|
||||
|
||||
@@ -778,7 +789,8 @@ private:
|
||||
LinkedList<UpdateMetadata> mOutstandingUpdates;
|
||||
|
||||
ServiceUpdateId mServiceUpdateId;
|
||||
bool mEnabled : 1;
|
||||
uint16_t mPort;
|
||||
State mState;
|
||||
bool mHasRegisteredAnyService : 1;
|
||||
};
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
#include "config/logging.h"
|
||||
#include "config/mac.h"
|
||||
#include "config/mle.h"
|
||||
#include "config/netdata_publisher.h"
|
||||
#include "config/parent_search.h"
|
||||
#include "config/ping_sender.h"
|
||||
#include "config/platform.h"
|
||||
|
||||
@@ -106,6 +106,7 @@ constexpr Iterator kIteratorInit = OT_NETWORK_DATA_ITERATOR_INIT; ///< Initializ
|
||||
class NetworkData : public InstanceLocator
|
||||
{
|
||||
friend class Service::Manager;
|
||||
friend class Publisher;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kMaxSize = 254; ///< Maximum size of Thread Network Data in bytes.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* Copyright (c) 2021, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definition of Network Data Publisher.
|
||||
*/
|
||||
|
||||
#ifndef NETWORK_DATA_PUBLISHER_HPP_
|
||||
#define NETWORK_DATA_PUBLISHER_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
|
||||
#if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE && !OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
#error "OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE requires either OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE"\
|
||||
"or OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE"
|
||||
#endif
|
||||
|
||||
#include <openthread/netdata_publisher.h>
|
||||
|
||||
#include "common/clearable.hpp"
|
||||
#include "common/equatable.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/non_copyable.hpp"
|
||||
#include "common/notifier.hpp"
|
||||
#include "common/string.hpp"
|
||||
#include "common/timer.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
#include "thread/network_data_types.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace NetworkData {
|
||||
|
||||
/**
|
||||
* This class implements the Network Data Publisher.
|
||||
*
|
||||
* It provides mechanisms to limit the number of similar Service and/or Prefix (on-mesh prefix or external route)
|
||||
* entries in the Thread Network Data by monitoring the Network Data and managing if or when to add or remove entries.
|
||||
*
|
||||
*/
|
||||
class Publisher : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
friend class ot::Notifier;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This enumeration represents the events reported from the Publisher callbacks.
|
||||
*
|
||||
*/
|
||||
enum Event : uint8_t
|
||||
{
|
||||
kEventEntryAdded = OT_NETDATA_PUBLISHER_EVENT_ENTRY_ADDED, ///< Entry is added to Network Data.
|
||||
kEventEntryRemoved = OT_NETDATA_PUBLISHER_EVENT_ENTRY_REMOVED, ///< Entry is removed from Network Data.
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes `Publisher` object.
|
||||
*
|
||||
* @param[in] aInstance A reference to the OpenThread instance.
|
||||
*
|
||||
*/
|
||||
explicit Publisher(Instance &aInstance);
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
/**
|
||||
* This type represents the callback function pointer used to notify when a "DNS/SRP Service" entry is added to or
|
||||
* removed from the Thread Network Data.
|
||||
*
|
||||
* On remove the callback is invoked independent of whether the entry is removed by `Publisher` (e.g., when there
|
||||
* are too many similar entries already present in the Network Data) or through an explicit call to unpublish the
|
||||
* entry (i.e., a call to `UnpublishDnsSrpService()`).
|
||||
*
|
||||
*/
|
||||
typedef otNetDataDnsSrpServicePublisherCallback DnsSrpServiceCallback;
|
||||
|
||||
/**
|
||||
* This method sets a callback for notifying when a published "DNS/SRP Service" is actually added to or removed
|
||||
* from the Thread Network Data.
|
||||
*
|
||||
* A subsequent call to this method replaces any previously set callback function.
|
||||
*
|
||||
* @param[in] aCallback The callback function pointer (can be NULL if not needed).
|
||||
* @param[in] aContext A pointer to application-specific context (used when @p aCallback is invoked).
|
||||
*
|
||||
*/
|
||||
void SetDnsSrpServiceCallback(DnsSrpServiceCallback aCallback, void *aContext)
|
||||
{
|
||||
mDnsSrpServiceEntry.SetCallback(aCallback, aContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method requests "DNS/SRP Service Anycast Address" to be published in the Thread Network Data.
|
||||
*
|
||||
* A call to this method will remove and replace any previous "DNS/SRP Service" entry that was being published
|
||||
* (from earlier call to any of `PublishDnsSrpService{Type}()` methods).
|
||||
*
|
||||
* @param[in] aSequenceNumber The sequence number of DNS/SRP Anycast Service.
|
||||
*
|
||||
*/
|
||||
void PublishDnsSrpServiceAnycast(uint8_t aSequenceNumber) { mDnsSrpServiceEntry.PublishAnycast(aSequenceNumber); }
|
||||
|
||||
/**
|
||||
* This method requests "DNS/SRP Service Unicast Address" to be published in the Thread Network Data.
|
||||
*
|
||||
* A call to this method will remove and replace any previous "DNS/SRP Service" entry that was being published
|
||||
* (from earlier call to any of `PublishDnsSrpService{Type}()` methods).
|
||||
*
|
||||
* This method publishes the "DNS/SRP Service Unicast Address" by including the address and port info in the
|
||||
* Service TLV data.
|
||||
*
|
||||
* @param[in] aAddress The DNS/SRP server address to publish.
|
||||
* @param[in] aPort The SRP server port number to publish.
|
||||
*
|
||||
*/
|
||||
void PublishDnsSrpServiceUnicast(const Ip6::Address &aAddress, uint16_t aPort)
|
||||
{
|
||||
mDnsSrpServiceEntry.PublishUnicast(aAddress, aPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method requests "DNS/SRP Service Unicast Address" to be published in the Thread Network Data.
|
||||
*
|
||||
* A call to this method will remove and replace any previous "DNS/SRP Service" entry that was being published
|
||||
* (from earlier call to any of `PublishDnsSrpService{Type}()` methods).
|
||||
*
|
||||
* Unlike the `PublishDnsSrpServiceUnicast(aAddress, aPort)` which requires the published address to be given and
|
||||
* includes the info in the Service TLV data, this method uses the device's mesh-local EID and includes the info
|
||||
* in the Server TLV data.
|
||||
*
|
||||
* @param[in] aPort The SRP server port number to publish.
|
||||
*
|
||||
*/
|
||||
void PublishDnsSrpServiceUnicast(uint16_t aPort) { mDnsSrpServiceEntry.PublishUnicast(aPort); }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not currently the "DNS/SRP Service" entry is added to the Thread Network Data.
|
||||
*
|
||||
* @retval TRUE The published DNS/SRP Service entry is added to the Thread Network Data.
|
||||
* @retval FLASE The entry is not added to Thread Network Data or there is no entry to publish.
|
||||
*
|
||||
*/
|
||||
bool IsDnsSrpServiceAdded(void) const { return mDnsSrpServiceEntry.IsAdded(); }
|
||||
|
||||
/**
|
||||
* This method unpublishes any previously added "DNS/SRP (Anycast or Unicast) Service" entry from the Thread
|
||||
* Network Data.
|
||||
*
|
||||
*/
|
||||
void UnpublishDnsSrpService(void) { mDnsSrpServiceEntry.Unpublish(); }
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
/**
|
||||
* This type represents the callback function pointer used to notify when a prefix (on-mesh or external route)
|
||||
* entry is added to or removed from the Thread Network Data.
|
||||
*
|
||||
* On remove the callback is invoked independent of whether the entry is removed by `Publisher` (e.g., when there
|
||||
* are too many similar entries already present in the Network Data) or through an explicit call to unpublish the
|
||||
* entry.
|
||||
*
|
||||
*/
|
||||
typedef otNetDataPrefixPublisherCallback PrefixCallback;
|
||||
|
||||
/**
|
||||
* This method sets a callback for notifying when a published prefix entry is actually added to or removed from
|
||||
* the Thread Network Data.
|
||||
*
|
||||
* A subsequent call to this method replaces any previously set callback function.
|
||||
*
|
||||
* @param[in] aCallback The callback function pointer (can be NULL if not needed).
|
||||
* @param[in] aContext A pointer to application-specific context (used when @p aCallback is invoked).
|
||||
*
|
||||
*/
|
||||
void SetPrefixCallback(PrefixCallback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* This method requests an on-mesh prefix to be published in the Thread Network Data.
|
||||
*
|
||||
* Only stable entries can be published (i.e.,`aConfig.mStable` MUST be `true`).
|
||||
*
|
||||
* @param[in] aConfig The on-mesh prefix config to publish.
|
||||
*
|
||||
* @retval kErrorNone The on-mesh prefix is published successfully.
|
||||
* @retval kErrorInvalidArgs The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
|
||||
* @retval kErrorAlready An entry with the same prefix is already in the published list.
|
||||
* @retval kErrorNoBufs Could not allocate an entry for the new request. Publisher supports a limited number
|
||||
* of entries (shared between on-mesh prefix and external route) determined by config
|
||||
* `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.
|
||||
*
|
||||
*
|
||||
*/
|
||||
Error PublishOnMeshPrefix(const OnMeshPrefixConfig &aConfig);
|
||||
|
||||
/**
|
||||
* This method requests an external route prefix to be published in the Thread Network Data.
|
||||
*
|
||||
* Only stable entries can be published (i.e.,`aConfig.mStable` MUST be `true`).
|
||||
*
|
||||
* @param[in] aConfig The external route config to publish.
|
||||
*
|
||||
* @retval kErrorNone The external route is published successfully.
|
||||
* @retval kErrorInvalidArgs The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
|
||||
* @retval kErrorAlready An entry with the same prefix is already in the published list.
|
||||
* @retval kErrorNoBufs Could not allocate an entry for the new request. Publisher supports a limited number
|
||||
* of entries (shared between on-mesh prefix and external route) determined by config
|
||||
* `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.
|
||||
*
|
||||
*
|
||||
*/
|
||||
Error PublishExternalRoute(const ExternalRouteConfig &aConfig);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not currently a published prefix entry (on-mesh or external route) is added to
|
||||
* the Thread Network Data.
|
||||
*
|
||||
* @param[in] aPrefix The prefix to check.
|
||||
*
|
||||
* @retval TRUE The published prefix entry is added to the Thread Network Data.
|
||||
* @retval FLASE The entry is not added to Thread Network Data or there is no matching entry to publish.
|
||||
*
|
||||
*/
|
||||
bool IsPrefixAdded(const Ip6::Prefix &aPrefix) const;
|
||||
|
||||
/**
|
||||
* This method unpublishes a previously published prefix (on-mesh or external route).
|
||||
*
|
||||
* @param[in] aPrefix The prefix to unpublish.
|
||||
*
|
||||
* @retval kErrorNone The prefix was unpublished successfully.
|
||||
* @retval kErrorNotFound Could not find the prefix in the published list.
|
||||
*
|
||||
*/
|
||||
Error UnpublishPrefix(const Ip6::Prefix &aPrefix);
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
|
||||
private:
|
||||
class Entry : public InstanceLocatorInit
|
||||
{
|
||||
protected:
|
||||
enum State : uint8_t
|
||||
{
|
||||
kNoEntry, // Entry is unused (there is no entry).
|
||||
kToAdd, // Entry is ready to be added, monitoring network data to decide if/when to add it.
|
||||
kAdding, // Entry is being added in network data (random wait interval before add).
|
||||
kAdded, // Entry is added in network data, monitoring to determine if/when to remove.
|
||||
kRemoving, // Entry is being removed from network data (random wait interval before remove).
|
||||
};
|
||||
|
||||
// All intervals are in milliseconds.
|
||||
static constexpr uint32_t kMaxDelayToAdd = OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_ADD;
|
||||
static constexpr uint32_t kMaxDelayToRemove = OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_DELAY_TO_REMOVE;
|
||||
static constexpr uint32_t kExtraDelayToRemovePeferred =
|
||||
OPENTHREAD_CONFIG_NETDATA_PUBLISHER_EXTRA_DELAY_TIME_TO_REMOVE_PREFERRED;
|
||||
|
||||
static constexpr uint16_t kInfoStringSize = 50;
|
||||
|
||||
typedef String<kInfoStringSize> InfoString;
|
||||
|
||||
Entry(void)
|
||||
: mState(kNoEntry)
|
||||
{
|
||||
}
|
||||
|
||||
void Init(Instance &aInstance) { InstanceLocatorInit::Init(aInstance); }
|
||||
State GetState(void) const { return mState; }
|
||||
void SetState(State aState);
|
||||
const TimeMilli &GetUpdateTime(void) const { return mUpdateTime; }
|
||||
bool IsPreferred(uint16_t aRloc16) const;
|
||||
void UpdateState(uint8_t aNumEntries, uint8_t aNumPreferredEntries, uint8_t aDesiredNumEntries);
|
||||
bool HandleTimer(void);
|
||||
InfoString ToString(bool aIncludeState = true) const;
|
||||
|
||||
public:
|
||||
bool IsAdded(void) const { return (mState == kAdded); }
|
||||
|
||||
private:
|
||||
bool Add(void);
|
||||
bool Remove(State aNextState);
|
||||
void LogUpdateTime(void) const;
|
||||
static const char *StateToString(State aState);
|
||||
|
||||
TimeMilli mUpdateTime;
|
||||
State mState;
|
||||
};
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
class DnsSrpServiceEntry : public Entry, private NonCopyable
|
||||
{
|
||||
friend class Entry;
|
||||
|
||||
public:
|
||||
explicit DnsSrpServiceEntry(Instance &aInstance);
|
||||
void SetCallback(DnsSrpServiceCallback aCallback, void *aContext);
|
||||
void PublishAnycast(uint8_t aSequenceNumber);
|
||||
void PublishUnicast(const Ip6::Address &aAddress, uint16_t aPort);
|
||||
void PublishUnicast(uint16_t aPort);
|
||||
void Unpublish(void);
|
||||
bool HandleTimer(void) { return Entry::HandleTimer(); }
|
||||
bool HandleNotifierEvents(Events aEvents);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kDesiredNumAnycast =
|
||||
OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_ANYCAST_DNS_SRP_SERVICE_ENTRIES;
|
||||
|
||||
static constexpr uint8_t kDesiredNumUnicast =
|
||||
OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_UNICAST_DNS_SRP_SERVICE_ENTRIES;
|
||||
|
||||
enum Type : uint8_t
|
||||
{
|
||||
kTypeAnycast,
|
||||
kTypeUnicast,
|
||||
kTypeUnicastMeshLocalEid,
|
||||
};
|
||||
|
||||
class Info : public Clearable<Info>, public Equatable<Info>
|
||||
{
|
||||
public:
|
||||
Info(void) { Clear(); }
|
||||
Type GetType(void) const { return mType; }
|
||||
uint8_t GetSequenceNumber(void) const { return static_cast<uint8_t>(mPortOrSeqNumber); }
|
||||
uint16_t GetPort(void) const { return mPortOrSeqNumber; }
|
||||
const Ip6::Address &GetAddress(void) const { return mAddress; }
|
||||
void SetAddress(const Ip6::Address &aAddress) { mAddress = aAddress; }
|
||||
|
||||
static Info InfoAnycast(uint8_t aSequenceNumber) { return Info(kTypeAnycast, aSequenceNumber); }
|
||||
static Info InfoUnicast(Type aType, const Ip6::Address &aAddress, uint16_t aPort)
|
||||
{
|
||||
return Info(aType, aPort, &aAddress);
|
||||
}
|
||||
|
||||
private:
|
||||
Info(Type aType, uint16_t aPortOrSeqNumber, const Ip6::Address *aAddress = nullptr);
|
||||
|
||||
Ip6::Address mAddress;
|
||||
uint16_t mPortOrSeqNumber;
|
||||
Type mType;
|
||||
};
|
||||
|
||||
Type GetType(void) const { return mInfo.GetType(); }
|
||||
void Publish(const Info &aInfo);
|
||||
bool Add(void);
|
||||
bool Remove(State aNextState);
|
||||
void Notify(Event aEvent) const;
|
||||
void Process(void);
|
||||
void CountAnycastEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const;
|
||||
void CountUnicastEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const;
|
||||
|
||||
Info mInfo;
|
||||
DnsSrpServiceCallback mCallback;
|
||||
void * mCallbackContext;
|
||||
};
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
// Max number of prefix (on-mesh or external route) entries.
|
||||
static constexpr uint16_t kMaxPrefixEntries = OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES;
|
||||
|
||||
class PrefixEntry : public Entry, private NonCopyable
|
||||
{
|
||||
friend class Entry;
|
||||
|
||||
public:
|
||||
void Init(Instance &aInstance) { Entry::Init(aInstance); }
|
||||
bool IsInUse(void) const { return GetState() != kNoEntry; }
|
||||
bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; }
|
||||
void Publish(const OnMeshPrefixConfig &aConfig);
|
||||
void Publish(const ExternalRouteConfig &aConfig);
|
||||
void Unpublish(void);
|
||||
bool HandleTimer(void) { return Entry::HandleTimer(); }
|
||||
void HandleNotifierEvents(Events aEvents);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kDesiredNumOnMeshPrefix =
|
||||
OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_ON_MESH_PREFIX_ENTRIES;
|
||||
|
||||
static constexpr uint8_t kDesiredNumExternalRoute =
|
||||
OPENTHREAD_CONFIG_NETDATA_PUBLISHER_DESIRED_NUM_EXTERNAL_ROUTE_ENTRIES;
|
||||
|
||||
enum Type : uint8_t
|
||||
{
|
||||
kTypeOnMeshPrefix,
|
||||
kTypeExternalRoute,
|
||||
};
|
||||
|
||||
bool Add(void);
|
||||
Error AddOnMeshPrefix(void);
|
||||
Error AddExternalRoute(void);
|
||||
bool Remove(State aNextState);
|
||||
void Process(void);
|
||||
void CountOnMeshPrefixEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const;
|
||||
void CountExternalRouteEntries(uint8_t &aNumEntries, uint8_t &aNumPreferredEntries) const;
|
||||
|
||||
Type mType;
|
||||
Ip6::Prefix mPrefix;
|
||||
uint16_t mFlags;
|
||||
};
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
bool IsADnsSrpServiceEntry(const Entry &aEntry) const { return (&aEntry == &mDnsSrpServiceEntry); }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
Error AllocatePrefixEntry(const Ip6::Prefix &aPrefix, PrefixEntry *&aEntry);
|
||||
PrefixEntry * FindMatchingPrefixEntry(const Ip6::Prefix &aPrefix);
|
||||
const PrefixEntry *FindMatchingPrefixEntry(const Ip6::Prefix &aPrefix) const;
|
||||
bool IsAPrefixEntry(const Entry &aEntry) const;
|
||||
void NotifyPrefixEntryChange(Event aEvent, const Ip6::Prefix &aPrefix) const;
|
||||
#endif
|
||||
|
||||
TimerMilli &GetTimer(void) { return mTimer; }
|
||||
void HandleNotifierEvents(Events aEvents);
|
||||
static void HandleTimer(Timer &aTimer);
|
||||
void HandleTimer(void);
|
||||
|
||||
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
DnsSrpServiceEntry mDnsSrpServiceEntry;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
|
||||
PrefixEntry mPrefixEntries[kMaxPrefixEntries];
|
||||
PrefixCallback mPrefixCallback;
|
||||
void * mPrefixCallbackContext;
|
||||
#endif
|
||||
|
||||
TimerMilli mTimer;
|
||||
};
|
||||
|
||||
} // namespace NetworkData
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
|
||||
#endif // NETWORK_DATA_PUBLISHER_HPP_
|
||||
@@ -59,28 +59,15 @@ Error Manager::AddService(const void *aServiceData,
|
||||
const void *aServerData,
|
||||
uint8_t aServerDataLength)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Get<Local>().AddService(
|
||||
kThreadEnterpriseNumber, reinterpret_cast<const uint8_t *>(aServiceData), aServiceDataLength,
|
||||
aServerStable, reinterpret_cast<const uint8_t *>(aServerData), aServerDataLength));
|
||||
|
||||
Get<Notifier>().HandleServerDataUpdated();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
return Get<Local>().AddService(kThreadEnterpriseNumber, reinterpret_cast<const uint8_t *>(aServiceData),
|
||||
aServiceDataLength, aServerStable, reinterpret_cast<const uint8_t *>(aServerData),
|
||||
aServerDataLength);
|
||||
}
|
||||
|
||||
Error Manager::RemoveService(const void *aServiceData, uint8_t aServiceDataLength)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Get<Local>().RemoveService(
|
||||
kThreadEnterpriseNumber, reinterpret_cast<const uint8_t *>(aServiceData), aServiceDataLength));
|
||||
Get<Notifier>().HandleServerDataUpdated();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
return Get<Local>().RemoveService(kThreadEnterpriseNumber, reinterpret_cast<const uint8_t *>(aServiceData),
|
||||
aServiceDataLength);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
@@ -421,9 +421,6 @@ public:
|
||||
/**
|
||||
* This method adds a Thread Service entry to the local Thread Network Data.
|
||||
*
|
||||
* When successfully added, this method also invokes `Notifier::HandleServerDataUpdated()` to register the changes
|
||||
* in local Network Data with leader.
|
||||
*
|
||||
* This version of `Add<SeviceType>()` is intended for use with a `ServiceType` that has a constant service data
|
||||
* format with a non-empty and potentially non-const server data format (provided as input parameter).
|
||||
*
|
||||
@@ -451,9 +448,6 @@ public:
|
||||
/**
|
||||
* This method adds a Thread Service entry to the local Thread Network Data.
|
||||
*
|
||||
* When successfully added, this method also invokes `Notifier::HandleServerDataUpdated()` to register the changes
|
||||
* in local Network Data with leader.
|
||||
*
|
||||
* This version of `Add<SeviceType>()` is intended for use with a `ServiceType` that has a non-const service data
|
||||
* format (provided as input parameter) with an empty server data.
|
||||
*
|
||||
@@ -479,9 +473,6 @@ public:
|
||||
/**
|
||||
* This method removes a Thread Service entry from the local Thread Network Data.
|
||||
*
|
||||
* When successfully removed, this method also invokes `Notifier::HandleServerDataUpdated()` to register the
|
||||
* changes in local Network Data with leader.
|
||||
*
|
||||
* This version of `Remove<SeviceType>()` is intended for use with a `ServiceType` that has a constant service data
|
||||
* format.
|
||||
*
|
||||
@@ -502,9 +493,6 @@ public:
|
||||
/**
|
||||
* This method removes a Thread Service entry from the local Thread Network Data.
|
||||
*
|
||||
* When successfully removed, this method also invokes `Notifier::HandleServerDataUpdated()` to register the
|
||||
* changes in local Network Data with leader.
|
||||
*
|
||||
* This version of `Remove<SeviceType>()` is intended for use with a `ServiceType` that has a non-const service data
|
||||
* format (provided as input parameter).
|
||||
*
|
||||
@@ -514,6 +502,8 @@ public:
|
||||
*
|
||||
* @tparam ServiceType The service type to be removed.
|
||||
*
|
||||
* @param[in] aServiceData The service data.
|
||||
*
|
||||
* @retval kErrorNone Successfully removed the Service entry.
|
||||
* @retval kErrorNotFound Could not find the Service entry.
|
||||
*
|
||||
|
||||
@@ -391,7 +391,7 @@ public:
|
||||
* @returns The preference value.
|
||||
*
|
||||
*/
|
||||
int8_t GetPreference(void) const { return static_cast<int8_t>(mFlags) >> kPreferenceOffset; }
|
||||
int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); }
|
||||
|
||||
/**
|
||||
* This method gets the Flags value.
|
||||
@@ -434,6 +434,30 @@ public:
|
||||
*/
|
||||
const HasRouteEntry *GetNext(void) const { return (this + 1); }
|
||||
|
||||
/**
|
||||
* This static method returns an updated flags bitmask by removing the preference bits (sets them to zero) from a
|
||||
* given flags bitmask.
|
||||
*
|
||||
* @param[in] aFlags The flags bitmask.
|
||||
*
|
||||
* @returns An updated version @p aFlags with preference bits cleared.
|
||||
*
|
||||
*/
|
||||
static uint8_t FlagsWithoutPreference(uint8_t aFlags) { return (aFlags & ~kPreferenceMask); }
|
||||
|
||||
/**
|
||||
* This static method gets the preference field from a flags bitmask.
|
||||
*
|
||||
* @param[in] aFlags The flags.
|
||||
*
|
||||
* @returns The preference field from the @p aFlags.
|
||||
*
|
||||
*/
|
||||
static int8_t PreferenceFromFlags(uint8_t aFlags)
|
||||
{
|
||||
return static_cast<int8_t>(static_cast<int8_t>(aFlags) >> kPreferenceOffset);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kPreferenceOffset = 6;
|
||||
static constexpr uint8_t kPreferenceMask = 3 << kPreferenceOffset;
|
||||
@@ -890,10 +914,7 @@ public:
|
||||
* @returns the Preference value.
|
||||
*
|
||||
*/
|
||||
int8_t GetPreference(void) const
|
||||
{
|
||||
return static_cast<int8_t>(static_cast<int16_t>(HostSwap16(mFlags)) >> kPreferenceOffset);
|
||||
}
|
||||
int8_t GetPreference(void) const { return PreferenceFromFlags(GetFlags()); }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the Preferred flag is set.
|
||||
@@ -983,6 +1004,30 @@ public:
|
||||
*/
|
||||
const BorderRouterEntry *GetNext(void) const { return (this + 1); }
|
||||
|
||||
/**
|
||||
* This static method returns an updated flags bitmask by removing the preference bits (sets them to zero) from a
|
||||
* given flags bitmask.
|
||||
*
|
||||
* @param[in] aFlags The flags bitmask.
|
||||
*
|
||||
* @returns An updated version @p aFlags with preference bits cleared.
|
||||
*
|
||||
*/
|
||||
static uint16_t FlagsWithoutPreference(uint16_t aFlags) { return (aFlags & ~kPreferenceMask); }
|
||||
|
||||
/**
|
||||
* This static method gets the preference field from a flags bitmask.
|
||||
*
|
||||
* @param[in] aFlags The flags.
|
||||
*
|
||||
* @returns The preference field from the @p aFlags.
|
||||
*
|
||||
*/
|
||||
static int8_t PreferenceFromFlags(uint16_t aFlags)
|
||||
{
|
||||
return static_cast<int8_t>(static_cast<int16_t>(aFlags) >> kPreferenceOffset);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kPreferenceOffset = 14;
|
||||
static constexpr uint16_t kPreferenceMask = 3 << kPreferenceOffset;
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace NetworkData {
|
||||
// Forward declarations
|
||||
class NetworkData;
|
||||
class Local;
|
||||
class Publisher;
|
||||
class PrefixTlv;
|
||||
class BorderRouterTlv;
|
||||
class BorderRouterEntry;
|
||||
@@ -74,6 +75,7 @@ class OnMeshPrefixConfig : public otBorderRouterConfig,
|
||||
{
|
||||
friend class NetworkData;
|
||||
friend class Local;
|
||||
friend class Publisher;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -125,6 +127,7 @@ class ExternalRouteConfig : public otExternalRouteConfig,
|
||||
{
|
||||
friend class NetworkData;
|
||||
friend class Local;
|
||||
friend class Publisher;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
||||
@@ -95,6 +95,9 @@ ThreadNetif::ThreadNetif(Instance &aInstance)
|
||||
, mNetworkDataLeader(aInstance)
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
, mNetworkDataNotifier(aInstance)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
, mNetworkDataPublisher(aInstance)
|
||||
#endif
|
||||
, mNetworkDataServiceManager(aInstance)
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
#include "thread/mle_router.hpp"
|
||||
#include "thread/network_data_local.hpp"
|
||||
#include "thread/network_data_notifier.hpp"
|
||||
#include "thread/network_data_publisher.hpp"
|
||||
#include "thread/network_data_service.hpp"
|
||||
#include "thread/network_diagnostic.hpp"
|
||||
#include "thread/panid_query_server.hpp"
|
||||
@@ -239,6 +240,9 @@ private:
|
||||
NetworkData::Leader mNetworkDataLeader;
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
NetworkData::Notifier mNetworkDataNotifier;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
NetworkData::Publisher mNetworkDataPublisher;
|
||||
#endif
|
||||
NetworkData::Service::Manager mNetworkDataServiceManager;
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
|
||||
|
||||
@@ -63,6 +63,7 @@ MAC_FILTER ?= 1
|
||||
MAX_POWER_TABLE ?= 1
|
||||
MTD_NETDIAG ?= 1
|
||||
NEIGHBOR_DISCOVERY_AGENT ?= 1
|
||||
NETDATA_PUBLISHER ?= 1
|
||||
PING_SENDER ?= 1
|
||||
READLINE ?= readline
|
||||
REFERENCE_DEVICE ?= 1
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
-DOT_LOG_OUTPUT=APP \
|
||||
-DOT_MAC_FILTER=ON \
|
||||
-DOT_MTD_NETDIAG=ON \
|
||||
-DOT_NETDATA_PUBLISHER=ON \
|
||||
-DOT_PING_SENDER=ON \
|
||||
-DOT_SERVICE=ON \
|
||||
-DOT_SLAAC=ON \
|
||||
|
||||
@@ -168,6 +168,7 @@ EXTRA_DIST = \
|
||||
test_lowpan.py \
|
||||
test_mac802154.py \
|
||||
test_mle.py \
|
||||
test_netdata_publisher.py \
|
||||
test_network_data.py \
|
||||
test_network_layer.py \
|
||||
test_on_mesh_prefix.py \
|
||||
@@ -233,6 +234,7 @@ check_SCRIPTS = \
|
||||
test_lowpan.py \
|
||||
test_mac802154.py \
|
||||
test_mle.py \
|
||||
test_netdata_publisher.py \
|
||||
test_network_data.py \
|
||||
test_network_layer.py \
|
||||
test_on_mesh_prefix.py \
|
||||
|
||||
@@ -157,7 +157,7 @@ class SingleHostAndService(thread_cert.TestCase):
|
||||
#
|
||||
|
||||
server.srp_server_set_enabled(False)
|
||||
self.simulator.go(2)
|
||||
self.simulator.go(5)
|
||||
|
||||
self.assertEqual(len(server.srp_server_get_hosts()), 0)
|
||||
self.assertEqual(len(server.srp_server_get_services()), 0)
|
||||
|
||||
@@ -1715,6 +1715,34 @@ class NodeImpl:
|
||||
self.send_command('netdata register')
|
||||
self._expect_done()
|
||||
|
||||
def netdata_publish_dnssrp_anycast(self, seqnum):
|
||||
self.send_command(f'netdata publish dnssrp anycast {seqnum}')
|
||||
self._expect_done()
|
||||
|
||||
def netdata_publish_dnssrp_unicast(self, address, port):
|
||||
self.send_command(f'netdata publish dnssrp unicast {address} {port}')
|
||||
self._expect_done()
|
||||
|
||||
def netdata_publish_dnssrp_unicast_mleid(self, port):
|
||||
self.send_command(f'netdata publish dnssrp unicast {port}')
|
||||
self._expect_done()
|
||||
|
||||
def netdata_unpublish_dnssrp(self):
|
||||
self.send_command('netdata unpublish dnssrp')
|
||||
self._expect_done()
|
||||
|
||||
def netdata_publish_prefix(self, prefix, flags='paosr', prf='med'):
|
||||
self.send_command(f'netdata publish prefix {prefix} {flags} {prf}')
|
||||
self._expect_done()
|
||||
|
||||
def netdata_publish_route(self, prefix, flags='s', prf='med'):
|
||||
self.send_command(f'netdata publish route {prefix} {flags} {prf}')
|
||||
self._expect_done()
|
||||
|
||||
def netdata_unpublish_prefix(self, prefix):
|
||||
self.send_command(f'netdata unpublish {prefix}')
|
||||
self._expect_done()
|
||||
|
||||
def send_network_diag_get(self, addr, tlv_types):
|
||||
self.send_command('networkdiagnostic get %s %s' % (addr, ' '.join([str(t.value) for t in tlv_types])))
|
||||
|
||||
|
||||
+452
@@ -0,0 +1,452 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2021, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import ipaddress
|
||||
import unittest
|
||||
|
||||
import command
|
||||
import thread_cert
|
||||
|
||||
# Test description:
|
||||
# This test verifies network data publisher behavior with DNS/SRP service entries and on-mesh prefix and external
|
||||
# route entries.
|
||||
#
|
||||
# Topology:
|
||||
#
|
||||
# 1 leader, 5 routers and 5 end-devices all connected.
|
||||
#
|
||||
|
||||
LEADER = 1
|
||||
ROUTER1 = 2
|
||||
ROUTER2 = 3
|
||||
ROUTER3 = 4
|
||||
ROUTER4 = 5
|
||||
ROUTER5 = 6
|
||||
END_DEV1 = 7
|
||||
END_DEV2 = 8
|
||||
END_DEV3 = 9
|
||||
END_DEV4 = 10
|
||||
END_DEV5 = 11
|
||||
|
||||
WAIT_TIME = 55
|
||||
|
||||
ON_MESH_PREFIX = 'fd00:1234::/64'
|
||||
ON_MESH_FLAGS = 'paso'
|
||||
|
||||
EXTERNAL_ROUTE = 'fd00:abce::/64'
|
||||
EXTERNAL_FLAGS = 's'
|
||||
|
||||
ANYCAST_SEQ_NUM = 4
|
||||
|
||||
DNSSRP_ADDRESS = 'fd00::cdef'
|
||||
DNSSRP_PORT = 49152
|
||||
|
||||
# The desired number of entries (based on related config).
|
||||
DESIRED_NUM_DNSSRP_ANYCAST = 8
|
||||
DESIRED_NUM_DNSSRP_UNCIAST = 2
|
||||
DESIRED_NUM_ON_MESH_PREFIX = 3
|
||||
DESIRED_NUM_EXTERNAL_ROUTE = 10
|
||||
|
||||
THREAD_ENTERPRISE_NUMBER = 44970
|
||||
ANYCAST_SERVICE_NUM = 0x5c
|
||||
UNICAST_SERVICE_NUM = 0x5d
|
||||
|
||||
|
||||
class NetDataPublisher(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER1',
|
||||
'mode': 'rdn',
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER2',
|
||||
'mode': 'rdn',
|
||||
},
|
||||
ROUTER3: {
|
||||
'name': 'ROUTER3',
|
||||
'mode': 'rdn',
|
||||
},
|
||||
ROUTER4: {
|
||||
'name': 'ROUTER4',
|
||||
'mode': 'rdn',
|
||||
},
|
||||
ROUTER5: {
|
||||
'name': 'ROUTER5',
|
||||
'mode': 'rdn',
|
||||
},
|
||||
END_DEV1: {
|
||||
'name': 'END_DEV1',
|
||||
'mode': 'rn',
|
||||
},
|
||||
END_DEV2: {
|
||||
'name': 'END_DEV2',
|
||||
'mode': 'rn',
|
||||
},
|
||||
END_DEV3: {
|
||||
'name': 'END_DEV3',
|
||||
'mode': 'rn',
|
||||
},
|
||||
END_DEV4: {
|
||||
'name': 'END_DEV4',
|
||||
'mode': 'rn',
|
||||
},
|
||||
END_DEV5: {
|
||||
'name': 'END_DEV5',
|
||||
'mode': 'rn',
|
||||
},
|
||||
}
|
||||
|
||||
def verify_anycast_service(self, service):
|
||||
# Verify the data in a single anycast `service` from `get_services()`
|
||||
# Example of `service`: ['44970', '5c04', '', 's', 'bc00']
|
||||
self.assertEqual(int(service[0]), THREAD_ENTERPRISE_NUMBER)
|
||||
# Check service data
|
||||
service_data = bytes.fromhex(service[1])
|
||||
self.assertTrue(len(service_data) >= 2)
|
||||
self.assertEqual(service_data[0], ANYCAST_SERVICE_NUM)
|
||||
self.assertEqual(service_data[1], int(ANYCAST_SEQ_NUM))
|
||||
# Verify that it stable
|
||||
self.assertEqual(service[3], 's')
|
||||
|
||||
def verify_anycast_services(self, services):
|
||||
# Verify a list of anycast `services` from `get_services()`
|
||||
for service in services:
|
||||
self.verify_anycast_service(service)
|
||||
|
||||
def verify_unicast_service(self, service):
|
||||
# Verify the data in a single unicast `service` from `get_services()`
|
||||
# Example of `service`: ['44970', '5d', 'fd000db800000000c6b0e5ee81f940e8223d', 's', '7000']
|
||||
self.assertEqual(int(service[0]), THREAD_ENTERPRISE_NUMBER)
|
||||
# Check service data
|
||||
service_data = bytes.fromhex(service[1])
|
||||
self.assertTrue(len(service_data) >= 1)
|
||||
self.assertEqual(service_data[0], UNICAST_SERVICE_NUM)
|
||||
# Verify that it stable
|
||||
self.assertEqual(service[3], 's')
|
||||
|
||||
def verify_unicast_services(self, services):
|
||||
# Verify a list of unicast `services` from `get_services()`
|
||||
for service in services:
|
||||
self.verify_unicast_service(service)
|
||||
|
||||
def check_num_of_prefixes(self, prefixes, num_low, num_med, num_high):
|
||||
# Check and validate the prefix entries in network data (from
|
||||
# `prefixes`) based on number of published prefix entries at
|
||||
# different preference levels given by `num_low`, `num_med`,
|
||||
# `num_high`. Prefixes is a list of the format
|
||||
# 'fd00:1234:0:0::/64 paos low a802'.
|
||||
self.assertEqual(len(prefixes), min(num_high + num_med + num_low, DESIRED_NUM_ON_MESH_PREFIX))
|
||||
prfs = [prefix.split(' ')[2] for prefix in prefixes]
|
||||
self.assertEqual(prfs.count('high'), min(num_high, DESIRED_NUM_ON_MESH_PREFIX))
|
||||
self.assertEqual(prfs.count('med'), min(num_med, max(0, DESIRED_NUM_ON_MESH_PREFIX - num_high)))
|
||||
self.assertEqual(prfs.count('low'), min(num_low, max(0, DESIRED_NUM_ON_MESH_PREFIX - num_high - num_med)))
|
||||
|
||||
def check_num_of_routes(self, routes, num_low, num_med, num_high):
|
||||
# Check and validate the prefix entries in network data (from
|
||||
# `routes`) based on number of published prefix entries at
|
||||
# different preference levels given by `num_low`, `num_med`,
|
||||
# `num_high`. Prefixes is a list of the format
|
||||
# 'fd00:abce:0:0::/64 s med 6c01'.
|
||||
self.assertEqual(len(routes), min(num_high + num_med + num_low, DESIRED_NUM_EXTERNAL_ROUTE))
|
||||
prfs = [route.split(' ')[2] for route in routes]
|
||||
self.assertEqual(prfs.count('high'), min(num_high, DESIRED_NUM_EXTERNAL_ROUTE))
|
||||
self.assertEqual(prfs.count('med'), min(num_med, max(0, DESIRED_NUM_EXTERNAL_ROUTE - num_high)))
|
||||
self.assertEqual(prfs.count('low'), min(num_low, max(0, DESIRED_NUM_EXTERNAL_ROUTE - num_high - num_med)))
|
||||
|
||||
def test(self):
|
||||
leader = self.nodes[LEADER]
|
||||
router1 = self.nodes[ROUTER1]
|
||||
router2 = self.nodes[ROUTER2]
|
||||
router3 = self.nodes[ROUTER3]
|
||||
router4 = self.nodes[ROUTER4]
|
||||
router5 = self.nodes[ROUTER5]
|
||||
end_dev1 = self.nodes[END_DEV1]
|
||||
end_dev2 = self.nodes[END_DEV2]
|
||||
end_dev3 = self.nodes[END_DEV3]
|
||||
end_dev4 = self.nodes[END_DEV4]
|
||||
end_dev5 = self.nodes[END_DEV5]
|
||||
|
||||
nodes = self.nodes.values()
|
||||
routers = [router1, router2, router3, router4, router5]
|
||||
end_devs = [end_dev1, end_dev2, end_dev3, end_dev4, end_dev5]
|
||||
|
||||
# Start the nodes
|
||||
|
||||
leader.start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(leader.get_state(), 'leader')
|
||||
|
||||
for router in routers:
|
||||
router.start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(router.get_state(), 'router')
|
||||
|
||||
for end_dev in end_devs:
|
||||
end_dev.start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(end_dev.get_state(), 'child')
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# DNS/SRP anycast entries
|
||||
|
||||
# Publish DNS/SRP anycast on leader and all routers (6 nodes).
|
||||
|
||||
leader.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM)
|
||||
for node in routers:
|
||||
node.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM)
|
||||
self.simulator.go(WAIT_TIME)
|
||||
|
||||
# Check all entries are present in the network data
|
||||
|
||||
services = leader.get_services()
|
||||
self.assertEqual(len(services), min(1 + len(routers), DESIRED_NUM_DNSSRP_ANYCAST))
|
||||
self.verify_anycast_services(services)
|
||||
|
||||
# Publish same entry on all end-devices (5 nodes).
|
||||
|
||||
for node in end_devs:
|
||||
node.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM)
|
||||
print(node.name)
|
||||
self.simulator.go(WAIT_TIME)
|
||||
|
||||
# Check number of entries in the network data is limited to
|
||||
# the desired number (8 entries).
|
||||
|
||||
services = leader.get_services()
|
||||
self.assertEqual(len(leader.get_services()), min(len(nodes), DESIRED_NUM_DNSSRP_ANYCAST))
|
||||
self.verify_anycast_services(services)
|
||||
|
||||
# Unpublish the entry from nodes one by one starting from leader
|
||||
# and check that number of entries is correct in each step.
|
||||
|
||||
num = len(nodes)
|
||||
for node in nodes:
|
||||
node.netdata_unpublish_dnssrp()
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num -= 1
|
||||
services = leader.get_services()
|
||||
self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_ANYCAST))
|
||||
self.verify_anycast_services(services)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# DNS/SRP unicast entries
|
||||
|
||||
# Publish DNS/SRP unicast address on all routers, first using
|
||||
# MLE-EID address, then change to use specific address. Verify
|
||||
# that number of entries in network data is correct in each step
|
||||
# and that entries are switched correctly.
|
||||
|
||||
num = 0
|
||||
for node in routers:
|
||||
node.netdata_publish_dnssrp_unicast_mleid(DNSSRP_PORT)
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num += 1
|
||||
services = leader.get_services()
|
||||
self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNCIAST))
|
||||
self.verify_unicast_services(services)
|
||||
|
||||
for node in routers:
|
||||
node.netdata_publish_dnssrp_unicast(DNSSRP_ADDRESS, DNSSRP_PORT)
|
||||
self.simulator.go(WAIT_TIME)
|
||||
services = leader.get_services()
|
||||
self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNCIAST))
|
||||
self.verify_unicast_services(services)
|
||||
|
||||
for node in routers:
|
||||
node.netdata_unpublish_dnssrp()
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num -= 1
|
||||
services = leader.get_services()
|
||||
self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNCIAST))
|
||||
self.verify_unicast_services(services)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# DNS/SRP entries: Verify publisher preference when removing
|
||||
# entries.
|
||||
#
|
||||
# Publish DNS/SRP anycast on 8 nodes: leader, router1,
|
||||
# router2, and all 5 end-devices. Afterwards, manually add
|
||||
# the same service entry in Network Data on router3, router4,
|
||||
# and router5 and at each step check that entry from one of
|
||||
# the end-devices is removed (publisher prefers
|
||||
# entries from routers over the ones from end-devices).
|
||||
|
||||
num = 0
|
||||
test_routers = [leader, router1, router2]
|
||||
for node in test_routers + end_devs:
|
||||
node.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM)
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num += 1
|
||||
services = leader.get_services()
|
||||
self.assertEqual(len(services), num)
|
||||
self.verify_anycast_services(services)
|
||||
|
||||
self.assertEqual(num, DESIRED_NUM_DNSSRP_ANYCAST)
|
||||
|
||||
service_data = '%02x%02x' % (ANYCAST_SERVICE_NUM, int(ANYCAST_SEQ_NUM))
|
||||
for node in [router3, router4, router5]:
|
||||
node.add_service(str(THREAD_ENTERPRISE_NUMBER), service_data, '00')
|
||||
node.register_netdata()
|
||||
self.simulator.go(WAIT_TIME)
|
||||
|
||||
services = leader.get_services()
|
||||
self.assertEqual(len(services), num)
|
||||
self.verify_anycast_services(services)
|
||||
|
||||
service_rlocs = [int(service[4], 16) for service in services]
|
||||
test_routers.append(node)
|
||||
|
||||
for router in test_routers:
|
||||
self.assertIn(router.get_addr16(), service_rlocs)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# On-mesh prefix
|
||||
|
||||
# Publish the same on-mesh prefix on different nodes (low
|
||||
# preference on end-devices, medium preference on routers, and
|
||||
# high on leader) one by one and then unpublish them one by one.
|
||||
# Verify that at each step the entries in the network data are
|
||||
# correct. Particularly verify that that higher preference
|
||||
# entries replace lower preference ones even when there are
|
||||
# already desired number in network data.
|
||||
|
||||
num_low = 0
|
||||
num_med = 0
|
||||
num_high = 0
|
||||
|
||||
for node in end_devs:
|
||||
node.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'low')
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num_low += 1
|
||||
prefixes = leader.get_prefixes()
|
||||
self.check_num_of_prefixes(prefixes, num_low, num_med, num_high)
|
||||
|
||||
# Now add the entry as 'med' on routers and check that we see those in the list.
|
||||
for node in routers:
|
||||
node.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'med')
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num_med += 1
|
||||
prefixes = leader.get_prefixes()
|
||||
self.check_num_of_prefixes(prefixes, num_low, num_med, num_high)
|
||||
|
||||
leader.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'high')
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num_high += 1
|
||||
prefixes = leader.get_prefixes()
|
||||
self.check_num_of_prefixes(prefixes, num_low, num_med, num_high)
|
||||
|
||||
for node in routers:
|
||||
node.netdata_unpublish_prefix(ON_MESH_PREFIX)
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num_med -= 1
|
||||
prefixes = leader.get_prefixes()
|
||||
self.check_num_of_prefixes(prefixes, num_low, num_med, num_high)
|
||||
|
||||
leader.netdata_unpublish_prefix(ON_MESH_PREFIX)
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num_high -= 1
|
||||
prefixes = leader.get_prefixes()
|
||||
self.check_num_of_prefixes(prefixes, num_low, num_med, num_high)
|
||||
|
||||
for node in end_devs:
|
||||
node.netdata_unpublish_prefix(ON_MESH_PREFIX)
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num_low -= 1
|
||||
prefixes = leader.get_prefixes()
|
||||
self.check_num_of_prefixes(prefixes, num_low, num_med, num_high)
|
||||
|
||||
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Verify that when removing extra entries, non-preferred entries
|
||||
# are removed first over preferred ones. Entries from routers are
|
||||
# preferred over similar entries from end-devices.
|
||||
|
||||
# Publish prefix entry on `end_dev1` and verify that it is added.
|
||||
|
||||
end_dev1.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'med')
|
||||
self.simulator.go(WAIT_TIME)
|
||||
prefixes = leader.get_prefixes()
|
||||
self.check_num_of_prefixes(prefixes, 0, 1, 0)
|
||||
|
||||
# Publish same prefix on all routers (again as `med` preference).
|
||||
# Verify that we reach the desired number of prefix entries in network
|
||||
# data and that the entry from `end_dev1` is present in network data.
|
||||
|
||||
for node in routers:
|
||||
node.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'med')
|
||||
self.simulator.go(WAIT_TIME)
|
||||
prefixes = leader.get_prefixes()
|
||||
self.check_num_of_prefixes(prefixes, 0, 1 + len(routers), 0)
|
||||
self.assertTrue(1 + len(routers) >= DESIRED_NUM_ON_MESH_PREFIX)
|
||||
# `prefixes` is a list of format 'fd00:1234:0:0::/64 paos low a802'
|
||||
rlocs = [int(prefix.split(' ')[3], 16) for prefix in prefixes]
|
||||
self.assertTrue(rlocs.count(end_dev1.get_addr16()) == 1)
|
||||
|
||||
# Publish same prefix now with `high` preference on leader.
|
||||
# Since it is `high` preference, it is added to network data
|
||||
# which leads to total number of entries to go above the desired
|
||||
# number temporarily and trigger other nodes to try to remove
|
||||
# their entry. The entries from routers should be preferred over
|
||||
# the one from `end_dev1` so that is the one we expect to be
|
||||
# removed. We check that this is the case (i.e., the entry from
|
||||
# `end_dev1` is no longer present in network data).
|
||||
|
||||
leader.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'high')
|
||||
self.simulator.go(WAIT_TIME)
|
||||
prefixes = leader.get_prefixes()
|
||||
self.check_num_of_prefixes(prefixes, 0, 1 + len(routers), 1)
|
||||
rlocs = [int(prefix.split(' ')[3], 16) for prefix in prefixes]
|
||||
self.assertTrue(rlocs.count(end_dev1.get_addr16()) == 0)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# External route
|
||||
|
||||
num = 0
|
||||
for node in nodes:
|
||||
node.netdata_publish_route(EXTERNAL_ROUTE, EXTERNAL_FLAGS, 'low')
|
||||
self.simulator.go(WAIT_TIME)
|
||||
num += 1
|
||||
routes = leader.get_routes()
|
||||
self.check_num_of_routes(routes, num, 0, 0)
|
||||
|
||||
leader.netdata_unpublish_prefix(EXTERNAL_ROUTE)
|
||||
leader.netdata_publish_route(EXTERNAL_ROUTE, EXTERNAL_FLAGS, 'high')
|
||||
self.simulator.go(WAIT_TIME)
|
||||
routes = leader.get_routes()
|
||||
self.check_num_of_routes(routes, num - 1, 0, 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -128,7 +128,7 @@ class SrpAutoStartMode(thread_cert.TestCase):
|
||||
#
|
||||
|
||||
server1.srp_server_set_enabled(True)
|
||||
self.simulator.go(2)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(client.srp_client_get_state(), 'Enabled')
|
||||
self.assertEqual(client.srp_client_get_server_address(), server2_address)
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ class SrpAutoStartMode(thread_cert.TestCase):
|
||||
# Enable auto start mode on client and check that server1 is used.
|
||||
|
||||
server1.srp_server_set_enabled(True)
|
||||
self.simulator.go(WAIT_TIME)
|
||||
|
||||
client.srp_client_set_host_name('host')
|
||||
client.srp_client_set_host_address('2001::1')
|
||||
|
||||
@@ -79,6 +79,7 @@ class SrpSubType(thread_cert.TestCase):
|
||||
|
||||
server.srp_server_set_enabled(True)
|
||||
client.srp_client_enable_auto_start_mode()
|
||||
self.simulator.go(5)
|
||||
|
||||
# Register a single service with 3 subtypes and verify that it worked.
|
||||
|
||||
|
||||
@@ -103,6 +103,14 @@
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 1
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
|
||||
*
|
||||
* Define to 1 to enable Network Data Publisher.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE 1
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LEGACY_ENABLE
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user