[mle] enhance role restoration logic in Start() (#11679)

This commit refactors `Mle::Start()` by moving the logic for restoring
the previous role into a new method, `RestorePrevRole()`.

This change simplifies the startup process and improves robustness by
adding more validation checks within `RestorePrevRole()`. The new
method ensures that the previously saved state information is
consistent before it is applied. For example, it verifies that
`mLastSavedRole` matches the saved RLOC16 and that parent information
is valid if the saved role was Child. These checks protect against
loading invalid settings and allow the device to start more quickly
by ignoring inconsistent state.
This commit is contained in:
Abtin Keshavarzian
2025-07-08 22:50:40 -07:00
committed by GitHub
parent 6e07db0898
commit 87a919fd0a
2 changed files with 47 additions and 18 deletions
+46 -18
View File
@@ -225,29 +225,23 @@ Error Mle::Start(StartMode aMode)
Get<KeyManager>().Start();
if (aMode == kNormalAttach)
switch (aMode)
{
case kNormalAttach:
mReattachState =
(Get<MeshCoP::ActiveDatasetManager>().Restore() == kErrorNone) ? kReattachActive : kReattachStop;
if (RestorePrevRole() == kErrorNone)
{
ExitNow();
}
break;
case kAnnounceAttach:
break;
}
if ((aMode == kAnnounceAttach) || (GetRloc16() == kInvalidRloc16))
{
Attach(kAnyPartition);
}
#if OPENTHREAD_FTD
else if (IsRouterRloc16(GetRloc16()))
{
if (BecomeRouter(ThreadStatusTlv::kTooFewRouters) != kErrorNone)
{
Attach(kAnyPartition);
}
}
#endif
else
{
IgnoreError(SendChildUpdateRequestToParent());
}
Attach(kAnyPartition);
exit:
return error;
@@ -286,6 +280,40 @@ exit:
}
}
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(GetRloc16() != kInvalidRloc16);
if (IsRouterRloc16(GetRloc16()))
{
#if OPENTHREAD_FTD
VerifyOrExit(mLastSavedRole == kRoleRouter || mLastSavedRole == kRoleLeader);
error = BecomeRouter(ThreadStatusTlv::kTooFewRouters);
#endif
ExitNow();
}
VerifyOrExit(mLastSavedRole == kRoleChild);
VerifyOrExit(mParent.IsStateValidOrRestoring());
IgnoreError(SendChildUpdateRequestToParent());
error = kErrorNone;
exit:
return error;
}
const Counters &Mle::GetCounters(void)
{
UpdateRoleTimeCounters(mRole);
+1
View File
@@ -1958,6 +1958,7 @@ private:
Error Start(StartMode aMode);
void Stop(StopMode aMode);
Error RestorePrevRole(void);
TxMessage *NewMleMessage(Command aCommand);
void SetRole(DeviceRole aRole);
void Attach(AttachMode aMode);