From e363faedee3181be42c48df71e1cea270483a15e Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 22 Jan 2025 15:52:55 -0800 Subject: [PATCH] [mle] enhance neighbor aging & suppress Link Requests on FTD children (#10985) This commit updates neighbor aging and recovery on FTD children. An FTD child establishes links with neighboring routers to receive multicast MPL (re)transmissions. If the device is an FTD child and has more than `mChildRouterLinks` neighbors, it uses a longer neighbor age (`kMaxNeighborAgeOnChild = 150s`) and removes the neighboring router upon expiration without attempting to re-establish the link. This differs from the existing behavior (which is still used when the device is a router or an FTD child with `mChildRouterLinks` or fewer neighbors), where a 100-second age is used, and the device attempts to re-establish links upon expiration by sending Link Requests. Link Requests from FTD children are suppressed when a neighboring router becomes unavailable, and the child already has more than `mChildRouterLinks` neighbors. This helps reduce unnecessary network traffic on denser networks, especially when a router device is powered off. --- src/core/thread/mle_router.cpp | 59 ++++++++++++++++++++++++---------- src/core/thread/mle_router.hpp | 3 +- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index cbaedd5b392..7e23f5cfd78 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -1728,26 +1728,51 @@ void MleRouter::HandleTimeTick(void) router.SetSelectableAsParent(false); } #endif - - if (router.IsStateValid() && (age >= kMaxNeighborAge)) - { - // Once router age expires, we send Link Request every - // time tick (second), up to max attempts. 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. - - if (!mDelayedSender.HasAnyScheduledLinkRequest(router) && !router.IsWaitingForLinkAccept()) + if (router.IsStateValid()) + { + // Neighbor router age and link recovery + // + // If the device is an FTD child and has more than + // `mChildRouterLinks` neighbors, it uses a longer age, + // `kMaxNeighborAgeOnChild`, and removes the neighboring + // router upon expiration without trying to re-establish + // its link with it. + // + // Otherwise, if the device itself is a router, or it is an + // FTD child with `mChildRouterLinks` or fewer neighbors, + // it uses a shorter `kMaxNeighborAge`. Upon expiration, it + // tries to re-establish its link with the neighboring router. + + if (IsChild() && (mRouterTable.GetNeighborCount(kLinkQuality1) > mChildRouterLinks)) { - LogInfo("No Adv from router 0x%04x - sending Link Request", router.GetRloc16()); - router.SetLinkRequestAttemptsToMax(); + if (age >= kMaxNeighborAgeOnChild) + { + LogInfo("No Adv from router 0x%04x - removing router", router.GetRloc16()); + mDelayedSender.RemoveScheduledLinkRequest(router); + RemoveNeighbor(router); + continue; + } } - - if (router.HasRemainingLinkRequestAttempts()) + else if (age >= kMaxNeighborAge) { - router.DecrementLinkRequestAttempts(); - mDelayedSender.ScheduleLinkRequest( - router, Random::NonCrypto::GetUint32InRange(0, kMaxLinkRequestDelayOnRouter)); + // We send a Link Request every time tick (second), up to + // max attempts. Each transmission is randomly delayed + // (one-second window). After the last attempt, we wait for + // the "Link Accept" timeout (~3 seconds) before removing the + // neighboring router. + + if (!mDelayedSender.HasAnyScheduledLinkRequest(router) && !router.IsWaitingForLinkAccept()) + { + LogInfo("No Adv from router 0x%04x - sending Link Request", router.GetRloc16()); + router.SetLinkRequestAttemptsToMax(); + } + + if (router.HasRemainingLinkRequestAttempts()) + { + router.DecrementLinkRequestAttempts(); + mDelayedSender.ScheduleLinkRequest( + router, Random::NonCrypto::GetUint32InRange(0, kMaxLinkRequestDelayOnRouter)); + } } } diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 42da00cf4f1..a9e8ccd37b4 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -503,7 +503,8 @@ class MleRouter : public Mle #endif static constexpr uint32_t kMaxUnicastAdvertisementDelay = 1000; // Max random delay for unciast Adv tx - static constexpr uint32_t kMaxNeighborAge = 100000; // Max neighbor age (in msec) + static constexpr uint32_t kMaxNeighborAge = 100000; // Max neighbor age on router (in msec) + static constexpr uint32_t kMaxNeighborAgeOnChild = 150000; // Max neighbor age on FTD child (in msec) static constexpr uint32_t kMaxLeaderToRouterTimeout = 90000; // (in msec) static constexpr uint8_t kMinDowngradeNeighbors = 7; static constexpr uint8_t kNetworkIdTimeout = 120; // (in sec)