[bbr] (Un)Subscribe AllDomainBBRs multicast address (#4795)

This commit includes:
- cache domain prefix in the Thread Network
- subscribe/unsubscribe AllDomainBBRs Multicast address
- update test to cover AllNetworkBBRs and AllDomainBBRs subscription
This commit is contained in:
Rongli Sun
2020-04-14 19:36:14 -07:00
committed by GitHub
parent 911010a9bf
commit b37528645a
10 changed files with 266 additions and 37 deletions
+113 -15
View File
@@ -35,16 +35,9 @@
#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 {
@@ -57,8 +50,11 @@ Leader::Leader(Instance &aInstance)
void Leader::Reset(void)
{
memset(&mConfig, 0, sizeof(mConfig));
// Invalid server short address indicates no available Backbone Router service in the Thread Network.
mConfig.mServer16 = Mac::kShortAddrInvalid;
// Domain Prefix Length 0 indicates no available Domain Prefix in the Thread network.
mDomainPrefix.mLength = 0;
}
otError Leader::GetConfig(BackboneRouterConfig &aConfig) const
@@ -87,11 +83,12 @@ exit:
return error;
}
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_NETDATA == 1)
void Leader::LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const
{
OT_UNUSED_VARIABLE(aConfig);
otLogInfoNetData("BBR state %s", StateToString(aState));
otLogInfoNetData("PBBR state: %s", StateToString(aState));
if (aState != kStateRemoved && aState != kStateNone)
{
@@ -100,6 +97,14 @@ void Leader::LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &
}
}
void Leader::LogDomainPrefix(DomainPrefixState aState, const otIp6Prefix &aPrefix) const
{
otLogInfoNetData("Domain Prefix: %s/%d, state: %s",
aPrefix.mLength == 0 ? ""
: static_cast<const Ip6::Address *>(&aPrefix.mPrefix)->ToString().AsCString(),
aPrefix.mLength, DomainPrefixStateToString(aState));
}
const char *Leader::StateToString(State aState)
{
const char *logString = "Unknown";
@@ -107,27 +112,27 @@ const char *Leader::StateToString(State aState)
switch (aState)
{
case kStateNone:
logString = "PBBR: None";
logString = "None";
break;
case kStateAdded:
logString = "PBBR: Added";
logString = "Added";
break;
case kStateRemoved:
logString = "PBBR: Removed";
logString = "Removed";
break;
case kStateToTriggerRereg:
logString = "PBBR: To trigger re-registration";
logString = "Rereg triggered";
break;
case kStateRefreshed:
logString = "PBBR: Refreshed";
logString = "Refreshed";
break;
case kStateUnchanged:
logString = "PBBR: Unchanged";
logString = "Unchanged";
break;
default:
@@ -137,7 +142,44 @@ const char *Leader::StateToString(State aState)
return logString;
}
const char *Leader::DomainPrefixStateToString(DomainPrefixState aState)
{
const char *logString = "Unknown";
switch (aState)
{
case kDomainPrefixNone:
logString = "None";
break;
case kDomainPrefixAdded:
logString = "Added";
break;
case kDomainPrefixRemoved:
logString = "Removed";
break;
case kDomainPrefixRefreshed:
logString = "Refreshed";
break;
case kDomainPrefixUnchanged:
logString = "Unchanged";
break;
}
return logString;
}
#endif
void Leader::Update(void)
{
UpdateBackboneRouterPrimary();
UpdateDomainPrefixConfig();
}
void Leader::UpdateBackboneRouterPrimary(void)
{
BackboneRouterConfig config;
State state;
@@ -186,6 +228,62 @@ void Leader::Update(void)
#endif
}
void Leader::UpdateDomainPrefixConfig(void)
{
NetworkData::Iterator iterator = NetworkData::kIteratorInit;
NetworkData::OnMeshPrefixConfig config;
DomainPrefixState state;
bool found = false;
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == OT_ERROR_NONE)
{
if (config.mDp)
{
found = true;
break;
}
}
if (!found)
{
if (mDomainPrefix.mLength != 0)
{
// Domain Prefix does not exist any more.
mDomainPrefix.mLength = 0;
state = kDomainPrefixRemoved;
}
else
{
state = kDomainPrefixNone;
}
}
else if (config.mPrefix.mLength == mDomainPrefix.mLength &&
Ip6::Address::PrefixMatch(mDomainPrefix.mPrefix.mFields.m8, config.mPrefix.mPrefix.mFields.m8,
BitVectorBytes(mDomainPrefix.mLength)) >= mDomainPrefix.mLength)
{
state = kDomainPrefixUnchanged;
}
else
{
if (mDomainPrefix.mLength == 0)
{
state = kDomainPrefixAdded;
}
else
{
state = kDomainPrefixRefreshed;
}
mDomainPrefix = config.mPrefix;
}
LogDomainPrefix(state, mDomainPrefix);
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
Get<Mle::Mle>().UpdateAllDomainBackboneRouters(state);
#endif
}
} // namespace BackboneRouter
} // namespace ot
+48 -12
View File
@@ -56,16 +56,26 @@ typedef otBackboneRouterConfig BackboneRouterConfig;
class Leader : public InstanceLocator
{
public:
// Primary Backbone Router Service State or State change.
// 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).
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).
};
// Domain Prefix state or state change.
enum DomainPrefixState
{
kDomainPrefixNone = 0, ///< Not available.
kDomainPrefixAdded, ///< Added.
kDomainPrefixRemoved, ///< Removed.
kDomainPrefixRefreshed, ///< Changed.
kDomainPrefixUnchanged, ///< Nothing changed.
};
/**
@@ -126,11 +136,37 @@ public:
*/
bool HasPrimary(void) const { return mConfig.mServer16 != Mac::kShortAddrInvalid; }
private:
void LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const;
static const char *StateToString(State aState);
/**
* This method gets the Domain Prefix in the Thread Network.
*
* @retval A pointer to the Domain Prefix or NULL if there is no Domain Prefix.
*
*/
const otIp6Prefix *GetDomainPrefix(void) const { return (mDomainPrefix.mLength == 0) ? NULL : &mDomainPrefix; }
BackboneRouterConfig mConfig; ///< Primary Backbone Router information.
/**
* This method indicates whether or not the Domain Prefix is available in the Thread Network.
*
* @retval TRUE if there is Domain Prefix, FALSE otherwise.
*
*/
bool HasDomainPrefix(void) const { return (mDomainPrefix.mLength > 0); }
private:
void UpdateBackboneRouterPrimary(void);
void UpdateDomainPrefixConfig(void);
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_NETDATA == 1)
void LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const;
void LogDomainPrefix(DomainPrefixState aState, const otIp6Prefix &aPrefix) const;
static const char *StateToString(State aState);
static const char *DomainPrefixStateToString(DomainPrefixState aState);
#else
void LogBackboneRouterPrimary(State, const BackboneRouterConfig &) const {}
void LogDomainPrefix(DomainPrefixState, const otIp6Prefix &) const {}
#endif
BackboneRouterConfig mConfig; ///< Primary Backbone Router information.
otIp6Prefix mDomainPrefix; ///< Domain Prefix on the Thread Network.
};
} // namespace BackboneRouter
-1
View File
@@ -40,7 +40,6 @@
#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"
+1
View File
@@ -41,6 +41,7 @@
#include <openthread/backbone_router_ftd.h>
#include "backbone_router/leader.hpp"
#include "common/locator.hpp"
#include "net/netif.hpp"
#include "thread/network_data.hpp"
+12 -1
View File
@@ -325,7 +325,7 @@ public:
/**
* This method sets the prefix content of Mesh Local Prefix-Based Multicast Address.
*
* @param[in] aMeshLocalPrefix A reference to the Mesh Local Prefix.
* @param[in] aMeshLocalPrefix A reference to the Mesh Local Prefix.
*
*/
void SetMulticastNetworkPrefix(const Mle::MeshLocalPrefix &aMeshLocalPrefix)
@@ -333,6 +333,17 @@ public:
SetMulticastNetworkPrefix(aMeshLocalPrefix.m8, Mle::MeshLocalPrefix::kLength);
}
/**
* This method sets the prefix content of Prefix-Based Multicast Address.
*
* @param[in] aPrefix A reference to an IPv6 Prefix.
*
*/
void SetMulticastNetworkPrefix(const otIp6Prefix &aPrefix)
{
SetMulticastNetworkPrefix(aPrefix.mPrefix.mFields.m8, aPrefix.mLength);
}
/**
* This method returns a pointer to the Interface Identifier.
*
+37 -6
View File
@@ -55,10 +55,6 @@
#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 {
@@ -181,6 +177,13 @@ Mle::Mle(Instance &aInstance)
mAllNetworkBackboneRouters.GetAddress().mFields.m8[2] = 0; // Reserved
mAllNetworkBackboneRouters.GetAddress().mFields.m8[15] = 3; // Group ID = 3
// All Domain Backbone Routers Multicast Address.
mAllDomainBackboneRouters.Clear();
mAllDomainBackboneRouters.GetAddress().mFields.m8[0] = 0xff; // Multicast
mAllDomainBackboneRouters.GetAddress().mFields.m8[1] = 0x32; // Flags = 3, Scope = 2
mAllDomainBackboneRouters.GetAddress().mFields.m8[2] = 0; // Reserved
mAllDomainBackboneRouters.GetAddress().mFields.m8[15] = 3; // Group ID = 3
#endif
// initialize Mesh Local Prefix
@@ -1025,7 +1028,7 @@ void Mle::ApplyMeshLocalPrefix(void)
if (Get<BackboneRouter::Local>().IsEnabled())
{
// Subscribe All Network Backbone Routers Multicast Address for both Seconday and Primary state.
// Subscribe All Network Backbone Routers Multicast Address for both Secondary and Primary state.
Get<ThreadNetif>().SubscribeMulticast(mAllNetworkBackboneRouters);
}
@@ -1653,7 +1656,7 @@ void Mle::HandleStateChanged(otChangedFlags aFlags)
if (Get<BackboneRouter::Local>().IsEnabled())
{
// Subscribe All Network Backbone Routers Multicast Address for both Seconday and Primary state.
// Subscribe All Network Backbone Routers Multicast Address for both Secondary and Primary state.
Get<ThreadNetif>().SubscribeMulticast(mAllNetworkBackboneRouters);
}
else
@@ -4437,5 +4440,33 @@ void Mle::DelayedResponseMetadata::RemoveFrom(Message &aMessage) const
OT_UNUSED_VARIABLE(error);
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
void Mle::UpdateAllDomainBackboneRouters(BackboneRouter::Leader::DomainPrefixState aState)
{
if (!Get<BackboneRouter::Local>().IsEnabled())
{
Get<ThreadNetif>().UnsubscribeMulticast(mAllDomainBackboneRouters);
ExitNow();
}
if (aState == BackboneRouter::Leader::kDomainPrefixRemoved ||
aState == BackboneRouter::Leader::kDomainPrefixRefreshed)
{
Get<ThreadNetif>().UnsubscribeMulticast(mAllDomainBackboneRouters);
}
if (aState == BackboneRouter::Leader::kDomainPrefixAdded ||
aState == BackboneRouter::Leader::kDomainPrefixRefreshed)
{
mAllDomainBackboneRouters.GetAddress().SetMulticastNetworkPrefix(
*Get<BackboneRouter::Leader>().GetDomainPrefix());
Get<ThreadNetif>().SubscribeMulticast(mAllDomainBackboneRouters);
}
exit:
return;
}
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
} // namespace Mle
} // namespace ot
+25 -1
View File
@@ -45,6 +45,9 @@
#include "thread/mle_tlvs.hpp"
#include "thread/mle_types.hpp"
#include "thread/topology.hpp"
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#include "backbone_router/leader.hpp"
#endif
namespace ot {
@@ -666,7 +669,27 @@ public:
{
return mAllNetworkBackboneRouters.GetAddress();
}
#endif
/**
* This method returns a reference to the All Domain Backbone Routers Multicast Address.
*
* @returns A reference to the All Domain Backbone Routers Multicast Address.
*
*/
const Ip6::Address &GetAllDomainBackboneRoutersAddress(void) const
{
return mAllDomainBackboneRouters.GetAddress();
}
/**
* This method updates the subscription of All Domain Backbone Routers Multicast Address.
*
* @param[in] aState The Domain Prefix state or state change.
*
*/
void UpdateAllDomainBackboneRouters(BackboneRouter::Leader::DomainPrefixState aState);
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
/**
* This method gets the parent when operating in End Device mode.
@@ -1850,6 +1873,7 @@ private:
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
Ip6::NetifUnicastAddress mBackboneRouterPrimaryAloc;
Ip6::NetifMulticastAddress mAllNetworkBackboneRouters;
Ip6::NetifMulticastAddress mAllDomainBackboneRouters;
#endif
otMleCounters mCounters;
+2
View File
@@ -57,6 +57,8 @@ LINK_LOCAL_ALL_NODES_ADDRESS = 'ff02::1'
LINK_LOCAL_ALL_ROUTERS_ADDRESS = 'ff02::2'
DOMAIN_PREFIX = 'fd00:7d03:7d03:7d03::/64'
ALL_DOMAIN_BBRS_ADDRESS = 'ff32:40:fd00:7d03:7d03:7d03:0:3'
ALL_NETWORK_BBRS_ADDRESS = 'ff32:40:fdde:ad00:beef:0:0:3'
DEFAULT_MASTER_KEY = bytearray([
0x00,
+14
View File
@@ -734,6 +734,20 @@ class Node:
return None
def get_ipmaddrs(self):
self.send_command('ipmaddr')
return self._expect_results(r'\S+(:\S*)+')
def has_ipmaddr(self, address):
ipmaddr = ipaddress.ip_address(address)
ipmaddrs = self.get_ipmaddrs()
for addr in ipmaddrs:
if isinstance(addr, bytearray):
addr = bytes(addr)
if ipaddress.ip_address(addr) == ipmaddr:
return True
return False
def get_addr_leader_aloc(self):
addrs = self.get_addrs()
for addr in addrs:
@@ -96,7 +96,6 @@ class TestBackboneRouterService(thread_cert.TestCase):
# 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_domain_prefix(config.DOMAIN_PREFIX)
self.nodes[BBR_1].set_backbone_router(seqno=1)
self.nodes[BBR_1].start()
WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
@@ -107,6 +106,13 @@ class TestBackboneRouterService(thread_cert.TestCase):
self.simulator.go(WAIT_TIME)
self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(),
'Primary')
assert self.nodes[BBR_1].has_ipmaddr(config.ALL_NETWORK_BBRS_ADDRESS)
assert not self.nodes[BBR_1].has_ipmaddr(config.ALL_DOMAIN_BBRS_ADDRESS)
self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX)
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
assert self.nodes[BBR_1].has_ipmaddr(config.ALL_DOMAIN_BBRS_ADDRESS)
# 2) Reset BBR_1 and bring it back soon.
# Verify that it restores Primary State with sequence number
@@ -172,6 +178,10 @@ class TestBackboneRouterService(thread_cert.TestCase):
self.assertEqual(self.nodes[BBR_2].get_backbone_router_state(),
'Disabled')
assert not self.nodes[BBR_2].has_ipmaddr(
config.ALL_NETWORK_BBRS_ADDRESS)
assert not self.nodes[BBR_2].has_ipmaddr(config.ALL_DOMAIN_BBRS_ADDRESS)
# Enable Backbone function, it will stay at Secondary state as
# there is Primary Backbone Router already.
# Here removes the Domain Prefix before enabling backbone function
@@ -241,6 +251,9 @@ class TestBackboneRouterService(thread_cert.TestCase):
self.assertEqual(self.nodes[BBR_2].get_backbone_router_state(),
'Secondary')
assert self.nodes[BBR_1].has_ipmaddr(config.ALL_NETWORK_BBRS_ADDRESS)
assert self.nodes[BBR_1].has_ipmaddr(config.ALL_DOMAIN_BBRS_ADDRESS)
if __name__ == '__main__':
unittest.main()