Skip to content

Commit a1c1291

Browse files
[mle] Refactor RoleTransitioner for a state-driven design
1 parent ca52657 commit a1c1291

3 files changed

Lines changed: 355 additions & 207 deletions

File tree

src/core/thread/mle.cpp

Lines changed: 8 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,7 @@ void Mle::SetStateDetached(void)
599595
Get<MeshForwarder>().SetRxOnWhenIdle(true);
600596
Get<Mac::Mac>().SetBeaconEnabled(false);
601597
#if OPENTHREAD_FTD
602-
mRoleTransitioner.SetDowngradeBlocked(false);
598+
mRoleTransitioner.SignalDowngradeBlocked(false);
603599
ClearAlternateRloc16();
604600
HandleDetachStart();
605601
#endif
@@ -720,7 +716,7 @@ Error Mle::SetDeviceMode(DeviceMode aDeviceMode)
720716
ClearAlternateRloc16();
721717
}
722718

723-
UpdateRouterRoleAllowed(kReasonDeviceModeChanged);
719+
mRoleTransitioner.SignalFtdModeChanged(IsFullThreadDevice());
724720
#endif
725721

726722
if (IsAttached())
@@ -1045,7 +1041,7 @@ void Mle::HandleNotifierEvents(Events aEvents)
10451041
#if OPENTHREAD_FTD
10461042
if (aEvents.Contains(kEventSecurityPolicyChanged))
10471043
{
1048-
UpdateRouterRoleAllowed(kReasonSecurityPolicyChanged);
1044+
HandleRouterRoleAllowedFromSecurityPolicy();
10491045
}
10501046

10511047
if (mRoleTransitioner.IsDowngradeBlocked() && aEvents.Contains(kEventThreadChildRemoved))
@@ -1061,7 +1057,7 @@ void Mle::HandleNotifierEvents(Events aEvents)
10611057
}
10621058
}
10631059

1064-
mRoleTransitioner.SetDowngradeBlocked(shouldBlock);
1060+
mRoleTransitioner.SignalDowngradeBlocked(shouldBlock);
10651061
}
10661062
#endif
10671063

src/core/thread/mle.hpp

Lines changed: 85 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,6 @@ class Mle : public InstanceLocator, private NonCopyable
769769
* @param[in] aEligible TRUE to configure device router-eligible, FALSE otherwise.
770770
*
771771
* @retval kErrorNone Successfully set the router-eligible configuration.
772-
* @retval kErrorNotCapable The device is not capable of becoming a router.
773772
*/
774773
Error SetRouterEligible(bool aEligible);
775774

@@ -1022,7 +1021,7 @@ class Mle : public InstanceLocator, private NonCopyable
10221021
* @retval TRUE If the REED is going to become a Router soon.
10231022
* @retval FALSE If the REED is not going to become a Router soon.
10241023
*/
1025-
bool MayBecomeRouterSoon(void) const { return IsChild() && mRoleTransitioner.MayTransitionRoleSoon(); }
1024+
bool MayBecomeRouterSoon(void) const { return mRoleTransitioner.MayBecomeRouterSoon(); }
10261025

10271026
/**
10281027
* Removes a link to a neighbor.
@@ -1346,7 +1345,6 @@ class Mle : public InstanceLocator, private NonCopyable
13461345
static constexpr uint8_t kNetworkIdTimeout = 120; // (in sec)
13471346
static constexpr uint16_t kDiscoveryMaxJitter = 250; // Max jitter delay Discovery Responses (in msec).
13481347
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).
13501348
static constexpr uint8_t kDefaultLeaderWeight = 64;
13511349
static constexpr uint8_t kAlternateRloc16Timeout = 8; // Time to use alternate RLOC16 (in sec).
13521350

@@ -1471,16 +1469,6 @@ class Mle : public InstanceLocator, private NonCopyable
14711469
kAddrSolicitUnrecognizedReason = 6,
14721470
};
14731471

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-
14841472
enum MessageAction : uint8_t
14851473
{
14861474
kMessageSend,
@@ -2214,61 +2202,112 @@ class Mle : public InstanceLocator, private NonCopyable
22142202
class RoleTransitioner
22152203
{
22162204
public:
2217-
enum AddressSolicitState : uint8_t
2218-
{
2219-
kAddressSolicitStateIdle,
2220-
kAddressSolicitStatePending,
2221-
kAddressSolicitStateRejected,
2222-
};
2223-
22242205
explicit RoleTransitioner(void);
22252206

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

22312218
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;
2219+
2220+
bool MayBeginReedAdvertisments(void) const;
2221+
bool MayBeginDowngradeTimer(uint8_t aRouterCount, uint16_t aValidChildren) const;
2222+
bool MayCompleteTimedDowngrade(uint8_t aRouterCount) const;
2223+
bool MayUpgrade(uint8_t aRouterCount) const;
2224+
bool MayBecomeRouterSoon(void) const;
22352225

22362226
uint8_t GetTimeout(void) const { return mTimeout; }
22372227
uint8_t GetJitter(void) const { return mJitter; }
22382228
uint8_t GetUpgradeThreshold(void) const { return mUpgradeThreshold; }
22392229
uint8_t GetDowngradeThreshold(void) const { return mDowngradeThreshold; }
22402230

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-
22482231
void SetJitter(uint8_t aJitter) { mJitter = aJitter; }
22492232
void SetUpgradeThreshold(uint8_t aThreshold) { mUpgradeThreshold = aThreshold; }
22502233
void SetDowngradeThreshold(uint8_t aThreshold) { mDowngradeThreshold = aThreshold; }
2251-
void SetDowngradeBlocked(bool aBlocked) { mDowngradeBlocked = aBlocked; }
22522234

2253-
void StartTimeout(void);
2254-
void StopTimeout(void) { mTimeout = 0; }
2255-
void IncreaseTimeout(uint8_t aIncrement) { mTimeout += aIncrement; }
2235+
void HandleTimeTick(void) { mTimeout = (mTimeout > 0) ? mTimeout - 1 : mTimeout; }
2236+
2237+
// ------------------------
2238+
// State transition signals
2239+
void SignalAddressSolicitFinished(void);
2240+
void SignalAddressSolicitPending(void) { mTransitionerState = kChildAddressSolicitStatePending; }
2241+
void SignalAddressSolicitRejected(void) { mTransitionerState = kChildAddressSolicitStateRejected; }
2242+
void SignalBeginTimedRouterDowngrade(void);
2243+
void SignalChildUpgradeStart(void);
2244+
void SignalDowngradeBlocked(bool aShouldBlock);
2245+
void SignalLeaderDowngradeAborted(void) { mTransitionerState = kLeaderIdle; }
2246+
void SignalRoleChanged(DeviceRole aRole);
2247+
void SignalRouterDowngradeAborted(void) { mTransitionerState = kRouterIdle; }
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)