diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 1aac2c6ad..42d2d29a7 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -69,7 +69,6 @@ RoutingManager::RoutingManager(Instance &aInstance) #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE , mPdPrefixManager(aInstance) #endif - , mRsSender(aInstance) , mRoutingPolicyTimer(aInstance) { mBrUlaPrefix.Clear(); @@ -310,7 +309,6 @@ void RoutingManager::Start(void) mOnLinkPrefixManager.Start(); mOmrPrefixManager.Start(); mRoutePublisher.Start(); - mRsSender.Start(); #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE mPdPrefixManager.Start(); #endif @@ -345,8 +343,6 @@ void RoutingManager::Stop(void) mTxRaInfo.mTxCount = 0; - mRsSender.Stop(); - mRoutingPolicyTimer.Stop(); mRoutePublisher.Stop(); @@ -656,21 +652,6 @@ bool RoutingManager::IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix) return aBrUlaPrefix.mLength == kBrUlaPrefixLength && aBrUlaPrefix.mPrefix.mFields.m8[0] == 0xfd; } -void RoutingManager::HandleRsSenderFinished(TimeMilli aStartTime) -{ - // This is a callback from `RsSender` and is invoked when it - // finishes a cycle of sending Router Solicitations. `aStartTime` - // specifies the start time of the RS transmission cycle. - // - // We remove or deprecate old entries in discovered table that are - // not refreshed during Router Solicitation. We also invalidate - // the learned RA header if it is not refreshed during Router - // Solicitation. - - Get().RemoveOrDeprecateOldEntries(aStartTime); - ScheduleRoutingPolicyEvaluation(kImmediately); -} - void RoutingManager::HandleRouterSolicit(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress) { OT_UNUSED_VARIABLE(aPacket); @@ -1527,7 +1508,7 @@ exit: void RoutingManager::OnLinkPrefixManager::Evaluate(void) { - VerifyOrExit(!Get().mRsSender.IsInProgress()); + VerifyOrExit(!Get().IsRsTxInProgress()); SetAilPrefix(Get().GetFavoredOnLinkPrefix()); @@ -2719,104 +2700,6 @@ void RoutingManager::TxRaInfo::CalculateHash(const RouterAdvert::RxMessage &aRaM sha256.Finish(aHash); } -//--------------------------------------------------------------------------------------------------------------------- -// RsSender - -RoutingManager::RsSender::RsSender(Instance &aInstance) - : InstanceLocator(aInstance) - , mTxCount(0) - , mTimer(aInstance) -{ -} - -void RoutingManager::RsSender::Start(void) -{ - uint32_t delay; - - VerifyOrExit(!IsInProgress()); - - delay = Random::NonCrypto::GetUint32InRange(0, kMaxStartDelay); - - LogInfo("RsSender: Starting - will send first RS in %lu msec", ToUlong(delay)); - - mTxCount = 0; - mStartTime = TimerMilli::GetNow(); - mTimer.Start(delay); - -exit: - return; -} - -void RoutingManager::RsSender::Stop(void) { mTimer.Stop(); } - -Error RoutingManager::RsSender::SendRs(void) -{ - Ip6::Address destAddress; - RouterSolicitHeader rsHdr; - TxMessage rsMsg; - InfraIf::LinkLayerAddress linkAddr; - InfraIf::Icmp6Packet packet; - Error error; - - SuccessOrExit(error = rsMsg.Append(rsHdr)); - - if (Get().GetLinkLayerAddress(linkAddr) == kErrorNone) - { - SuccessOrExit(error = rsMsg.AppendLinkLayerOption(linkAddr, Option::kSourceLinkLayerAddr)); - } - - rsMsg.GetAsPacket(packet); - destAddress.SetToLinkLocalAllRoutersMulticast(); - - error = Get().mInfraIf.Send(packet, destAddress); - - if (error == kErrorNone) - { - Get().GetBorderRoutingCounters().mRsTxSuccess++; - } - else - { - Get().GetBorderRoutingCounters().mRsTxFailure++; - } -exit: - return error; -} - -void RoutingManager::RsSender::HandleTimer(void) -{ - Error error; - uint32_t delay; - - if (mTxCount >= kMaxTxCount) - { - LogInfo("RsSender: Finished sending RS msgs and waiting for RAs"); - Get().HandleRsSenderFinished(mStartTime); - ExitNow(); - } - - error = SendRs(); - - if (error == kErrorNone) - { - mTxCount++; - delay = (mTxCount == kMaxTxCount) ? kWaitOnLastAttempt : kTxInterval; - LogInfo("RsSender: Sent RS %u/%u", mTxCount, kMaxTxCount); - } - else - { - LogCrit("RsSender: Failed to send RS %u/%u: %s", mTxCount + 1, kMaxTxCount, ErrorToString(error)); - - // Note that `mTxCount` is intentionally not incremented - // if the tx fails. - delay = kRetryDelay; - } - - mTimer.Start(delay); - -exit: - return; -} - //--------------------------------------------------------------------------------------------------------------------- // PdPrefixManager diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index 724306dbc..f23abc0b6 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -1021,44 +1021,6 @@ private: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void HandleRsSenderTimer(void) { mRsSender.HandleTimer(); } - - class RsSender : public InstanceLocator - { - public: - // This class implements tx of Router Solicitation (RS) - // messages to discover other routers. `Start()` schedules - // a cycle of RS transmissions of `kMaxTxCount` separated - // by `kTxInterval`. At the end of cycle the callback - // `HandleRsSenderFinished()` is invoked to inform end of - // the cycle to `RoutingManager`. - - explicit RsSender(Instance &aInstance); - - bool IsInProgress(void) const { return mTimer.IsRunning(); } - void Start(void); - void Stop(void); - void HandleTimer(void); - - private: - // All time intervals are in msec. - static constexpr uint32_t kMaxStartDelay = 1000; // Max random delay to send the first RS. - static constexpr uint32_t kTxInterval = 4000; // Interval between RS tx. - static constexpr uint32_t kRetryDelay = kTxInterval; // Interval to wait to retry a failed RS tx. - static constexpr uint32_t kWaitOnLastAttempt = 1000; // Wait interval after last RS tx. - static constexpr uint8_t kMaxTxCount = 3; // Number of RS tx in one cycle. - - Error SendRs(void); - - using RsTimer = TimerMilliIn; - - uint8_t mTxCount; - RsTimer mTimer; - TimeMilli mStartTime; - }; - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE void HandlePdPrefixManagerTimer(void) { mPdPrefixManager.HandleTimer(); } @@ -1149,7 +1111,6 @@ private: void EvaluateRoutingPolicy(void); bool IsInitialPolicyEvaluationDone(void) const; void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode); - void HandleRsSenderFinished(TimeMilli aStartTime); void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode); void HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress); @@ -1205,7 +1166,6 @@ private: #endif TxRaInfo mTxRaInfo; - RsSender mRsSender; Heap::Data mExtraRaOptions; RoutingPolicyTimer mRoutingPolicyTimer; diff --git a/src/core/border_router/rx_ra_tracker.cpp b/src/core/border_router/rx_ra_tracker.cpp index 4fe6dec83..2a5c74558 100644 --- a/src/core/border_router/rx_ra_tracker.cpp +++ b/src/core/border_router/rx_ra_tracker.cpp @@ -48,6 +48,7 @@ RegisterLogModule("BorderRouting"); RxRaTracker::RxRaTracker(Instance &aInstance) : InstanceLocator(aInstance) + , mRsSender(aInstance) , mExpirationTimer(aInstance) , mStaleTimer(aInstance) , mRouterTimer(aInstance) @@ -58,7 +59,11 @@ RxRaTracker::RxRaTracker(Instance &aInstance) mLocalRaHeader.Clear(); } -void RxRaTracker::Start(void) { HandleNetDataChange(); } +void RxRaTracker::Start(void) +{ + mRsSender.Start(); + HandleNetDataChange(); +} void RxRaTracker::Stop(void) { @@ -71,6 +76,23 @@ void RxRaTracker::Stop(void) mStaleTimer.Stop(); mRouterTimer.Stop(); mRdnssAddrTimer.Stop(); + + mRsSender.Stop(); +} + +void RxRaTracker::HandleRsSenderFinished(TimeMilli aStartTime) +{ + // This is a callback from `RsSender` and is invoked when it + // finishes a cycle of sending Router Solicitations. `aStartTime` + // specifies the start time of the RS transmission cycle. + // + // We remove or deprecate old entries in discovered table that are + // not refreshed during Router Solicitation. We also invalidate + // the learned RA header if it is not refreshed during Router + // Solicitation. + + RemoveOrDeprecateOldEntries(aStartTime); + Get().ScheduleRoutingPolicyEvaluation(RoutingManager::kImmediately); } void RxRaTracker::ProcessRouterAdvertMessage(const RouterAdvert::RxMessage &aRaMessage, @@ -804,7 +826,7 @@ void RxRaTracker::HandleStaleTimer(void) VerifyOrExit(Get().IsRunning()); LogInfo("Stale timer expired"); - Get().mRsSender.Start(); + mRsSender.Start(); exit: return; @@ -894,7 +916,7 @@ void RxRaTracker::SendNeighborSolicitToRouter(const Router &aRouter) TxMessage nsMsg; InfraIf::LinkLayerAddress linkAddr; - VerifyOrExit(!Get().mRsSender.IsInProgress()); + VerifyOrExit(!mRsSender.IsInProgress()); nsHdr.SetTargetAddress(aRouter.mAddress); SuccessOrExit(nsMsg.Append(nsHdr)); @@ -1448,6 +1470,104 @@ exit: return; } +//--------------------------------------------------------------------------------------------------------------------- +// RxRaTracker::RsSender + +RxRaTracker::RsSender::RsSender(Instance &aInstance) + : InstanceLocator(aInstance) + , mTxCount(0) + , mTimer(aInstance) +{ +} + +void RxRaTracker::RsSender::Start(void) +{ + uint32_t delay; + + VerifyOrExit(!IsInProgress()); + + delay = Random::NonCrypto::GetUint32InRange(0, kMaxStartDelay); + + LogInfo("RsSender: Starting - will send first RS in %lu msec", ToUlong(delay)); + + mTxCount = 0; + mStartTime = TimerMilli::GetNow(); + mTimer.Start(delay); + +exit: + return; +} + +void RxRaTracker::RsSender::Stop(void) { mTimer.Stop(); } + +Error RxRaTracker::RsSender::SendRs(void) +{ + Ip6::Address destAddress; + RouterSolicitHeader rsHdr; + TxMessage rsMsg; + InfraIf::LinkLayerAddress linkAddr; + InfraIf::Icmp6Packet packet; + Error error; + + SuccessOrExit(error = rsMsg.Append(rsHdr)); + + if (Get().GetLinkLayerAddress(linkAddr) == kErrorNone) + { + SuccessOrExit(error = rsMsg.AppendLinkLayerOption(linkAddr, Option::kSourceLinkLayerAddr)); + } + + rsMsg.GetAsPacket(packet); + destAddress.SetToLinkLocalAllRoutersMulticast(); + + error = Get().mInfraIf.Send(packet, destAddress); + + if (error == kErrorNone) + { + Get().GetBorderRoutingCounters().mRsTxSuccess++; + } + else + { + Get().GetBorderRoutingCounters().mRsTxFailure++; + } +exit: + return error; +} + +void RxRaTracker::RsSender::HandleTimer(void) +{ + Error error; + uint32_t delay; + + if (mTxCount >= kMaxTxCount) + { + LogInfo("RsSender: Finished sending RS msgs and waiting for RAs"); + Get().HandleRsSenderFinished(mStartTime); + ExitNow(); + } + + error = SendRs(); + + if (error == kErrorNone) + { + mTxCount++; + delay = (mTxCount == kMaxTxCount) ? kWaitOnLastAttempt : kTxInterval; + LogInfo("RsSender: Sent RS %u/%u", mTxCount, kMaxTxCount); + } + else + { + LogCrit("RsSender: Failed to send RS %u/%u: %s", mTxCount + 1, kMaxTxCount, ErrorToString(error)); + + // Note that `mTxCount` is intentionally not incremented + // if the tx fails. + delay = kRetryDelay; + } + + mTimer.Start(delay); + +exit: + return; +} + } // namespace BorderRouter } // namespace ot diff --git a/src/core/border_router/rx_ra_tracker.hpp b/src/core/border_router/rx_ra_tracker.hpp index 9c0e02219..aa25c534f 100644 --- a/src/core/border_router/rx_ra_tracker.hpp +++ b/src/core/border_router/rx_ra_tracker.hpp @@ -103,6 +103,20 @@ public: */ void Stop(void); + /** + * Indicates whether the Router Solicitation (RS) transmission process is in progress. + * + * 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. + * + * @retval TRUE If the Router Solicitation transmission process is in progress. + * @retval FALSE If the Router Solicitation transmission process is not in progress. + */ + bool IsRsTxInProgress(void) const { return mRsSender.IsInProgress(); } + /** * Processes a received Router Advertisement (RA) message. * @@ -278,7 +292,6 @@ public: bool IsAddressReachableThroughExplicitRoute(const Ip6::Address &aAddress) const; // Callbacks notifying of changes - void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold); void HandleLocalOnLinkPrefixChanged(void); private: @@ -482,11 +495,51 @@ private: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + void HandleRsSenderTimer(void) { mRsSender.HandleTimer(); } + + class RsSender : public InstanceLocator + { + public: + // This class implements tx of Router Solicitation (RS) + // messages to discover other routers. `Start()` schedules + // a cycle of RS transmissions of `kMaxTxCount` separated + // by `kTxInterval`. At the end of cycle the callback + // `HandleRsSenderFinished()` is invoked to inform end of + // the cycle to `RxRaTracker`. + + explicit RsSender(Instance &aInstance); + + bool IsInProgress(void) const { return mTimer.IsRunning(); } + void Start(void); + void Stop(void); + void HandleTimer(void); + + private: + // All time intervals are in msec. + static constexpr uint32_t kMaxStartDelay = 1000; // Max random delay to send the first RS. + static constexpr uint32_t kTxInterval = 4000; // Interval between RS tx. + static constexpr uint32_t kRetryDelay = kTxInterval; // Interval to wait to retry a failed RS tx. + static constexpr uint32_t kWaitOnLastAttempt = 1000; // Wait interval after last RS tx. + static constexpr uint8_t kMaxTxCount = 3; // Number of RS tx in one cycle. + + Error SendRs(void); + + using RsTimer = TimerMilliIn; + + uint8_t mTxCount; + RsTimer mTimer; + TimeMilli mStartTime; + }; + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + void HandleRsSenderFinished(TimeMilli aStartTime); void ProcessRaHeader(const RouterAdvert::Header &aRaHeader, Router &aRouter, RouterAdvOrigin aRaOrigin); void ProcessPrefixInfoOption(const PrefixInfoOption &aPio, Router &aRouter); void ProcessRouteInfoOption(const RouteInfoOption &aRio, Router &aRouter); void ProcessRecursiveDnsServerOption(const RecursiveDnsServerOption &aRdnss, Router &aRouter); void UpdateIfAddresses(const Ip6::Address &aAddress); + void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold); void Evaluate(void); void DetermineStaleTimeFor(const OnLinkPrefix &aPrefix, NextFireTime &aStaleTime); void DetermineStaleTimeFor(const RoutePrefix &aPrefix, NextFireTime &aStaleTime); @@ -524,6 +577,7 @@ private: using IfAddressList = OwningList>; using RdnssCallback = Callback; + RsSender mRsSender; DecisionFactors mDecisionFactors; RouterList mRouters; IfAddressList mIfAddresses;