mirror of
https://github.com/espressif/openthread.git
synced 2026-08-11 21:27:46 +00:00
[mle-router] add RouterRoleTransition nested class (#9490)
This commit adds `RouterRoleTransition` nested class to `MleRouter`. This class tracks the timeout and jitter intervals for router role transitions, i.e., device upgrading to router role from REED or downgrading from router to REED. It provides helper methods like `IsPending()` and `StartTimeout()` to check if role transition is pending or to start the timeout countdown. These methods help to simplify the code and make it more readable.
This commit is contained in:
@@ -222,7 +222,7 @@ uint8_t otThreadGetRouterSelectionJitter(otInstance *aInstance)
|
||||
|
||||
void otThreadSetRouterSelectionJitter(otInstance *aInstance, uint8_t aRouterJitter)
|
||||
{
|
||||
IgnoreError(AsCoreType(aInstance).Get<Mle::MleRouter>().SetRouterSelectionJitter(aRouterJitter));
|
||||
AsCoreType(aInstance).Get<Mle::MleRouter>().SetRouterSelectionJitter(aRouterJitter);
|
||||
}
|
||||
|
||||
otError otThreadGetChildInfoById(otInstance *aInstance, uint16_t aChildId, otChildInfo *aChildInfo)
|
||||
|
||||
@@ -289,9 +289,10 @@ exit:
|
||||
|
||||
void Local::HandleTimeTick(void)
|
||||
{
|
||||
// Delay registration when `GetRouterSelectionJitterTimeout()` is non-zero,
|
||||
// which indicates device may soon switch its role (e.g., REED to router).
|
||||
VerifyOrExit(Get<Mle::MleRouter>().GetRouterSelectionJitterTimeout() == 0);
|
||||
// Delay registration while router role transition is pending
|
||||
// (i.e., device may soon switch from REED to router role).
|
||||
|
||||
VerifyOrExit(!Get<Mle::MleRouter>().IsRouterRoleTransitionPending());
|
||||
|
||||
if (mRegistrationTimeout > 0)
|
||||
{
|
||||
|
||||
@@ -334,7 +334,7 @@ void DuaManager::HandleNotifierEvents(Events aEvents)
|
||||
else if (mle.IsExpectedToBecomeRouterSoon())
|
||||
{
|
||||
// Will check again in case the device decides to stay REED when jitter timeout expires.
|
||||
UpdateRegistrationDelay(mle.GetRouterSelectionJitterTimeout() + kNewRouterRegistrationDelay + 1);
|
||||
UpdateRegistrationDelay(mle.GetRouterRoleTransitionTimeout() + kNewRouterRegistrationDelay + 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -770,7 +770,7 @@ void Mle::InformPreviousChannel(void)
|
||||
VerifyOrExit(IsChild() || IsRouter());
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
VerifyOrExit(!IsFullThreadDevice() || IsRouter() || Get<MleRouter>().GetRouterSelectionJitterTimeout() == 0);
|
||||
VerifyOrExit(!IsFullThreadDevice() || IsRouter() || !Get<MleRouter>().IsRouterRoleTransitionPending());
|
||||
#endif
|
||||
|
||||
mAlternatePanId = Mac::kPanIdBroadcast;
|
||||
|
||||
@@ -82,8 +82,6 @@ MleRouter::MleRouter(Instance &aInstance)
|
||||
, mPreviousPartitionId(0)
|
||||
, mPreviousPartitionRouterIdSequence(0)
|
||||
, mPreviousPartitionIdTimeout(0)
|
||||
, mRouterSelectionJitter(kRouterSelectionJitter)
|
||||
, mRouterSelectionJitterTimeout(0)
|
||||
, mChildRouterLinks(kChildRouterLinks)
|
||||
, mParentPriority(kParentPriorityUnspecified)
|
||||
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
||||
@@ -193,16 +191,13 @@ void MleRouter::HandleSecurityPolicyChanged(void)
|
||||
|
||||
VerifyOrExit(IsRouterOrLeader() && !IsRouterEligible());
|
||||
|
||||
// `mRouterSelectionJitterTimeout` is non-zero if we are already
|
||||
// waiting to downgrade.
|
||||
VerifyOrExit(!mRouterRoleTransition.IsPending());
|
||||
|
||||
VerifyOrExit(mRouterSelectionJitterTimeout == 0);
|
||||
|
||||
mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
|
||||
mRouterRoleTransition.StartTimeout();
|
||||
|
||||
if (IsLeader())
|
||||
{
|
||||
mRouterSelectionJitterTimeout += kLeaderDowngradeExtraDelay;
|
||||
mRouterRoleTransition.IncreaseTimeout(kLeaderDowngradeExtraDelay);
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -229,7 +224,7 @@ Error MleRouter::BecomeRouter(ThreadStatusTlv::Status aStatus)
|
||||
LogInfo("Attempt to become router");
|
||||
|
||||
Get<MeshForwarder>().SetRxOnWhenIdle(true);
|
||||
mRouterSelectionJitterTimeout = 0;
|
||||
mRouterRoleTransition.StopTimeout();
|
||||
|
||||
switch (mRole)
|
||||
{
|
||||
@@ -329,7 +324,7 @@ void MleRouter::HandleChildStart(AttachMode aMode)
|
||||
{
|
||||
mAddressSolicitRejected = false;
|
||||
|
||||
mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
|
||||
mRouterRoleTransition.StartTimeout();
|
||||
|
||||
StopLeader();
|
||||
Get<TimeTicker>().RegisterReceiver(TimeTicker::kMleRouter);
|
||||
@@ -1072,18 +1067,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error MleRouter::SetRouterSelectionJitter(uint8_t aRouterJitter)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(aRouterJitter > 0, error = kErrorInvalidArgs);
|
||||
|
||||
mRouterSelectionJitter = aRouterJitter;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error MleRouter::ProcessRouteTlv(const RouteTlv &aRouteTlv, RxInfo &aRxInfo)
|
||||
{
|
||||
// This method processes `aRouteTlv` read from an MLE message.
|
||||
@@ -1292,9 +1275,9 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo, uint16_t aSourceAddress, c
|
||||
ExitNow(error = kErrorDetached);
|
||||
}
|
||||
|
||||
if ((mRouterSelectionJitterTimeout == 0) && (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold))
|
||||
if (!mRouterRoleTransition.IsPending() && (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold))
|
||||
{
|
||||
mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
|
||||
mRouterRoleTransition.StartTimeout();
|
||||
}
|
||||
|
||||
mRouterTable.UpdateRoutesOnFed(routeTlv, routerId);
|
||||
@@ -1323,12 +1306,9 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo, uint16_t aSourceAddress, c
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Update routers as a router or leader.
|
||||
|
||||
if (IsRouter())
|
||||
if (IsRouter() && ShouldDowngrade(routerId, routeTlv))
|
||||
{
|
||||
if (ShouldDowngrade(routerId, routeTlv))
|
||||
{
|
||||
mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
|
||||
}
|
||||
mRouterRoleTransition.StartTimeout();
|
||||
}
|
||||
|
||||
router = mRouterTable.FindRouterById(routerId);
|
||||
@@ -1514,7 +1494,7 @@ exit:
|
||||
|
||||
void MleRouter::HandleTimeTick(void)
|
||||
{
|
||||
bool routerStateUpdate = false;
|
||||
bool roleTransitionTimeoutExpired = false;
|
||||
|
||||
VerifyOrExit(IsFullThreadDevice(), Get<TimeTicker>().UnregisterReceiver(TimeTicker::kMleRouter));
|
||||
|
||||
@@ -1528,15 +1508,7 @@ void MleRouter::HandleTimeTick(void)
|
||||
mPreviousPartitionIdTimeout--;
|
||||
}
|
||||
|
||||
if (mRouterSelectionJitterTimeout > 0)
|
||||
{
|
||||
mRouterSelectionJitterTimeout--;
|
||||
|
||||
if (mRouterSelectionJitterTimeout == 0)
|
||||
{
|
||||
routerStateUpdate = true;
|
||||
}
|
||||
}
|
||||
roleTransitionTimeoutExpired = mRouterRoleTransition.HandleTimeTick();
|
||||
|
||||
switch (mRole)
|
||||
{
|
||||
@@ -1550,11 +1522,10 @@ void MleRouter::HandleTimeTick(void)
|
||||
break;
|
||||
|
||||
case kRoleChild:
|
||||
if (routerStateUpdate)
|
||||
if (roleTransitionTimeoutExpired)
|
||||
{
|
||||
if (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold && HasNeighborWithGoodLinkQuality())
|
||||
{
|
||||
// upgrade to Router
|
||||
IgnoreError(BecomeRouter(ThreadStatusTlv::kTooFewRouters));
|
||||
}
|
||||
else
|
||||
@@ -1576,7 +1547,6 @@ void MleRouter::HandleTimeTick(void)
|
||||
OT_FALL_THROUGH;
|
||||
|
||||
case kRoleRouter:
|
||||
// verify path to leader
|
||||
LogDebg("network id timeout = %lu", ToUlong(mRouterTable.GetLeaderAge()));
|
||||
|
||||
if ((mRouterTable.GetActiveRouterCount() > 0) && (mRouterTable.GetLeaderAge() >= mNetworkIdTimeout))
|
||||
@@ -1585,7 +1555,7 @@ void MleRouter::HandleTimeTick(void)
|
||||
Attach(kSamePartition);
|
||||
}
|
||||
|
||||
if (routerStateUpdate && mRouterTable.GetActiveRouterCount() > mRouterDowngradeThreshold)
|
||||
if (roleTransitionTimeoutExpired && mRouterTable.GetActiveRouterCount() > mRouterDowngradeThreshold)
|
||||
{
|
||||
LogNote("Downgrade to REED");
|
||||
Attach(kDowngradeToReed);
|
||||
@@ -1594,7 +1564,7 @@ void MleRouter::HandleTimeTick(void)
|
||||
OT_FALL_THROUGH;
|
||||
|
||||
case kRoleLeader:
|
||||
if (routerStateUpdate && !IsRouterEligible())
|
||||
if (roleTransitionTimeoutExpired && !IsRouterEligible())
|
||||
{
|
||||
LogInfo("No longer router eligible");
|
||||
IgnoreError(BecomeDetached());
|
||||
@@ -3573,7 +3543,7 @@ bool MleRouter::IsExpectedToBecomeRouterSoon(void) const
|
||||
static constexpr uint8_t kMaxDelay = 10;
|
||||
|
||||
return IsRouterEligible() && IsChild() && !mAddressSolicitRejected &&
|
||||
((GetRouterSelectionJitterTimeout() != 0 && GetRouterSelectionJitterTimeout() <= kMaxDelay) ||
|
||||
((mRouterRoleTransition.IsPending() && mRouterRoleTransition.GetTimeout() <= kMaxDelay) ||
|
||||
mAddressSolicitPending);
|
||||
}
|
||||
|
||||
@@ -3826,10 +3796,7 @@ bool MleRouter::ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv)
|
||||
VerifyOrExit(IsRouter());
|
||||
VerifyOrExit(mRouterTable.IsAllocated(aNeighborId));
|
||||
|
||||
// `mRouterSelectionJitterTimeout` is non-zero if we are already
|
||||
// waiting to downgrade.
|
||||
|
||||
VerifyOrExit(mRouterSelectionJitterTimeout == 0);
|
||||
VerifyOrExit(!mRouterRoleTransition.IsPending());
|
||||
|
||||
VerifyOrExit(activeRouterCount > mRouterDowngradeThreshold);
|
||||
|
||||
@@ -4037,6 +4004,32 @@ exit:
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// RouterRoleTransition
|
||||
|
||||
MleRouter::RouterRoleTransition::RouterRoleTransition(void)
|
||||
: mTimeout(0)
|
||||
, mJitter(kRouterSelectionJitter)
|
||||
{
|
||||
}
|
||||
|
||||
void MleRouter::RouterRoleTransition::StartTimeout(void)
|
||||
{
|
||||
mTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mJitter);
|
||||
}
|
||||
|
||||
bool MleRouter::RouterRoleTransition::HandleTimeTick(void)
|
||||
{
|
||||
bool expired = false;
|
||||
|
||||
VerifyOrExit(mTimeout > 0);
|
||||
mTimeout--;
|
||||
expired = (mTimeout == 0);
|
||||
|
||||
exit:
|
||||
return expired;
|
||||
}
|
||||
|
||||
} // namespace Mle
|
||||
} // namespace ot
|
||||
|
||||
|
||||
@@ -265,26 +265,36 @@ public:
|
||||
/**
|
||||
* Returns the ROUTER_SELECTION_JITTER value.
|
||||
*
|
||||
* @returns The ROUTER_SELECTION_JITTER value.
|
||||
* @returns The ROUTER_SELECTION_JITTER value in seconds.
|
||||
*
|
||||
*/
|
||||
uint8_t GetRouterSelectionJitter(void) const { return mRouterSelectionJitter; }
|
||||
uint8_t GetRouterSelectionJitter(void) const { return mRouterRoleTransition.GetJitter(); }
|
||||
|
||||
/**
|
||||
* Sets the ROUTER_SELECTION_JITTER value.
|
||||
*
|
||||
* @returns The ROUTER_SELECTION_JITTER value.
|
||||
* @param[in] aRouterJitter The router selection jitter value (in seconds).
|
||||
*
|
||||
*/
|
||||
Error SetRouterSelectionJitter(uint8_t aRouterJitter);
|
||||
void SetRouterSelectionJitter(uint8_t aRouterJitter) { mRouterRoleTransition.SetJitter(aRouterJitter); }
|
||||
|
||||
/**
|
||||
* Returns the current router selection jitter timeout value.
|
||||
* Indicates whether or not router role transition (upgrade from REED or downgrade to REED) is pending.
|
||||
*
|
||||
* @returns The current router selection jitter timeout value.
|
||||
* @retval TRUE Router role transition is pending.
|
||||
* @retval FALSE Router role transition is not pending
|
||||
*
|
||||
*/
|
||||
uint8_t GetRouterSelectionJitterTimeout(void) const { return mRouterSelectionJitterTimeout; }
|
||||
bool IsRouterRoleTransitionPending(void) const { return mRouterRoleTransition.IsPending(); }
|
||||
|
||||
/**
|
||||
* Returns the current timeout delay in seconds till router role transition (upgrade from REED or downgrade to
|
||||
* REED).
|
||||
*
|
||||
* @returns The timeout in seconds till router role transition, or zero if not pending role transition.
|
||||
*
|
||||
*/
|
||||
uint8_t GetRouterRoleTransitionTimeout(void) const { return mRouterRoleTransition.GetTimeout(); }
|
||||
|
||||
/**
|
||||
* Returns the ROUTER_UPGRADE_THRESHOLD value.
|
||||
@@ -616,6 +626,25 @@ private:
|
||||
static constexpr int8_t kParentPriorityLow = -1;
|
||||
static constexpr int8_t kParentPriorityUnspecified = -2;
|
||||
|
||||
class RouterRoleTransition
|
||||
{
|
||||
public:
|
||||
RouterRoleTransition(void);
|
||||
|
||||
bool IsPending(void) const { return (mTimeout != 0); }
|
||||
void StartTimeout(void);
|
||||
void StopTimeout(void) { mTimeout = 0; }
|
||||
void IncreaseTimeout(uint8_t aIncrement) { mTimeout += aIncrement; }
|
||||
uint8_t GetTimeout(void) const { return mTimeout; }
|
||||
bool HandleTimeTick(void);
|
||||
uint8_t GetJitter(void) const { return mJitter; }
|
||||
void SetJitter(uint8_t aJitter) { mJitter = aJitter; }
|
||||
|
||||
private:
|
||||
uint8_t mTimeout;
|
||||
uint8_t mJitter;
|
||||
};
|
||||
|
||||
void HandleDetachStart(void);
|
||||
void HandleChildStart(AttachMode aMode);
|
||||
void HandleSecurityPolicyChanged(void);
|
||||
@@ -727,8 +756,7 @@ private:
|
||||
uint8_t mPreviousPartitionRouterIdSequence; ///< The router ID sequence when last attached
|
||||
uint8_t mPreviousPartitionIdTimeout; ///< The partition ID timeout when last attached
|
||||
|
||||
uint8_t mRouterSelectionJitter; ///< The variable to save the assigned jitter value.
|
||||
uint8_t mRouterSelectionJitterTimeout; ///< The Timeout prior to request/release Router ID.
|
||||
RouterRoleTransition mRouterRoleTransition;
|
||||
|
||||
uint8_t mChildRouterLinks;
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ exit:
|
||||
break;
|
||||
#if OPENTHREAD_FTD
|
||||
case kErrorInvalidState:
|
||||
mTimer.Start(Time::SecToMsec(Get<Mle::MleRouter>().GetRouterSelectionJitterTimeout() + 1));
|
||||
mTimer.Start(Time::SecToMsec(Get<Mle::MleRouter>().GetRouterRoleTransitionTimeout() + 1));
|
||||
break;
|
||||
#endif
|
||||
case kErrorNotFound:
|
||||
|
||||
Reference in New Issue
Block a user