mirror of
https://github.com/espressif/openthread.git
synced 2026-08-01 00:27:47 +00:00
[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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user