diff --git a/Android.mk b/Android.mk index 01dd981c9..40b72f52d 100644 --- a/Android.mk +++ b/Android.mk @@ -125,6 +125,8 @@ LOCAL_CPPFLAGS := \ $(NULL) LOCAL_SRC_FILES := \ + src/core/api/backbone_router_api.cpp \ + src/core/api/backbone_router_ftd_api.cpp \ src/core/api/border_router_api.cpp \ src/core/api/channel_manager_api.cpp \ src/core/api/channel_monitor_api.cpp \ @@ -153,6 +155,8 @@ LOCAL_SRC_FILES := \ src/core/api/thread_api.cpp \ src/core/api/thread_ftd_api.cpp \ src/core/api/udp_api.cpp \ + src/core/backbone_router/leader.cpp \ + src/core/backbone_router/local.cpp \ src/core/coap/coap.cpp \ src/core/coap/coap_message.cpp \ src/core/coap/coap_secure.cpp \ diff --git a/BUILD.gn b/BUILD.gn index 49ac2270d..5f5602050 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -30,6 +30,8 @@ static_library("lib-ot-core") { cflags_cc = [ "-Wno-non-virtual-dtor" ] sources = [ + "src/core/api/backbone_router_api.cpp", + "src/core/api/backbone_router_ftd_api.cpp", "src/core/api/border_agent_api.cpp", "src/core/api/border_router_api.cpp", "src/core/api/channel_manager_api.cpp", @@ -64,6 +66,8 @@ static_library("lib-ot-core") { "src/core/api/thread_api.cpp", "src/core/api/thread_ftd_api.cpp", "src/core/api/udp_api.cpp", + "src/core/backbone_router/leader.cpp", + "src/core/backbone_router/local.cpp", "src/core/coap/coap.cpp", "src/core/coap/coap_message.cpp", "src/core/coap/coap_secure.cpp", diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake index 624abf818..ecc250276 100644 --- a/etc/cmake/options.cmake +++ b/etc/cmake/options.cmake @@ -26,6 +26,11 @@ # POSSIBILITY OF SUCH DAMAGE. # +option(OT_BACKBONE_ROUTER "enable backbone router functionality") +if(OT_BACKBONE_ROUTER) + list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE=1") +endif() + option(OT_BIG_ENDIAN "host platform uses big-endian byte order") if(OT_BIG_ENDIAN) list(APPEND OT_PRIVATE_DEFINES "BYTE_ORDER_BIG_ENDIAN=1") diff --git a/examples/common-switches.mk b/examples/common-switches.mk index 736757f5e..e7fa7d0bb 100644 --- a/examples/common-switches.mk +++ b/examples/common-switches.mk @@ -28,6 +28,7 @@ # OpenThread Features (Makefile default configuration). +BACKBONE_ROUTER ?= 0 BIG_ENDIAN ?= 0 BORDER_AGENT ?= 0 BORDER_ROUTER ?= 0 @@ -71,6 +72,10 @@ TIME_SYNC ?= 0 UDP_FORWARD ?= 0 +ifeq ($(BACKBONE_ROUTER),1) +COMMONCFLAGS += -DOPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE=1 +endif + ifeq ($(BIG_ENDIAN),1) COMMONCFLAGS += -DBYTE_ORDER_BIG_ENDIAN=1 endif diff --git a/include/openthread/Makefile.am b/include/openthread/Makefile.am index f5f8cb5fd..b32ca95f3 100644 --- a/include/openthread/Makefile.am +++ b/include/openthread/Makefile.am @@ -41,6 +41,10 @@ SUBDIRS = \ $(NULL) openthread_headers = \ + backbone_router.h \ + backbone_router_ftd.h \ + border_agent.h \ + border_router.h \ channel_manager.h \ channel_monitor.h \ child_supervision.h \ @@ -49,8 +53,6 @@ openthread_headers = \ coap.h \ commissioner.h \ crypto.h \ - border_agent.h \ - border_router.h \ dataset.h \ dataset_ftd.h \ diag.h \ diff --git a/include/openthread/backbone_router.h b/include/openthread/backbone_router.h new file mode 100644 index 000000000..23cb4d426 --- /dev/null +++ b/include/openthread/backbone_router.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019, 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 Backbone Router API (Thread 1.2) + */ + +#ifndef OPENTHREAD_BACKBONE_ROUTER_H_ +#define OPENTHREAD_BACKBONE_ROUTER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup api-backbone-router + * + * @brief + * This module includes functions for the OpenThread Backbone Router Service. + * + * @{ + * + */ + +/** + * This structure represents Backbone Router configuration. + * + */ +typedef struct otBackboneRouterConfig +{ + uint16_t mServer16; ///< Only used when get Primary Backbone Router information in the Thread Network + uint16_t mReregistrationDelay; ///< Reregistration Delay (in seconds) + uint32_t mMlrTimeout; ///< Multicast Listener Registration Timeout (in seconds) + uint8_t mSequenceNumber; ///< Sequence Number +} otBackboneRouterConfig; + +/** + * This function gets the Primary Backbone Router information in the Thread Network. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[out] aConfig A pointer to where to put Primary Backbone Router information. + * + * @retval OT_ERROR_NONE Successfully got Primary Backbone Router information. + * @retval OT_ERROR_NOT_FOUND No Primary Backbone Router exists. + * + */ +otError otBackboneRouterGetPrimary(otInstance *aInstance, otBackboneRouterConfig *aConfig); + +/** + * @} + * + */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // OPENTHREAD_BACKBONE_ROUTER_H_ diff --git a/include/openthread/backbone_router_ftd.h b/include/openthread/backbone_router_ftd.h new file mode 100644 index 000000000..e5cafbd29 --- /dev/null +++ b/include/openthread/backbone_router_ftd.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2019, 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 Backbone Router API (for Thread 1.2 FTD with + * `OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE`). + * + */ + +#ifndef OPENTHREAD_BACKBONE_ROUTER_FTD_H_ +#define OPENTHREAD_BACKBONE_ROUTER_FTD_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup api-backbone-router + * + * @{ + * + */ + +/** + * Represents the Backbone Router Status. + * + */ +typedef enum +{ + OT_BACKBONE_ROUTER_STATE_DISABLED = 0, ///< Backbone function is disabled. + OT_BACKBONE_ROUTER_STATE_SECONDARY = 1, ///< Secondary Backbone Router. + OT_BACKBONE_ROUTER_STATE_PRIMARY = 2, ///< The Primary Backbone Router. +} otBackboneRouterState; + +/** + * This function enables or disables Backbone functionality. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aEnable TRUE to enable Backbone functionality, FALSE otherwise. + * + * @sa otBackboneRouterGetState + * @sa otBackboneRouterGetConfig + * @sa otBackboneRouterSetConfig + * @sa otBackboneRouterRegister + * + */ +void otBackboneRouterSetEnabled(otInstance *aInstance, bool aEnable); + +/** + * This function gets the Backbone Router state. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @retval OT_BACKBONE_ROUTER_STATE_DISABLED Backbone functionality is disabled. + * @retval OT_BACKBONE_ROUTER_STATE_SECONDARY Secondary Backbone Router. + * @retval OT_BACKBONE_ROUTER_STATE_PRIMARY The Primary Backbone Router. + * + * @sa otBackboneRouterSetEnabled + * @sa otBackboneRouterGetConfig + * @sa otBackboneRouterSetConfig + * @sa otBackboneRouterRegister + * + */ +otBackboneRouterState otBackboneRouterGetState(otInstance *aInstance); + +/** + * This function gets the local Backbone Router configuration. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[out] aConfig A pointer where to put local Backbone Router configuration. + * + * + * @sa otBackboneRouterSetEnabled + * @sa otBackboneRouterGetState + * @sa otBackboneRouterSetConfig + * @sa otBackboneRouterRegister + * + */ +void otBackboneRouterGetConfig(otInstance *aInstance, otBackboneRouterConfig *aConfig); + +/** + * This function sets the local Backbone Router configuration. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aConfig A pointer to the Backbone Router configuration to take effect. + * + * @sa otBackboneRouterSetEnabled + * @sa otBackboneRouterGetState + * @sa otBackboneRouterGetConfig + * @sa otBackboneRouterRegister + * + */ +void otBackboneRouterSetConfig(otInstance *aInstance, const otBackboneRouterConfig *aConfig); + +/** + * This function explicitly registers local Backbone Router configuration. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @retval OT_ERROR_NO_BUFS Insufficient space to add the Backbone Router service. + * @retval OT_ERROR_NONE Successfully queued a Server Data Request message for delivery. + * + * @sa otBackboneRouterSetEnabled + * @sa otBackboneRouterGetState + * @sa otBackboneRouterGetConfig + * @sa otBackboneRouterSetConfig + * + */ +otError otBackboneRouterRegister(otInstance *aInstance); + +/** + * This method returns the Backbone Router registration jitter value. + * + * @returns The Backbone Router registration jitter value. + * + * @sa otBackboneRouterSetRegistrationJitter + * + */ +uint8_t otBackboneRouterGetRegistrationJitter(otInstance *aInstance); + +/** + * This method sets the Backbone Router registration jitter value. + * + * @param[in] aJitter the Backbone Router registration jitter value to set. + * + * @sa otBackboneRouterGetRegistrationJitter + * + */ +void otBackboneRouterSetRegistrationJitter(otInstance *aInstance, uint8_t aJitter); + +/** + * @} + * + */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // OPENTHREAD_BACKBONE_ROUTER_FTD_H_ diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 1657bf7eb..89a094724 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -122,31 +122,33 @@ void otInstanceFinalize(otInstance *aInstance); */ enum { - OT_CHANGED_IP6_ADDRESS_ADDED = 1 << 0, ///< IPv6 address was added - OT_CHANGED_IP6_ADDRESS_REMOVED = 1 << 1, ///< IPv6 address was removed - OT_CHANGED_THREAD_ROLE = 1 << 2, ///< Role (disabled, detached, child, router, leader) changed - OT_CHANGED_THREAD_LL_ADDR = 1 << 3, ///< The link-local address changed - OT_CHANGED_THREAD_ML_ADDR = 1 << 4, ///< The mesh-local address changed - OT_CHANGED_THREAD_RLOC_ADDED = 1 << 5, ///< RLOC was added - OT_CHANGED_THREAD_RLOC_REMOVED = 1 << 6, ///< RLOC was removed - OT_CHANGED_THREAD_PARTITION_ID = 1 << 7, ///< Partition ID changed - OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER = 1 << 8, ///< Thread Key Sequence changed - OT_CHANGED_THREAD_NETDATA = 1 << 9, ///< Thread Network Data changed - OT_CHANGED_THREAD_CHILD_ADDED = 1 << 10, ///< Child was added - OT_CHANGED_THREAD_CHILD_REMOVED = 1 << 11, ///< Child was removed - OT_CHANGED_IP6_MULTICAST_SUBSCRIBED = 1 << 12, ///< Subscribed to a IPv6 multicast address - OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED = 1 << 13, ///< Unsubscribed from a IPv6 multicast address - OT_CHANGED_THREAD_CHANNEL = 1 << 14, ///< Thread network channel changed - OT_CHANGED_THREAD_PANID = 1 << 15, ///< Thread network PAN Id changed - OT_CHANGED_THREAD_NETWORK_NAME = 1 << 16, ///< Thread network name changed - OT_CHANGED_THREAD_EXT_PANID = 1 << 17, ///< Thread network extended PAN ID changed - OT_CHANGED_MASTER_KEY = 1 << 18, ///< Master key changed - OT_CHANGED_PSKC = 1 << 19, ///< PSKc changed - OT_CHANGED_SECURITY_POLICY = 1 << 20, ///< Security Policy changed - OT_CHANGED_CHANNEL_MANAGER_NEW_CHANNEL = 1 << 21, ///< Channel Manager new pending Thread channel changed - OT_CHANGED_SUPPORTED_CHANNEL_MASK = 1 << 22, ///< Supported channel mask changed - OT_CHANGED_BORDER_AGENT_STATE = 1 << 23, ///< Border agent state changed - OT_CHANGED_THREAD_NETIF_STATE = 1 << 24, ///< Thread network interface state changed + OT_CHANGED_IP6_ADDRESS_ADDED = 1 << 0, ///< IPv6 address was added + OT_CHANGED_IP6_ADDRESS_REMOVED = 1 << 1, ///< IPv6 address was removed + OT_CHANGED_THREAD_ROLE = 1 << 2, ///< Role (disabled, detached, child, router, leader) changed + OT_CHANGED_THREAD_LL_ADDR = 1 << 3, ///< The link-local address changed + OT_CHANGED_THREAD_ML_ADDR = 1 << 4, ///< The mesh-local address changed + OT_CHANGED_THREAD_RLOC_ADDED = 1 << 5, ///< RLOC was added + OT_CHANGED_THREAD_RLOC_REMOVED = 1 << 6, ///< RLOC was removed + OT_CHANGED_THREAD_PARTITION_ID = 1 << 7, ///< Partition ID changed + OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER = 1 << 8, ///< Thread Key Sequence changed + OT_CHANGED_THREAD_NETDATA = 1 << 9, ///< Thread Network Data changed + OT_CHANGED_THREAD_CHILD_ADDED = 1 << 10, ///< Child was added + OT_CHANGED_THREAD_CHILD_REMOVED = 1 << 11, ///< Child was removed + OT_CHANGED_IP6_MULTICAST_SUBSCRIBED = 1 << 12, ///< Subscribed to a IPv6 multicast address + OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED = 1 << 13, ///< Unsubscribed from a IPv6 multicast address + OT_CHANGED_THREAD_CHANNEL = 1 << 14, ///< Thread network channel changed + OT_CHANGED_THREAD_PANID = 1 << 15, ///< Thread network PAN Id changed + OT_CHANGED_THREAD_NETWORK_NAME = 1 << 16, ///< Thread network name changed + OT_CHANGED_THREAD_EXT_PANID = 1 << 17, ///< Thread network extended PAN ID changed + OT_CHANGED_MASTER_KEY = 1 << 18, ///< Master key changed + OT_CHANGED_PSKC = 1 << 19, ///< PSKc changed + OT_CHANGED_SECURITY_POLICY = 1 << 20, ///< Security Policy changed + OT_CHANGED_CHANNEL_MANAGER_NEW_CHANNEL = 1 << 21, ///< Channel Manager new pending Thread channel changed + OT_CHANGED_SUPPORTED_CHANNEL_MASK = 1 << 22, ///< Supported channel mask changed + OT_CHANGED_BORDER_AGENT_STATE = 1 << 23, ///< Border agent state changed + OT_CHANGED_THREAD_NETIF_STATE = 1 << 24, ///< Thread network interface state changed + OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE = 1 << 25, ///< Backbone Router state changed + OT_CHANGED_THREAD_BACKBONE_ROUTER_LOCAL = 1 << 26, ///< Local Backbone Router configuration changed }; /** diff --git a/include/openthread/netdata.h b/include/openthread/netdata.h index 36a5a61ba..c87fcbaba 100644 --- a/include/openthread/netdata.h +++ b/include/openthread/netdata.h @@ -179,7 +179,7 @@ typedef struct otServerConfig */ typedef struct otServiceConfig { - uint8_t mServiceID; ///< Used to return service ID when iterating over the partition's Network Data. + uint8_t mServiceId; ///< Used to return Service ID when iterating over the partition's Network Data. uint32_t mEnterpriseNumber; ///< IANA Enterprise Number. uint8_t mServiceDataLength; ///< Length of service data. uint8_t mServiceData[OT_SERVICE_DATA_MAX_SIZE]; ///< Service data bytes. diff --git a/script/test b/script/test index acff6a756..3ffc58853 100755 --- a/script/test +++ b/script/test @@ -92,6 +92,21 @@ build_simulation() && cmake -GNinja "${OT_SRCDIR}" "${options[@]}" \ && ninja) + if [[ "${version}" == "1.2" ]]; then + + options+=( + "-DOT_BACKBONE_ROUTER=ON" + "-DOT_BORDER_ROUTER=ON" + "-DOT_SERVICE=ON" + ) + + local builddir="${OT_BUILDDIR}/cmake/openthread-simulation-${version}-bbr" + (mkdir -p "${builddir}" \ + && cd "${builddir}" \ + && cmake -GNinja "${OT_SRCDIR}" "${options[@]}" \ + && ninja) + + fi } build_posix() @@ -114,6 +129,21 @@ build_posix() && cd "${builddir}" \ && cmake -GNinja "${OT_SRCDIR}" "${options[@]}" \ && ninja) + + if [[ "${version}" == "1.2" ]]; then + + options+=( + "-DOT_BACKBONE_ROUTER=ON" + "-DOT_BORDER_ROUTER=ON" + "-DOT_SERVICE=ON" + ) + + local builddir="${OT_BUILDDIR}/cmake/openthread-posix-${version}-bbr" + (mkdir -p "${builddir}" \ + && cd "${builddir}" \ + && cmake -GNinja "${OT_SRCDIR}" "${options[@]}" \ + && ninja) + fi } do_build() { @@ -142,6 +172,7 @@ do_cert() { if [[ "${THREAD_VERSION}" == "1.2" ]]; then export top_builddir_1_1="${OT_BUILDDIR}/cmake/openthread-simulation-1.1" + export top_builddir_1_2_bbr="${OT_BUILDDIR}/cmake/openthread-simulation-1.2-bbr" fi [[ ! -d tmp ]] || rm -rvf tmp @@ -153,6 +184,7 @@ do_cert_suite() { if [[ "${THREAD_VERSION}" == "1.2" ]]; then export top_builddir_1_1="${OT_BUILDDIR}/cmake/openthread-simulation-1.1" + export top_builddir_1_2_bbr="${OT_BUILDDIR}/cmake/openthread-simulation-1.2-bbr" fi local pass_count=0 @@ -268,6 +300,8 @@ envsetup() export RADIO_DEVICE_1_1="${OT_BUILDDIR}/cmake/openthread-simulation-1.1/examples/apps/ncp/ot-rcp" export OT_CLI_PATH_1_1="${OT_BUILDDIR}/cmake/openthread-posix-1.1/src/posix/ot-cli" export OT_NCP_PATH_1_1="${OT_BUILDDIR}/cmake/openthread-posix-1.1/src/posix/ot-ncp" + export OT_CLI_PATH_1_2_BBR="${OT_BUILDDIR}/cmake/openthread-posix-1.2-bbr/src/posix/ot-cli" + export OT_NCP_PATH_1_2_BBR="${OT_BUILDDIR}/cmake/openthread-posix-1.2-bbr/src/posix/ot-ncp" fi fi diff --git a/src/cli/README.md b/src/cli/README.md index b378a7a6e..ca4028d80 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -28,6 +28,7 @@ Done ## OpenThread Command List +* [bbr](#bbr) * [bufferinfo](#bufferinfo) * [channel](#channel) * [child](#child-list) @@ -99,6 +100,131 @@ Done ## OpenThread Command Details +### bbr + +Show current Primary Backbone Router information for Thread 1.2 device. + +```bash +> bbr +BBR Primary: +server16: 0xE400 +seqno: 10 +delay: 120 secs +timeout: 300 secs +Done +``` + +```bash +> bbr +BBR Primary: None +Done +``` + +### bbr state +Show local Backbone state ([`Disabled`,`Primary`, `Secondary`]) for Thread 1.2 FTD. + +`OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is required. + + +```bash +> bbr state +Disabled +Done + +> bbr state +Primary +Done + +> bbr state +Secondary +Done +``` + +### bbr enable +Enable Backbone Router Service for Thread 1.2 FTD. +`SRV_DATA.ntf` would be triggerred for attached device if there is no +Backbone Router Service in Thread Network Data. + +`OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is required. + +```bash +> bbr enable +Done +``` + +### bbr disable +Disable Backbone Router Service for Thread 1.2 FTD. +`SRV_DATA.ntf` would be triggerred if Backbone Router is Primary state. +o +`OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is required. + +```bash +> bbr disable +Done +``` + +### bbr register +Register Backbone Router Service for Thread 1.2 FTD. +`SRV_DATA.ntf` would be triggerred for attached device. + +`OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is required. + +```bash +> bbr register +Done +``` + +### bbr config + +Show local Backbone Router configuration for Thread 1.2 FTD. + +`OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is required. + +```bash +> bbr config +seqno: 10 +delay: 120 secs +timeout: 300 secs +Done +``` + +### bbr config \[seqno \\] \[delay \\] \[timeout \\] + +Configure local Backbone Router configuration for Thread 1.2 FTD. +`bbr register` should be issued explicitly to register Backbone Router service to Leader for +Secondary Backbone Router. `SRV_DATA.ntf` would be initiated automatically if BBR Dataset +changes for Primary Backbone Router. + +`OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is required. + +```bash +> bbr config seqno 20 delay 30 +Done +``` + +### bbr jitter + +Show jitter (in seconds) for Backbone Router registration for Thread 1.2 FTD. + +`OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is required. + +```bash +> bbr jitter +20 +Done +``` + +### bbr jitter \ + +Set jitter (in seconds) for Backbone Router registration for Thread 1.2 FTD. + +`OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is required. + +```bash +> bbr jitter 10 +Done +``` + ### bufferinfo Show the current message buffer information. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 3a33b15c0..4da6887c6 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -66,6 +66,13 @@ #include "common/new.hpp" #include "net/ip6.hpp" +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#include +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +#include +#endif +#endif + #include "cli_dataset.hpp" #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD @@ -92,6 +99,9 @@ namespace ot { namespace Cli { const struct Command Interpreter::sCommands[] = { +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + {"bbr", &Interpreter::ProcessBackboneRouter}, +#endif {"bufferinfo", &Interpreter::ProcessBufferInfo}, {"channel", &Interpreter::ProcessChannel}, #if OPENTHREAD_FTD @@ -435,6 +445,140 @@ void Interpreter::ProcessHelp(uint8_t aArgsLength, char *aArgs[]) AppendResult(OT_ERROR_NONE); } +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +void Interpreter::ProcessBackboneRouter(uint8_t aArgsLength, char *aArgs[]) +{ + OT_UNUSED_VARIABLE(aArgs); + otError error = OT_ERROR_INVALID_COMMAND; + otBackboneRouterConfig config; + + if (aArgsLength == 0) + { + if (otBackboneRouterGetPrimary(mInstance, &config) == OT_ERROR_NONE) + { + mServer->OutputFormat("BBR Primary:\r\n"); + mServer->OutputFormat("server16: 0x%04X\r\n", config.mServer16); + mServer->OutputFormat("seqno: %d\r\n", config.mSequenceNumber); + mServer->OutputFormat("delay: %d secs\r\n", config.mReregistrationDelay); + mServer->OutputFormat("timeout: %d secs\r\n", config.mMlrTimeout); + } + else + { + mServer->OutputFormat("BBR Primary: None\r\n"); + } + + error = OT_ERROR_NONE; + } +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + else + { + error = ProcessBackboneRouterLocal(aArgsLength, aArgs); + } +#endif + + AppendResult(error); +} + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +otError Interpreter::ProcessBackboneRouterLocal(uint8_t aArgsLength, char *aArgs[]) +{ + otError error = OT_ERROR_NONE; + ; + otBackboneRouterConfig config; + unsigned long value; + + if (strcmp(aArgs[0], "disable") == 0) + { + otBackboneRouterSetEnabled(mInstance, false); + } + else if (strcmp(aArgs[0], "enable") == 0) + { + otBackboneRouterSetEnabled(mInstance, true); + } + else if (strcmp(aArgs[0], "jitter") == 0) + { + if (aArgsLength == 1) + { + mServer->OutputFormat("%d\r\n", otBackboneRouterGetRegistrationJitter(mInstance)); + } + else if (aArgsLength == 2) + { + SuccessOrExit(error = ParseUnsignedLong(aArgs[1], value)); + otBackboneRouterSetRegistrationJitter(mInstance, static_cast(value)); + } + } + else if (strcmp(aArgs[0], "register") == 0) + { + SuccessOrExit(error = otBackboneRouterRegister(mInstance)); + } + else if (strcmp(aArgs[0], "state") == 0) + { + switch (otBackboneRouterGetState(mInstance)) + { + case OT_BACKBONE_ROUTER_STATE_DISABLED: + mServer->OutputFormat("Disabled\r\n"); + break; + case OT_BACKBONE_ROUTER_STATE_SECONDARY: + mServer->OutputFormat("Secondary\r\n"); + break; + case OT_BACKBONE_ROUTER_STATE_PRIMARY: + mServer->OutputFormat("Primary\r\n"); + break; + } + } + else if (strcmp(aArgs[0], "config") == 0) + { + otBackboneRouterGetConfig(mInstance, &config); + + if (aArgsLength == 1) + { + mServer->OutputFormat("seqno: %d\r\n", config.mSequenceNumber); + mServer->OutputFormat("delay: %d secs\r\n", config.mReregistrationDelay); + mServer->OutputFormat("timeout: %d secs\r\n", config.mMlrTimeout); + } + else + { + // Set local Backbone Router configuration. + for (int argCur = 1; argCur < aArgsLength; argCur++) + { + VerifyOrExit(argCur + 1 < aArgsLength, error = OT_ERROR_INVALID_ARGS); + + if (strcmp(aArgs[argCur], "seqno") == 0) + { + SuccessOrExit(error = ParseUnsignedLong(aArgs[++argCur], value)); + config.mSequenceNumber = static_cast(value); + } + else if (strcmp(aArgs[argCur], "delay") == 0) + { + SuccessOrExit(error = ParseUnsignedLong(aArgs[++argCur], value)); + config.mReregistrationDelay = static_cast(value); + } + else if (strcmp(aArgs[argCur], "timeout") == 0) + { + SuccessOrExit(error = ParseUnsignedLong(aArgs[++argCur], value)); + config.mMlrTimeout = static_cast(value); + } + else + { + ExitNow(error = OT_ERROR_INVALID_ARGS); + } + } + + otBackboneRouterSetConfig(mInstance, &config); + } + } + else + { + error = OT_ERROR_INVALID_COMMAND; + } + +exit: + return error; +} +#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + void Interpreter::ProcessBufferInfo(uint8_t aArgsLength, char *aArgs[]) { OT_UNUSED_VARIABLE(aArgsLength); diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 34f00f8bc..35f0fa449 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -203,6 +203,13 @@ private: void ProcessHelp(uint8_t aArgsLength, char *aArgs[]); void ProcessBufferInfo(uint8_t aArgsLength, char *aArgs[]); void ProcessChannel(uint8_t aArgsLength, char *aArgs[]); +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + void ProcessBackboneRouter(uint8_t aArgsLength, char *aArgs[]); +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + otError ProcessBackboneRouterLocal(uint8_t aArgsLength, char *aArgs[]); +#endif +#endif + #if OPENTHREAD_FTD void ProcessChild(uint8_t aArgsLength, char *aArgs[]); void ProcessChildIp(uint8_t aArgsLength, char *aArgs[]); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e9803d1e6..49fc372b6 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -70,6 +70,8 @@ set(COMMON_INCLUDES ) set(COMMON_SOURCES + api/backbone_router_api.cpp + api/backbone_router_ftd_api.cpp api/border_router_api.cpp api/channel_manager_api.cpp api/channel_monitor_api.cpp @@ -103,6 +105,8 @@ set(COMMON_SOURCES api/thread_api.cpp api/thread_ftd_api.cpp api/udp_api.cpp + backbone_router/leader.cpp + backbone_router/local.cpp coap/coap.cpp coap/coap_message.cpp coap/coap_secure.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index b25a52b75..c85b8f2f1 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -108,6 +108,8 @@ libopenthread_mtd_a_CPPFLAGS = \ # SOURCES_COMMON = \ + api/backbone_router_api.cpp \ + api/backbone_router_ftd_api.cpp \ api/border_router_api.cpp \ api/channel_manager_api.cpp \ api/channel_monitor_api.cpp \ @@ -141,6 +143,8 @@ SOURCES_COMMON = \ api/thread_api.cpp \ api/thread_ftd_api.cpp \ api/udp_api.cpp \ + backbone_router/leader.cpp \ + backbone_router/local.cpp \ coap/coap.cpp \ coap/coap_message.cpp \ coap/coap_secure.cpp \ @@ -302,6 +306,8 @@ endif # OPENTHREAD_ENABLE_VENDOR_EXTENSION HEADERS_COMMON = \ openthread-core-config.h \ + backbone_router/leader.hpp \ + backbone_router/local.hpp \ coap/coap.hpp \ coap/coap_message.hpp \ coap/coap_secure.hpp \ @@ -328,6 +334,7 @@ HEADERS_COMMON = \ common/tlvs.hpp \ common/trickle_timer.hpp \ config/announce_sender.h \ + config/backbone_router.h \ config/border_router.h \ config/channel_manager.h \ config/channel_monitor.h \ diff --git a/src/core/api/backbone_router_api.cpp b/src/core/api/backbone_router_api.cpp new file mode 100644 index 000000000..033000e5a --- /dev/null +++ b/src/core/api/backbone_router_api.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019, 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 defines the OpenThread Backbone Router API (Thread 1.2) + */ + +#include "openthread-core-config.h" + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#include +#include "common/instance.hpp" + +using namespace ot; + +otError otBackboneRouterGetPrimary(otInstance *aInstance, otBackboneRouterConfig *aConfig) +{ + Instance &instance = *static_cast(aInstance); + + OT_ASSERT(aConfig != NULL); + + return instance.Get().GetConfig(*aConfig); +} + +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) diff --git a/src/core/api/backbone_router_ftd_api.cpp b/src/core/api/backbone_router_ftd_api.cpp new file mode 100644 index 000000000..57c6923f5 --- /dev/null +++ b/src/core/api/backbone_router_ftd_api.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019, 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 defines the OpenThread Backbone Router API (for Thread 1.2 FTD with + * `OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE`). + */ + +#include "openthread-core-config.h" + +#include + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +#include "common/instance.hpp" + +using namespace ot; + +void otBackboneRouterSetEnabled(otInstance *aInstance, bool aEnabled) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().SetEnabled(aEnabled); +} + +otBackboneRouterState otBackboneRouterGetState(otInstance *aInstance) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().GetState(); +} + +void otBackboneRouterGetConfig(otInstance *aInstance, otBackboneRouterConfig *aConfig) +{ + Instance &instance = *static_cast(aInstance); + + OT_ASSERT(aConfig != NULL); + + instance.Get().GetConfig(*aConfig); +} + +void otBackboneRouterSetConfig(otInstance *aInstance, const otBackboneRouterConfig *aConfig) +{ + Instance &instance = *static_cast(aInstance); + + OT_ASSERT(aConfig != NULL); + + instance.Get().SetConfig(*aConfig); +} + +otError otBackboneRouterRegister(otInstance *aInstance) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().AddService(true /* Force registration */); +} + +uint8_t otBackboneRouterGetRegistrationJitter(otInstance *aInstance) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().GetRegistrationJitter(); +} + +void otBackboneRouterSetRegistrationJitter(otInstance *aInstance, uint8_t aJitter) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().SetRegistrationJitter(aJitter); +} + +#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE diff --git a/src/core/backbone_router/leader.cpp b/src/core/backbone_router/leader.cpp new file mode 100644 index 000000000..3f9b52b59 --- /dev/null +++ b/src/core/backbone_router/leader.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2019, 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 Primary Backbone Router service management in the Thread Network. + */ + +#include "leader.hpp" + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + +#include "common/code_utils.hpp" +#include "common/debug.hpp" +#include "common/instance.hpp" +#include "common/locator-getters.hpp" +#include "common/logging.hpp" +#include "common/settings.hpp" + +#include "thread/network_data_leader.hpp" +#include "thread/network_data_tlvs.hpp" +#include "thread/thread_netif.hpp" + +namespace ot { +namespace BackboneRouter { + +Leader::Leader(Instance &aInstance) + : InstanceLocator(aInstance) +{ + Reset(); +} + +void Leader::Reset(void) +{ + memset(&mConfig, 0, sizeof(mConfig)); + mConfig.mServer16 = Mac::kShortAddrInvalid; +} + +otError Leader::GetConfig(BackboneRouterConfig &aConfig) const +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(HasPrimary(), error = OT_ERROR_NOT_FOUND); + + aConfig = mConfig; + +exit: + return error; +} + +otError Leader::GetServiceId(uint8_t &aServiceId) const +{ + otError error = OT_ERROR_NONE; + uint8_t serviceData = NetworkData::ServiceTlv::kServiceDataBackboneRouter; + + VerifyOrExit(HasPrimary(), error = OT_ERROR_NOT_FOUND); + + error = Get().GetServiceId(THREAD_ENTERPRISE_NUMBER, &serviceData, sizeof(serviceData), true, + aServiceId); + +exit: + return error; +} + +void Leader::LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const +{ + OT_UNUSED_VARIABLE(aConfig); + + otLogInfoNetData("BBR state %s", StateToString(aState)); + + if (aState != kStateRemoved && aState != kStateNone) + { + otLogInfoNetData("Rloc16: 0x%4X, seqno: %d, delay: %d, timeout %d", aConfig.mServer16, aConfig.mSequenceNumber, + aConfig.mReregistrationDelay, aConfig.mMlrTimeout); + } +} + +const char *Leader::StateToString(State aState) +{ + const char *logString = "Unknown"; + + switch (aState) + { + case kStateNone: + logString = "PBBR: None"; + break; + + case kStateAdded: + logString = "PBBR: Added"; + break; + + case kStateRemoved: + logString = "PBBR: Removed"; + break; + + case kStateToTriggerRereg: + logString = "PBBR: To trigger re-registration"; + break; + + case kStateRefreshed: + logString = "PBBR: Refreshed"; + break; + + case kStateUnchanged: + logString = "PBBR: Unchanged"; + break; + + default: + break; + } + + return logString; +} + +void Leader::Update(void) +{ + BackboneRouterConfig config; + State state; + + Get().GetBackboneRouterPrimary(config); + + if (config.mServer16 != mConfig.mServer16) + { + if (config.mServer16 == Mac::kShortAddrInvalid) + { + state = kStateRemoved; + } + else if (mConfig.mServer16 == Mac::kShortAddrInvalid) + { + state = kStateAdded; + } + else + { + // Short Address of PBBR changes + state = kStateToTriggerRereg; + } + } + else if (config.mServer16 == Mac::kShortAddrInvalid) + { + // If no primary all the time + state = kStateNone; + } + else if (config.mSequenceNumber != mConfig.mSequenceNumber) + { + state = kStateToTriggerRereg; + } + else if (config.mReregistrationDelay != mConfig.mReregistrationDelay || config.mMlrTimeout != mConfig.mMlrTimeout) + { + state = kStateRefreshed; + } + else + { + state = kStateUnchanged; + } + + mConfig = config; + LogBackboneRouterPrimary(state, mConfig); + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + Get().UpdateBackboneRouterPrimary(state, mConfig); +#endif +} + +} // namespace BackboneRouter +} // namespace ot + +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) diff --git a/src/core/backbone_router/leader.hpp b/src/core/backbone_router/leader.hpp new file mode 100644 index 000000000..8ea1a96f3 --- /dev/null +++ b/src/core/backbone_router/leader.hpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2019, 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 Primary Backbone Router service management in the Thread Network. + */ + +#ifndef BACKBONE_ROUTER_LEADER_HPP_ +#define BACKBONE_ROUTER_LEADER_HPP_ + +#include "openthread-core-config.h" + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#include +#include + +#include "common/locator.hpp" +#include "net/ip6_address.hpp" + +namespace ot { + +namespace BackboneRouter { + +typedef otBackboneRouterConfig BackboneRouterConfig; + +/** + * This class implements the basic Primary Backbone Router service operations. + * + */ +class Leader : public InstanceLocator +{ +public: + // Primary Backbone Router Service State or State change. + enum State + { + kStateNone = 0, // Not exist (trigger Backbone Router register its service). + kStateAdded, // Newly added. + kStateRemoved, // Newly removed (trigger Backbone Router register its service). + kStateToTriggerRereg, // Short address or sequence number changes (trigger re-registration). + // May also have ReregistrationDelay or MlrTimeout update. + kStateRefreshed, // Only ReregistrationDelay or MlrTimeout changes. + kStateUnchanged, // No change on Primary Backbone Router information (only for logging). + }; + + /** + * This constructor initializes the `Leader`. + * + * @param[in] aInstance A reference to the OpenThread instance. + * + */ + explicit Leader(Instance &aInstance); + + /** + * This method resets the cached Primary Backbone Router. + * + */ + void Reset(void); + + /** + * This method updates the cached Primary Backbone Router if any when new network data is available. + * + */ + void Update(void); + + /** + * This method gets the Primary Backbone Router in the Thread Network. + * + * @param[out] aConfig The Primary Backbone Router information. + * + * @retval OT_ERROR_NONE Successfully got the Primary Backbone Router information. + * @retval OT_ERROR_NOT_FOUND No Backbone Router in the Thread Network. + * + */ + otError GetConfig(BackboneRouterConfig &aConfig) const; + + /** + * This method gets the Backbone Router Service ID. + * + * @param[out] aServiceId The reference whether to put the Backbone Router Service ID. + * + * @retval OT_ERROR_NONE Successfully got the Backbone Router Service ID. + * @retval OT_ERROR_NOT_FOUND Backbone Router service doesn't exist. + * + */ + otError GetServiceId(uint8_t &aServiceId) const; + + /** + * This method gets the short address of the Primary Backbone Router. + * + * @returns short address of Primary Backbone Router, or Mac::kShortAddrInvalid if no Primary Backbone Router. + * + */ + uint16_t GetServer16(void) const { return mConfig.mServer16; } + + /** + * This method indicates whether or not there is Primary Backbone Router. + * + * @retval TRUE if there is Primary Backbone Router, FALSE otherwise. + * + */ + bool HasPrimary(void) const { return mConfig.mServer16 != Mac::kShortAddrInvalid; } + +private: + void LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const; + static const char *StateToString(State aState); + + BackboneRouterConfig mConfig; ///< Primary Backbone Router information. +}; + +} // namespace BackboneRouter + +/** + * @} + */ + +} // namespace ot + +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + +#endif // BACKBONE_ROUTER_LEADER_HPP_ diff --git a/src/core/backbone_router/local.cpp b/src/core/backbone_router/local.cpp new file mode 100644 index 000000000..c657e4565 --- /dev/null +++ b/src/core/backbone_router/local.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2019, 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 local Backbone Router service. + */ + +#include "local.hpp" + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + +#include "common/code_utils.hpp" +#include "common/instance.hpp" +#include "common/locator-getters.hpp" +#include "common/logging.hpp" +#include "common/random.hpp" +#include "thread/mle.hpp" +#include "thread/mle_types.hpp" +#include "thread/thread_netif.hpp" + +namespace ot { + +namespace BackboneRouter { + +Local::Local(Instance &aInstance) + : InstanceLocator(aInstance) + , mState(OT_BACKBONE_ROUTER_STATE_DISABLED) + , mMlrTimeout(Mle::kMlrTimeoutDefault) + , mReregistrationDelay(Mle::kRegistrationDelayDefault) + , mSequenceNumber(Random::NonCrypto::GetUint8()) + , mRegistrationJitter(Mle::kBackboneRouterRegistrationJitter) + , mIsServiceAdded(false) +{ +} + +void Local::SetEnabled(bool aEnable) +{ + VerifyOrExit(aEnable == (mState == OT_BACKBONE_ROUTER_STATE_DISABLED)); + + if (aEnable) + { + SetState(OT_BACKBONE_ROUTER_STATE_SECONDARY); + AddService(); + } + else + { + RemoveService(); + SetState(OT_BACKBONE_ROUTER_STATE_DISABLED); + } + +exit: + return; +} + +void Local::Reset(void) +{ + VerifyOrExit(mState != OT_BACKBONE_ROUTER_STATE_DISABLED); + + RemoveService(); + + if (mState == OT_BACKBONE_ROUTER_STATE_PRIMARY) + { + // Increase sequence number when changing from primary to secondary. + mSequenceNumber++; + Get().Signal(OT_CHANGED_THREAD_BACKBONE_ROUTER_LOCAL); + SetState(OT_BACKBONE_ROUTER_STATE_SECONDARY); + } + +exit: + return; +} + +void Local::GetConfig(BackboneRouterConfig &aConfig) const +{ + aConfig.mSequenceNumber = mSequenceNumber; + aConfig.mReregistrationDelay = mReregistrationDelay; + aConfig.mMlrTimeout = mMlrTimeout; +} + +void Local::SetConfig(const BackboneRouterConfig &aConfig) +{ + bool update = false; + + if (aConfig.mReregistrationDelay != mReregistrationDelay) + { + mReregistrationDelay = aConfig.mReregistrationDelay; + update = true; + } + + if (aConfig.mMlrTimeout != mMlrTimeout) + { + mMlrTimeout = aConfig.mMlrTimeout; + update = true; + } + + if (aConfig.mSequenceNumber != mSequenceNumber) + { + mSequenceNumber = aConfig.mSequenceNumber; + update = true; + } + + if (update) + { + IgnoreReturnValue(AddService()); + Get().Signal(OT_CHANGED_THREAD_BACKBONE_ROUTER_LOCAL); + } + + otLogDebgNetData("BBR local: seqno (%d), delay (%ds), timeout (%ds)", mSequenceNumber, mReregistrationDelay, + mMlrTimeout); +} + +otError Local::AddService(bool aForce) +{ + otError error = OT_ERROR_INVALID_STATE; + uint8_t serviceData = NetworkData::ServiceTlv::kServiceDataBackboneRouter; + NetworkData::BackboneRouterServerData serverData; + + VerifyOrExit(mState != OT_BACKBONE_ROUTER_STATE_DISABLED && Get().IsAttached()); + + VerifyOrExit(aForce /* if register by force */ || + !Get().HasPrimary() /* if no available Backbone Router service */ || + Get().GetServer16() == Get().GetRloc16() + /* If the device itself should be BBR. */ + ); + + serverData.SetSequenceNumber(mSequenceNumber); + serverData.SetReregistrationDelay(mReregistrationDelay); + serverData.SetMlrTimeout(mMlrTimeout); + + SuccessOrExit(error = Get().AddService( + THREAD_ENTERPRISE_NUMBER, &serviceData, sizeof(serviceData), true, + reinterpret_cast(&serverData), sizeof(serverData))); + + mIsServiceAdded = true; + Get().SendServerDataNotification(); + + otLogInfoNetData("BBR Service added: seqno (%d), delay (%ds), timeout (%ds)", mSequenceNumber, mReregistrationDelay, + mMlrTimeout); + +exit: + otLogInfoNetData("Add BBR Service: %s", otThreadErrorToString(error)); + return error; +} + +otError Local::RemoveService(void) +{ + otError error = OT_ERROR_NONE; + uint8_t serviceData = NetworkData::ServiceTlv::kServiceDataBackboneRouter; + + SuccessOrExit( + error = Get().RemoveService(THREAD_ENTERPRISE_NUMBER, &serviceData, sizeof(serviceData))); + + mIsServiceAdded = false; + + if (Get().IsAttached()) + { + Get().SendServerDataNotification(); + } + +exit: + otLogInfoNetData("Remove BBR Service %s", otThreadErrorToString(error)); + return error; +} + +void Local::SetState(BackboneRouterState aState) +{ + VerifyOrExit(mState != aState); + + mState = aState; + Get().Signal(OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE); + +exit: + return; +} + +void Local::UpdateBackboneRouterPrimary(Leader::State aState, const BackboneRouterConfig &aConfig) +{ + OT_UNUSED_VARIABLE(aState); + + VerifyOrExit(mState != OT_BACKBONE_ROUTER_STATE_DISABLED && Get().IsAttached()); + + // Wait some jitter before trying to Register. + if (aConfig.mServer16 == Mac::kShortAddrInvalid) + { + uint8_t delay = 1; + + if (Get().GetRole() != OT_DEVICE_ROLE_LEADER) + { + delay += Random::NonCrypto::GetUint8InRange(0, mRegistrationJitter < 255 ? mRegistrationJitter + 1 + : mRegistrationJitter); + } + + // Here uses the timer resource in Mle. + Get().SetBackboneRouterRegistrationDelay(delay); + } + else if (aConfig.mServer16 != Get().GetRloc16()) + { + Reset(); + } + else if (!mIsServiceAdded) + { + // Here original PBBR restores its Backbone Router Service from Thread Network, + // Intentionally skips the state update as PBBR will refresh its service. + mSequenceNumber = aConfig.mSequenceNumber + 1; + mReregistrationDelay = aConfig.mReregistrationDelay; + mMlrTimeout = aConfig.mMlrTimeout; + Get().Signal(OT_CHANGED_THREAD_BACKBONE_ROUTER_LOCAL); + AddService(true /* Force registration to refresh and restore Primary state */); + } + else + { + SetState(OT_BACKBONE_ROUTER_STATE_PRIMARY); + } + +exit: + return; +} + +} // namespace BackboneRouter + +} // namespace ot + +#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE diff --git a/src/core/backbone_router/local.hpp b/src/core/backbone_router/local.hpp new file mode 100644 index 000000000..3c251fc95 --- /dev/null +++ b/src/core/backbone_router/local.hpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2019, 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 local Backbone Router service. + */ + +#ifndef BACKBONE_ROUTER_LOCAL_HPP_ +#define BACKBONE_ROUTER_LOCAL_HPP_ + +#include "openthread-core-config.h" + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +#include +#include + +#include "backbone_router/leader.hpp" +#include "net/netif.hpp" + +namespace ot { + +namespace BackboneRouter { + +/** + * This class implements the definitions for local Backbone Router service. + * + */ +class Local : public InstanceLocator +{ +public: + typedef otBackboneRouterState BackboneRouterState; + + /** + * This constructor initializes the local Backbone Router. + * + * @param[in] aInstance A reference to the OpenThread instance. + * + */ + explicit Local(Instance &aInstance); + + /** + * This methhod enables/disables Backbone function. + * + * @param[in] aEnable TRUE to enable the backbone function, FALSE otherwise. + * + */ + void SetEnabled(bool aEnable); + + /** + * This methhod retrieves the Backbone Router state. + * + * + * @retval OT_BACKBONE_ROUTER_STATE_DISABLED Backbone function is disabled. + * @retval OT_BACKBONE_ROUTER_STATE_SECONDARY Secondary Backbone Router. + * @retval OT_BACKBONE_ROUTER_STATE_PRIMARY Primary Backbone Router. + * + */ + BackboneRouterState GetState(void) const { return mState; } + + /** + * This method resets the local Thread Network Data. + * + */ + void Reset(void); + + /** + * This method gets local Backbone Router configuration. + * + * @param[out] aConfig The local Backbone Router configuration. + * + */ + void GetConfig(BackboneRouterConfig &aConfig) const; + + /** + * This method sets local Backbone Router configuration. + * + * @param[in] aConfig The configuration to set. + * + */ + void SetConfig(const BackboneRouterConfig &aConfig); + + /** + * This method registers Backbone Router Dataset to Leader. + * + * @param[in] aForce True to force registration regardless of current BackboneRouterState. + * False to decide based on current BackboneRouterState. + * + * + * @retval OT_ERROR_NONE Successfully added the Service entry. + * @retval OT_ERROR_INVALID_STATE Not in the ready state to register. + * @retval OT_ERROR_NO_BUFS Insufficient space to add the Service entry. + * + */ + otError AddService(bool aForce = false); + + /** + * This method indicates whether or not the Backbone Router is primary. + * + * @retval True if the backbone router is primary. + * @retval False if the backbone router is not primary. + * + */ + bool IsPrimary(void) const { return mState == OT_BACKBONE_ROUTER_STATE_PRIMARY; } + + /** + * This method sets the Backbone Router registration jitter value. + * + * @param[in] aRegistrationJitter the Backbone Router registration jitter value to set. + * + */ + void SetRegistrationJitter(uint8_t aRegistrationJitter) { mRegistrationJitter = aRegistrationJitter; } + + /** + * This method returns the Backbone Router registration jitter value. + * + * @returns The Backbone Router registration jitter value. + * + */ + uint8_t GetRegistrationJitter(void) const { return mRegistrationJitter; } + + /** + * This method notifies primary backbone router status. + * + * @param[in] aState The state or state change of primary backbone router. + * @param[in] aConfig The primary backbone router service. + * + */ + void UpdateBackboneRouterPrimary(Leader::State aState, const BackboneRouterConfig &aConfig); + +private: + void SetState(BackboneRouterState aState); + otError RemoveService(void); + + BackboneRouterState mState; + uint32_t mMlrTimeout; + uint16_t mReregistrationDelay; + uint8_t mSequenceNumber; + uint8_t mRegistrationJitter; + + // Indicates whether or not already add Backbone Router Service to local server data. + // Used to check whether or not in restore stage after reset or whether to remove bbr + // service for secondary bbr if it is added by force. + bool mIsServiceAdded; +}; + +} // namespace BackboneRouter + +/** + * @} + */ + +} // namespace ot + +#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + +#endif // BACKBONE_ROUTER_LOCAL_HPP_ diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index b7a550c05..d8fad2315 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -73,6 +73,16 @@ #if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE #include "utils/channel_monitor.hpp" #endif + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#include "backbone_router/leader.hpp" + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +#include "backbone_router/local.hpp" +#endif + +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + #endif // OPENTHREAD_FTD || OPENTHREAD_MTD #if OPENTHREAD_ENABLE_VENDOR_EXTENSION #include "common/extension.hpp" @@ -685,6 +695,20 @@ template <> inline MessagePool &Instance::Get(void) return mMessagePool; } +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +template <> inline BackboneRouter::Leader &Instance::Get(void) +{ + return mThreadNetif.mBackboneRouterLeader; +} + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +template <> inline BackboneRouter::Local &Instance::Get(void) +{ + return mThreadNetif.mBackboneRouterLocal; +} +#endif +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + #endif // OPENTHREAD_MTD || OPENTHREAD_FTD #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE diff --git a/src/core/config/backbone_router.h b/src/core/config/backbone_router.h new file mode 100644 index 000000000..204e3f46c --- /dev/null +++ b/src/core/config/backbone_router.h @@ -0,0 +1,48 @@ +/* + * 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 compile-time configurations for Backbone Router services. + * + */ + +#ifndef CONFIG_BACKBONE_ROUTER_H_ +#define CONFIG_BACKBONE_ROUTER_H_ + +/** + * @def OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + * + * Define to 1 to enable Backbone Router support. + * + */ +#ifndef OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +#define OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 0 +#endif + +#endif // CONFIG_BACKBONE_ROUTER_H_ diff --git a/src/core/config/openthread-core-config-check.h b/src/core/config/openthread-core-config-check.h index 28f5fb12e..506b0d628 100644 --- a/src/core/config/openthread-core-config-check.h +++ b/src/core/config/openthread-core-config-check.h @@ -468,4 +468,15 @@ "OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT (in seconds) was replaced by OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS (in milliseconds)" #endif +#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" +#endif + +#if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE +#error "OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE is required for OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE" +#endif + +#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + #endif // OPENTHREAD_CORE_CONFIG_CHECK_H_ diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp index 7d3dab6b2..a936d75ca 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -100,7 +100,7 @@ public: /** * This method generate the response header according to the saved metadata. * - * @param[out] aHeader A refernce to the response header. + * @param[out] aHeader A reference to the response header. * @param[in] aCode The response code to fill in the response header. * * @retval OT_ERROR_NONE Successfully generated the response header. diff --git a/src/core/openthread-core-config.h b/src/core/openthread-core-config.h index d62ec67a5..5f79261bb 100644 --- a/src/core/openthread-core-config.h +++ b/src/core/openthread-core-config.h @@ -53,6 +53,7 @@ #include "config/openthread-core-default-config.h" #include "config/announce_sender.h" +#include "config/backbone_router.h" #include "config/border_router.h" #include "config/channel_manager.h" #include "config/channel_monitor.h" diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 6b49ae347..c9ef5672a 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -420,6 +420,14 @@ otError MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header) { SuccessOrExit(error = MeshCoP::GetBorderAgentRloc(Get(), mMeshDest)); } + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + else if (aloc16 == Mle::kAloc16BackboneRouterPrimary) + { + VerifyOrExit(Get().HasPrimary(), error = OT_ERROR_DROP); + mMeshDest = Get().GetServer16(); + } +#endif else { // TODO: support for Neighbor Discovery Agent ALOC diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index e7370ad68..27539e010 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -55,6 +55,10 @@ #include "thread/thread_netif.hpp" #include "thread/time_sync_service.hpp" +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +#include "backbone_router/local.hpp" +#endif + using ot::Encoding::BigEndian::HostSwap16; namespace ot { @@ -155,6 +159,17 @@ Mle::Mle(Instance &aInstance) mServiceAlocs[i].GetAddress().SetLocator(Mac::kShortAddrInvalid); } +#endif +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + // Primary Backbone Router Aloc + mBackboneRouterPrimaryAloc.Clear(); + + mBackboneRouterPrimaryAloc.mPrefixLength = 64; + mBackboneRouterPrimaryAloc.mPreferred = true; + mBackboneRouterPrimaryAloc.mValid = true; + mBackboneRouterPrimaryAloc.mScopeOverride = Ip6::Address::kRealmLocalScope; + mBackboneRouterPrimaryAloc.mScopeOverrideValid = true; + mBackboneRouterPrimaryAloc.GetAddress().SetLocator(kAloc16BackboneRouterPrimary); #endif // initialize Mesh Local Prefix @@ -748,6 +763,13 @@ bool Mle::IsAttached(void) const void Mle::SetStateDetached(void) { +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + Get().Reset(); +#endif +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + Get().Reset(); +#endif + if (mRole == OT_DEVICE_ROLE_LEADER) { Get().RemoveUnicastAddress(mLeaderAloc); @@ -921,12 +943,23 @@ void Mle::SetMeshLocalPrefix(const MeshLocalPrefix &aMeshLocalPrefix) Get().RemoveUnicastAddress(mMeshLocal16); Get().UnsubscribeMulticast(mLinkLocalAllThreadNodes); Get().UnsubscribeMulticast(mRealmLocalAllThreadNodes); + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + if (Get().IsPrimary()) + { + Get().RemoveUnicastAddress(mBackboneRouterPrimaryAloc); + } +#endif } mMeshLocal64.GetAddress().SetPrefix(aMeshLocalPrefix); mMeshLocal16.GetAddress().SetPrefix(aMeshLocalPrefix); mLeaderAloc.GetAddress().SetPrefix(aMeshLocalPrefix); +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + mBackboneRouterPrimaryAloc.GetAddress().SetPrefix(GetMeshLocalPrefix()); +#endif + // Just keep mesh local prefix if network interface is down VerifyOrExit(Get().IsUp()); @@ -952,6 +985,13 @@ void Mle::ApplyMeshLocalPrefix(void) #endif +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + if (Get().IsPrimary()) + { + Get().AddUnicastAddress(mBackboneRouterPrimaryAloc); + } +#endif + mLinkLocalAllThreadNodes.GetAddress().mFields.m8[3] = 64; memcpy(mLinkLocalAllThreadNodes.GetAddress().mFields.m8 + 4, mMeshLocal64.GetAddress().mFields.m8, 8); @@ -1549,6 +1589,9 @@ void Mle::HandleStateChanged(otChangedFlags aFlags) } } +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + Get().Update(); +#endif #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE Get().SendServerDataNotification(); #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE @@ -1582,6 +1625,20 @@ void Mle::HandleStateChanged(otChangedFlags aFlags) (Get().GetSecurityPolicyFlags() & OT_SECURITY_POLICY_NATIVE_COMMISSIONING) != 0); } +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE) + { + if (Get().IsPrimary()) + { + Get().AddUnicastAddress(mBackboneRouterPrimaryAloc); + } + else + { + Get().RemoveUnicastAddress(mBackboneRouterPrimaryAloc); + } + } +#endif + exit: return; } diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 90c5ce6c9..e5084031e 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -732,7 +732,7 @@ public: /** * This method retrieves the Service ALOC for given Service ID. * - * @param[in] aServiceID Service ID to get ALOC for. + * @param[in] aServiceId Service ID to get ALOC for. * @param[out] aAddress A reference to the Service ALOC. * * @retval OT_ERROR_NONE Successfully retrieved the Service ALOC. @@ -1767,7 +1767,11 @@ private: Ip6::NetifUnicastAddress mLeaderAloc; #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - Ip6::NetifUnicastAddress mServiceAlocs[OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_MAX_ALOCS]; + Ip6::NetifUnicastAddress mServiceAlocs[kMaxServiceAlocs]; +#endif + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + Ip6::NetifUnicastAddress mBackboneRouterPrimaryAloc; #endif otMleCounters mCounters; diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 173853868..59573ecf3 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -80,6 +80,9 @@ MleRouter::MleRouter(Instance &aInstance) , mRouterSelectionJitter(kRouterSelectionJitter) , mRouterSelectionJitterTimeout(0) , mParentPriority(kParentPriorityUnspecified) +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + , mBackboneRouterRegistrationDelay(0) +#endif { mDeviceMode.Set(mDeviceMode.Get() | DeviceMode::kModeFullThreadDevice | DeviceMode::kModeFullNetworkData); @@ -1725,6 +1728,23 @@ void MleRouter::HandleStateUpdateTimer(void) routerStateUpdate = true; } } +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + // Delay register only when `mRouterSelectionJitterTimeout` is 0, + // that is, when the device has decided to stay as REED or Router. + else if (mBackboneRouterRegistrationDelay > 0) + { + mBackboneRouterRegistrationDelay--; + + if (mBackboneRouterRegistrationDelay == 0) + { + // If no Backbone Router service after jitter, try to register its own Backbone Router Service. + if (!Get().HasPrimary()) + { + Get().AddService(); + } + } + } +#endif switch (mRole) { diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index f5f4be03d..fcc479120 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -659,6 +659,16 @@ public: otError SendTimeSync(void); #endif +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + /** + * This method sets the delay before registering Backbone Router service. + * + * @param[in] aDelay The delay before registering Backbone Router service. + * + */ + void SetBackboneRouterRegistrationDelay(uint8_t aDelay) { mBackboneRouterRegistrationDelay = aDelay; } +#endif + private: enum { @@ -803,6 +813,9 @@ private: uint8_t mRouterSelectionJitterTimeout; ///< The Timeout prior to request/release Router ID. int8_t mParentPriority; ///< The assigned parent priority value, -2 means not assigned. +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + uint8_t mBackboneRouterRegistrationDelay; ///< Delay before registering Backbone Router service. +#endif #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE MeshCoP::SteeringDataTlv mSteeringData; diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp index d96c345e5..298599bdd 100644 --- a/src/core/thread/mle_types.hpp +++ b/src/core/thread/mle_types.hpp @@ -63,6 +63,12 @@ enum kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN, kMaxChildKeepAliveAttempts = 4, ///< Maximum keep alive attempts before attempting to reattach to a new Parent kFailedChildTransmissions = OPENTHREAD_CONFIG_FAILED_CHILD_TRANSMISSIONS, ///< FAILED_CHILD_TRANSMISSIONS +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + // Extra one for core Backbone Router Service. + kMaxServiceAlocs = OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_MAX_ALOCS + 1, +#else + kMaxServiceAlocs = OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_MAX_ALOCS, +#endif }; /** @@ -90,12 +96,12 @@ enum kMaxChildUpdateResponseTimeout = 2000, ///< Maximum delay for receiving a Child Update Response kMaxLinkRequestTimeout = 2000, ///< Maximum delay for receiving a Link Accept kMinTimeoutKeepAlive = (((kMaxChildKeepAliveAttempts + 1) * kUnicastRetransmissionDelay) / - 1000), ///< Minimum timeout(s) for keep alive + 1000), ///< Minimum timeout(in seconds) for keep alive kMinTimeoutDataPoll = (OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD + OPENTHREAD_CONFIG_FAILED_CHILD_TRANSMISSIONS * OPENTHREAD_CONFIG_MAC_RETX_POLL_PERIOD) / - 1000, ///< Minimum timeout(s) for data poll + 1000, ///< Minimum timeout(in seconds) for data poll kMinTimeout = (kMinTimeoutKeepAlive >= kMinTimeoutDataPoll ? kMinTimeoutKeepAlive - : kMinTimeoutDataPoll), ///< Minimum timeout(s) + : kMinTimeoutDataPoll), ///< Minimum timeout(in seconds) }; enum @@ -210,6 +216,7 @@ enum AlocAllocation kAloc16ServiceEnd = 0xfc2f, kAloc16CommissionerStart = 0xfc30, kAloc16CommissionerEnd = 0xfc37, + kAloc16BackboneRouterPrimary = 0xfc38, kAloc16CommissionerMask = 0x0007, kAloc16NeighborDiscoveryAgentStart = 0xfc40, kAloc16NeighborDiscoveryAgentEnd = 0xfc4e, @@ -219,12 +226,27 @@ enum AlocAllocation * Service IDs * */ -enum ServiceID +enum ServiceId { kServiceMinId = 0x00, ///< Minimal Service ID. kServiceMaxId = 0x0f, ///< Maximal Service ID. }; +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + +/** + * Backbone Router constants + * + */ +enum +{ + kRegistrationDelayDefault = 1200, //< In seconds. + kMlrTimeoutDefault = 3600, //< In seconds. + kBackboneRouterRegistrationJitter = 5, //< In seconds. +}; + +#endif + /** * This type represents a MLE device mode. * diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp index c5050bfa7..693afee43 100644 --- a/src/core/thread/network_data.cpp +++ b/src/core/thread/network_data.cpp @@ -275,7 +275,7 @@ otError NetworkData::GetNextService(Iterator &aIterator, uint16_t aRloc16, Servi { memset(&aConfig, 0, sizeof(aConfig)); - aConfig.mServiceID = service->GetServiceID(); + aConfig.mServiceId = service->GetServiceId(); aConfig.mEnterpriseNumber = service->GetEnterpriseNumber(); aConfig.mServiceDataLength = service->GetServiceDataLength(); @@ -347,7 +347,7 @@ otError NetworkData::GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uin if ((aRloc16 == Mac::kShortAddrBroadcast) || (server->GetServer16() == aRloc16)) { - aServiceId = service->GetServiceID(); + aServiceId = service->GetServiceId(); if (subCur->GetNext() >= cur->GetNext()) { @@ -486,7 +486,7 @@ bool NetworkData::ContainsService(uint8_t aServiceId, uint16_t aRloc16) service = static_cast(cur); - if (service->GetServiceID() == aServiceId) + if (service->GetServiceId() == aServiceId) { subCur = service->GetSubTlvs(); subEnd = cur->GetNext(); @@ -715,7 +715,7 @@ void NetworkData::RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength, Serv case NetworkDataTlv::kTypeServer: { server = static_cast(cur); - server->SetServer16(Mle::Mle::ServiceAlocFromId(aService.GetServiceID())); + server->SetServer16(Mle::Mle::ServiceAlocFromId(aService.GetServiceId())); break; } diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp index 9dcb30320..c2206f8e8 100644 --- a/src/core/thread/network_data.hpp +++ b/src/core/thread/network_data.hpp @@ -240,11 +240,11 @@ public: otError GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig); /** - * This method provides the next service ID in the Thread Network Data for a given RLOC16. + * This method provides the next Service ID in the Thread Network Data for a given RLOC16. * * @param[inout] aIterator A reference to the Network Data iterator. * @param[in] aRloc16 The RLOC16 value. - * @param[out] aServiceID A reference to variable where the service ID will be placed. + * @param[out] aServiceId A reference to variable where the Service ID will be placed. * * @retval OT_ERROR_NONE Successfully found the next service. * @retval OT_ERROR_NOT_FOUND No subsequent service exists in the Thread Network Data. @@ -295,7 +295,7 @@ public: * This method indicates whether or not the Thread Network Data contains the service with given Service ID * associated with @p aRloc16. * - * @param[in] aServiceID The Service ID to search for. + * @param[in] aServiceId The Service ID to search for. * @param[in] aRloc16 The RLOC16 to consider. * * @returns TRUE if this object contains the service with given ID associated with @p aRloc16, diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index f3c5fde7b..872908c8e 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -67,6 +67,91 @@ void LeaderBase::Reset(void) Get().Signal(OT_CHANGED_THREAD_NETDATA); } +otError LeaderBase::GetServiceId(uint32_t aEnterpriseNumber, + const uint8_t *aServiceData, + uint8_t aServiceDataLength, + bool aServerStable, + uint8_t & aServiceId) +{ + otError error = OT_ERROR_NOT_FOUND; + Iterator iterator = kIteratorInit; + otServiceConfig serviceConfig; + + while (GetNextService(iterator, serviceConfig) == OT_ERROR_NONE) + { + if (aEnterpriseNumber == serviceConfig.mEnterpriseNumber && + aServiceDataLength == serviceConfig.mServiceDataLength && + memcmp(aServiceData, serviceConfig.mServiceData, aServiceDataLength) == 0 && + aServerStable == serviceConfig.mServerConfig.mStable) + { + aServiceId = serviceConfig.mServiceId; + ExitNow(error = OT_ERROR_NONE); + } + } + +exit: + return error; +} + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +otError LeaderBase::GetBackboneRouterPrimary(BackboneRouter::BackboneRouterConfig &aConfig) +{ + otError error = OT_ERROR_NOT_FOUND; + uint8_t serviceData = ServiceTlv::kServiceDataBackboneRouter; + const ServerTlv * rvalServerTlv = NULL; + const BackboneRouterServerData *rvalServerData = NULL; + ServiceTlv * serviceTlv; + NetworkDataTlv * subCur; + NetworkDataTlv * subEnd; + + serviceTlv = Get().FindService(THREAD_ENTERPRISE_NUMBER, &serviceData, sizeof(serviceData)); + + if (serviceTlv == NULL) + { + aConfig.mServer16 = Mac::kShortAddrInvalid; + ExitNow(); + } + + subCur = serviceTlv->GetSubTlvs(); + subEnd = serviceTlv->GetNext(); + + while (subCur < subEnd) + { + ServerTlv * serverTlv; + const BackboneRouterServerData *serverData; + + VerifyOrExit((subCur + 1) <= subEnd && subCur->GetNext() <= subEnd, error = OT_ERROR_PARSE); + + serverTlv = static_cast(subCur); + serverData = reinterpret_cast(serverTlv->GetServerData()); + + if (rvalServerTlv == NULL || + (serverTlv->GetServer16() == Mle::Mle::Rloc16FromRouterId(Get().GetLeaderId())) || + serverData->GetSequenceNumber() > rvalServerData->GetSequenceNumber() || + (serverData->GetSequenceNumber() == rvalServerData->GetSequenceNumber() && + serverTlv->GetServer16() > rvalServerTlv->GetServer16())) + { + rvalServerTlv = const_cast(serverTlv); + rvalServerData = serverData; + } + + subCur = subCur->GetNext(); + } + + VerifyOrExit(rvalServerTlv != NULL); + + aConfig.mServer16 = rvalServerTlv->GetServer16(); + aConfig.mSequenceNumber = rvalServerData->GetSequenceNumber(); + aConfig.mReregistrationDelay = rvalServerData->GetReregistrationDelay(); + aConfig.mMlrTimeout = rvalServerData->GetMlrTimeout(); + + error = OT_ERROR_NONE; + +exit: + return error; +} +#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) { PrefixTlv * prefix; diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp index 2d0b99abf..7d454df29 100644 --- a/src/core/thread/network_data_leader.hpp +++ b/src/core/thread/network_data_leader.hpp @@ -38,6 +38,10 @@ #include +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#include "backbone_router/leader.hpp" +#endif + #include "coap/coap.hpp" #include "common/timer.hpp" #include "net/ip6_address.hpp" @@ -229,6 +233,38 @@ public: */ otError GetRlocByContextId(uint8_t aContextId, uint16_t &aRloc16); + /** + * This method gets the Service ID for the specified service. + * + * @param[in] aEnterpriseNumber Enterprise Number (IANA-assigned) for Service TLV + * @param[in] aServiceData A pointer to the Service Data + * @param[in] aServiceDataLength The length of @p aServiceData in bytes. + * @param[in] aServerStable The Stable flag value for Server TLV + * @param[out] aServiceId A reference where to put the Service ID. + * + * @retval OT_ERROR_NONE Successfully got the Service ID. + * @retval OT_ERROR_NOT_FOUND The specified service was not found. + * + */ + otError GetServiceId(uint32_t aEnterpriseNumber, + const uint8_t *aServiceData, + uint8_t aServiceDataLength, + bool aServerStable, + uint8_t & aServiceId); + +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + /** + * This method gets the Primary Backbone Router (PBBR) in the Thread Network. + * + * @param[out] aConfig The Primary Backbone Router configuration. + * + * @retval OT_ERROR_NONE Successfully got the Primary Backbone Router configuration. + * @retval OT_ERROR_NOT_FOUND No Backbone Router Service in the Thread Network. + * + */ + otError GetBackboneRouterPrimary(BackboneRouter::BackboneRouterConfig &aConfig); +#endif + protected: uint8_t mStableVersion; uint8_t mVersion; diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index cedf89957..5af673050 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -750,7 +750,7 @@ otError Leader::RegisterNetworkData(uint16_t aRloc16, uint8_t *aTlvs, uint8_t aT rlocStable = true; } - // Store old Service IDs for given rloc16, so updates to server will reuse the same Service ID + // Store old Service IDs for given rloc16, so updates to server will reuse the same Service ID. SuccessOrExit(error = GetNetworkData(false, oldTlvs, oldTlvsLength)); RemoveRloc(aRloc16, kMatchModeRloc16); @@ -946,7 +946,7 @@ otError Leader::AddServer(ServiceTlv &aService, ServerTlv &aServer, uint8_t *aOl ServiceTlv *oldService = NULL; ServerTlv * dstServer = NULL; uint16_t appendLength = 0; - uint8_t serviceID = 0; + uint8_t serviceId = 0; uint8_t serviceInsertLength = sizeof(ServiceTlv) + sizeof(uint8_t) /*mServiceDataLength*/ + ServiceTlv::GetEnterpriseNumberFieldLength(aService.GetEnterpriseNumber()) + aService.GetServiceDataLength(); @@ -972,21 +972,21 @@ otError Leader::AddServer(ServiceTlv &aService, ServerTlv &aServer, uint8_t *aOl if (oldService != NULL) { // The same service is not found in current data, but was in old data. So, it had to be just removed by - // RemoveRloc() Lets use the same ServiceID - serviceID = oldService->GetServiceID(); + // RemoveRloc() Lets use the same ServiceId + serviceId = oldService->GetServiceId(); } else { uint8_t i; - // This seems like completely new service. Lets try to find new ServiceID for it. If all are taken, error + // This seems like completely new service. Lets try to find new ServiceId for it. If all are taken, error // out. Since we call FindServiceById() on mTlv, we need to execute this before Insert() call, otherwise // we'll find uninitialized service as well. for (i = Mle::kServiceMinId; i <= Mle::kServiceMaxId; i++) { if (FindServiceById(i) == NULL) { - serviceID = i; + serviceId = i; break; } } @@ -999,7 +999,7 @@ otError Leader::AddServer(ServiceTlv &aService, ServerTlv &aServer, uint8_t *aOl dstService = reinterpret_cast(mTlvs + mLength); Insert(reinterpret_cast(dstService), serviceInsertLength); dstService->Init(); - dstService->SetServiceID(serviceID); + dstService->SetServiceId(serviceId); dstService->SetEnterpriseNumber(aService.GetEnterpriseNumber()); dstService->SetServiceData(aService.GetServiceData(), aService.GetServiceDataLength()); dstService->SetLength(serviceInsertLength - sizeof(NetworkDataTlv)); @@ -1038,7 +1038,7 @@ ServiceTlv *Leader::FindServiceById(uint8_t aServiceId) { compare = static_cast(cur); - if (compare->GetServiceID() == aServiceId) + if (compare->GetServiceId() == aServiceId) { ExitNow(); } diff --git a/src/core/thread/network_data_leader_ftd.hpp b/src/core/thread/network_data_leader_ftd.hpp index e86b46cb3..f0db3879b 100644 --- a/src/core/thread/network_data_leader_ftd.hpp +++ b/src/core/thread/network_data_leader_ftd.hpp @@ -160,7 +160,7 @@ public: void UpdateContextsAfterReset(void); /** - * This method scans network data for given service ID and returns pointer to the respective TLV, if present. + * This method scans network data for given Service ID and returns pointer to the respective TLV, if present. * * @param aServiceId Service ID to look for. * @return Pointer to the Service TLV for given Service ID, or NULL if not present. diff --git a/src/core/thread/network_data_local.cpp b/src/core/thread/network_data_local.cpp index 13edc3760..fdbfe0c61 100644 --- a/src/core/thread/network_data_local.cpp +++ b/src/core/thread/network_data_local.cpp @@ -248,7 +248,7 @@ otError Local::AddService(uint32_t aEnterpriseNumber, serviceTlv->Init(); serviceTlv->SetEnterpriseNumber(aEnterpriseNumber); - serviceTlv->SetServiceID(0); + serviceTlv->SetServiceId(0); serviceTlv->SetServiceData(aServiceData, aServiceDataLength); serviceTlv->SetLength(static_cast(serviceTlvLength)); diff --git a/src/core/thread/network_data_tlvs.hpp b/src/core/thread/network_data_tlvs.hpp index 34e95c684..c678ee170 100644 --- a/src/core/thread/network_data_tlvs.hpp +++ b/src/core/thread/network_data_tlvs.hpp @@ -808,6 +808,11 @@ OT_TOOL_PACKED_BEGIN class ServiceTlv : public NetworkDataTlv { public: + enum + { + kServiceDataBackboneRouter = 0x01, // const THREAD_SERVICE_DATA_BBR + }; + /** * This method initializes the TLV. * Initial length is set to 2, to hold S_service_data_length field. @@ -945,16 +950,16 @@ public: * * @returns Service ID */ - uint8_t GetServiceID(void) const { return (mTResSId & kSIdMask) >> kSIdOffset; } + uint8_t GetServiceId(void) const { return (mTResSId & kSIdMask) >> kSIdOffset; } /** * This method sets Service ID. * - * @param [in] aServiceID Service ID to be set. Expected range: 0x00-0x0f. + * @param [in] aServiceId Service ID to be set. Expected range: 0x00-0x0f. */ - void SetServiceID(uint8_t aServiceID) + void SetServiceId(uint8_t aServiceId) { - mTResSId = static_cast((mTResSId & ~kSIdMask) | (aServiceID << kSIdOffset)); + mTResSId = static_cast((mTResSId & ~kSIdMask) | (aServiceId << kSIdOffset)); } /** @@ -1100,6 +1105,67 @@ private: uint16_t mServer16; } OT_TOOL_PACKED_END; +OT_TOOL_PACKED_BEGIN +class BackboneRouterServerData +{ +public: + /** + * This method returns the sequence number of Backbone Router. + * + * @returns The sequence number of the Backbone Router. + * + */ + uint8_t GetSequenceNumber(void) const { return mSequenceNumber; } + + /** + * This method sets the sequence number of Backbone Router. + * + * @param[in] aSequenceNumber The sequence number of Backbone Router. + * + */ + void SetSequenceNumber(uint8_t aSequenceNumber) { mSequenceNumber = aSequenceNumber; } + + /** + * This method returns the Registration Delay (in seconds) of Backbone Router. + * + * @returns The BBR Registration Delay (in seconds) of Backbone Router. + * + */ + uint16_t GetReregistrationDelay(void) const { return HostSwap16(mReregistrationDelay); } + + /** + * This method sets the Registration Delay (in seconds) of Backbone Router. + * + * @param[in] aReregistrationDelay The Registration Delay (in seconds) of Backbone Router. + * + */ + void SetReregistrationDelay(uint16_t aReregistrationDelay) + { + mReregistrationDelay = HostSwap16(aReregistrationDelay); + } + + /** + * This method returns the multicast listener report timeout (in seconds) of Backbone Router. + * + * @returns The multicast listener report timeout (in seconds) of Backbone Router. + * + */ + uint32_t GetMlrTimeout(void) const { return HostSwap32(mMlrTimeout); } + + /** + * This method sets multicast listener report timeout (in seconds) of Backbone Router. + * + * @param[in] aMlrTimeout The multicast listener report timeout (in seconds) of Backbone Router. + * + */ + void SetMlrTimeout(uint32_t aMlrTimeout) { mMlrTimeout = HostSwap32(aMlrTimeout); } + +private: + uint8_t mSequenceNumber; + uint16_t mReregistrationDelay; + uint32_t mMlrTimeout; +} OT_TOOL_PACKED_END; + /** * @} * diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp index 0bd37680c..ee8f2ce75 100644 --- a/src/core/thread/thread_netif.cpp +++ b/src/core/thread/thread_netif.cpp @@ -100,6 +100,12 @@ ThreadNetif::ThreadNetif(Instance &aInstance) , mLeader(aInstance) , mAddressResolver(aInstance) #endif // OPENTHREAD_FTD +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + , mBackboneRouterLeader(aInstance) +#endif +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + , mBackboneRouterLocal(aInstance) +#endif , mChildSupervisor(aInstance) , mSupervisionListener(aInstance) , mAnnounceBegin(aInstance) diff --git a/src/core/thread/thread_netif.hpp b/src/core/thread/thread_netif.hpp index 46aa3d025..0a06dea51 100644 --- a/src/core/thread/thread_netif.hpp +++ b/src/core/thread/thread_netif.hpp @@ -47,6 +47,12 @@ #include "meshcop/commissioner.hpp" #endif // OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#include "backbone_router/leader.hpp" +#endif +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +#include "backbone_router/local.hpp" +#endif #include "meshcop/dataset_manager.hpp" #if OPENTHREAD_CONFIG_JOINER_ENABLE @@ -221,6 +227,12 @@ private: AddressResolver mAddressResolver; #endif // OPENTHREAD_FTD +#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) + BackboneRouter::Leader mBackboneRouterLeader; +#endif +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + BackboneRouter::Local mBackboneRouterLocal; +#endif Utils::ChildSupervisor mChildSupervisor; Utils::SupervisionListener mSupervisionListener; AnnounceBeginServer mAnnounceBegin; diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 4f5ffb202..5a10d1def 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -926,7 +926,7 @@ template <> otError NcpBase::HandlePropertyGet