Skip to content

Commit e4c4703

Browse files
[mle] Refactor RoleTransitioner for a state-driven design
This commit refactors the RoleTransitioner with an enumerated state and state transition functions to clarify role transitions and prepare for additional parameters configured in an upcoming Router Administration feature. This commit is intended to not change any functionality, though some expected enhancements have been described in several TODO comments. Key changes include: - Increased scope of 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. - The conditions related to beginning REED advertisements has been separated from - Enumerated tracking of substates of the `DeviceRole` related to role transitions for FTDs. - The `AddressSolicitState` has become specific cases of the `RoleTransitionerState` - The `RoleTransitioner` now controls the extra delay when downgrading from the leader role. - Parameters affecting the `mRouterRoleAllowed` state are tracked more independently - Separate bits track the state for `mRouterEligible`, `mUsingFtdMode`, and `mRouterRoleAllowedBySecurityPolicy`, which all update `mRouterRoleAllowed` when changed - `mCcmEnabled` and `mThreadVersionCheckEnabled` are saved with the `RoleTransitioner` but are used with getters to determine `mRouterRoleAllowedBySecurityPolicy` - SetRouterEligible() no longer returns an error code - Different timer states within `RoleTransitionerState` control cases where the timer is used, to differentiate the state to restore if the timer is canceled: `kChildUpgradeTimerStarted`, `kRouterDowngradeTimerStarted`, `kRouterDisallowedTimerStarted`, and `kLeaderDisallowedTimerStarted` - 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 ca52657 commit e4c4703

3 files changed

Lines changed: 384 additions & 217 deletions

File tree

src/core/thread/mle.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,6 @@ Mle::Mle(Instance &aInstance)
8080
, mWedAttachTimer(aInstance)
8181
#endif
8282
#if OPENTHREAD_FTD
83-
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
84-
, mCcmEnabled(false)
85-
, mThreadVersionCheckEnabled(true)
86-
#endif
8783
, mNetworkIdTimeout(kNetworkIdTimeout)
8884
, mPreviousPartitionRouterIdSequence(0)
8985
, mPreviousPartitionIdTimeout(0)
@@ -295,6 +291,10 @@ void Mle::SetRole(DeviceRole aRole)
295291

296292
SuccessOrExit(Get<Notifier>().Update(mRole, aRole, kEventThreadRoleChanged));
297293

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

300300
if ((oldRole == kRoleDetached) && IsAttached())
@@ -447,10 +447,6 @@ void Mle::Restore(void)
447447
// non-volatile settings after boot.
448448
mHasRestored = true;
449449

450-
#if OPENTHREAD_FTD
451-
UpdateRouterRoleAllowed(kReasonMleInit);
452-
#endif
453-
454450
exit:
455451
return;
456452
}
@@ -599,7 +595,6 @@ void Mle::SetStateDetached(void)
599595
Get<MeshForwarder>().SetRxOnWhenIdle(true);
600596
Get<Mac::Mac>().SetBeaconEnabled(false);
601597
#if OPENTHREAD_FTD
602-
mRoleTransitioner.SetDowngradeBlocked(false);
603598
ClearAlternateRloc16();
604599
HandleDetachStart();
605600
#endif
@@ -720,7 +715,7 @@ Error Mle::SetDeviceMode(DeviceMode aDeviceMode)
720715
ClearAlternateRloc16();
721716
}
722717

723-
UpdateRouterRoleAllowed(kReasonDeviceModeChanged);
718+
mRoleTransitioner.SignalFtdModeChanged(IsFullThreadDevice());
724719
#endif
725720

726721
if (IsAttached())
@@ -1045,7 +1040,7 @@ void Mle::HandleNotifierEvents(Events aEvents)
10451040
#if OPENTHREAD_FTD
10461041
if (aEvents.Contains(kEventSecurityPolicyChanged))
10471042
{
1048-
UpdateRouterRoleAllowed(kReasonSecurityPolicyChanged);
1043+
HandleRouterRoleAllowedFromSecurityPolicy();
10491044
}
10501045

