From 6b5493c9f1fe26232709b1da6439c84ad5330fea Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 28 Apr 2025 09:38:14 -0700 Subject: [PATCH] [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()`. --- src/core/thread/mle_ftd.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/core/thread/mle_ftd.cpp b/src/core/thread/mle_ftd.cpp index 5b7812954..7161d8c12 100644 --- a/src/core/thread/mle_ftd.cpp +++ b/src/core/thread/mle_ftd.cpp @@ -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());