diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index df7c0802a..7551a5ea6 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -225,29 +225,23 @@ Error Mle::Start(StartMode aMode) Get().Start(); - if (aMode == kNormalAttach) + switch (aMode) { + case kNormalAttach: mReattachState = (Get().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); diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 1763d564f..4f5de6063 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -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);