Skip to content

Commit a23b5c8

Browse files
[mle] Consolidate role transition management in RoleTransitioner
This commit introduces the `RoleTransitioner` class (renamed from `RouterRoleTransition`) to centralize the management of state related to router role allowed, up/downgrade thresholds, and the address solicit state without introducing functional changes, to support future changes related to configuring these parameters. This commit is intended to not change any functionality, though some expected enhancements have been added in several TODO comments. The following state and logic are moved from the `Mle` class into the `RoleTransitioner`: - Increased scope of the state tracked by the `RoleTransitioner` class for all operations directly related to determining the transition state or timing for FTDs. This includes logic on values that can be passed with simple parameters to check functions, but excludes `InstanceLocator` operations, so that the class can remain focused on determining the role transition state. - `Signal...` methods of the `RoleTransitioner` class have been defined to clarify events affecting state transitions. - Named transition conditions on thresholds to `MayUpgrade()`, `MayBeginDowngradeTimer()`, and `MayCompleteTimedDowngrade()` to clarify that additional conditions may apply where called and to be more descriptive of the use of each threshold. - Renamed `WillBecomeRouterSoon()` -> `MayBecomeRouterSoon()` to match other related name changes and indicate that a pending upgrade may fail to take effect. - This also includes the downgrade blocking state (`mDowngradeBlocked`). - Includes adding an extra delay in the Leader role when starting a downgrade timer due to the router role no longer allowed. - Caches separate states affecting the `mRouterRoleAllowed` state, also detecting if a downgrade timer should be started based on - Some related switch cases have been replaced by short if-else blocks where it has a measurable improvement on codespace for the size-check build.
1 parent 8e6469d commit a23b5c8

5 files changed

Lines changed: 348 additions & 264 deletions

File tree

src/core/thread/dua_manager.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ void DuaManager::HandleNotifierEvents(Events aEvents)
319319
// Wait for link establishment with neighboring routers.
320320
UpdateRegistrationDelay(kNewRouterRegistrationDelay);
321321
}
322-
else if (Get<Mle::Mle>().WillBecomeRouterSoon())
322+
else if (Get<Mle::Mle>().MayBecomeRouterSoon())
323323
{
324324
// Will check again in case the device decides to stay REED when jitter timeout expires.
325325
UpdateRegistrationDelay(Get<Mle::Mle>().GetRouterRoleTransitionTimeout() + kNewRouterRegistrationDelay + 1);
@@ -432,7 +432,7 @@ void DuaManager::PerformNextRegistration(void)
432432
// Only send DUA.req when necessary
433433
#if OPENTHREAD_CONFIG_DUA_ENABLE
434434
#if OPENTHREAD_FTD
435-
if (!Get<Mle::Mle>().IsRouterOrLeader() && Get<Mle::Mle>().WillBecomeRouterSoon())
435+
if (!Get<Mle::Mle>().IsRouterOrLeader() && Get<Mle::Mle>().MayBecomeRouterSoon())
436436
{
437437
UpdateRegistrationDelay(Get<Mle::Mle>().GetRouterRoleTransitionTimeout() + kNewRouterRegistrationDelay + 1);
438438
ExitNow();

src/core/thread/mle.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ Mle::Mle(Instance &aInstance)
8080
, mWedAttachTimer(aInstance)
8181
#endif
8282
#if OPENTHREAD_FTD
83-
, mAddressSolicitPending(false)
84-
, mAddressSolicitRejected(false)
8583
, mNetworkIdTimeout(kNetworkIdTimeout)
8684
, mPreviousPartitionRouterIdSequence(0)
8785
, mPreviousPartitionIdTimeout(0)
@@ -99,7 +97,6 @@ Mle::Mle(Instance &aInstance)
9997
, mAdvertiseTrickleTimer(aInstance, Mle::HandleAdvertiseTrickleTimer)
10098
, mChildTable(aInstance)
10199
, mRouterTable(aInstance)
102-
, mRoleTransitioner(aInstance)
103100
#endif // OPENTHREAD_FTD
104101
#if OPENTHREAD_CONFIG_P2P_ENABLE
105102
, mP2p(aInstance)
@@ -294,6 +291,10 @@ void Mle::SetRole(DeviceRole aRole)
294291

295292
SuccessOrExit(Get<Notifier>().Update(mRole, aRole, kEventThreadRoleChanged));
296293

294+
#if OPENTHREAD_FTD
295+
mRoleTransitioner.SignalRoleChanged();
296+
#endif
297+
297298
LogNote("Role %s -> %s", RoleToString(oldRole), RoleToString(mRole));
298299

299300
if ((oldRole == kRoleDetached) && IsAttached())
@@ -446,10 +447,6 @@ void Mle::Restore(void)
446447
// non-volatile settings after boot.
447448
mHasRestored = true;
448449

449-
#if OPENTHREAD_FTD
450-
mRoleTransitioner.UpdateRouterRoleAllowed(RoleTransitioner::kReasonMleInit);
451-
#endif
452-
453450
exit:
454451
return;
455452
}
@@ -598,7 +595,7 @@ void Mle::SetStateDetached(void)
598595
Get<MeshForwarder>().SetRxOnWhenIdle(true);
599596
Get<Mac::Mac>().SetBeaconEnabled(false);
600597
#if OPENTHREAD_FTD
601-
mRoleTransitioner.SetDowngradeBlocked(false);
598+
mRoleTransitioner.SignalDowngradeBlocked(false);
602599
ClearAlternateRloc16();
603600
HandleDetachStart();
604601
#endif
@@ -719,7 +716,7 @@ Error Mle::SetDeviceMode(DeviceMode aDeviceMode)
719716
ClearAlternateRloc16();
720717
}
721718

