[bbr] add backbone router service (#4430)

- Introduce BACKBONE_ROUTER option for Backbone Router function.
- Implement Backbone Router service registration.
  - Add basic Backbone Router service.
  - Primary Backbone Router restores its Dataset when reattached after
    short reset, increases sequence number and re-register to Leader.
  - Add configurable jitter for Backbone Router service registration.
- Add Backbone Router service test.
This commit is contained in:
Rongli Sun
2020-03-26 08:54:23 -07:00
committed by GitHub
parent 6606f2befe
commit 315a27bf08
46 changed files with 2384 additions and 95 deletions
+4
View File
@@ -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 \
+4
View File
@@ -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",
+5
View File
@@ -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")
+5
View File
@@ -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
+4 -2
View File
@@ -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 \
+87
View File
@@ -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 <openthread/instance.h>
#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_
+170
View File
@@ -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 <openthread/backbone_router.h>
#include <openthread/ip6.h>
#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_
+27 -25
View File
@@ -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
};
/**
+1 -1
View File
@@ -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.
+34
View File
@@ -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
+126
View File
@@ -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 \<seqno\>\] \[delay \<delay\>\] \[timeout \<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 \<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.
+144
View File
@@ -66,6 +66,13 @@
#include "common/new.hpp"
#include "net/ip6.hpp"
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
#include <openthread/backbone_router.h>
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#include <openthread/backbone_router_ftd.h>
#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<uint8_t>(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<uint8_t>(value);
}
else if (strcmp(aArgs[argCur], "delay") == 0)
{
SuccessOrExit(error = ParseUnsignedLong(aArgs[++argCur], value));
config.mReregistrationDelay = static_cast<uint16_t>(value);
}
else if (strcmp(aArgs[argCur], "timeout") == 0)
{
SuccessOrExit(error = ParseUnsignedLong(aArgs[++argCur], value));
config.mMlrTimeout = static_cast<uint32_t>(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);
+7
View File
@@ -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[]);
+4
View File
@@ -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
+7
View File
@@ -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 \
+51
View File
@@ -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 <openthread/backbone_router.h>
#include "common/instance.hpp"
using namespace ot;
otError otBackboneRouterGetPrimary(otInstance *aInstance, otBackboneRouterConfig *aConfig)
{
Instance &instance = *static_cast<Instance *>(aInstance);
OT_ASSERT(aConfig != NULL);
return instance.Get<BackboneRouter::Leader>().GetConfig(*aConfig);
}
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+97
View File
@@ -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 <openthread/backbone_router_ftd.h>
#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<Instance *>(aInstance);
return instance.Get<BackboneRouter::Local>().SetEnabled(aEnabled);
}
otBackboneRouterState otBackboneRouterGetState(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<BackboneRouter::Local>().GetState();
}
void otBackboneRouterGetConfig(otInstance *aInstance, otBackboneRouterConfig *aConfig)
{
Instance &instance = *static_cast<Instance *>(aInstance);
OT_ASSERT(aConfig != NULL);
instance.Get<BackboneRouter::Local>().GetConfig(*aConfig);
}
void otBackboneRouterSetConfig(otInstance *aInstance, const otBackboneRouterConfig *aConfig)
{
Instance &instance = *static_cast<Instance *>(aInstance);
OT_ASSERT(aConfig != NULL);
instance.Get<BackboneRouter::Local>().SetConfig(*aConfig);
}
otError otBackboneRouterRegister(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<BackboneRouter::Local>().AddService(true /* Force registration */);
}
uint8_t otBackboneRouterGetRegistrationJitter(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<BackboneRouter::Local>().GetRegistrationJitter();
}
void otBackboneRouterSetRegistrationJitter(otInstance *aInstance, uint8_t aJitter)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<BackboneRouter::Local>().SetRegistrationJitter(aJitter);
}
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+192
View File
@@ -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<NetworkData::Leader>().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<NetworkData::Leader>().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<BackboneRouter::Local>().UpdateBackboneRouterPrimary(state, mConfig);
#endif
}
} // namespace BackboneRouter
} // namespace ot
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+146
View File
@@ -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 <openthread/backbone_router.h>
#include <openthread/ip6.h>
#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_
+249
View File
@@ -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<Notifier>().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<Notifier>().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<Mle::Mle>().IsAttached());
VerifyOrExit(aForce /* if register by force */ ||
!Get<BackboneRouter::Leader>().HasPrimary() /* if no available Backbone Router service */ ||
Get<BackboneRouter::Leader>().GetServer16() == Get<Mle::MleRouter>().GetRloc16()
/* If the device itself should be BBR. */
);
serverData.SetSequenceNumber(mSequenceNumber);
serverData.SetReregistrationDelay(mReregistrationDelay);
serverData.SetMlrTimeout(mMlrTimeout);
SuccessOrExit(error = Get<NetworkData::Local>().AddService(
THREAD_ENTERPRISE_NUMBER, &serviceData, sizeof(serviceData), true,
reinterpret_cast<const uint8_t *>(&serverData), sizeof(serverData)));
mIsServiceAdded = true;
Get<NetworkData::Local>().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<NetworkData::Local>().RemoveService(THREAD_ENTERPRISE_NUMBER, &serviceData, sizeof(serviceData)));
mIsServiceAdded = false;
if (Get<Mle::MleRouter>().IsAttached())
{
Get<NetworkData::Local>().SendServerDataNotification();
}
exit:
otLogInfoNetData("Remove BBR Service %s", otThreadErrorToString(error));
return error;
}
void Local::SetState(BackboneRouterState aState)
{
VerifyOrExit(mState != aState);
mState = aState;
Get<Notifier>().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<Mle::MleRouter>().IsAttached());
// Wait some jitter before trying to Register.
if (aConfig.mServer16 == Mac::kShortAddrInvalid)
{
uint8_t delay = 1;
if (Get<Mle::MleRouter>().GetRole() != OT_DEVICE_ROLE_LEADER)
{
delay += Random::NonCrypto::GetUint8InRange(0, mRegistrationJitter < 255 ? mRegistrationJitter + 1
: mRegistrationJitter);
}
// Here uses the timer resource in Mle.
Get<Mle::MleRouter>().SetBackboneRouterRegistrationDelay(delay);
}
else if (aConfig.mServer16 != Get<Mle::MleRouter>().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<Notifier>().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
+182
View File
@@ -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 <openthread/backbone_router.h>
#include <openthread/backbone_router_ftd.h>
#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_
+24
View File
@@ -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
+48
View File
@@ -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_
@@ -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_
+1 -1
View File
@@ -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.
+1
View File
@@ -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"
+8
View File
@@ -420,6 +420,14 @@ otError MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header)
{
SuccessOrExit(error = MeshCoP::GetBorderAgentRloc(Get<ThreadNetif>(), mMeshDest));
}
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
else if (aloc16 == Mle::kAloc16BackboneRouterPrimary)
{
VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = OT_ERROR_DROP);
mMeshDest = Get<BackboneRouter::Leader>().GetServer16();
}
#endif
else
{
// TODO: support for Neighbor Discovery Agent ALOC
+57
View File
@@ -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<BackboneRouter::Local>().Reset();
#endif
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
Get<BackboneRouter::Leader>().Reset();
#endif
if (mRole == OT_DEVICE_ROLE_LEADER)
{
Get<ThreadNetif>().RemoveUnicastAddress(mLeaderAloc);
@@ -921,12 +943,23 @@ void Mle::SetMeshLocalPrefix(const MeshLocalPrefix &aMeshLocalPrefix)
Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocal16);
Get<ThreadNetif>().UnsubscribeMulticast(mLinkLocalAllThreadNodes);
Get<ThreadNetif>().UnsubscribeMulticast(mRealmLocalAllThreadNodes);
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
if (Get<BackboneRouter::Local>().IsPrimary())
{
Get<ThreadNetif>().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<ThreadNetif>().IsUp());
@@ -952,6 +985,13 @@ void Mle::ApplyMeshLocalPrefix(void)
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
if (Get<BackboneRouter::Local>().IsPrimary())
{
Get<ThreadNetif>().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<BackboneRouter::Leader>().Update();
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
Get<NetworkData::Local>().SendServerDataNotification();
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
@@ -1582,6 +1625,20 @@ void Mle::HandleStateChanged(otChangedFlags aFlags)
(Get<KeyManager>().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<BackboneRouter::Local>().IsPrimary())
{
Get<ThreadNetif>().AddUnicastAddress(mBackboneRouterPrimaryAloc);
}
else
{
Get<ThreadNetif>().RemoveUnicastAddress(mBackboneRouterPrimaryAloc);
}
}
#endif
exit:
return;
}
+6 -2
View File
@@ -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;
+20
View File
@@ -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<BackboneRouter::Leader>().HasPrimary())
{
Get<BackboneRouter::Local>().AddService();
}
}
}
#endif
switch (mRole)
{
+13
View File
@@ -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;
+26 -4
View File
@@ -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.
*
+4 -4
View File
@@ -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<ServiceTlv *>(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<ServerTlv *>(cur);
server->SetServer16(Mle::Mle::ServiceAlocFromId(aService.GetServiceID()));
server->SetServer16(Mle::Mle::ServiceAlocFromId(aService.GetServiceId()));
break;
}
+3 -3
View File
@@ -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,
+85
View File
@@ -67,6 +67,91 @@ void LeaderBase::Reset(void)
Get<Notifier>().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<Leader>().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<ServerTlv *>(subCur);
serverData = reinterpret_cast<const BackboneRouterServerData *>(serverTlv->GetServerData());
if (rvalServerTlv == NULL ||
(serverTlv->GetServer16() == Mle::Mle::Rloc16FromRouterId(Get<Mle::MleRouter>().GetLeaderId())) ||
serverData->GetSequenceNumber() > rvalServerData->GetSequenceNumber() ||
(serverData->GetSequenceNumber() == rvalServerData->GetSequenceNumber() &&
serverTlv->GetServer16() > rvalServerTlv->GetServer16()))
{
rvalServerTlv = const_cast<ServerTlv *>(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;
+36
View File
@@ -38,6 +38,10 @@
#include <stdint.h>
#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;
+8 -8
View File
@@ -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<ServiceTlv *>(mTlvs + mLength);
Insert(reinterpret_cast<uint8_t *>(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<ServiceTlv *>(cur);
if (compare->GetServiceID() == aServiceId)
if (compare->GetServiceId() == aServiceId)
{
ExitNow();
}
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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<uint8_t>(serviceTlvLength));
+70 -4
View File
@@ -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<uint8_t>((mTResSId & ~kSIdMask) | (aServiceID << kSIdOffset));
mTResSId = static_cast<uint8_t>((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;
/**
* @}
*
+6
View File
@@ -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)
+12
View File
@@ -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;
+1 -1
View File
@@ -926,7 +926,7 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SERVER_LEADER_SERVICE
{
SuccessOrExit(error = mEncoder.OpenStruct());
SuccessOrExit(error = mEncoder.WriteUint8(cfg.mServiceID));
SuccessOrExit(error = mEncoder.WriteUint8(cfg.mServiceId));
SuccessOrExit(error = mEncoder.WriteUint32(cfg.mEnterpriseNumber));
SuccessOrExit(error = mEncoder.WriteDataWithLen(cfg.mServiceData, cfg.mServiceDataLength));
SuccessOrExit(error = mEncoder.WriteBool(cfg.mServerConfig.mStable));
+159 -38
View File
@@ -43,11 +43,17 @@ import binascii
class Node:
def __init__(self, nodeid, is_mtd=False, simulator=None, version=None):
def __init__(self,
nodeid,
is_mtd=False,
simulator=None,
version=None,
is_bbr=False):
self.nodeid = nodeid
self.verbose = int(float(os.getenv('VERBOSE', 0)))
self.node_type = os.getenv('NODE_TYPE', 'sim')
self.env_version = os.getenv('THREAD_VERSION', '1.1')
self.is_bbr = is_bbr
self._initialized = False
if version is not None:
@@ -76,24 +82,45 @@ class Node:
def __init_sim(self, nodeid, mode):
""" Initialize a simulation node. """
if 'OT_CLI_PATH' in os.environ:
cmd = os.environ['OT_CLI_PATH']
elif (self.version == '1.1' and self.version != self.env_version):
# Default command if no match below, will be overridden if below conditions are met.
cmd = './ot-cli-%s' % (mode)
# If Thread version of node matches the testing environment version.
if self.version == self.env_version:
# Load Thread 1.2 BBR device when testing Thread 1.2 scenarios
# which requires device with Backbone functionality.
if self.version == '1.2' and self.is_bbr:
if 'OT_CLI_PATH_1_2_BBR' in os.environ:
cmd = os.environ['OT_CLI_PATH_1_2_BBR']
elif 'top_builddir_1_2_bbr' in os.environ:
srcdir = os.environ['top_builddir_1_2_bbr']
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
# Load Thread device of the testing environment version (may be 1.1 or 1.2)
else:
if 'OT_CLI_PATH' in os.environ:
cmd = os.environ['OT_CLI_PATH']
elif 'top_builddir' in os.environ:
srcdir = os.environ['top_builddir']
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
if 'RADIO_DEVICE' in os.environ:
cmd += ' -v %s' % os.environ['RADIO_DEVICE']
os.environ['NODE_ID'] = str(nodeid)
# Load Thread 1.1 node when testing Thread 1.2 scenarios for interoperability
elif self.version == '1.1':
# Posix app
if 'OT_CLI_PATH_1_1' in os.environ:
cmd = os.environ['OT_CLI_PATH_1_1']
elif ('top_builddir_1_1') in os.environ:
elif 'top_builddir_1_1' in os.environ:
srcdir = os.environ['top_builddir_1_1']
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
elif ('top_builddir') in os.environ:
srcdir = os.environ['top_builddir']
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
else:
cmd = '%s/ot-cli-%s' % (self.version, mode)
if 'RADIO_DEVICE' in os.environ:
cmd += ' -v %s' % os.environ['RADIO_DEVICE']
os.environ['NODE_ID'] = str(nodeid)
if 'RADIO_DEVICE_1_1' in os.environ:
cmd += ' -v %s' % os.environ['RADIO_DEVICE_1_1']
os.environ['NODE_ID'] = str(nodeid)
cmd += ' %d' % nodeid
print("%s" % cmd)
@@ -112,43 +139,69 @@ class Node:
def __init_ncp_sim(self, nodeid, mode):
""" Initialize an NCP simulation node. """
if 'RADIO_DEVICE' in os.environ:
args = ' %s' % os.environ['RADIO_DEVICE']
os.environ['NODE_ID'] = str(nodeid)
else:
args = ''
if 'OT_NCP_PATH' in os.environ:
cmd = 'spinel-cli.py -p "%s%s" -n' % (
os.environ['OT_NCP_PATH'],
args,
)
elif (self.version == '1.1' and self.version != self.env_version):
# Default command if no match below, will be overridden if below conditions are met.
cmd = 'spinel-cli.py -p ./ot-ncp-%s -n' % mode
# If Thread version of node matches the testing environment version.
if self.version == self.env_version:
if 'RADIO_DEVICE' in os.environ:
args = ' %s' % os.environ['RADIO_DEVICE']
os.environ['NODE_ID'] = str(nodeid)
else:
args = ''
# Load Thread 1.2 BBR device when testing Thread 1.2 scenarios
# which requires device with Backbone functionality.
if self.version == '1.2' and self.is_bbr:
if 'OT_NCP_PATH_1_2_BBR' in os.environ:
cmd = 'spinel-cli.py -p "%s%s" -n' % (
os.environ['OT_NCP_PATH_1_2_BBR'],
args,
)
elif 'top_builddir_1_2_bbr' in os.environ:
srcdir = os.environ['top_builddir_1_2_bbr']
cmd = '%s/examples/apps/ncp/ot-ncp-%s' % (srcdir, mode)
cmd = 'spinel-cli.py -p "%s%s" -n' % (
cmd,
args,
)
# Load Thread device of the testing environment version (may be 1.1 or 1.2).
else:
if 'OT_NCP_PATH' in os.environ:
cmd = 'spinel-cli.py -p "%s%s" -n' % (
os.environ['OT_NCP_PATH'],
args,
)
elif 'top_builddir' in os.environ:
srcdir = os.environ['top_builddir']
cmd = '%s/examples/apps/ncp/ot-ncp-%s' % (srcdir, mode)
cmd = 'spinel-cli.py -p "%s%s" -n' % (
cmd,
args,
)
# Load Thread 1.1 node when testing Thread 1.2 scenarios for interoperability.
elif self.version == '1.1':
if 'RADIO_DEVICE_1_1' in os.environ:
args = ' %s' % os.environ['RADIO_DEVICE_1_1']
os.environ['NODE_ID'] = str(nodeid)
else:
args = ''
if 'OT_NCP_PATH_1_1' in os.environ:
cmd = 'spinel-cli.py -p "%s%s" -n' % (
os.environ['OT_NCP_PATH_1_1'],
args,
)
elif ('top_builddir_1_1') in os.environ:
elif 'top_builddir_1_1' in os.environ:
srcdir = os.environ['top_builddir_1_1']
cmd = '%s/examples/apps/ncp/ot-ncp-%s' % (srcdir, mode)
cmd = 'spinel-cli.py -p "%s%s" -n' % (
cmd,
args,
)
elif ('top_builddir') in os.environ:
srcdir = os.environ['top_builddir']
cmd = '%s/examples/apps/ncp/ot-ncp-%s' % (srcdir, mode)
cmd = 'spinel-cli.py -p "%s%s" -n' % (
cmd,
args,
)
else:
cmd = 'spinel-cli.py -p "%s/ot-ncp-%s%s" -n' % (
self.version,
mode,
args,
)
cmd += ' %d' % nodeid
print("%s" % cmd)
@@ -388,6 +441,74 @@ class Node:
self.send_command(cmd)
self._expect('Done')
def get_bbr_registration_jitter(self):
self.send_command('bbr jitter')
return int(self._expect_result(r'\d+'))
def set_bbr_registration_jitter(self, jitter):
cmd = 'bbr jitter %d' % jitter
self.send_command(cmd)
self._expect('Done')
def enable_backbone_router(self):
cmd = 'bbr enable'
self.send_command(cmd)
self._expect('Done')
def disable_backbone_router(self):
cmd = 'bbr disable'
self.send_command(cmd)
self._expect('Done')
def register_backbone_router(self):
cmd = 'bbr register'
self.send_command(cmd)
self._expect('Done')
def get_backbone_router_state(self):
states = [r'Disabled', r'Primary', r'Secondary']
self.send_command('bbr state')
return self._expect_result(states)
def get_backbone_router(self):
cmd = 'bbr config'
self.send_command(cmd)
self._expect(r'(.*)Done')
g = self.pexpect.match.groups()
output = g[0].decode("utf-8")
lines = output.strip().split('\n')
lines = [l.strip() for l in lines]
ret = {}
for l in lines:
z = re.search(r'seqno:\s+([0-9]+)', l)
if z:
ret['seqno'] = int(z.groups()[0])
z = re.search(r'delay:\s+([0-9]+)', l)
if z:
ret['delay'] = int(z.groups()[0])
z = re.search(r'timeout:\s+([0-9]+)', l)
if z:
ret['timeout'] = int(z.groups()[0])
return ret
def set_backbone_router(self, seqno=None, reg_delay=None, mlr_timeout=None):
cmd = 'bbr config'
if seqno is not None:
cmd += ' seqno %d' % seqno
if reg_delay is not None:
cmd += ' delay %d' % reg_delay
if mlr_timeout is not None:
cmd += ' timeout %d' % mlr_timeout
self.send_command(cmd)
self._expect('Done')
def set_link_quality(self, addr, lqi):
cmd = 'macfilter rss add-lqi %s %s' % (addr, lqi)
self.send_command(cmd)
+2
View File
@@ -35,6 +35,7 @@ from node import Node
DEFAULT_PARAMS = {
'is_mtd': False,
'is_bbr': False,
'mode': 'rsdn',
'panid': 0xface,
'whitelist': None,
@@ -73,6 +74,7 @@ class TestCase(unittest.TestCase):
params['is_mtd'],
simulator=self.simulator,
version=params['version'],
is_bbr=params['is_bbr'],
)
self.nodes[i].set_panid(params['panid'])
self.nodes[i].set_mode(params['mode'])
@@ -0,0 +1,235 @@
#!/usr/bin/env python3
#
# 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.
#
import unittest
import thread_cert
LEADER_1_1 = 1
BBR_1 = 2
BBR_2 = 3
WAIT_ATTACH = 5
WAIT_REDUNDANCE = 3
ROUTER_SELECTION_JITTER = 1
BBR_REGISTRATION_JITTER = 5
"""
Topology
LEADER_1_1 --- BBR_1
\ |
\ |
\ |
BBR_2
1) Bring up Leader_1_1 and then BBR_1, BBR_1 becomes Primary Backbone Router.
2) Reset BBR_1, if bring back soon, it could restore the Backbone Router Service
from the network, after increasing sequence number, it will reregister its
Backbone Router Service to the Leader and become Primary.
3) Reset BBR_1, if bring back after it is released in the network, BBR_1 will
choose a random sequence number, register its Backbone Router Service to
Leader and become Primary.
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.
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.
"""
class TestBackboneRouterService(thread_cert.TestCase):
topology = {
LEADER_1_1: {
'version': '1.1',
'whitelist': [BBR_1, BBR_2],
},
BBR_1: {
'version': '1.2',
'whitelist': [LEADER_1_1, BBR_2],
'is_bbr': True
},
BBR_2: {
'version': '1.2',
'whitelist': [LEADER_1_1, BBR_1],
'is_bbr': True
},
}
"""All nodes are created with default configurations"""
def test(self):
self.nodes[LEADER_1_1].start()
WAIT_TIME = WAIT_ATTACH
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[LEADER_1_1].get_state(), 'leader')
# 1) First Backbone Router would become the Primary.
self.nodes[BBR_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
self.nodes[BBR_1].set_bbr_registration_jitter(BBR_REGISTRATION_JITTER)
self.nodes[BBR_1].set_backbone_router(seqno=1)
self.nodes[BBR_1].start()
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_1].get_state(), 'router')
self.nodes[BBR_1].enable_backbone_router()
WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(),
'Primary')
# 2) Reset BBR_1 and bring it back soon.
# Verify that it restores Primary State with sequence number
# increased by 1.
self.nodes[BBR_1].reset()
self.nodes[BBR_1].set_bbr_registration_jitter(BBR_REGISTRATION_JITTER)
self.nodes[BBR_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
self.nodes[BBR_1].enable_backbone_router()
self.nodes[BBR_1].start()
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_1].get_state(), 'router')
WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(),
'Primary')
assert self.nodes[BBR_1].get_backbone_router()['seqno'] == 2
# 3) Reset BBR_1 and bring it back after its original router id is released
# 200s (100s MaxNeighborAge + 90s InfiniteCost + 10s redundance)
# Verify it becomes Primary again.
# Note: To ensure test in next step, here Step 3) will repeat until
# the random sequence number is not the highest value 255.
while True:
self.nodes[BBR_1].reset()
WAIT_TIME = 200
self.simulator.go(WAIT_TIME)
self.nodes[BBR_1].set_router_selection_jitter(
ROUTER_SELECTION_JITTER)
self.nodes[BBR_1].set_bbr_registration_jitter(
BBR_REGISTRATION_JITTER)
self.nodes[BBR_1].enable_backbone_router()
self.nodes[BBR_1].start()
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_1].get_state(), 'router')
WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(),
'Primary')
BBR_1_SEQNO = self.nodes[BBR_1].get_backbone_router()['seqno']
if (BBR_1_SEQNO != 255):
break
#4) Configure BBR_2 with highest sequence number (255) and
# explicitly trigger SRV_DATA.ntf.
# Verify BBR_2 would become Primary and BBR_1 would change to
# Secondary with sequence number increased by 1.
# Bring up BBR_2, it becomes Router with backbone function disabled
# by default.
self.nodes[BBR_2].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
self.nodes[BBR_2].set_bbr_registration_jitter(BBR_REGISTRATION_JITTER)
self.nodes[BBR_2].start()
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_2].get_state(), 'router')
WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_2].get_backbone_router_state(),
'Disabled')
# Enable Backbone function, it will stay at Secondary state as
# there is Primary Backbone Router already.
self.nodes[BBR_2].enable_backbone_router()
self.nodes[BBR_2].set_backbone_router(seqno=255)
WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_2].get_backbone_router_state(),
'Secondary')
# Check no SRV_DATA.ntf.
messages = self.simulator.get_messages_sent_by(BBR_2)
msg = messages.next_coap_message('0.02', '/a/sd', False)
assert (
msg is None
), "Error: %d sent unexpected SRV_DATA.ntf when there is PBbr already"
# Flush relative message queue.
self.flush_nodes([BBR_1])
# BBR_2 registers SRV_DATA.ntf explicitly.
self.nodes[BBR_2].register_backbone_router()
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_2].get_backbone_router_state(),
'Primary')
# Verify BBR_1 becomes Secondary and sends SRV_DATA.ntf to deregister
# its service.
messages = self.simulator.get_messages_sent_by(BBR_1)
messages.next_coap_message('0.02', '/a/sd', True)
self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(),
'Secondary')
# Verify Sequence number increases when become Secondary from Primary.
assert self.nodes[BBR_1].get_backbone_router()['seqno'] == (
BBR_1_SEQNO + 1)
# 5) Stop BBR_2, BBR_1 becomes Primary after detecting there is no
# available Backbone Router Service.
self.nodes[BBR_2].reset()
self.nodes[LEADER_1_1].release_router_id(
self.nodes[BBR_2].get_router_id())
# Wait for the dissemination of Network Data without backbone router service
self.simulator.go(10)
# BBR_1 becomes Primary.
self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(),
'Primary')
messages = self.simulator.get_messages_sent_by(BBR_1)
messages.next_coap_message('0.02', '/a/sd', True)
# 6) Bring back BBR_2.
# Verify that BBR_2 stays at Secondary.
self.nodes[BBR_2].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
self.nodes[BBR_2].set_bbr_registration_jitter(BBR_REGISTRATION_JITTER)
self.nodes[BBR_2].enable_backbone_router()
self.nodes[BBR_2].interface_up()
self.nodes[BBR_2].thread_start()
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_2].get_state(), 'router')
WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_2].get_backbone_router_state(),
'Secondary')
if __name__ == '__main__':
unittest.main()