10511046
if (mRoleTransitioner.IsDowngradeBlocked() && aEvents.Contains(kEventThreadChildRemoved))
@@ -1061,7 +1056,7 @@ void Mle::HandleNotifierEvents(Events aEvents)
10611056
}
10621057
}
10631058

1064-
mRoleTransitioner.SetDowngradeBlocked(shouldBlock);
1059+
mRoleTransitioner.SignalDowngradeBlocked(shouldBlock);
10651060
}
10661061
#endif
10671062

src/core/thread/mle.hpp

Lines changed: 84 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -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 MayBecomeRouterSoon(void) const { return IsChild() && mRoleTransitioner.MayTransitionRoleSoon(); }
1025+
bool MayBecomeRouterSoon(void) const { return mRoleTransitioner.MayBecomeRouterSoon(); }
10261026

10271027
/**
10281028
* Removes a link to a neighbor.
@@ -1346,7 +1346,6 @@ class Mle : public InstanceLocator, private NonCopyable
13461346
static constexpr uint8_t kNetworkIdTimeout = 120; // (in sec)
13471347
static constexpr uint16_t kDiscoveryMaxJitter = 250; // Max jitter delay Discovery Responses (in msec).
13481348
static constexpr uint16_t kUnsolicitedDataResponseJitter = 500; // Max delay for unsol Data Response (in msec).
1349-
static constexpr uint8_t kLeaderDowngradeExtraDelay = 10; // Extra delay to downgrade leader (in sec).
13501349
static constexpr uint8_t kDefaultLeaderWeight = 64;
13511350
static constexpr uint8_t kAlternateRloc16Timeout = 8; // Time to use alternate RLOC16 (in sec).
13521351

@@ -1471,16 +1470,6 @@ class Mle : public InstanceLocator, private NonCopyable
14711470
kAddrSolicitUnrecognizedReason = 6,
14721471
};
14731472

1474-
#if OPENTHREAD_FTD
1475-
enum UpdateRouterRoleAllowedReason : uint8_t // Used in `UpdateRouterRoleAllowed()`
1476-
{
1477-
kReasonMleInit,
1478-
kReasonDeviceModeChanged,
1479-
kReasonConfigParameterChanged,
1480-
kReasonSecurityPolicyChanged,
1481-
};
1482-
#endif
1483-
14841473
enum MessageAction : uint8_t
14851474
{
14861475
kMessageSend,
@@ -2214,61 +2203,111 @@ class Mle : public InstanceLocator, private NonCopyable
22142203
class RoleTransitioner
22152204
{
22162205
public:
2217-
enum AddressSolicitState : uint8_t
2218-
{
2219-
kAddressSolicitStateIdle,
2220-
kAddressSolicitStatePending,
2221-
kAddressSolicitStateRejected,
2222-
};
2223-
22242206
explicit RoleTransitioner(void);
22252207

2208+
bool IsAddressSolicitPending(void) const { return mTransitionerState == kChildAddressSolicitStatePending; }
2209+
bool IsDowngradeBlocked(void) const { return mTransitionerState == kRouterDowngradeBlocked; }
22262210
bool IsRouterEligible(void) const { return mRouterEligible; }
22272211
bool IsRouterRoleAllowed(void) const { return mRouterRoleAllowed; }
2228-
bool IsTransitionPending(void) const { return (mTimeout != 0); }
2229-
bool IsDowngradeBlocked(void) const { return mDowngradeBlocked; }
2212+
bool IsTransitionPending(void) const;
2213+
2214+
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2215+
bool IsCcmEnabled(void) const { return mCcmEnabled; }
2216+
bool IsThreadVersionCheckEnabled(void) const { return mThreadVersionCheckEnabled; }
2217+
#endif
22302218

22312219
bool IsRouterCountBelowUpgradeThreshold(uint8_t aCount) const { return aCount < mUpgradeThreshold; }
2232-
bool IsRouterCountAboveDowngradeThreshold(uint8_t aCount) const { return aCount > mDowngradeThreshold; }
2233-
bool MayDowngrade(uint8_t aRouterCount, uint16_t aValidChildren) const;
2234-
bool MayTransitionRoleSoon(void) const;
2220+
2221+
bool MayBeginReedAdvertisments(void) const;
2222+
bool MayBeginDowngradeTimer(uint8_t aRouterCount, uint16_t aValidChildren) const;
2223+
bool MayCompleteTimedDowngrade(uint8_t aRouterCount) const;
2224+
bool MayUpgrade(uint8_t aRouterCount) const;
2225+
bool MayBecomeRouterSoon(void) const;
22352226

22362227
uint8_t GetTimeout(void) const { return mTimeout; }
22372228
uint8_t GetJitter(void) const { return mJitter; }
22382229
uint8_t GetUpgradeThreshold(void) const { return mUpgradeThreshold; }
22392230
uint8_t GetDowngradeThreshold(void) const { return mDowngradeThreshold; }
22402231

2241-
AddressSolicitState GetAddressSolicitState(void) { return mAddressSolicitState; }
2242-
2243-
void SetAddressSolicitState(AddressSolicitState aState) { mAddressSolicitState = aState; }
2244-
2245-
bool SetRouterEligibleAndGetChanged(bool aStatus);
2246-
bool SetRouterRoleAllowedAndGetChanged(bool aStatus);
2247-
22482232
void SetJitter(uint8_t aJitter) { mJitter = aJitter; }
22492233
void SetUpgradeThreshold(uint8_t aThreshold) { mUpgradeThreshold = aThreshold; }
22502234
void SetDowngradeThreshold(uint8_t aThreshold) { mDowngradeThreshold = aThreshold; }
2251-
void SetDowngradeBlocked(bool aBlocked) { mDowngradeBlocked = aBlocked; }
22522235

2253-
void StartTimeout(void);
2254-
void StopTimeout(void) { mTimeout = 0; }
2255-
void IncreaseTimeout(uint8_t aIncrement) { mTimeout += aIncrement; }
2236+
void HandleTimeTick(void) { mTimeout = (mTimeout > 0) ? mTimeout - 1 : mTimeout; }
2237+
2238+
// ------------------------
2239+
// State transition signals
2240+
void SignalAddressSolicitFinished(void);
2241+
void SignalAddressSolicitPending(void) { mTransitionerState = kChildAddressSolicitStatePending; }
2242+
void SignalAddressSolicitRejected(void) { mTransitionerState = kChildAddressSolicitStateRejected; }
2243+
void SignalBeginTimedRouterDowngrade(void);
2244+
void SignalChildUpgradeStart(void);
2245+
void SignalDowngradeAborted(void);
2246+
void SignalDowngradeBlocked(bool aShouldBlock);
2247+
void SignalRoleChanged(DeviceRole aRole);
2248+
void SignalUpgradeAttemptFailed(void) { mTransitionerState = kChildIdle; }
2249+
2250+
// ------------------------
2251+
// State transition signals affecting the Router role allowed status
2252+
void SignalFtdModeChanged(bool aIsFtdMode);
2253+
void SignalRouterEligible(bool aEligible);
2254+
void SignalRouterRoleAllowedBySecurityPolicy(bool aAllowed);
22562255

2257-
bool HandleTimeTick(void);
2258-
void StartUpgradeIfConditionsAllow(uint8_t aRouterCount);
2256+
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2257+
void SetCcmEnabled(bool aCcmEnabled) { mCcmEnabled = aCcmEnabled; }
2258+
void SetThreadVersionCheckEnabled(bool aThreadVersionCheckEnabled)
2259+
{
2260+
mThreadVersionCheckEnabled = aThreadVersionCheckEnabled;
2261+
}
2262+
#endif
2263+
2264+
// ---------------------------------------------------
2265+
// State transition signals with state change feedback
2266+
2267+
// Polling signals that may result in a transition
2268+
void StartRouterUpgradeIfConditionsAllow(uint8_t aRouterCount);
22592269

22602270
private:
2271+
/** Transition substates of @ref DeviceRole */
2272+
enum RoleTransitionerState : uint8_t
2273+
{
2274+
kInit,
2275+
kDetached,
2276+
kChildIdle,
2277+
kChildUpgradeTimerStarted,
2278+
kChildAddressSolicitStatePending,
2279+
kChildAddressSolicitStateRejected,
2280+
kRouterIdle,
2281+
kRouterDowngradeBlocked, ///< Downgrades from the Router role are blocked
2282+
kRouterDowngradeTimerStarted, ///< The downgrade timer has been started
2283+
kRouterDisallowedTimerStarted,
2284+
kLeaderIdle,
2285+
kLeaderDisallowedTimerStarted,
2286+
};
2287+
2288+
void BeginTimer(void);
2289+
void BeginLeaderDowngradeTimer(void);
2290+
void SignalRouterRoleAllowedUpdate(void);
2291+
22612292
static constexpr uint8_t kMaxDelayToTransitionSoon = 10;
22622293

