mirror of
https://github.com/espressif/openthread.git
synced 2026-09-07 01:30:11 +00:00
[mle] apply random delay when sending Link Request on advertisement reception (#10870)
This commit updates `DelayedSender` to allow scheduling of delayed MLE Link Request messages. This is used to apply a random delay when sending a Link Request after receiving an MLE Advertisement from a neighbor. Advertisement messages are multicast transmissions and can be received by multiple nodes, potentially causing synchronized generation of Link Requests. This change helps distribute the transmission time over a random window (one second if the requester is a router, or [1.5-3] seconds window if it is a child). When a router timeout occurs (i.e., no advertisements are received from a neighboring router for more than the maximum allowed age), the device sends Link Requests to restore its link. This commit updates this process to apply a random delay (over a one-second window) to each Link Request transmission. This aligns the implementation with the Thread specification and can improve network behavior when a new router is added or abruptly removed.
This commit is contained in:
@@ -4540,6 +4540,21 @@ void Mle::DelayedSender::ScheduleMulticastDataResponse(uint16_t aDelay)
|
||||
AddSchedule(kTypeDataResponse, destination, aDelay, nullptr, 0);
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::ScheduleLinkRequest(const Router &aRouter, uint16_t aDelay)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
uint16_t routerRloc16;
|
||||
|
||||
destination.SetToLinkLocalAddress(aRouter.GetExtAddress());
|
||||
|
||||
VerifyOrExit(!HasMatchingSchedule(kTypeLinkRequest, destination));
|
||||
routerRloc16 = aRouter.GetRloc16();
|
||||
AddSchedule(kTypeLinkRequest, destination, aDelay, &routerRloc16, sizeof(uint16_t));
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::ScheduleLinkAccept(const LinkAcceptInfo &aInfo, uint16_t aDelay)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
@@ -4662,6 +4677,22 @@ void Mle::DelayedSender::Execute(const Schedule &aSchedule)
|
||||
break;
|
||||
}
|
||||
|
||||
case kTypeLinkRequest:
|
||||
{
|
||||
uint16_t rlco16;
|
||||
Router *router;
|
||||
|
||||
IgnoreError(aSchedule.Read(sizeof(Header), rlco16));
|
||||
router = Get<RouterTable>().FindRouterByRloc16(rlco16);
|
||||
|
||||
if (router != nullptr)
|
||||
{
|
||||
Get<MleRouter>().SendLinkRequest(router);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case kTypeDiscoveryResponse:
|
||||
{
|
||||
DiscoveryResponseInfo info;
|
||||
|
||||
@@ -766,6 +766,9 @@ private:
|
||||
static constexpr uint32_t kParentResponseMaxDelayRouters = 500; // Max response delay for Parent Req to routers
|
||||
static constexpr uint32_t kParentResponseMaxDelayAll = 1000; // Max response delay for Parent Req to all
|
||||
static constexpr uint32_t kChildUpdateRequestDelay = 100; // Delay for aggregating Child Update Req
|
||||
static constexpr uint32_t kMaxLinkRequestDelayOnRouter = 1000; // Max delay to tx Link Request on Adv rx
|
||||
static constexpr uint32_t kMinLinkRequestDelayOnChild = 1500; // Min delay to tx Link Request on Adv rx (child)
|
||||
static constexpr uint32_t kMaxLinkRequestDelayOnChild = 3000; // Max delay to tx Link Request on Adv rx (child)
|
||||
static constexpr uint32_t kMaxLinkAcceptDelay = 1000; // Max delay to tx Link Accept for multicast Req
|
||||
static constexpr uint32_t kChildIdRequestTimeout = 5000; // Max delay to rx a Child ID Req after Parent Res
|
||||
static constexpr uint32_t kLinkRequestTimeout = 2000; // Max delay to rx a Link Accept
|
||||
@@ -1134,6 +1137,7 @@ private:
|
||||
#if OPENTHREAD_FTD
|
||||
void ScheduleParentResponse(const ParentResponseInfo &aInfo, uint16_t aDelay);
|
||||
void ScheduleMulticastDataResponse(uint16_t aDelay);
|
||||
void ScheduleLinkRequest(const Router &aRouter, uint16_t aDelay);
|
||||
void ScheduleLinkAccept(const LinkAcceptInfo &aInfo, uint16_t aDelay);
|
||||
void ScheduleDiscoveryResponse(const Ip6::Address &aDestination,
|
||||
const DiscoveryResponseInfo &aInfo,
|
||||
|
||||
@@ -1188,6 +1188,7 @@ Error MleRouter::HandleAdvertisementOnFtd(RxInfo &aRxInfo, uint16_t aSourceAddre
|
||||
RouteTlv routeTlv;
|
||||
Router *router;
|
||||
uint8_t routerId;
|
||||
uint32_t delay;
|
||||
|
||||
switch (aRxInfo.mMessage.ReadRouteTlv(routeTlv))
|
||||
{
|
||||
@@ -1301,7 +1302,8 @@ Error MleRouter::HandleAdvertisementOnFtd(RxInfo &aRxInfo, uint16_t aSourceAddre
|
||||
{
|
||||
InitNeighbor(*router, aRxInfo);
|
||||
router->SetState(Neighbor::kStateLinkRequest);
|
||||
SendLinkRequest(router);
|
||||
delay = Random::NonCrypto::GetUint32InRange(kMinLinkRequestDelayOnChild, kMaxLinkRequestDelayOnChild);
|
||||
mDelayedSender.ScheduleLinkRequest(*router, delay);
|
||||
ExitNow(error = kErrorNoRoute);
|
||||
}
|
||||
}
|
||||
@@ -1350,7 +1352,8 @@ Error MleRouter::HandleAdvertisementOnFtd(RxInfo &aRxInfo, uint16_t aSourceAddre
|
||||
{
|
||||
InitNeighbor(*router, aRxInfo);
|
||||
router->SetState(Neighbor::kStateLinkRequest);
|
||||
SendLinkRequest(router);
|
||||
delay = Random::NonCrypto::GetUint32InRange(0, kMaxLinkRequestDelayOnRouter);
|
||||
mDelayedSender.ScheduleLinkRequest(*router, delay);
|
||||
ExitNow(error = kErrorNoRoute);
|
||||
}
|
||||
|
||||
@@ -1651,7 +1654,8 @@ void MleRouter::HandleTimeTick(void)
|
||||
bool sendLinkRequest = true;
|
||||
|
||||
// Once router age expires, we send Link Request every
|
||||
// time tick, up to `kMaxTxCount`. After the last
|
||||
// time tick (second), up to `kMaxTxCount`. Each rx is
|
||||
// randomly delayed (one second window). After the last
|
||||
// attempt, we wait for the "Link Accept" timeout
|
||||
// (~3 seconds), before the router is removed.
|
||||
|
||||
@@ -1666,7 +1670,8 @@ void MleRouter::HandleTimeTick(void)
|
||||
|
||||
if (sendLinkRequest)
|
||||
{
|
||||
SendLinkRequest(&router);
|
||||
mDelayedSender.ScheduleLinkRequest(
|
||||
router, Random::NonCrypto::GetUint32InRange(0, kMaxLinkRequestDelayOnRouter));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user