mirror of
https://github.com/espressif/openthread.git
synced 2026-08-15 15:17:46 +00:00
[border-router] move RsSender to RxRaTracker (#12015)
This change moves the `RsSender` class from `RoutingManager` to `RxRaTracker`. The `RxRaTracker` is responsible for tracking received Router Advertisements (RAs). Since sending Router Solicitations (RS) is the mechanism to discover routers and solicit RAs, it is more appropriate for `RxRaTracker` to own the `RsSender`. This improves the separation of concerns by centralizing the logic for both sending RS messages and processing the resulting RAs within the `RxRaTracker` class. The `RoutingManager` is now decoupled from the details of the RS transmission process. The `IsRsTxInProgress()` method is also moved to `RxRaTracker` and its Doxygen documentation is improved to provide more detail on the RS transmission process.
This commit is contained in:
@@ -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<RxRaTracker>().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<RoutingManager>().mRsSender.IsInProgress());
|
||||
VerifyOrExit(!Get<RxRaTracker>().IsRsTxInProgress());
|
||||
|
||||
SetAilPrefix(Get<RxRaTracker>().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<InfraIf>().GetLinkLayerAddress(linkAddr) == kErrorNone)
|
||||
{
|
||||
SuccessOrExit(error = rsMsg.AppendLinkLayerOption(linkAddr, Option::kSourceLinkLayerAddr));
|
||||
}
|
||||
|
||||
rsMsg.GetAsPacket(packet);
|
||||
destAddress.SetToLinkLocalAllRoutersMulticast();
|
||||
|
||||
error = Get<RoutingManager>().mInfraIf.Send(packet, destAddress);
|
||||
|
||||
if (error == kErrorNone)
|
||||
{
|
||||
Get<Ip6::Ip6>().GetBorderRoutingCounters().mRsTxSuccess++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Get<Ip6::Ip6>().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<RoutingManager>().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
|
||||
|
||||
|
||||
@@ -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<RoutingManager, &RoutingManager::HandleRsSenderTimer>;
|
||||
|
||||
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;
|
||||
|
||||
@@ -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<RoutingManager>().ScheduleRoutingPolicyEvaluation(RoutingManager::kImmediately);
|
||||
}
|
||||
|
||||
void RxRaTracker::ProcessRouterAdvertMessage(const RouterAdvert::RxMessage &aRaMessage,
|
||||
@@ -804,7 +826,7 @@ void RxRaTracker::HandleStaleTimer(void)
|
||||
VerifyOrExit(Get<RoutingManager>().IsRunning());
|
||||
|
||||
LogInfo("Stale timer expired");
|
||||
Get<RoutingManager>().mRsSender.Start();
|
||||
mRsSender.Start();
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -894,7 +916,7 @@ void RxRaTracker::SendNeighborSolicitToRouter(const Router &aRouter)
|
||||
TxMessage nsMsg;
|
||||
InfraIf::LinkLayerAddress linkAddr;
|
||||
|
||||
VerifyOrExit(!Get<RoutingManager>().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<InfraIf>().GetLinkLayerAddress(linkAddr) == kErrorNone)
|
||||
{
|
||||
SuccessOrExit(error = rsMsg.AppendLinkLayerOption(linkAddr, Option::kSourceLinkLayerAddr));
|
||||
}
|
||||
|
||||
rsMsg.GetAsPacket(packet);
|
||||
destAddress.SetToLinkLocalAllRoutersMulticast();
|
||||
|
||||
error = Get<RoutingManager>().mInfraIf.Send(packet, destAddress);
|
||||
|
||||
if (error == kErrorNone)
|
||||
{
|
||||
Get<Ip6::Ip6>().GetBorderRoutingCounters().mRsTxSuccess++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Get<Ip6::Ip6>().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<RxRaTracker>().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
|
||||
|
||||
|
||||
@@ -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<RxRaTracker, &RxRaTracker::HandleRsSenderTimer>;
|
||||
|
||||
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<Entry<IfAddress>>;
|
||||
using RdnssCallback = Callback<RdnssAddrCallback>;
|
||||
|
||||
RsSender mRsSender;
|
||||
DecisionFactors mDecisionFactors;
|
||||
RouterList mRouters;
|
||||
IfAddressList mIfAddresses;
|
||||
|
||||
Reference in New Issue
Block a user