722-
mRoleTransitioner.UpdateRouterRoleAllowed(RoleTransitioner::kReasonDeviceModeChanged);
719+
mRoleTransitioner.SignalFtdModeChanged(IsFullThreadDevice(), mRole);
723720
#endif
724721

725722
if (IsAttached())
@@ -1044,7 +1041,7 @@ void Mle::HandleNotifierEvents(Events aEvents)
10441041
#if OPENTHREAD_FTD
10451042
if (aEvents.Contains(kEventSecurityPolicyChanged))
10461043
{
1047-
mRoleTransitioner.UpdateRouterRoleAllowed(RoleTransitioner::kReasonSecurityPolicyChanged);
1044+
HandleRouterRoleAllowedFromSecurityPolicy();
10481045
}
10491046

10501047
if (mRoleTransitioner.IsDowngradeBlocked() && aEvents.Contains(kEventThreadChildRemoved))
@@ -1060,7 +1057,7 @@ void Mle::HandleNotifierEvents(Events aEvents)
10601057
}
10611058
}
10621059

1063-
mRoleTransitioner.SetDowngradeBlocked(shouldBlock);
1060+
mRoleTransitioner.SignalDowngradeBlocked(shouldBlock);
10641061
}
10651062
#endif
10661063

src/core/thread/mle.hpp

Lines changed: 93 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ class Mle : public InstanceLocator, private NonCopyable
771771
* @retval kErrorNone Successfully set the router-eligible configuration.
772772
* @retval kErrorNotCapable The device is not capable of becoming a router.
773773
*/
774-
Error SetRouterEligible(bool aEligible) { return mRoleTransitioner.SetRouterEligible(aEligible); }
774+
Error SetRouterEligible(bool aEligible);
775775

776776
/**
777777
* Indicates whether the router role is currently allowed.
@@ -1022,7 +1022,7 @@ class Mle : public InstanceLocator, private NonCopyable
10221022
* @retval TRUE If the REED is going to become a Router soon.
10231023
* @retval FALSE If the REED is not going to become a Router soon.
10241024
*/
1025-
bool WillBecomeRouterSoon(void) const { return mRoleTransitioner.WillBecomeRouterSoon(); }
1025+
bool MayBecomeRouterSoon(void) const { return IsChild() && mRoleTransitioner.MayBecomeRouterSoon(); }
10261026

10271027
/**
10281028
* Removes a link to a neighbor.
@@ -1179,14 +1179,14 @@ class Mle : public InstanceLocator, private NonCopyable
11791179
*
11801180
* @param[in] aEnabled TRUE if the device was commissioned using CCM, FALSE otherwise.
11811181
*/
1182-
void SetCcmEnabled(bool aEnabled) { mRoleTransitioner.SetCcmEnabled(aEnabled); }
1182+
void SetCcmEnabled(bool aEnabled);
11831183