2263-
static constexpr uint8_t kRouterSelectionJitterDefault = 120; // (in sec)
2294+
static constexpr uint8_t kRouterSelectionJitterDefault = 120; ///< (in sec)
2295+
static constexpr uint8_t kLeaderDowngradeExtraDelay = 10; ///< Extra delay to downgrade leader (in sec).
2296+
22642297
static constexpr uint8_t kRouterUpgradeThresholdDefault = 16;
22652298
static constexpr uint8_t kRouterDowngradeThresholdDefault = 23;
22662299

2267-
bool mDowngradeBlocked : 1;
2268-
bool mRouterEligible : 1;
2269-
bool mRouterRoleAllowed : 1;
2300+
// Router Role Allowed statuses
2301+
bool mRouterRoleAllowed : 1; ///< Cached state of the router role allowed status
2302+
bool mRouterEligible : 1; ///< Router Eligible configuration affecting the role allowed status
2303+
bool mUsingFtdMode : 1; ///< FTD mode
2304+
bool mRouterRoleAllowedBySecurityPolicy : 1; ///< Cached state of the security policy router role allowed status
2305+
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2306+
bool mCcmEnabled : 1; ///< Whether to allow the security policy CCM commissioned check
2307+
bool mThreadVersionCheckEnabled : 1; ///< Whether to allow the security policy version check
2308+
#endif
22702309

