Skip to content

Commit ee0d33e

Browse files
[mle] Refactor of Router Role Upgrade and Downgrade conditions
Key changes: - Router role upgrade attempts may no longer be started when beginning the child role, which may allow REEDs to advertise immediately after swapping parents when the network is already stable. - Split ShouldDowngrade() into ShouldBeginDowngradeTimer for when the downgrade timer is started from advertisement conditions and ShouldRouterDowngrade() for checks that apply when the timer is started or when it is performed. - Created ShouldUpgrade() for conditions to check when the timer is started and when the upgrade is attempted
1 parent 4ae9e63 commit ee0d33e

2 files changed

Lines changed: 97 additions & 39 deletions

File tree

src/core/thread/mle.hpp

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,11 +2518,49 @@ class Mle : public InstanceLocator, private NonCopyable
25182518
void SetChildStateToValid(Child &aChild);
25192519
bool HasChildren(void);
25202520
void RemoveChildren(void);
2521-
bool ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const;
2522-
bool NeighborHasComparableConnectivity(const RouteTlv &aRouteTlv, uint8_t aNeighborId) const;
2523-
void HandleAdvertiseTrickleTimer(void);
2524-
void HandleTimeTick(void);
2525-
void HandleRouterTableEvent(RouterTable::Events aEvents);
2521+
2522+
/**
2523+
* Determine if a router downgrade transition should occur or timer should be started.
2524+
*
2525+
* Note: Checks all downgrade conditions except having comparable connectivity to a neighbor router both when
2526+
* the timer is started and when the downgrade is performed.
2527+
*
2528+
* @retval TRUE Downgrade conditions may apply for the Router role.
2529+
* @retval FALSE The device should not downgrade or is not in the Router role.
2530+
*
2531+
* @sa ShouldBeginDowngradeTimer
2532+
*/
2533+
bool ShouldRouterDowngrade(void) const;
2534+
2535+
/**
2536+
* Determine if a router downgrade transition timer should be started.
2537+
*
2538+
* Note: Checks all conditions known when handling advertisments.
2539+
*
2540+
* @retval TRUE The unit should begin its downgrade timer.
2541+
* @retval FALSE The device should not downgrade.
2542+
*/
2543+
bool ShouldBeginDowngradeTimer(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const;
2544+
2545+
/**
2546+
* Determine if a router upgrade transition should occur or timer should be started.
2547+
*
2548+
* Note: This checks all upgrade conditions both when the timer is started and when the upgrade is attempted but
2549+
* does not check `HasNeighborWithGoodLinkQuality()`, so that the runtime required by that check will only
2550+
* apply just before making the attempt to upgrade.
2551+
*
2552+
* @retval TRUE Upgrade conditions may apply.
2553+
* @retval FALSE The device should not upgrade.
2554+
*
2555+
* @sa HasNeighborWithGoodLinkQuality
2556+
*/
2557+
bool ShouldUpgrade(void) const;
2558+
2559+
bool NeighborHasComparableConnectivity(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const;
2560+
2561+
void HandleAdvertiseTrickleTimer(void);
2562+
void HandleTimeTick(void);
2563+
void HandleRouterTableEvent(RouterTable::Events aEvents);
25262564

25272565
template <Uri kUri> void HandleTmf(Coap::Msg &aMsg);
25282566

src/core/thread/mle_ftd.cpp

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ void Mle::UpdateRouterRoleAllowed(UpdateRouterRoleAllowedReason aReason)
131131
// Take action based on the current role, the new `mRouterRoleAllowed`,
132132
// and the reason for the change.
133133

134-
if (IsChild() && mRouterRoleAllowed && (aReason == kReasonConfigParameterChanged))
134+
if (IsChild() && mRouterRoleAllowed && (aReason == kReasonConfigParameterChanged) && ShouldUpgrade())
135135
{
136136
StartRouterRoleUpgradeTransition();
137137
}
@@ -343,11 +343,12 @@ void Mle::HandleChildStart(void)
343343
{
344344
mAddressSolicitRejected = false;
345345

346-
if (IsRouterRoleAllowed())
346+
if (ShouldUpgrade())
347347
{
348348
// As a REED, re-start the timer to check for a role upgrade when re-attaching as a Child
349349
StartRouterRoleUpgradeTransition();
350350
}
351+
// If the REED shouldn't upgrade, then it may begin sending advertisements on the next time tick.
351352

352353
StopLeader();
353354
Get<TimeTicker>().RegisterReceiver(TimeTicker::kMle);
@@ -1310,7 +1311,7 @@ Error Mle::HandleAdvertisementOnFtd(RxInfo &aRxInfo, uint16_t aSourceAddress, co
13101311
ExitNow(error = kErrorDetached);
13111312
}
13121313

1313-
if (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold)
1314+
if (ShouldUpgrade())
13141315
{
13151316
if (!IsRouterRoleTransitioning())
13161317
{
@@ -1348,7 +1349,7 @@ Error Mle::HandleAdvertisementOnFtd(RxInfo &aRxInfo, uint16_t aSourceAddress, co
13481349
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
13491350
// Update routers as a router or leader.
13501351

1351-
if (ShouldDowngrade(routerId, routeTlv))
1352+
if (ShouldBeginDowngradeTimer(routerId, routeTlv))
13521353
{
13531354
// Downgrade conditions have been met after an advertisement from another active router
13541355
StartRouterRoleDowngradeTransition();
@@ -1623,7 +1624,7 @@ void Mle::HandleTimeTick(void)
16231624
else if (IsRouterRoleUpgradePending())
16241625
{
16251626
// An upgrade should be performed, if the conditions to upgrade still apply
1626-
if (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold && HasNeighborWithGoodLinkQuality())
1627+
if (ShouldUpgrade() && HasNeighborWithGoodLinkQuality())
16271628
{
16281629
IgnoreError(BecomeRouter(kReasonTooFewRouters));
16291630
// Any attempt to become a router will also clear the current role transition
@@ -1649,7 +1650,7 @@ void Mle::HandleTimeTick(void)
16491650
if (mRouterRoleTransition.IsDowngradePending())
16501651
{
16511652
bool roleAllowed = IsRouterRoleAllowed();
1652-
bool shouldRouterDowngrade = IsRouter() && mRouterTable.GetActiveRouterCount() > mRouterDowngradeThreshold;
1653+
bool shouldRouterDowngrade = ShouldRouterDowngrade();
16531654
if (!roleAllowed || shouldRouterDowngrade)
16541655
{
16551656
if (IsRouter())
@@ -3830,71 +3831,90 @@ void Mle::FillConnectivityTlvValue(ConnectivityTlvValue &aTlvValue) const
38303831
aTlvValue.InitFrom(connectivity);
38313832
}
38323833

3833-
bool Mle::ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const
3834+
bool Mle::ShouldBeginDowngradeTimer(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const
38343835
{
38353836
// Determine whether all conditions are satisfied for the router
38363837
// to downgrade after receiving info for a neighboring router
38373838
// with Router ID `aNeighborId` along with its `aRouteTlv`.
38383839

3839-
bool shouldDowngrade = false;
3840-
uint8_t activeRouterCount = mRouterTable.GetActiveRouterCount();
3841-
uint8_t count;
3840+
bool shouldDowngrade = false;
38423841

3843-
VerifyOrExit(IsRouter());
38443842
VerifyOrExit(mRouterTable.IsAllocated(aNeighborId));
3845-
VerifyOrExit(!mBlockDowngrade);
38463843

38473844
// Return false, to let an existing downgrade transition continue
38483845
VerifyOrExit(!mRouterRoleTransition.IsDowngrading());
38493846

3847+
VerifyOrExit(ShouldRouterDowngrade());
3848+
3849+
// Check that the neighbor has as good or better-quality links to the same routers.
3850+
VerifyOrExit(NeighborHasComparableConnectivity(aNeighborId, aRouteTlv));
3851+
3852+
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
3853+
// Check if we are eligible to be router due to being a BR.
3854+
VerifyOrExit(!Get<NetworkData::Notifier>().IsEligibleForRouterRoleUpgradeAsBorderRouter());
3855+
#endif
3856+
3857+
shouldDowngrade = true;
3858+
3859+
exit:
3860+
return shouldDowngrade;
3861+
}
3862+
3863+
bool Mle::ShouldRouterDowngrade(void) const
3864+
{
3865+
uint8_t count;
3866+
uint8_t excessRouters;
3867+
bool shouldDowngrade = false;
3868+
uint8_t activeRouterCount = mRouterTable.GetActiveRouterCount();
3869+
3870+
// Only kRoleRouter may downgrade.
3871+
// kRoleLeader may not downgrade due to these conditions, and other roles are not applicable.
3872+
VerifyOrExit(IsRouter());
3873+
3874+
VerifyOrExit(!mBlockDowngrade);
38503875
VerifyOrExit(activeRouterCount > mRouterDowngradeThreshold);
38513876

3877+
excessRouters = (activeRouterCount > mRouterDowngradeThreshold) ? activeRouterCount - mRouterDowngradeThreshold : 0;
3878+
VerifyOrExit(mChildTable.GetNumChildren(Child::kInStateValid) < excessRouters * 3);
3879+
38523880
// Check that we have at least `kMinDowngradeNeighbors`
38533881
// neighboring routers with two-way link quality of 2 or better.
3854-
38553882
count = 0;
3856-
38573883
for (const Router &router : mRouterTable)
38583884
{
38593885
if (!router.IsStateValid() || (router.GetTwoWayLinkQuality() < kLinkQuality2))
38603886
{
38613887
continue;
38623888
}
3863-
38643889
count++;
3865-
38663890
if (count >= kMinDowngradeNeighbors)
38673891
{
38683892
break;
38693893
}
38703894
}
3871-
38723895
VerifyOrExit(count >= kMinDowngradeNeighbors);
38733896

3874-
// Check that we have fewer children than three times the number
3875-
// of excess routers (defined as the difference between number of
3876-
// active routers and `mRouterDowngradeThreshold`).
3877-
3878-
count = activeRouterCount - mRouterDowngradeThreshold;
3879-
VerifyOrExit(mChildTable.GetNumChildren(Child::kInStateValid) < count * 3);
3880-
3881-
// Check that the neighbor has as good or better-quality links to
3882-
// same routers.
3897+
shouldDowngrade = true;
3898+
exit:
3899+
return shouldDowngrade;
3900+
}
38833901

3884-
VerifyOrExit(NeighborHasComparableConnectivity(aRouteTlv, aNeighborId));
3902+
bool Mle::ShouldUpgrade(void) const
3903+
{
3904+
bool shouldUpgrade = false;
38853905

3886-
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
3887-
// Check if we are eligible to be router due to being a BR.
3888-
VerifyOrExit(!Get<NetworkData::Notifier>().IsEligibleForRouterRoleUpgradeAsBorderRouter());
3889-
#endif
3906+
VerifyOrExit(IsRouterRoleAllowed());
38903907

3891-
shouldDowngrade = true;
3908+
if (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold)
3909+
{
3910+
shouldUpgrade = true;
3911+
}
38923912

38933913
exit:
3894-
return shouldDowngrade;
3914+
return shouldUpgrade;
38953915
}
38963916

3897-
bool Mle::NeighborHasComparableConnectivity(const RouteTlv &aRouteTlv, uint8_t aNeighborId) const
3917+
bool Mle::NeighborHasComparableConnectivity(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const
38983918
{
38993919
// Check whether the neighboring router with Router ID `aNeighborId`
39003920
// (along with its `aRouteTlv`) has as good or better-quality links

0 commit comments

Comments
 (0)