From 537d790c0dd6d2fa551bb2690a12d4ec36583704 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 31 Oct 2025 07:14:34 -0700 Subject: [PATCH] [rx-ra-tracker] add state to track initial router discovery process (#12080) Adds a new state, `mInitialDiscoveryFinished`, to `RxRaTracker` to track the completion of the initial router discovery (RS transmission) process. A new method, `IsInitialRouterDiscoveryFinished()`, exposes this state. This new method replaces `IsRsTxInProgress()`, which previously checked if any RS transmission was ongoing. The new model ensures the initial discovery is tracked only once after `RxRaTracker` starts, rather than every time RS messages are sent (e.g., due to stale timer expiration). Additionally, the `RoutingManager` now checks this state and ignores incoming RS messages until the initial router discovery is complete. This prevents the BR from replying to its own RS messages or sending an RA prematurely with incomplete information before all routers are discovered and decision factors are determined. --- src/core/border_router/routing_manager.cpp | 9 ++++++++- src/core/border_router/rx_ra_tracker.cpp | 7 ++++++- src/core/border_router/rx_ra_tracker.hpp | 17 ++++++++--------- tests/unit/test_routing_manager.cpp | 1 + 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 8df3b9c2a..c094e92e7 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -586,6 +586,13 @@ void RoutingManager::HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, co Get().GetBorderRoutingCounters().mRsRx++; LogInfo("Received RS from %s on %s", aSrcAddress.ToString().AsCString(), Get().ToString().AsCString()); + // We ignore a received Router Solicit (RS) message while + // `RxRaTracker` is performing its initial router discovery + // and sending RS. This ensures that we do not reply to our own + // RS and cause a premature routing policy evaluation. + + VerifyOrExit(Get().IsInitialRouterDiscoveryFinished()); + ScheduleRoutingPolicyEvaluation(kToReplyToRs); exit: @@ -1288,7 +1295,7 @@ exit: void RoutingManager::OnLinkPrefixManager::Evaluate(void) { - VerifyOrExit(!Get().IsRsTxInProgress()); + VerifyOrExit(Get().IsInitialRouterDiscoveryFinished()); SetAilPrefix(Get().GetFavoredOnLinkPrefix()); diff --git a/src/core/border_router/rx_ra_tracker.cpp b/src/core/border_router/rx_ra_tracker.cpp index 2d5165294..9d46ff919 100644 --- a/src/core/border_router/rx_ra_tracker.cpp +++ b/src/core/border_router/rx_ra_tracker.cpp @@ -51,6 +51,7 @@ RxRaTracker::RxRaTracker(Instance &aInstance) , mRoutingManagerEnabled(false) , mMultiAilDetectorEnabled(false) , mIsRunning(false) + , mInitialDiscoveryFinished(false) , mRsSender(aInstance) , mExpirationTimer(aInstance) , mStaleTimer(aInstance) @@ -92,7 +93,9 @@ void RxRaTracker::UpdateState(void) void RxRaTracker::Start(void) { VerifyOrExit(!mIsRunning); - mIsRunning = true; + + mIsRunning = true; + mInitialDiscoveryFinished = false; mRsSender.Start(); HandleNetDataChange(); @@ -134,6 +137,8 @@ void RxRaTracker::HandleRsSenderFinished(TimeMilli aStartTime) // Solicitation. RemoveOrDeprecateOldEntries(aStartTime); + + mInitialDiscoveryFinished = true; Get().ScheduleRoutingPolicyEvaluation(RoutingManager::kImmediately); } diff --git a/src/core/border_router/rx_ra_tracker.hpp b/src/core/border_router/rx_ra_tracker.hpp index 1426bdcae..030cef1da 100644 --- a/src/core/border_router/rx_ra_tracker.hpp +++ b/src/core/border_router/rx_ra_tracker.hpp @@ -105,18 +105,16 @@ public: void SetEnabled(bool aEnable, Requester aRequester); /** - * Indicates whether the Router Solicitation (RS) transmission process is in progress. + * Indicates whether the initial router discovery process (sending Router Solicitation (RS) message) is finished. * - * Upon `Start()`, the device performs the RS transmission process to discover routers on the infrastructure - * interface. The device sends three Router Solicitation (RS) messages every four seconds, starting with a random - * delay of up to one second for the first RS transmission. After sending the final RS message, the device waits - * one second before concluding the RS transmission process, at which point `IsRsTxInProgress()` returns `FALSE`. - * The RS transmission process is also performed if the stale timer for any discovered prefix expires. + * When `RxRaTracker` is started, it sends multiple RS messages to discover routers on the infrastructure interface. + * It sends three RS messages every four seconds, starting with a random delay of up to one second for the first + * RS transmission. After sending the final RS message, it waits one second before concluding discovery process. * - * @retval TRUE If the Router Solicitation transmission process is in progress. - * @retval FALSE If the Router Solicitation transmission process is not in progress. + * @retval TRUE If the initial router discovery process is finished. + * @retval FALSE If the initial router discovery process is not finished. */ - bool IsRsTxInProgress(void) const { return mRsSender.IsInProgress(); } + bool IsInitialRouterDiscoveryFinished(void) const { return mInitialDiscoveryFinished; } /** * Initializes a `PrefixTableIterator`. @@ -581,6 +579,7 @@ private: bool mRoutingManagerEnabled : 1; bool mMultiAilDetectorEnabled : 1; bool mIsRunning : 1; + bool mInitialDiscoveryFinished : 1; RsSender mRsSender; DecisionFactors mDecisionFactors; RouterList mRouters; diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp index 760ff98d1..a17ac3d98 100644 --- a/tests/unit/test_routing_manager.cpp +++ b/tests/unit/test_routing_manager.cpp @@ -318,6 +318,7 @@ otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex, case Ip6::Icmp::Header::kTypeRouterSolicit: Log(" Router Solicit message"); sRsEmitted = true; + otPlatInfraIfRecvIcmp6Nd(sInstance, kInfraIfIndex, &sInfraIfAddress, aBuffer, aBufferLength); break; case Ip6::Icmp::Header::kTypeRouterAdvert: