mirror of
https://github.com/espressif/openthread.git
synced 2026-07-28 14:47:46 +00:00
[mle] work around MLE Link Accept messages that are too large
This commit addresses an issue where the MLE Link Accept message may be too large to fit within a single IEEE 802.15.4 frame. Thread requires any MLE message transported using 6LoWPAN fragmentation to also enable IEEE 802.15.4 MAC frame security. However, the purpose of MLE Link Accept messages is to establish a secure link and cannot itself be transported with IEEE 802.15.4 MAC frame security enabled. An MLE Link Accept message may carry a Route64 TLV that has a length dependent on the number of active routers in the network. When there are many active routers, the Route64 TLV is large and the MLE Link Accept message can no longer fit within a single IEEE 802.15.4 frame. The side effect is that a router coming out of reset will not be able to diretly restore its router role and must first attach as an end device. This commit limits the size of a Route64 TLV when included in MLE Link Accept messages. When the number of active routers is above a threshold, some routers will be elided from the Route64 TLV and the Router ID Sequence value is decremented. This allows the device coming out of reset to restore its router role and retrieve the current Route64 TLV in a subsequent message exchange.
This commit is contained in:
@@ -725,7 +725,7 @@ otError MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
|
||||
switch (aRequestedTlvs.mTlvs[i])
|
||||
{
|
||||
case Tlv::kRoute:
|
||||
SuccessOrExit(error = AppendRoute(*message));
|
||||
SuccessOrExit(error = AppendRoute(*message, aNeighbor));
|
||||
break;
|
||||
|
||||
case Tlv::kAddress16:
|
||||
@@ -4139,15 +4139,62 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MleRouter::FillRouteTlv(RouteTlv &aTlv)
|
||||
void MleRouter::FillRouteTlv(RouteTlv &aTlv, Neighbor *aNeighbor)
|
||||
{
|
||||
uint8_t routerCount = 0;
|
||||
uint8_t routerIdSequence = mRouterTable.GetRouterIdSequence();
|
||||
RouterIdSet routerIdSet = mRouterTable.GetRouterIdSet();
|
||||
uint8_t routerCount;
|
||||
|
||||
aTlv.SetRouterIdSequence(mRouterTable.GetRouterIdSequence());
|
||||
aTlv.SetRouterIdMask(mRouterTable.GetRouterIdSet());
|
||||
if (aNeighbor && IsActiveRouter(aNeighbor->GetRloc16()))
|
||||
{
|
||||
// Sending a Link Accept message that may require truncation
|
||||
// of Route64 TLV
|
||||
|
||||
routerCount = mRouterTable.GetActiveRouterCount();
|
||||
|
||||
if (routerCount > RouteTlv::kLinkAcceptMaxRouters)
|
||||
{
|
||||
for (uint8_t routerId = 0; routerId <= kMaxRouterId; routerId++)
|
||||
{
|
||||
if (routerCount <= RouteTlv::kLinkAcceptMaxRouters)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((routerId == RouterIdFromRloc16(GetRloc16())) || (routerId == aNeighbor->GetRouterId()) ||
|
||||
(routerId == GetLeaderId()))
|
||||
{
|
||||
// Route64 TLV must contain this device and the
|
||||
// neighboring router to ensure that at least this
|
||||
// link can be established.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (routerIdSet.Contains(routerId))
|
||||
{
|
||||
routerIdSet.Remove(routerId);
|
||||
routerCount--;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the neighbor will process the current
|
||||
// Route64 TLV in a subsequent message exchange
|
||||
routerIdSequence -= RouteTlv::kLinkAcceptSequenceRollback;
|
||||
}
|
||||
}
|
||||
|
||||
aTlv.SetRouterIdSequence(routerIdSequence);
|
||||
aTlv.SetRouterIdMask(routerIdSet);
|
||||
|
||||
routerCount = 0;
|
||||
|
||||
for (Router &router : Get<RouterTable>().Iterate())
|
||||
{
|
||||
if (!routerIdSet.Contains(router.GetRouterId()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (router.GetRloc16() == GetRloc16())
|
||||
{
|
||||
aTlv.SetLinkQualityIn(routerCount, 0);
|
||||
@@ -4193,12 +4240,12 @@ void MleRouter::FillRouteTlv(RouteTlv &aTlv)
|
||||
aTlv.SetRouteDataLength(routerCount);
|
||||
}
|
||||
|
||||
otError MleRouter::AppendRoute(Message &aMessage)
|
||||
otError MleRouter::AppendRoute(Message &aMessage, Neighbor *aNeighbor)
|
||||
{
|
||||
RouteTlv tlv;
|
||||
|
||||
tlv.Init();
|
||||
FillRouteTlv(tlv);
|
||||
FillRouteTlv(tlv, aNeighbor);
|
||||
|
||||
return tlv.AppendTo(aMessage);
|
||||
}
|
||||
|
||||
@@ -419,7 +419,7 @@ public:
|
||||
* @param[out] aTlv A reference to the tlv to be filled.
|
||||
*
|
||||
*/
|
||||
void FillRouteTlv(RouteTlv &aTlv);
|
||||
void FillRouteTlv(RouteTlv &aTlv, Neighbor *aNeighbor = nullptr);
|
||||
|
||||
/**
|
||||
* This method generates an MLE Child Update Request message to be sent to the parent.
|
||||
@@ -582,7 +582,7 @@ private:
|
||||
|
||||
otError AppendConnectivity(Message &aMessage);
|
||||
otError AppendChildAddresses(Message &aMessage, Child &aChild);
|
||||
otError AppendRoute(Message &aMessage);
|
||||
otError AppendRoute(Message &aMessage, Neighbor *aNeighbor = nullptr);
|
||||
otError AppendActiveDataset(Message &aMessage);
|
||||
otError AppendPendingDataset(Message &aMessage);
|
||||
void HandleDetachStart(void);
|
||||
|
||||
@@ -142,6 +142,16 @@ OT_TOOL_PACKED_BEGIN
|
||||
class RouteTlv : public Tlv
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
kLinkAcceptMaxRouters = 3,
|
||||
#else
|
||||
kLinkAcceptMaxRouters = 20,
|
||||
#endif
|
||||
kLinkAcceptSequenceRollback = 64,
|
||||
};
|
||||
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user