2271-
AddressSolicitState mAddressSolicitState;
2310+
RoleTransitionerState mTransitionerState;
22722311

22732312
uint8_t mTimeout;
22742313
uint8_t mJitter;
@@ -2460,8 +2499,8 @@ class Mle : public InstanceLocator, private NonCopyable
24602499
void ClearAlternateRloc16(void);
24612500
uint8_t SelectLeaderId(void) const;
24622501
uint32_t SelectPartitionId(void) const;
2463-
bool DetermineIfRouterRoleAllowed(void) const;
2464-
void UpdateRouterRoleAllowed(UpdateRouterRoleAllowedReason aReason);
2502+
void HandleRouterRoleAllowedFromSecurityPolicy(void);
2503+
void HandleRoleAllowedChangedFromConfig(void);
24652504
void DetermineConnectivity(Connectivity &aConnectivity) const;
24662505
void HandleDetachStart(void);
24672506
void HandleChildStart(void);
@@ -2509,7 +2548,7 @@ class Mle : public InstanceLocator, private NonCopyable
25092548
void SetChildStateToValid(Child &aChild);
25102549
bool HasChildren(void);
25112550
void RemoveChildren(void);
2512-
bool ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const;
2551+
void CheckOrBeginRouterDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv);
25132552
bool NeighborHasComparableConnectivity(const RouteTlv &aRouteTlv, uint8_t aNeighborId) const;
25142553
void HandleAdvertiseTrickleTimer(void);
25152554
void HandleTimeTick(void);
@@ -2589,10 +2628,6 @@ class Mle : public InstanceLocator, private NonCopyable
25892628

25902629
#if OPENTHREAD_FTD
25912630

2592-
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
2593-
bool mCcmEnabled : 1;
2594-
bool mThreadVersionCheckEnabled : 1;
2595-
#endif
25962631
uint8_t mRouterId;
25972632
uint8_t mPreviousRouterId;
25982633
uint8_t mNetworkIdTimeout;

0 commit comments

Comments
 (0)