11841184
/**
11851185
* Sets whether the Security Policy TLV version-threshold for routing (VR field) is enabled.
11861186
*
11871187
* @param[in] aEnabled TRUE to enable Security Policy TLV version-threshold for routing, FALSE otherwise.
11881188
*/
1189-
void SetThreadVersionCheckEnabled(bool aEnabled) { mRoleTransitioner.SetThreadVersionCheckEnabled(aEnabled); }
1189+
void SetThreadVersionCheckEnabled(bool aEnabled);
11901190

11911191
/**
11921192
* Gets the current Interval Max value used by Advertisement trickle timer.
@@ -1344,12 +1344,8 @@ class Mle : public InstanceLocator, private NonCopyable
13441344
static constexpr uint32_t kMaxLeaderToRouterTimeout = 90000; // (in msec)
13451345
static constexpr uint8_t kMinDowngradeNeighbors = 7;
13461346
static constexpr uint8_t kNetworkIdTimeout = 120; // (in sec)
1347-
static constexpr uint8_t kRouterSelectionJitter = 120; // (in sec)
1348-
static constexpr uint8_t kRouterDowngradeThreshold = 23;
1349-
static constexpr uint8_t kRouterUpgradeThreshold = 16;
13501347
static constexpr uint16_t kDiscoveryMaxJitter = 250; // Max jitter delay Discovery Responses (in msec).
13511348
static constexpr uint16_t kUnsolicitedDataResponseJitter = 500; // Max delay for unsol Data Response (in msec).
1352-
static constexpr uint8_t kLeaderDowngradeExtraDelay = 10; // Extra delay to downgrade leader (in sec).
13531349
static constexpr uint8_t kDefaultLeaderWeight = 64;
13541350
static constexpr uint8_t kAlternateRloc16Timeout = 8; // Time to use alternate RLOC16 (in sec).
13551351

@@ -2204,58 +2200,103 @@ class Mle : public InstanceLocator, private NonCopyable
22042200

22052201
#if OPENTHREAD_FTD
22062202

2207-
class RoleTransitioner : public InstanceLocator
2203+
class RoleTransitioner
22082204
{
2209-
// Manages the router role upgrade/downgrade transitions
2210-
22112205
public:
2212-
enum UpdateRouterRoleAllowedReason : uint8_t // Used in `UpdateRouterRoleAllowed()`
2206+
enum AddressSolicitState : uint8_t
22132207
{
2214-
kReasonMleInit,
2215-
kReasonDeviceModeChanged,
2216-
kReasonConfigParameterChanged,
2217-
kReasonSecurityPolicyChanged,
2208+
kAddressSolicitStateIdle,
2209+
kAddressSolicitStatePending,
2210+
kAddressSolicitStateRejected,
22182211
};
22192212

2220-
explicit RoleTransitioner(Instance &aInstance);
2213+
explicit RoleTransitioner(void);
2214+
2215+
bool IsAddressSolicitPending(void) const { return mAddressSolicitState == kAddressSolicitStatePending; }
2216+
bool IsAddressSolicitRejected(void) const { return mAddressSolicitState == kAddressSolicitStateRejected; }
2217+
bool IsRouterEligible(void) const { return mRouterEligible; }
2218+
bool IsRouterRoleAllowed(void) const { return mRouterRoleAllowed; }
2219+
bool IsTransitionPending(void) const { return (mTimeout != 0); }
2220+
bool IsDowngradeBlocked(void) const { return mDowngradeBlocked; }
2221+
2222+
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2223+
bool IsCcmEnabled(void) const { return mCcmEnabled; }
2224+
bool IsThreadVersionCheckEnabled(void) const { return mThreadVersionCheckEnabled; }
2225+
#endif
2226+
2227+
bool MayBeginDowngradeTimer(uint8_t aRouterCount, uint16_t aValidChildren) const;
2228+
bool MayCompleteTimedDowngrade(uint8_t aRouterCount) const;
2229+
bool MayUpgrade(uint8_t aRouterCount) const;
2230+
bool MayBecomeRouterSoon(void) const;
22212231

2222-
bool IsRouterRoleAllowed(void) const { return mRouterRoleAllowed; }
2223-
void UpdateRouterRoleAllowed(UpdateRouterRoleAllowedReason aReason);
2224-
Error SetRouterEligible(bool aEligible);
2232+
uint8_t GetTimeout(void) const { return mTimeout; }
22252233
uint8_t GetJitter(void) const { return mJitter; }
2226-
void SetJitter(uint8_t aJitter) { mJitter = aJitter; }
22272234
uint8_t GetUpgradeThreshold(void) const { return mUpgradeThreshold; }
2228-
void SetUpgradeThreshold(uint8_t aThreshold) { mUpgradeThreshold = aThreshold; }
22292235
uint8_t GetDowngradeThreshold(void) const { return mDowngradeThreshold; }
2230-
void SetDowngradeThreshold(uint8_t aThreshold) { mDowngradeThreshold = aThreshold; }
2231-
bool IsDowngradeBlocked(void) const { return mDowngradeBlocked; }
2232-
void SetDowngradeBlocked(bool aBlocked) { mDowngradeBlocked = aBlocked; }
2233-
bool IsTransitionPending(void) const { return (mTimeout != 0); }
2234-
bool WillBecomeRouterSoon(void) const;
2235-
void StartTimeout(void);
2236-
void StopTimeout(void) { mTimeout = 0; }
2237-
void IncreaseTimeout(uint8_t aIncrement) { mTimeout += aIncrement; }
2238-
uint8_t GetTimeout(void) const { return mTimeout; }
2239-
bool IsRouterCountBelowUpgradeThreshold(void) const;
2240-
void HandleTimeTick(void);
2241-
void DecideWhetherToUpgrade(void);
2242-
void DecideWhetherToDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv);
2236+
2237+
bool SetRouterEligibleAndGetChanged(bool aStatus);
2238+
bool SetRouterRoleAllowedAndGetChanged(bool aStatus);
2239+
2240+
void SetJitter(uint8_t aJitter) { mJitter = aJitter; }
2241+
void SetUpgradeThreshold(uint8_t aThreshold) { mUpgradeThreshold = aThreshold; }
2242+
void SetDowngradeThreshold(uint8_t aThreshold) { mDowngradeThreshold = aThreshold; }
2243+
2244+
bool HandleTimeTick(void);
2245+
void StartRouterUpgradeIfConditionsAllow(uint8_t aRouterCount);
2246+
2247+
// ------------------------
2248+
// Transition signals
2249+
void SignalAddressSolicitFinished(void);
2250+
void SignalAddressSolicitPending(void) { mAddressSolicitState = kAddressSolicitStatePending; }
2251+
void SignalAddressSolicitRejected(void) { mAddressSolicitState = kAddressSolicitStateRejected; }
2252+
void SignalBecomingRouter(void) { StopTimer(); }
2253+
void SignalBeginTimedLeaderDowngrade(void);
2254+
void SignalBeginTimedRouterDowngrade(void);
2255+
void SignalChildUpgradeStart(void);
2256+
void SignalDowngradeAborted(void);
2257+
void SignalDowngradeBlocked(bool aShouldBlock);
2258+
void SignalRoleChanged(void);
2259+
2260+
// ------------------------
2261+
// State transition signals affecting the Router role allowed status
2262+
void SignalFtdModeChanged(bool aIsFtdMode, DeviceRole aRole);
2263+
void SignalRouterEligible(bool aEligible, DeviceRole aRole);
2264+
void SignalRouterRoleAllowedBySecurityPolicy(bool aAllowed, DeviceRole aRole);
2265+
22432266
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2244-
void SetCcmEnabled(bool aEnabled);
2245-
void SetThreadVersionCheckEnabled(bool aEnabled);
2267+
void SetCcmEnabled(bool aCcmEnabled) { mCcmEnabled = aCcmEnabled; }
2268+
void SetThreadVersionCheckEnabled(bool aThreadVersionCheckEnabled)
2269+
{
2270+
mThreadVersionCheckEnabled = aThreadVersionCheckEnabled;
2271+
}
22462272
#endif
22472273

22482274
private:
2249-
bool DetermineIfRouterRoleAllowed(void) const;
2250-
bool NeighborHasComparableConnectivity(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const;
2275+
void BeginTimer(void);
2276+
void StopTimer(void);
2277+
void SignalRouterRoleAllowedUpdate(DeviceRole aRole);
2278+
2279+
static constexpr uint8_t kMaxDelayToTransitionSoon = 10;
2280+
2281+
static constexpr uint8_t kRouterSelectionJitterDefault = 120; ///< (in sec)
2282+
static constexpr uint8_t kLeaderDowngradeExtraDelay = 10; ///< Extra delay to downgrade leader (in sec).
2283+
2284+
static constexpr uint8_t kRouterUpgradeThresholdDefault = 16;
2285+
static constexpr uint8_t kRouterDowngradeThresholdDefault = 23;
22512286

2252-
bool mRouterEligible : 1;
2253-
bool mRouterRoleAllowed : 1;
2254-
bool mDowngradeBlocked : 1;
2287+
// Router Role Allowed statuses
2288+
bool mRouterRoleAllowed : 1; ///< Cached state of the router role allowed status
2289+
bool mRouterEligible : 1; ///< Router Eligible configuration affecting the role allowed status
2290+
bool mUsingFtdMode : 1; ///< FTD mode
2291+
bool mRouterRoleAllowedBySecurityPolicy : 1; ///< Cached state of the security policy router role allowed status
2292+
bool mDowngradeBlocked : 1; ///< Router role blocked from downgrading
22552293
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2256-
bool mCcmEnabled : 1;
2257-
bool mThreadVersionCheckEnabled : 1;
2294+
bool mCcmEnabled : 1; ///< Whether to allow the security policy CCM commissioned check
2295+
bool mThreadVersionCheckEnabled : 1; ///< Whether to allow the security policy version check
22582296
#endif
2297+
2298+
AddressSolicitState mAddressSolicitState;
2299+
22592300
uint8_t mTimeout;
22602301
uint8_t mJitter;
22612302
uint8_t mUpgradeThreshold;
@@ -2446,6 +2487,8 @@ class Mle : public InstanceLocator, private NonCopyable
24462487
void ClearAlternateRloc16(void);
24472488
uint8_t SelectLeaderId(void) const;
24482489
uint32_t SelectPartitionId(void) const;
2490+
void HandleRouterRoleAllowedFromSecurityPolicy(void);
2491+
void HandleRoleAllowedChangedFromConfig(void);
24492492
void DetermineConnectivity(Connectivity &aConnectivity) const;
24502493
void HandleDetachStart(void);
24512494
void HandleChildStart(void);
@@ -2493,6 +2536,8 @@ class Mle : public InstanceLocator, private NonCopyable
24932536
void SetChildStateToValid(Child &aChild);
24942537
bool HasChildren(void);
24952538
void RemoveChildren(void);
2539+
void CheckOrBeginRouterDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv);
2540+
bool NeighborHasComparableConnectivity(const RouteTlv &aRouteTlv, uint8_t aNeighborId) const;
24962541
void HandleAdvertiseTrickleTimer(void);
24972542
void HandleTimeTick(void);
24982543
void HandleRouterTableEvent(RouterTable::Events aEvents);
@@ -2571,13 +2616,13 @@ class Mle : public InstanceLocator, private NonCopyable
25712616

25722617
#if OPENTHREAD_FTD
25732618

2574-
bool mAddressSolicitPending : 1;
2575-
bool mAddressSolicitRejected : 1;
2619+
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2620+
bool mCcmEnabled : 1;
2621+
bool mThreadVersionCheckEnabled : 1;
2622+
#endif
25762623
uint8_t mRouterId;
25772624
uint8_t mPreviousRouterId;
25782625
uint8_t mNetworkIdTimeout;
2579-
uint8_t mRouterUpgradeThreshold;
2580-
uint8_t mRouterDowngradeThreshold;
25812626
uint8_t mLeaderWeight;
25822627
uint8_t mPreviousPartitionRouterIdSequence;
25832628
uint8_t mPreviousPartitionIdTimeout;

0 commit comments

Comments
 (0)