[mle] add safeguard for link request scheduling failures (#11442)

This commit adds a safeguard check in `Mle::HandleTimeTick()` to
protect against cases where scheduling or sending a Link Request
message to a new neighboring router fails. This can happen, for
example, if the device is temporarily out of message buffers.

This scenario is determined by checking if `router.IsStateLinkRequest()`
is true, there is no Link Request message scheduled to be sent to
this router, and the device is not waiting for a Link Accept
(`!router.IsWaitingForLinkAccept()`). In such a case, the neighbor is
removed using `RemoveNeighbor()`.
This commit is contained in:
Abtin Keshavarzian
2025-04-28 09:38:14 -07:00
committed by GitHub
parent d6c35621bb
commit 6b5493c9f1
+20 -6
View File
@@ -665,18 +665,22 @@ void Mle::HandleLinkRequest(RxInfo &aRxInfo)
case kErrorNone:
if (IsRouterRloc16(sourceAddress))
{
neighbor = mRouterTable.FindRouterByRloc16(sourceAddress);
VerifyOrExit(neighbor != nullptr, error = kErrorParse);
Router *router = mRouterTable.FindRouterByRloc16(sourceAddress);
if (!neighbor->IsStateValid())
VerifyOrExit(router != nullptr, error = kErrorParse);
if (!router->IsStateValid())
{
InitNeighbor(*neighbor, aRxInfo);
neighbor->SetState(Neighbor::kStateLinkRequest);
InitNeighbor(*router, aRxInfo);
router->SetState(Neighbor::kStateLinkRequest);
router->ClearLinkAcceptTimeout();
}
else
{
VerifyOrExit(neighbor->GetExtAddress() == info.mExtAddress);
VerifyOrExit(router->GetExtAddress() == info.mExtAddress);
}
neighbor = router;
}
break;
@@ -1303,6 +1307,7 @@ Error Mle::HandleAdvertisementOnFtd(RxInfo &aRxInfo, uint16_t aSourceAddress, co
{
InitNeighbor(*router, aRxInfo);
router->SetState(Neighbor::kStateLinkRequest);
router->ClearLinkAcceptTimeout();
delay = Random::NonCrypto::GetUint32InRange(0, kMaxLinkRequestDelayOnRouter);
mDelayedSender.ScheduleLinkRequest(*router, delay);
ExitNow(error = kErrorNoRoute);
@@ -1377,6 +1382,7 @@ void Mle::EstablishRouterLinkOnFtdChild(Router &aRouter, RxInfo &aRxInfo, uint8_
InitNeighbor(aRouter, aRxInfo);
aRouter.SetState(Neighbor::kStateLinkRequest);
aRouter.ClearLinkAcceptTimeout();
mDelayedSender.ScheduleLinkRequest(aRouter, Random::NonCrypto::GetUint32InRange(minDelay, maxDelay));
exit:
@@ -1718,6 +1724,14 @@ void Mle::HandleTimeTick(void)
}
}
if (router.IsStateLinkRequest() && !mDelayedSender.HasAnyScheduledLinkRequest(router) &&
!router.IsWaitingForLinkAccept())
{
LogInfo("Router 0x%04x - Failed to schedule/send Link Request", router.GetRloc16());
RemoveNeighbor(router);
continue;
}
if (router.IsWaitingForLinkAccept() && (router.DecrementLinkAcceptTimeout() == 0))
{
LogInfo("Router 0x%04x - Link Accept timeout expired", router.GetRloc16());