From 2e8580108393fc463229374e8be05abe031147d9 Mon Sep 17 00:00:00 2001 From: Rongli Sun Date: Thu, 30 Apr 2020 11:12:28 +0800 Subject: [PATCH] [dua] Domain Unicast Address generation (#4854) This commit includes [Y] add `OPENTHREAD_CONFIG_DUA_ENABLE` option for DUA feature [Y] generate DUA via SLAAC [Y] update test script to verify communication via DUA --- Android.mk | 1 + BUILD.gn | 1 + etc/cmake/options.cmake | 5 + examples/common-switches.mk | 5 + script/test | 12 +++ src/core/CMakeLists.txt | 1 + src/core/Makefile.am | 2 + src/core/backbone_router/leader.cpp | 4 + src/core/common/instance.hpp | 9 ++ .../config/openthread-core-config-check.h | 6 +- .../config/openthread-core-default-config.h | 10 ++ src/core/thread/dua_manager.cpp | 96 +++++++++++++++++++ src/core/thread/dua_manager.hpp | 92 ++++++++++++++++++ src/core/thread/thread_netif.cpp | 3 + src/core/thread/thread_netif.hpp | 8 ++ .../v1_2_test_backbone_router_service.py | 15 +++ 16 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 src/core/thread/dua_manager.cpp create mode 100644 src/core/thread/dua_manager.hpp diff --git a/Android.mk b/Android.mk index 804ff8102..6d1095069 100644 --- a/Android.mk +++ b/Android.mk @@ -239,6 +239,7 @@ LOCAL_SRC_FILES := \ src/core/thread/announce_begin_server.cpp \ src/core/thread/announce_sender.cpp \ src/core/thread/child_table.cpp \ + src/core/thread/dua_manager.cpp \ src/core/thread/energy_scan_server.cpp \ src/core/thread/indirect_sender.cpp \ src/core/thread/key_manager.cpp \ diff --git a/BUILD.gn b/BUILD.gn index 4c904e22b..6be9e4f57 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -136,6 +136,7 @@ static_library("lib-ot-core") { "src/core/thread/announce_begin_server.cpp", "src/core/thread/announce_sender.cpp", "src/core/thread/child_table.cpp", + "src/core/thread/dua_manager.cpp", "src/core/thread/energy_scan_server.cpp", "src/core/thread/indirect_sender.cpp", "src/core/thread/key_manager.cpp", diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake index 75ba98e34..9cf507fa6 100644 --- a/etc/cmake/options.cmake +++ b/etc/cmake/options.cmake @@ -111,6 +111,11 @@ if(OT_ECDSA) list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_ECDSA_ENABLE=1") endif() +option(OT_DUA "enable Domain Unicast Address feature for Thread 1.2") +if(OT_DUA) + list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_DUA_ENABLE=1") +endif() + option(OT_EXTERNAL_HEAP "enable external heap support") if(OT_EXTERNAL_HEAP) list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_EXTERNAL_HEAP_ENABLE=1") diff --git a/examples/common-switches.mk b/examples/common-switches.mk index 8f29ddb28..fd87ea005 100644 --- a/examples/common-switches.mk +++ b/examples/common-switches.mk @@ -47,6 +47,7 @@ DIAGNOSTIC ?= 0 DISABLE_DOC ?= 0 DISABLE_TOOLS ?= 0 DNS_CLIENT ?= 0 +DUA ?= 0 DYNAMIC_LOG_LEVEL ?= 0 ECDSA ?= 0 EXTERNAL_HEAP ?= 0 @@ -149,6 +150,10 @@ ifeq ($(DNS_CLIENT),1) COMMONCFLAGS += -DOPENTHREAD_CONFIG_DNS_CLIENT_ENABLE=1 endif +ifeq ($(DUA),1) +COMMONCFLAGS += -DOPENTHREAD_CONFIG_DUA_ENABLE=1 +endif + ifeq ($(DYNAMIC_LOG_LEVEL),1) COMMONCFLAGS += -DOPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE=1 endif diff --git a/script/test b/script/test index 5b21c068b..41eaad4ec 100755 --- a/script/test +++ b/script/test @@ -77,6 +77,12 @@ build_simulation() "-DOT_THREAD_VERSION=${version}" ) + if [[ "${version}" == "1.2" ]]; then + options+=( + "-DOT_DUA=ON" + ) + fi + if [[ "${VIRTUAL_TIME}" == 1 ]]; then options+=("-DOT_SIMULATION_VIRTUAL_TIME=ON") @@ -120,6 +126,12 @@ build_posix() "-DOT_THREAD_VERSION=${version}" ) + if [[ "${version}" == "1.2" ]]; then + options+=( + "-DOT_DUA=ON" + ) + fi + if [[ "${VIRTUAL_TIME}" == 1 ]]; then options+=("-DOT_POSIX_VIRTUAL_TIME=ON") fi diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8d72e81ae..bc5ac2a92 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -176,6 +176,7 @@ set(COMMON_SOURCES thread/announce_begin_server.cpp thread/announce_sender.cpp thread/child_table.cpp + thread/dua_manager.cpp thread/energy_scan_server.cpp thread/indirect_sender.cpp thread/key_manager.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 5266d38d6..51a7b62a4 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -214,6 +214,7 @@ SOURCES_COMMON = \ thread/announce_begin_server.cpp \ thread/announce_sender.cpp \ thread/child_table.cpp \ + thread/dua_manager.cpp \ thread/energy_scan_server.cpp \ thread/indirect_sender.cpp \ thread/key_manager.cpp \ @@ -417,6 +418,7 @@ HEADERS_COMMON = \ thread/announce_begin_server.hpp \ thread/announce_sender.hpp \ thread/child_table.hpp \ + thread/dua_manager.hpp \ thread/energy_scan_server.hpp \ thread/indirect_sender.hpp \ thread/indirect_sender_frame_context.hpp \ diff --git a/src/core/backbone_router/leader.cpp b/src/core/backbone_router/leader.cpp index e7181dae7..c2a5cf49d 100644 --- a/src/core/backbone_router/leader.cpp +++ b/src/core/backbone_router/leader.cpp @@ -282,6 +282,10 @@ void Leader::UpdateDomainPrefixConfig(void) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE Get().UpdateAllDomainBackboneRouters(state); #endif + +#if OPENTHREAD_CONFIG_DUA_ENABLE + Get().UpdateDomainUnicastAddress(state); +#endif } } // namespace BackboneRouter diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index aa02d2f6f..d80dc8b36 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -713,6 +713,7 @@ template <> inline MessagePool &Instance::Get(void) } #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + template <> inline BackboneRouter::Leader &Instance::Get(void) { return mThreadNetif.mBackboneRouterLeader; @@ -724,6 +725,14 @@ template <> inline BackboneRouter::Local &Instance::Get(void) return mThreadNetif.mBackboneRouterLocal; } #endif + +#if OPENTHREAD_CONFIG_DUA_ENABLE +template <> inline DuaManager &Instance::Get(void) +{ + return mThreadNetif.mDuaManager; +} +#endif + #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) #if OPENTHREAD_CONFIG_OTNS_ENABLE diff --git a/src/core/config/openthread-core-config-check.h b/src/core/config/openthread-core-config-check.h index e4e16922b..14a915159 100644 --- a/src/core/config/openthread-core-config-check.h +++ b/src/core/config/openthread-core-config-check.h @@ -471,7 +471,7 @@ #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE #if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2) -#error "At least Thread Version 1.2 is required for OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE" +#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE" #endif #if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE @@ -480,4 +480,8 @@ #endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +#if OPENTHREAD_CONFIG_DUA_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2) +#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_DUA_ENABLE" +#endif + #endif // OPENTHREAD_CORE_CONFIG_CHECK_H_ diff --git a/src/core/config/openthread-core-default-config.h b/src/core/config/openthread-core-default-config.h index 452b6af92..f9a842331 100644 --- a/src/core/config/openthread-core-default-config.h +++ b/src/core/config/openthread-core-default-config.h @@ -450,4 +450,14 @@ #define OPENTHREAD_CONFIG_OTNS_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_DUA_ENABLE + * + * Define as 1 to support Thread 1.2 Domain Unicast Address feature. + * + */ +#ifndef OPENTHREAD_CONFIG_DUA_ENABLE +#define OPENTHREAD_CONFIG_DUA_ENABLE 0 +#endif + #endif // OPENTHREAD_CORE_DEFAULT_CONFIG_H_ diff --git a/src/core/thread/dua_manager.cpp b/src/core/thread/dua_manager.cpp new file mode 100644 index 000000000..b1336541b --- /dev/null +++ b/src/core/thread/dua_manager.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020, 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 managing DUA. + */ + +#include "dua_manager.hpp" + +#if (OPENTHREAD_FTD || OPENTHREAD_MTD) && OPENTHREAD_CONFIG_DUA_ENABLE + +#include "common/code_utils.hpp" +#include "common/instance.hpp" +#include "common/locator-getters.hpp" +#include "common/logging.hpp" +#include "net/ip6_address.hpp" +#include "thread/thread_netif.hpp" +#include "utils/slaac_address.hpp" + +namespace ot { + +DuaManager::DuaManager(Instance &aInstance) + : InstanceLocator(aInstance) + , mDadCounter(0) +{ + mDomainUnicastAddress.Clear(); + mDomainUnicastAddress.mPreferred = true; + mDomainUnicastAddress.mScopeOverride = Ip6::Address::kGlobalScope; + mDomainUnicastAddress.mScopeOverrideValid = true; +} + +void DuaManager::UpdateDomainUnicastAddress(BackboneRouter::Leader::DomainPrefixState aState) +{ + const otIp6Prefix *prefix; + + if ((aState == BackboneRouter::Leader::kDomainPrefixRemoved) || + (aState == BackboneRouter::Leader::kDomainPrefixRefreshed)) + { + Get().RemoveUnicastAddress(mDomainUnicastAddress); + } + + VerifyOrExit((aState == BackboneRouter::Leader::kDomainPrefixAdded) || + (aState == BackboneRouter::Leader::kDomainPrefixRefreshed), + OT_NOOP); + + prefix = Get().GetDomainPrefix(); + + OT_ASSERT(prefix != NULL); + + mDomainUnicastAddress.GetAddress().Clear(); + mDomainUnicastAddress.GetAddress().SetPrefix(prefix->mPrefix.mFields.m8, prefix->mLength); + mDomainUnicastAddress.mPrefixLength = prefix->mLength; + + if (Get().GenerateIid(mDomainUnicastAddress, NULL, 0, &mDadCounter) == OT_ERROR_NONE) + { + mDomainUnicastAddress.mValid = true; + Get().AddUnicastAddress(mDomainUnicastAddress); + } + else + { + otLogWarnCore("Failed to generate valid DUA"); + } + +exit: + return; +} + +} // namespace ot + +#endif // (OPENTHREAD_FTD || OPENTHREAD_MTD) && OPENTHREAD_CONFIG_DUA_ENABLE diff --git a/src/core/thread/dua_manager.hpp b/src/core/thread/dua_manager.hpp new file mode 100644 index 000000000..09f3635b9 --- /dev/null +++ b/src/core/thread/dua_manager.hpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020, 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 definitions for managing Domain Unicast Address feature defined in Thread 1.2. + */ + +#ifndef DUA_MANAGER_HPP_ +#define DUA_MANAGER_HPP_ + +#include "openthread-core-config.h" + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + +#include "backbone_router/leader.hpp" +#include "common/locator.hpp" +#include "net/netif.hpp" + +namespace ot { + +/** + * @addtogroup core-dua + * + * @brief + * This module includes definitions for generating, managing, registering Domain Unicast Address. + * + * @{ + * + * @defgroup core-dua Dua + * + * @} + * + */ + +/** + * This class implements managing DUA. + * + */ +class DuaManager : public InstanceLocator +{ +public: + /** + * This constructor initializes the object. + * + * @param[in] aInstance A reference to the OpenThread instance. + * + */ + explicit DuaManager(Instance &aInstance); + + /** + * This method updates Domain Unicast Address. + * + * @param[in] aState The Domain Prefix state or state change. + * + */ + void UpdateDomainUnicastAddress(BackboneRouter::Leader::DomainPrefixState aState); + +private: + Ip6::NetifUnicastAddress mDomainUnicastAddress; + uint8_t mDadCounter; +}; + +} // namespace ot + +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#endif // DUA_MANAGER_HPP_ diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp index cf1258ff8..ade576702 100644 --- a/src/core/thread/thread_netif.cpp +++ b/src/core/thread/thread_netif.cpp @@ -108,6 +108,9 @@ ThreadNetif::ThreadNetif(Instance &aInstance) #endif #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE , mBackboneRouterLocal(aInstance) +#endif +#if OPENTHREAD_CONFIG_DUA_ENABLE + , mDuaManager(aInstance) #endif , mChildSupervisor(aInstance) , mSupervisionListener(aInstance) diff --git a/src/core/thread/thread_netif.hpp b/src/core/thread/thread_netif.hpp index 2a6ffec1c..e1d6a8b9e 100644 --- a/src/core/thread/thread_netif.hpp +++ b/src/core/thread/thread_netif.hpp @@ -53,6 +53,11 @@ #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE #include "backbone_router/local.hpp" #endif + +#if OPENTHREAD_CONFIG_DUA_ENABLE +#include "thread/dua_manager.hpp" +#endif + #include "meshcop/dataset_manager.hpp" #if OPENTHREAD_CONFIG_JOINER_ENABLE @@ -236,6 +241,9 @@ private: #endif #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE BackboneRouter::Local mBackboneRouterLocal; +#endif +#if OPENTHREAD_CONFIG_DUA_ENABLE + DuaManager mDuaManager; #endif Utils::ChildSupervisor mChildSupervisor; Utils::SupervisionListener mSupervisionListener; diff --git a/tests/scripts/thread-cert/v1_2_test_backbone_router_service.py b/tests/scripts/thread-cert/v1_2_test_backbone_router_service.py index dabcfc84b..8d2b9940e 100755 --- a/tests/scripts/thread-cert/v1_2_test_backbone_router_service.py +++ b/tests/scripts/thread-cert/v1_2_test_backbone_router_service.py @@ -59,9 +59,12 @@ BBR_REGISTRATION_JITTER = 5 4) Configure BBR_2 with highest sequence number and explicitly trigger SRV_DATA.ntf. BBR_2 would become Primary and BBR_1 would change to Secondary with sequence number increased by 1. + a) Check communication via DUA. 5) Stop BBR_2, BBR_1 would become Primary after detecting there is no available Backbone Router Service in Thread Network. 6) Bring back BBR_2, and it would become Secondary. + a) Check the uniqueness of DUA by comparing the one in above 4a). + b) Check communication via DUA. """ @@ -221,6 +224,10 @@ class TestBackboneRouterService(thread_cert.TestCase): assert self.nodes[BBR_1].get_backbone_router()['seqno'] == ( BBR_1_SEQNO + 1) + # 4a) Check communication via DUA. + bbr2_dua = self.nodes[BBR_2].get_addr(config.DOMAIN_PREFIX) + self.assertTrue(self.nodes[BBR_1].ping(bbr2_dua)) + # 5) Stop BBR_2, BBR_1 becomes Primary after detecting there is no # available Backbone Router Service. self.nodes[BBR_2].reset() @@ -254,6 +261,14 @@ class TestBackboneRouterService(thread_cert.TestCase): assert self.nodes[BBR_1].has_ipmaddr(config.ALL_NETWORK_BBRS_ADDRESS) assert self.nodes[BBR_1].has_ipmaddr(config.ALL_DOMAIN_BBRS_ADDRESS) + # 6a) Check the uniqueness of DUA by comparing the one in above 4a). + bbr2_dua2 = self.nodes[BBR_2].get_addr(config.DOMAIN_PREFIX) + assert bbr2_dua == bbr2_dua2, 'Error: Unexpected different DUA (%s v.s. %s)'.format( + bbr2_dua, bbr2_dua2) + + # 6b) Check communication via DUA + self.assertTrue(self.nodes[BBR_1].ping(bbr2_dua)) + if __name__ == '__main__': unittest.main()