[backbone-router] backbone TMF enhancements (#5660)

This commit enhances Backbone TMF:

- Subscribe Backbone TMF on multicast addresses on the Backbone
  interface
  - All Network BBRs Multicast Address
  - All Domain BBRs Multicast Address

- Thread Netif no longer subscribe these two addresses, because BBR
  Multicast Addresses are only defined for the Backbone Link in Thread
  Spec 9.4.8.1

- Make sure backbone messages are using link local src addresses
  - Verify src addr for b/bmr messages
This commit is contained in:
Simon Lin
2020-10-23 08:48:54 -07:00
committed by GitHub
parent f83d1ff999
commit e00e5b3d70
17 changed files with 283 additions and 57 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (36)
#define OPENTHREAD_API_VERSION (37)
/**
* @addtogroup api-instance
+34
View File
@@ -121,6 +121,40 @@ otError otPlatUdpConnect(otUdpSocket *aUdpSocket);
*/
otError otPlatUdpSend(otUdpSocket *aUdpSocket, otMessage *aMessage, const otMessageInfo *aMessageInfo);
/**
* This function configures the UDP socket to join a UDP multicast group.
*
* Note: only available when `OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE` is used.
*
* @param[in] aUdpSocket A pointer to the UDP socket.
* @param[in] aNetifIdentifier The network interface identifier.
* @param[in] aAddress The UDP multicast group address.
*
* @retval OT_ERROR_NONE Successfully joined the multicast group.
* @retval OT_ERROR_FAILED Failed to join the multicast group.
*
*/
otError otPlatUdpJoinMulticastGroup(otUdpSocket * aUdpSocket,
otNetifIdentifier aNetifIdentifier,
const otIp6Address *aAddress);
/**
* This function configures the UDP socket to leave a UDP multicast group.
*
* Note: only available when `OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE` is used.
*
* @param[in] aUdpSocket A pointer to the UDP socket.
* @param[in] aNetifIdentifier The network interface identifier.
* @param[in] aAddress The UDP multicast group address.
*
* @retval OT_ERROR_NONE Successfully left the multicast group.
* @retval OT_ERROR_FAILED Failed to leave the multicast group.
*
*/
otError otPlatUdpLeaveMulticastGroup(otUdpSocket * aUdpSocket,
otNetifIdentifier aNetifIdentifier,
const otIp6Address *aAddress);
#ifdef __cplusplus
} // extern "C"
#endif
+39 -1
View File
@@ -42,7 +42,13 @@ namespace BackboneRouter {
otError BackboneTmfAgent::Start(void)
{
return Coap::Start(kBackboneUdpPort, OT_NETIF_BACKBONE);
otError error = OT_ERROR_NONE;
SuccessOrExit(error = Coap::Start(kBackboneUdpPort, OT_NETIF_BACKBONE));
SubscribeMulticast(Get<Local>().GetAllNetworkBackboneRoutersAddress());
exit:
return error;
}
otError BackboneTmfAgent::Filter(const ot::Coap::Message &aMessage,
@@ -71,6 +77,38 @@ bool BackboneTmfAgent::IsBackboneTmfMessage(const Ip6::MessageInfo &aMessageInfo
dst == Get<BackboneRouter::Local>().GetAllDomainBackboneRoutersAddress()));
}
void BackboneTmfAgent::SubscribeMulticast(const Ip6::Address &aAddress)
{
otError error;
error = mSocket.JoinNetifMulticastGroup(OT_NETIF_BACKBONE, aAddress);
if (error != OT_ERROR_NONE)
{
otLogDebgBbr("Backbone TMF subscribes %s: %s", aAddress.ToString().AsCString(), otThreadErrorToString(error));
}
else
{
otLogCritBbr("Backbone TMF subscribes %s: %s", aAddress.ToString().AsCString(), otThreadErrorToString(error));
}
}
void BackboneTmfAgent::UnsubscribeMulticast(const Ip6::Address &aAddress)
{
otError error;
error = mSocket.LeaveNetifMulticastGroup(OT_NETIF_BACKBONE, aAddress);
if (error == OT_ERROR_NONE)
{
otLogDebgBbr("Backbone TMF unsubscribes %s: %s", aAddress.ToString().AsCString(), otThreadErrorToString(error));
}
else
{
otLogCritBbr("Backbone TMF unsubscribes %s: %s", aAddress.ToString().AsCString(), otThreadErrorToString(error));
}
}
} // namespace BackboneRouter
} // namespace ot
+16
View File
@@ -81,6 +81,22 @@ public:
*/
bool IsBackboneTmfMessage(const Ip6::MessageInfo &aMessageInfo) const;
/**
* This method subscribes the Backbone TMF socket to a given Ip6 multicast group on the Backbone network.
*
* @param[in] aAddress The Ip6 multicast group address.
*
*/
void SubscribeMulticast(const Ip6::Address &aAddress);
/**
* This method unsubscribes the Backbone TMF socket from a given Ip6 multicast group on the Backbone network.
*
* @param[in] aAddress The Ip6 multicast group address.
*
*/
void UnsubscribeMulticast(const Ip6::Address &aAddress);
private:
static otError Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
};
+14 -22
View File
@@ -65,18 +65,16 @@ Local::Local(Instance &aInstance)
// All Network Backbone Routers Multicast Address.
mAllNetworkBackboneRouters.Clear();
mAllNetworkBackboneRouters.GetAddress().mFields.m8[0] = 0xff; // Multicast
mAllNetworkBackboneRouters.GetAddress().mFields.m8[1] = 0x32; // Flags = 3, Scope = 2
mAllNetworkBackboneRouters.GetAddress().mFields.m8[2] = 0; // Reserved
mAllNetworkBackboneRouters.GetAddress().mFields.m8[15] = 3; // Group ID = 3
mAllNetworkBackboneRouters.mFields.m8[0] = 0xff; // Multicast
mAllNetworkBackboneRouters.mFields.m8[1] = 0x32; // Flags = 3, Scope = 2
mAllNetworkBackboneRouters.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
mAllDomainBackboneRouters.mFields.m8[0] = 0xff; // Multicast
mAllDomainBackboneRouters.mFields.m8[1] = 0x32; // Flags = 3, Scope = 2
mAllDomainBackboneRouters.mFields.m8[15] = 3; // Group ID = 3
}
void Local::SetEnabled(bool aEnable)
@@ -227,13 +225,8 @@ void Local::SetState(BackboneRouterState aState)
if (mState == OT_BACKBONE_ROUTER_STATE_DISABLED)
{
// Subscribe All Network Backbone Routers Multicast Address for both Secondary and Primary state.
mAllNetworkBackboneRouters.GetAddress().SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
Get<ThreadNetif>().SubscribeMulticast(mAllNetworkBackboneRouters);
}
else if (aState == OT_BACKBONE_ROUTER_STATE_DISABLED)
{
Get<ThreadNetif>().UnsubscribeMulticast(mAllNetworkBackboneRouters);
// Update All Network Backbone Routers Multicast Address for both Secondary and Primary state.
mAllNetworkBackboneRouters.SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
}
if (mState == OT_BACKBONE_ROUTER_STATE_PRIMARY)
@@ -351,9 +344,9 @@ void Local::ApplyMeshLocalPrefix(void)
{
VerifyOrExit(IsEnabled());
Get<ThreadNetif>().UnsubscribeMulticast(mAllNetworkBackboneRouters);
mAllNetworkBackboneRouters.GetAddress().SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
Get<ThreadNetif>().SubscribeMulticast(mAllNetworkBackboneRouters);
Get<BackboneTmfAgent>().UnsubscribeMulticast(mAllNetworkBackboneRouters);
mAllNetworkBackboneRouters.SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
Get<BackboneTmfAgent>().SubscribeMulticast(mAllNetworkBackboneRouters);
if (IsPrimary())
{
@@ -370,19 +363,18 @@ void Local::UpdateAllDomainBackboneRouters(Leader::DomainPrefixState aState)
{
if (!IsEnabled())
{
Get<ThreadNetif>().UnsubscribeMulticast(mAllDomainBackboneRouters);
ExitNow();
}
if (aState == Leader::kDomainPrefixRemoved || aState == Leader::kDomainPrefixRefreshed)
{
Get<ThreadNetif>().UnsubscribeMulticast(mAllDomainBackboneRouters);
Get<BackboneTmfAgent>().UnsubscribeMulticast(mAllDomainBackboneRouters);
}
if (aState == Leader::kDomainPrefixAdded || aState == Leader::kDomainPrefixRefreshed)
{
mAllDomainBackboneRouters.GetAddress().SetMulticastNetworkPrefix(*Get<Leader>().GetDomainPrefix());
Get<ThreadNetif>().SubscribeMulticast(mAllDomainBackboneRouters);
mAllDomainBackboneRouters.SetMulticastNetworkPrefix(*Get<Leader>().GetDomainPrefix());
Get<BackboneTmfAgent>().SubscribeMulticast(mAllDomainBackboneRouters);
}
exit:
+5 -11
View File
@@ -205,10 +205,7 @@ public:
* @returns A reference to the All Network Backbone Routers Multicast Address.
*
*/
const Ip6::Address &GetAllNetworkBackboneRoutersAddress(void) const
{
return mAllNetworkBackboneRouters.GetAddress();
}
const Ip6::Address &GetAllNetworkBackboneRoutersAddress(void) const { return mAllNetworkBackboneRouters; }
/**
* This method returns a reference to the All Domain Backbone Routers Multicast Address.
@@ -216,10 +213,7 @@ public:
* @returns A reference to the All Domain Backbone Routers Multicast Address.
*
*/
const Ip6::Address &GetAllDomainBackboneRoutersAddress(void) const
{
return mAllDomainBackboneRouters.GetAddress();
}
const Ip6::Address &GetAllDomainBackboneRoutersAddress(void) const { return mAllDomainBackboneRouters; }
/**
* This method applies the Mesh Local Prefix.
@@ -261,9 +255,9 @@ private:
NetworkData::OnMeshPrefixConfig mDomainPrefixConfig;
Ip6::NetifUnicastAddress mBackboneRouterPrimaryAloc;
Ip6::NetifMulticastAddress mAllNetworkBackboneRouters;
Ip6::NetifMulticastAddress mAllDomainBackboneRouters;
Ip6::NetifUnicastAddress mBackboneRouterPrimaryAloc;
Ip6::Address mAllNetworkBackboneRouters;
Ip6::Address mAllDomainBackboneRouters;
};
} // namespace BackboneRouter
-1
View File
@@ -324,7 +324,6 @@ void Manager::SendBackboneMulticastListenerRegistration(const Ip6::Address *aAdd
messageInfo.SetPeerAddr(Get<BackboneRouter::Local>().GetAllNetworkBackboneRoutersAddress());
messageInfo.SetPeerPort(BackboneRouter::kBackboneUdpPort); // TODO: Provide API for configuring Backbone COAP port.
messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
messageInfo.SetHopLimit(Mle::kDefaultBackboneHoplimit);
messageInfo.SetIsHostInterface(true);
+8
View File
@@ -225,6 +225,10 @@ otError CoapBase::SendMessage(Message & aMessage,
metadata.mRetransmissionTimeout = aTxParameters.CalculateInitialRetransmissionTimeout();
metadata.mAcknowledged = false;
metadata.mConfirmable = aMessage.IsConfirmable();
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
metadata.mHopLimit = aMessageInfo.GetHopLimit();
metadata.mIsHostInterface = aMessageInfo.IsHostInterface();
#endif
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
metadata.mObserve = observe;
#endif
@@ -377,6 +381,10 @@ void CoapBase::HandleRetransmissionTimer(void)
messageInfo.SetPeerAddr(metadata.mDestinationAddress);
messageInfo.SetPeerPort(metadata.mDestinationPort);
messageInfo.SetSockAddr(metadata.mSourceAddress);
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
messageInfo.SetHopLimit(metadata.mHopLimit);
messageInfo.SetIsHostInterface(metadata.mIsHostInterface);
#endif
SendCopy(*message, messageInfo);
}
+8 -2
View File
@@ -540,8 +540,14 @@ private:
TimeMilli mNextTimerShot; // Time when the timer should shoot for this message.
uint32_t mRetransmissionTimeout; // Delay that is applied to next retransmission.
uint8_t mRetransmissionsRemaining; // Number of retransmissions remaining.
bool mAcknowledged : 1; // Information that request was acknowledged.
bool mConfirmable : 1; // Information that message is confirmable.
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
uint8_t mHopLimit; // The hop limit.
#endif
bool mAcknowledged : 1; // Information that request was acknowledged.
bool mConfirmable : 1; // Information that message is confirmable.
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
bool mIsHostInterface : 1; // TRUE if packets sent/received via host interface, FALSE otherwise.
#endif
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
bool mObserve : 1; // Information that this request involves Observations.
#endif
+36
View File
@@ -137,6 +137,42 @@ otError Udp::Socket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
return Get<Udp>().SendTo(*this, aMessage, aMessageInfo);
}
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
otError Udp::Socket::JoinNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress)
{
OT_UNUSED_VARIABLE(aNetifIdentifier);
OT_UNUSED_VARIABLE(aAddress);
otError error = OT_ERROR_NOT_IMPLEMENTED;
VerifyOrExit(aAddress.IsMulticast(), error = OT_ERROR_INVALID_ARGS);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpJoinMulticastGroup(this, aNetifIdentifier, &aAddress);
#endif
exit:
return error;
}
otError Udp::Socket::LeaveNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress)
{
OT_UNUSED_VARIABLE(aNetifIdentifier);
OT_UNUSED_VARIABLE(aAddress);
otError error = OT_ERROR_NOT_IMPLEMENTED;
VerifyOrExit(aAddress.IsMulticast(), error = OT_ERROR_INVALID_ARGS);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpLeaveMulticastGroup(this, aNetifIdentifier, &aAddress);
#endif
exit:
return error;
}
#endif
Udp::Udp(Instance &aInstance)
: InstanceLocator(aInstance)
, mEphemeralPort(kDynamicPortMin)
+26
View File
@@ -261,6 +261,32 @@ public:
*
*/
otError SendTo(Message &aMessage, const MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
/**
* This method configures the UDP socket to join a mutlicast group on a Host network interface.
*
* @param[in] aNetifIdentifier The network interface identifier.
* @param[in] aAddress The multicast group address.
*
* @retval OT_ERROR_NONE Successfully joined the multicast group.
* @retval OT_ERROR_FAILED Failed to join the multicast group.
*
*/
otError JoinNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress);
/**
* This method configures the UDP socket to leave a multicast group on a Host network interface.
*
* @param[in] aNetifIdentifier The network interface identifier.
* @param[in] aAddress The multicast group address.
*
* @retval OT_ERROR_NONE Successfully left the multicast group.
* @retval OT_ERROR_FAILED Failed to leave the multicast group.
*
*/
otError LeaveNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress);
#endif
};
/**
+91 -3
View File
@@ -289,6 +289,8 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId
{
otError error = OT_ERROR_NONE;
int fd = FdFromHandle(aUdpSocket->mHandle);
int one = 1;
int zero = 0;
switch (aNetifIdentifier)
{
@@ -298,7 +300,8 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId
VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, nullptr, 0) == 0, error = OT_ERROR_FAILED);
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
unsigned int netifIndex = 0;
VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &netifIndex, sizeof(netifIndex)), error = OT_ERROR_FAILED);
VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &netifIndex, sizeof(netifIndex)) == 0,
error = OT_ERROR_FAILED);
#endif // __linux__
break;
}
@@ -308,7 +311,7 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId
VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &gNetifName, strlen(gNetifName)) == 0,
error = OT_ERROR_FAILED);
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &gNetifIndex, sizeof(gNetifIndex)),
VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &gNetifIndex, sizeof(gNetifIndex)) == 0,
error = OT_ERROR_FAILED);
#endif // __linux__
break;
@@ -320,16 +323,21 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId
VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, gBackboneNetifName, strlen(gBackboneNetifName)) == 0,
error = OT_ERROR_FAILED);
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &gBackboneNetifIndex, sizeof(gBackboneNetifIndex)),
VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &gBackboneNetifIndex, sizeof(gBackboneNetifIndex)) == 0,
error = OT_ERROR_FAILED);
#endif // __linux__
#else
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&one, sizeof(one)) == 0,
error = OT_ERROR_FAILED);
break;
}
}
VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) == 0, error = OT_ERROR_FAILED);
exit:
return error;
}
@@ -427,6 +435,86 @@ exit:
return error;
}
otError otPlatUdpJoinMulticastGroup(otUdpSocket * aUdpSocket,
otNetifIdentifier aNetifIdentifier,
const otIp6Address *aAddress)
{
otError error = OT_ERROR_NONE;
struct ipv6_mreq mreq;
int fd;
VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS);
fd = FdFromHandle(aUdpSocket->mHandle);
memcpy(&mreq.ipv6mr_multiaddr, aAddress->mFields.m8, sizeof(mreq.ipv6mr_multiaddr));
switch (aNetifIdentifier)
{
case OT_NETIF_UNSPECIFIED:
break;
case OT_NETIF_THREAD:
mreq.ipv6mr_interface = gNetifIndex;
break;
case OT_NETIF_BACKBONE:
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
mreq.ipv6mr_interface = gBackboneNetifIndex;
#else
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
break;
}
VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == 0 || errno == EADDRINUSE,
error = OT_ERROR_FAILED);
exit:
if (error != OT_ERROR_NONE)
{
otLogCritPlat("IPV6_JOIN_GROUP failed: %s", strerror(errno));
}
return error;
}
otError otPlatUdpLeaveMulticastGroup(otUdpSocket * aUdpSocket,
otNetifIdentifier aNetifIdentifier,
const otIp6Address *aAddress)
{
otError error = OT_ERROR_NONE;
struct ipv6_mreq mreq;
int fd;
VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS);
fd = FdFromHandle(aUdpSocket->mHandle);
memcpy(&mreq.ipv6mr_multiaddr, aAddress->mFields.m8, sizeof(mreq.ipv6mr_multiaddr));
switch (aNetifIdentifier)
{
case OT_NETIF_UNSPECIFIED:
break;
case OT_NETIF_THREAD:
mreq.ipv6mr_interface = gNetifIndex;
break;
case OT_NETIF_BACKBONE:
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
mreq.ipv6mr_interface = gBackboneNetifIndex;
#else
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
break;
}
VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)) == 0 || errno == EADDRINUSE,
error = OT_ERROR_FAILED);
exit:
if (error != OT_ERROR_NONE)
{
otLogCritPlat("IPV6_LEAVE_GROUP failed: %s", strerror(errno));
}
return error;
}
void platformUdpUpdateFdSet(otInstance *aInstance, fd_set *aReadFdSet, int *aMaxFd)
{
VerifyOrExit(gNetifIndex != 0);
@@ -147,6 +147,7 @@ class BBR_5_11_01(thread_cert.TestCase):
pkts.filter_eth_src(PBBR_ETH).filter_coap_request('/b/bmr').must_next().must_verify(f"""
thread_meshcop.tlv.ipv6_addr == ['{MA1}']
and thread_bl.tlv.timeout == {MLR_TIMEOUT}
and ipv6.src.is_link_local
""")
# Router registers MA2 with default timeout
@@ -158,6 +159,7 @@ class BBR_5_11_01(thread_cert.TestCase):
pkts.filter_eth_src(PBBR_ETH).filter_coap_request('/b/bmr').must_next().must_verify(f"""
thread_meshcop.tlv.ipv6_addr == ['{MA2}']
and thread_bl.tlv.timeout == {MLR_TIMEOUT}
and ipv6.src.is_link_local
""")
# Commissioner registers MA3 with deafult timeout
@@ -169,6 +171,7 @@ class BBR_5_11_01(thread_cert.TestCase):
pkts.filter_eth_src(PBBR_ETH).filter_coap_request('/b/bmr').must_next().must_verify(f"""
thread_meshcop.tlv.ipv6_addr == ['{MA3}']
and thread_bl.tlv.timeout == {MLR_TIMEOUT}
and ipv6.src.is_link_local
""")
# Commissioner registers MA4 with custom timeout
@@ -180,6 +183,7 @@ class BBR_5_11_01(thread_cert.TestCase):
pkts.filter_eth_src(PBBR_ETH).filter_coap_request('/b/bmr').must_next().must_verify(f"""
thread_meshcop.tlv.ipv6_addr == ['{MA4}']
and thread_bl.tlv.timeout == {CUSTOM_MLR_TIMEOUT}
and ipv6.src.is_link_local
""")
# Commissioner unregisters MA5
@@ -190,6 +194,7 @@ class BBR_5_11_01(thread_cert.TestCase):
# Verify PBBR not sends `/b/bmr` on the Backbone link for MA5.
pkts.filter_eth_src(PBBR_ETH).filter_coap_request('/b/bmr').filter(f"""
thread_meshcop.tlv.ipv6_addr == ['{MA5}']
and ipv6.src.is_link_local
""").must_not_next()
@@ -108,13 +108,10 @@ class TestBackboneRouterService(thread_cert.TestCase):
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].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
@@ -175,9 +172,6 @@ class TestBackboneRouterService(thread_cert.TestCase):
self.simulator.go(WAIT_TIME)
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
@@ -242,9 +236,6 @@ class TestBackboneRouterService(thread_cert.TestCase):
self.simulator.go(WAIT_TIME)
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)
# 6a) Check the uniqueness of DUA by comparing the one in above 4a).
bbr2_dua2 = self.nodes[BBR_2].get_addr(config.DOMAIN_PREFIX)
assert bbr2_dua == bbr2_dua2, 'Error: Unexpected different DUA ({} v.s. {})'.format(bbr2_dua, bbr2_dua2)
@@ -166,13 +166,10 @@ class TestDomainUnicastAddress(thread_cert.TestCase):
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].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, 'prosD')
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
assert self.nodes[BBR_1].has_ipmaddr(config.ALL_DOMAIN_BBRS_ADDRESS)
self.simulator.set_lowpan_context(context_id, config.DOMAIN_PREFIX)
domain_prefix_cid = context_id
@@ -190,13 +190,10 @@ class TestDomainUnicastAddressRegistration(thread_cert.TestCase):
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].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, 'prosD')
WAIT_TIME = WAIT_REDUNDANCE
self.simulator.go(WAIT_TIME)
assert self.nodes[BBR_1].has_ipmaddr(config.ALL_DOMAIN_BBRS_ADDRESS)
self.simulator.set_lowpan_context(context_id, config.DOMAIN_PREFIX)
domain_prefix_cid = context_id
@@ -102,7 +102,6 @@ class TestDomainUnicastAddress(thread_cert.TestCase):
self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX, 'prosD')
self.simulator.go(WAIT_REDUNDANCE)
assert self.nodes[BBR_1].has_ipmaddr(config.ALL_DOMAIN_BBRS_ADDRESS)
# 2) Bring up ROUTER_1
self.nodes[ROUTER].start()