mirror of
https://github.com/espressif/openthread.git
synced 2026-10-08 08:47:38 +00:00
[mle] introduce PrevRoleRestorer to manage role restoration (#11731)
This commit introduces `Mle::PrevRoleRestorer` to consolidate the logic for restoring a device's previous role (child or router/leader) after an MLE restart. This new class replaces and encapsulates the functionality from the now-removed `RouterRoleRestorer` class and `RestorePrevRole()` method. `PrevRoleRestorer` manages its own timer and retransmission logic. It handles sending Child Update Requests to restore a child role, or multicast Link Requests to restore a router/leader role. It also adds a small random delay before the first transmission attempt to avoid synchronized transmissions when multiple devices restart at once. This change simplifies the `Mle` class by centralizing all role restoration logic into a single component, making future enhancements to this process easier.
This commit is contained in:
+156
-54
@@ -74,6 +74,7 @@ Mle::Mle(Instance &aInstance)
|
|||||||
, mNeighborTable(aInstance)
|
, mNeighborTable(aInstance)
|
||||||
, mDelayedSender(aInstance)
|
, mDelayedSender(aInstance)
|
||||||
, mSocket(aInstance, *this)
|
, mSocket(aInstance, *this)
|
||||||
|
, mPrevRoleRestorer(aInstance)
|
||||||
, mDetacher(aInstance)
|
, mDetacher(aInstance)
|
||||||
, mRetxTracker(aInstance)
|
, mRetxTracker(aInstance)
|
||||||
, mAnnounceHandler(aInstance)
|
, mAnnounceHandler(aInstance)
|
||||||
@@ -114,7 +115,6 @@ Mle::Mle(Instance &aInstance)
|
|||||||
, mAdvertiseTrickleTimer(aInstance, Mle::HandleAdvertiseTrickleTimer)
|
, mAdvertiseTrickleTimer(aInstance, Mle::HandleAdvertiseTrickleTimer)
|
||||||
, mChildTable(aInstance)
|
, mChildTable(aInstance)
|
||||||
, mRouterTable(aInstance)
|
, mRouterTable(aInstance)
|
||||||
, mRouterRoleRestorer(aInstance)
|
|
||||||
#endif // OPENTHREAD_FTD
|
#endif // OPENTHREAD_FTD
|
||||||
{
|
{
|
||||||
mParent.Init(aInstance);
|
mParent.Init(aInstance);
|
||||||
@@ -231,7 +231,7 @@ Error Mle::Start(StartMode aMode)
|
|||||||
mReattachState =
|
mReattachState =
|
||||||
(Get<MeshCoP::ActiveDatasetManager>().Restore() == kErrorNone) ? kReattachActive : kReattachStop;
|
(Get<MeshCoP::ActiveDatasetManager>().Restore() == kErrorNone) ? kReattachActive : kReattachStop;
|
||||||
|
|
||||||
if (RestorePrevRole() == kErrorNone)
|
if (mPrevRoleRestorer.Start() == kErrorNone)
|
||||||
{
|
{
|
||||||
ExitNow();
|
ExitNow();
|
||||||
}
|
}
|
||||||
@@ -258,6 +258,7 @@ void Mle::Stop(StopMode aMode)
|
|||||||
VerifyOrExit(!IsDisabled());
|
VerifyOrExit(!IsDisabled());
|
||||||
|
|
||||||
mDelayedSender.Stop();
|
mDelayedSender.Stop();
|
||||||
|
mPrevRoleRestorer.Stop();
|
||||||
mAnnounceHandler.Stop();
|
mAnnounceHandler.Stop();
|
||||||
Get<KeyManager>().Stop();
|
Get<KeyManager>().Stop();
|
||||||
SetStateDetached();
|
SetStateDetached();
|
||||||
@@ -266,54 +267,12 @@ void Mle::Stop(StopMode aMode)
|
|||||||
Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocalRloc);
|
Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocalRloc);
|
||||||
Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocalEid);
|
Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocalEid);
|
||||||
|
|
||||||
#if OPENTHREAD_FTD
|
|
||||||
mRouterRoleRestorer.Stop();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SetRole(kRoleDisabled);
|
SetRole(kRoleDisabled);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
mDetacher.HandleStop();
|
mDetacher.HandleStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error Mle::RestorePrevRole(void)
|
|
||||||
{
|
|
||||||
// Restores the device to its previously saved role after MLE
|
|
||||||
// start.
|
|
||||||
//
|
|
||||||
// Returns `kErrorNone` if the restoration process begins
|
|
||||||
// successfully. An error is returned if:
|
|
||||||
// - No previous role was saved.
|
|
||||||
// - The saved role info is inconsistent (e.g., RLOC16 indicates a
|
|
||||||
// router/leader, but `mLastSavedRole` doesn't match).
|
|
||||||
// - The last role is "Child," but no valid parent is available.
|
|
||||||
|
|
||||||
Error error = kErrorFailed;
|
|
||||||
|
|
||||||
VerifyOrExit(IsDetached());
|
|
||||||
VerifyOrExit(GetRloc16() != kInvalidRloc16);
|
|
||||||
|
|
||||||
if (IsRouterRloc16(GetRloc16()))
|
|
||||||
{
|
|
||||||
#if OPENTHREAD_FTD
|
|
||||||
VerifyOrExit(mLastSavedRole == kRoleRouter || mLastSavedRole == kRoleLeader);
|
|
||||||
VerifyOrExit(IsRouterEligible());
|
|
||||||
Get<MeshForwarder>().SetRxOnWhenIdle(true);
|
|
||||||
mRouterRoleRestorer.Start(mLastSavedRole);
|
|
||||||
error = kErrorNone;
|
|
||||||
#endif
|
|
||||||
ExitNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
VerifyOrExit(mLastSavedRole == kRoleChild);
|
|
||||||
VerifyOrExit(mParent.IsStateValidOrRestoring());
|
|
||||||
IgnoreError(SendChildUpdateRequestToParent());
|
|
||||||
error = kErrorNone;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Counters &Mle::GetCounters(void)
|
const Counters &Mle::GetCounters(void)
|
||||||
{
|
{
|
||||||
UpdateRoleTimeCounters(mRole);
|
UpdateRoleTimeCounters(mRole);
|
||||||
@@ -789,6 +748,7 @@ void Mle::SetStateChild(uint16_t aRloc16)
|
|||||||
mReattachState = kReattachStop;
|
mReattachState = kReattachStop;
|
||||||
Get<Mac::Mac>().SetBeaconEnabled(false);
|
Get<Mac::Mac>().SetBeaconEnabled(false);
|
||||||
mRetxTracker.UpdateOnRoleChangeToChild();
|
mRetxTracker.UpdateOnRoleChangeToChild();
|
||||||
|
mPrevRoleRestorer.Stop();
|
||||||
|
|
||||||
#if OPENTHREAD_FTD
|
#if OPENTHREAD_FTD
|
||||||
if (IsFullThreadDevice())
|
if (IsFullThreadDevice())
|
||||||
@@ -1471,14 +1431,6 @@ void Mle::HandleAttachTimer(void)
|
|||||||
bool shouldAnnounce = true;
|
bool shouldAnnounce = true;
|
||||||
ParentRequestType type;
|
ParentRequestType type;
|
||||||
|
|
||||||
#if OPENTHREAD_FTD
|
|
||||||
if (IsDetached() && mRouterRoleRestorer.IsActive())
|
|
||||||
{
|
|
||||||
mRouterRoleRestorer.HandleTimer();
|
|
||||||
ExitNow();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// First, check if we are waiting to receive parent responses and
|
// First, check if we are waiting to receive parent responses and
|
||||||
// found an acceptable parent candidate.
|
// found an acceptable parent candidate.
|
||||||
|
|
||||||
@@ -1938,11 +1890,19 @@ Error Mle::SendChildUpdateRequestToParent(ChildUpdateRequestMode aMode)
|
|||||||
mDelayedSender.RemoveScheduledChildUpdateRequestToParent();
|
mDelayedSender.RemoveScheduledChildUpdateRequestToParent();
|
||||||
|
|
||||||
// Track Child Update retx, except when gracefully detaching
|
// Track Child Update retx, except when gracefully detaching
|
||||||
// i.e., sending Child Update with zero timeout.
|
// i.e., sending Child Update with zero timeout, or restoring
|
||||||
|
// previous child role (re-establishing link with parent).
|
||||||
|
|
||||||
if (aMode != kAppendZeroTimeout)
|
switch (aMode)
|
||||||
{
|
{
|
||||||
|
case kNormalChildUpdateRequest:
|
||||||
|
case kAppendChallengeTlv:
|
||||||
mRetxTracker.UpdateOnChildUpdateRequestTx();
|
mRetxTracker.UpdateOnChildUpdateRequestTx();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kAppendZeroTimeout:
|
||||||
|
case kToRestoreChildRole:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
VerifyOrExit((message = NewMleMessage(kCommandChildUpdateRequest)) != nullptr, error = kErrorNoBufs);
|
VerifyOrExit((message = NewMleMessage(kCommandChildUpdateRequest)) != nullptr, error = kErrorNoBufs);
|
||||||
@@ -5330,6 +5290,148 @@ void Mle::ParentCandidate::CopyTo(Parent &aParent) const
|
|||||||
aParent = *candidateAsParent;
|
aParent = *candidateAsParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
// PrevRoleRestorer
|
||||||
|
|
||||||
|
Mle::PrevRoleRestorer::PrevRoleRestorer(Instance &aInstance)
|
||||||
|
: InstanceLocator(aInstance)
|
||||||
|
, mState(kIdle)
|
||||||
|
, mAttempts(0)
|
||||||
|
, mTimer(aInstance)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Error Mle::PrevRoleRestorer::Start(void)
|
||||||
|
{
|
||||||
|
// Starts the process of restoring the device to its previously
|
||||||
|
// saved role after MLE start.
|
||||||
|
//
|
||||||
|
// Returns `kErrorNone` if the restoration process begins
|
||||||
|
// successfully. An error is returned if:
|
||||||
|
// - No previous role was saved.
|
||||||
|
// - The saved role info is inconsistent (e.g., RLOC16 indicates a
|
||||||
|
// router/leader, but `mLastSavedRole` doesn't match).
|
||||||
|
|
||||||
|
Error error = kErrorFailed;
|
||||||
|
|
||||||
|
mState = kIdle;
|
||||||
|
mAttempts = 0;
|
||||||
|
VerifyOrExit(Get<Mle>().IsDetached());
|
||||||
|
VerifyOrExit(Get<Mle>().GetRloc16() != kInvalidRloc16);
|
||||||
|
|
||||||
|
if (IsRouterRloc16(Get<Mle>().GetRloc16()))
|
||||||
|
{
|
||||||
|
#if OPENTHREAD_FTD
|
||||||
|
VerifyOrExit((Get<Mle>().mLastSavedRole == kRoleRouter) || (Get<Mle>().mLastSavedRole == kRoleLeader));
|
||||||
|
VerifyOrExit(Get<Mle>().IsRouterEligible());
|
||||||
|
|
||||||
|
Get<MeshForwarder>().SetRxOnWhenIdle(true);
|
||||||
|
SetState(kRestoringRouterOrLeaderRole);
|
||||||
|
DetermineMaxLinkRequestAttempts();
|
||||||
|
mTimer.Start(Get<Mle>().GenerateRandomDelay(kMaxStartDelay));
|
||||||
|
error = kErrorNone;
|
||||||
|
#endif
|
||||||
|
ExitNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
VerifyOrExit(Get<Mle>().mLastSavedRole == kRoleChild);
|
||||||
|
VerifyOrExit(Get<Mle>().mParent.IsStateValidOrRestoring());
|
||||||
|
SetState(kRestoringChildRole);
|
||||||
|
mAttempts = kMaxChildUpdatesToRestoreRole;
|
||||||
|
mTimer.Start(Get<Mle>().GenerateRandomDelay(kMaxStartDelay));
|
||||||
|
error = kErrorNone;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mle::PrevRoleRestorer::Stop(void)
|
||||||
|
{
|
||||||
|
SetState(kIdle);
|
||||||
|
mTimer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mle::PrevRoleRestorer::SetState(State aState)
|
||||||
|
{
|
||||||
|
mState = aState;
|
||||||
|
|
||||||
|
if (mState != kIdle)
|
||||||
|
{
|
||||||
|
LogInfo("Attempting to restore prev role: %s", RoleToString(Get<Mle>().mLastSavedRole));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mle::PrevRoleRestorer::HandleTimer(void)
|
||||||
|
{
|
||||||
|
VerifyOrExit(mState != kIdle);
|
||||||
|
|
||||||
|
if (!Get<Mle>().IsDetached())
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
ExitNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAttempts == 0)
|
||||||
|
{
|
||||||
|
LogInfo("Failed to restore prev role");
|
||||||
|
Stop();
|
||||||
|
IgnoreError(Get<Mle>().BecomeDetached());
|
||||||
|
ExitNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
mAttempts--;
|
||||||
|
|
||||||
|
#if OPENTHREAD_FTD
|
||||||
|
if (mState == kRestoringRouterOrLeaderRole)
|
||||||
|
{
|
||||||
|
SendMulticastLinkRequest();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
SendChildUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mle::PrevRoleRestorer::SendChildUpdate(void)
|
||||||
|
{
|
||||||
|
mTimer.Start(Random::NonCrypto::AddJitter(kChildUpdateRetxDelay, kRetxJitter));
|
||||||
|
|
||||||
|
LogDebg("Sending Child Update Request to restore child role, remaining attempts: %u", mAttempts);
|
||||||
|
IgnoreError(Get<Mle>().SendChildUpdateRequestToParent(kToRestoreChildRole));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if OPENTHREAD_FTD
|
||||||
|
|
||||||
|
void Mle::PrevRoleRestorer::DetermineMaxLinkRequestAttempts(void)
|
||||||
|
{
|
||||||
|
mAttempts = kMaxCriticalTxCount;
|
||||||
|
|
||||||
|
if ((Get<Mle>().mLastSavedRole == kRoleRouter) &&
|
||||||
|
(Get<Mle>().mChildTable.GetNumChildren(Child::kInStateValidOrRestoring) < kMinCriticalChildrenCount))
|
||||||
|
{
|
||||||
|
mAttempts = kMaxTxCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mle::PrevRoleRestorer::SendMulticastLinkRequest(void)
|
||||||
|
{
|
||||||
|
uint32_t delay;
|
||||||
|
|
||||||
|
delay = (mAttempts == 0) ? kLinkRequestTimeout
|
||||||
|
: Random::NonCrypto::GetUint32InRange(kMulticastRetxDelayMin, kMulticastRetxDelayMax);
|
||||||
|
|
||||||
|
mTimer.Start(delay);
|
||||||
|
|
||||||
|
LogDebg("Sending multicast Link Request to restore role, remaining attempts: %u", mAttempts);
|
||||||
|
Get<Mle>().SendLinkRequest(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENTHREAD_FTD
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
// Detacher
|
// Detacher
|
||||||
|
|
||||||
|
|||||||
+79
-39
@@ -1356,6 +1356,7 @@ private:
|
|||||||
kNormalChildUpdateRequest, // Normal Child Update Request.
|
kNormalChildUpdateRequest, // Normal Child Update Request.
|
||||||
kAppendChallengeTlv, // Append Challenge TLV to Child Update Request even if currently attached.
|
kAppendChallengeTlv, // Append Challenge TLV to Child Update Request even if currently attached.
|
||||||
kAppendZeroTimeout, // Use zero timeout when appending Timeout TLV (used for graceful detach).
|
kAppendZeroTimeout, // Use zero timeout when appending Timeout TLV (used for graceful detach).
|
||||||
|
kToRestoreChildRole, // To restore previous child role (upon restart), re-establishing link with parent.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SecuritySuite : uint8_t
|
enum SecuritySuite : uint8_t
|
||||||
@@ -1717,6 +1718,71 @@ private:
|
|||||||
|
|
||||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
void HandleRoleRestorerTimer(void) { mPrevRoleRestorer.HandleTimer(); }
|
||||||
|
|
||||||
|
class PrevRoleRestorer : public InstanceLocator
|
||||||
|
{
|
||||||
|
// Attempts to restore the device's previously saved role
|
||||||
|
// (child/router/leader) after an MLE restart (e.g., after a
|
||||||
|
// device reboot).
|
||||||
|
//
|
||||||
|
// If the previous role was router/leader, it sends multicast
|
||||||
|
// Link Requests. If the role was child, it sends Child
|
||||||
|
// Update Requests to the parent. It manages message
|
||||||
|
// retransmissions and stops the restoration attempt if the
|
||||||
|
// maximum number of attempts is exhausted, setting the
|
||||||
|
// device to a detached state.
|
||||||
|
//
|
||||||
|
// To prevent synchronized transmissions when multiple devices
|
||||||
|
// reboot at once, it adds a random delay (up to 25 ms)
|
||||||
|
// before sending the first message.
|
||||||
|
|
||||||
|
public:
|
||||||
|
PrevRoleRestorer(Instance &aInstance);
|
||||||
|
|
||||||
|
Error Start(void);
|
||||||
|
void Stop(void);
|
||||||
|
bool IsRestoringChildRole(void) const { return mState == kRestoringChildRole; }
|
||||||
|
bool IsRestoringRouterOrLeaderRole(void) const { return mState == kRestoringRouterOrLeaderRole; }
|
||||||
|
void HandleTimer(void);
|
||||||
|
|
||||||
|
#if OPENTHREAD_FTD
|
||||||
|
void GenerateRandomChallenge(void) { mChallenge.GenerateRandom(); }
|
||||||
|
const TxChallenge &GetChallenge(void) const { return mChallenge; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr uint32_t kMaxStartDelay = 25;
|
||||||
|
static constexpr uint8_t kMaxChildUpdatesToRestoreRole = kMaxChildKeepAliveAttempts;
|
||||||
|
static constexpr uint32_t kChildUpdateRetxDelay = kUnicastRetxDelay; /// 1000 msec
|
||||||
|
static constexpr uint16_t kRetxJitter = 5;
|
||||||
|
|
||||||
|
enum State : uint8_t
|
||||||
|
{
|
||||||
|
kIdle,
|
||||||
|
kRestoringChildRole,
|
||||||
|
kRestoringRouterOrLeaderRole,
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetState(State aState);
|
||||||
|
void SendChildUpdate(void);
|
||||||
|
#if OPENTHREAD_FTD
|
||||||
|
void DetermineMaxLinkRequestAttempts(void);
|
||||||
|
void SendMulticastLinkRequest(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using DelayTimer = TimerMilliIn<Mle, &Mle::HandleRoleRestorerTimer>;
|
||||||
|
|
||||||
|
State mState;
|
||||||
|
uint8_t mAttempts;
|
||||||
|
DelayTimer mTimer;
|
||||||
|
#if OPENTHREAD_FTD
|
||||||
|
TxChallenge mChallenge;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
void HandleDetacherTimer(void) { mDetacher.HandleTimer(); }
|
void HandleDetacherTimer(void) { mDetacher.HandleTimer(); }
|
||||||
|
|
||||||
class Detacher : public InstanceLocator
|
class Detacher : public InstanceLocator
|
||||||
@@ -1943,33 +2009,7 @@ private:
|
|||||||
uint8_t mJitter;
|
uint8_t mJitter;
|
||||||
};
|
};
|
||||||
|
|
||||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
#endif
|
||||||
|
|
||||||
class RouterRoleRestorer : public InstanceLocator
|
|
||||||
{
|
|
||||||
// Attempts to restore the router or leader role after an MLE
|
|
||||||
// restart(e.g., after a device reboot) by sending multicast
|
|
||||||
// Link Requests.
|
|
||||||
|
|
||||||
public:
|
|
||||||
RouterRoleRestorer(Instance &aInstance);
|
|
||||||
|
|
||||||
bool IsActive(void) const { return mAttempts > 0; }
|
|
||||||
void Start(DeviceRole aPreviousRole);
|
|
||||||
void Stop(void) { mAttempts = 0; }
|
|
||||||
void HandleTimer(void);
|
|
||||||
|
|
||||||
void GenerateRandomChallenge(void) { mChallenge.GenerateRandom(); }
|
|
||||||
const TxChallenge &GetChallenge(void) const { return mChallenge; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SendMulticastLinkRequest(void);
|
|
||||||
|
|
||||||
uint8_t mAttempts;
|
|
||||||
TxChallenge mChallenge;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // OPENTHREAD_FTD
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------
|
||||||
// Methods
|
// Methods
|
||||||
@@ -2224,17 +2264,18 @@ private:
|
|||||||
uint32_t mLastAttachTime;
|
uint32_t mLastAttachTime;
|
||||||
uint64_t mLastUpdatedTimestamp;
|
uint64_t mLastUpdatedTimestamp;
|
||||||
|
|
||||||
LeaderData mLeaderData;
|
LeaderData mLeaderData;
|
||||||
Parent mParent;
|
Parent mParent;
|
||||||
NeighborTable mNeighborTable;
|
NeighborTable mNeighborTable;
|
||||||
DelayedSender mDelayedSender;
|
DelayedSender mDelayedSender;
|
||||||
TxChallenge mParentRequestChallenge;
|
TxChallenge mParentRequestChallenge;
|
||||||
ParentCandidate mParentCandidate;
|
ParentCandidate mParentCandidate;
|
||||||
MleSocket mSocket;
|
MleSocket mSocket;
|
||||||
Counters mCounters;
|
Counters mCounters;
|
||||||
Detacher mDetacher;
|
PrevRoleRestorer mPrevRoleRestorer;
|
||||||
RetxTracker mRetxTracker;
|
Detacher mDetacher;
|
||||||
AnnounceHandler mAnnounceHandler;
|
RetxTracker mRetxTracker;
|
||||||
|
AnnounceHandler mAnnounceHandler;
|
||||||
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
|
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
|
||||||
ParentSearch mParentSearch;
|
ParentSearch mParentSearch;
|
||||||
#endif
|
#endif
|
||||||
@@ -2293,7 +2334,6 @@ private:
|
|||||||
TrickleTimer mAdvertiseTrickleTimer;
|
TrickleTimer mAdvertiseTrickleTimer;
|
||||||
ChildTable mChildTable;
|
ChildTable mChildTable;
|
||||||
RouterTable mRouterTable;
|
RouterTable mRouterTable;
|
||||||
RouterRoleRestorer mRouterRoleRestorer;
|
|
||||||
RouterRoleTransition mRouterRoleTransition;
|
RouterRoleTransition mRouterRoleTransition;
|
||||||
Ip6::Netif::UnicastAddress mLeaderAloc;
|
Ip6::Netif::UnicastAddress mLeaderAloc;
|
||||||
#if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
|
#if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
|
||||||
|
|||||||
@@ -392,6 +392,8 @@ void Mle::SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, LeaderStart
|
|||||||
|
|
||||||
SetRole(aRole);
|
SetRole(aRole);
|
||||||
|
|
||||||
|
mPrevRoleRestorer.Stop();
|
||||||
|
|
||||||
SetAttachState(kAttachStateIdle);
|
SetAttachState(kAttachStateIdle);
|
||||||
mAttachCounter = 0;
|
mAttachCounter = 0;
|
||||||
mAttachTimer.Stop();
|
mAttachTimer.Stop();
|
||||||
@@ -595,8 +597,8 @@ void Mle::SendLinkRequest(Router *aRouter)
|
|||||||
|
|
||||||
if (aRouter == nullptr)
|
if (aRouter == nullptr)
|
||||||
{
|
{
|
||||||
mRouterRoleRestorer.GenerateRandomChallenge();
|
mPrevRoleRestorer.GenerateRandomChallenge();
|
||||||
SuccessOrExit(error = message->AppendChallengeTlv(mRouterRoleRestorer.GetChallenge()));
|
SuccessOrExit(error = message->AppendChallengeTlv(mPrevRoleRestorer.GetChallenge()));
|
||||||
destination.SetToLinkLocalAllRoutersMulticast();
|
destination.SetToLinkLocalAllRoutersMulticast();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -866,10 +868,9 @@ void Mle::HandleLinkAcceptVariant(RxInfo &aRxInfo, MessageType aMessageType)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Neighbor::kStateInvalid:
|
case Neighbor::kStateInvalid:
|
||||||
VerifyOrExit(mRouterRoleRestorer.IsActive() && (response == mRouterRoleRestorer.GetChallenge()),
|
VerifyOrExit(mPrevRoleRestorer.IsRestoringRouterOrLeaderRole(), error = kErrorSecurity);
|
||||||
error = kErrorSecurity);
|
VerifyOrExit(response == mPrevRoleRestorer.GetChallenge(), error = kErrorSecurity);
|
||||||
|
break;
|
||||||
OT_FALL_THROUGH;
|
|
||||||
|
|
||||||
case Neighbor::kStateValid:
|
case Neighbor::kStateValid:
|
||||||
break;
|
break;
|
||||||
@@ -927,7 +928,6 @@ void Mle::HandleLinkAcceptVariant(RxInfo &aRxInfo, MessageType aMessageType)
|
|||||||
SetStateRouter(GetRloc16());
|
SetStateRouter(GetRloc16());
|
||||||
}
|
}
|
||||||
|
|
||||||
mRouterRoleRestorer.Stop();
|
|
||||||
mRetrieveNewNetworkData = true;
|
mRetrieveNewNetworkData = true;
|
||||||
IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr()));
|
IgnoreError(SendDataRequest(aRxInfo.mMessageInfo.GetPeerAddr()));
|
||||||
shouldUpdateRoutes = true;
|
shouldUpdateRoutes = true;
|
||||||
@@ -3929,80 +3929,6 @@ exit:
|
|||||||
return expired;
|
return expired;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
// RouterRoleRestorer
|
|
||||||
|
|
||||||
Mle::RouterRoleRestorer::RouterRoleRestorer(Instance &aInstance)
|
|
||||||
: InstanceLocator(aInstance)
|
|
||||||
, mAttempts(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mle::RouterRoleRestorer::Start(DeviceRole aPreviousRole)
|
|
||||||
{
|
|
||||||
// If the device was previously the leader or had more than
|
|
||||||
// `kMinCriticalChildrenCount` children, we use more link
|
|
||||||
// request attempts.
|
|
||||||
|
|
||||||
mAttempts = 0;
|
|
||||||
|
|
||||||
switch (aPreviousRole)
|
|
||||||
{
|
|
||||||
case kRoleRouter:
|
|
||||||
if (Get<Mle>().mChildTable.GetNumChildren(Child::kInStateValidOrRestoring) < kMinCriticalChildrenCount)
|
|
||||||
{
|
|
||||||
mAttempts = kMaxTxCount;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
OT_FALL_THROUGH;
|
|
||||||
|
|
||||||
case kRoleLeader:
|
|
||||||
mAttempts = kMaxCriticalTxCount;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kRoleChild:
|
|
||||||
case kRoleDetached:
|
|
||||||
case kRoleDisabled:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendMulticastLinkRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mle::RouterRoleRestorer::HandleTimer(void)
|
|
||||||
{
|
|
||||||
if (mAttempts > 0)
|
|
||||||
{
|
|
||||||
mAttempts--;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendMulticastLinkRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mle::RouterRoleRestorer::SendMulticastLinkRequest(void)
|
|
||||||
{
|
|
||||||
uint32_t delay;
|
|
||||||
|
|
||||||
VerifyOrExit(Get<Mle>().IsDetached(), mAttempts = 0);
|
|
||||||
|
|
||||||
if (mAttempts == 0)
|
|
||||||
{
|
|
||||||
IgnoreError(Get<Mle>().BecomeDetached());
|
|
||||||
ExitNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
Get<Mle>().SendLinkRequest(nullptr);
|
|
||||||
|
|
||||||
delay = (mAttempts == 1) ? kLinkRequestTimeout
|
|
||||||
: Random::NonCrypto::GetUint32InRange(kMulticastRetxDelayMin, kMulticastRetxDelayMax);
|
|
||||||
|
|
||||||
Get<Mle>().mAttachTimer.Start(delay);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Mle
|
} // namespace Mle
|
||||||
} // namespace ot
|
} // namespace ot
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user