Skip to content

Commit 87a919f

Browse files
authored
[mle] enhance role restoration logic in Start() (openthread#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.
1 parent 6e07db0 commit 87a919f

2 files changed

Lines changed: 45 additions & 16 deletions

File tree

src/core/thread/mle.cpp

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -225,29 +225,23 @@ Error Mle::Start(StartMode aMode)
225225

226226
Get<KeyManager>().Start();
227227

228-
if (aMode == kNormalAttach)
228+
switch (aMode)
229229
{
230+
case kNormalAttach:
230231
mReattachState =
231232
(Get<MeshCoP::ActiveDatasetManager>().Restore() == kErrorNone) ? kReattachActive : kReattachStop;
232-
}
233233

234-
if ((aMode == kAnnounceAttach) || (GetRloc16() == kInvalidRloc16))
235-
{
236-
Attach(kAnyPartition);
237-
}
238-
#if OPENTHREAD_FTD
239-
else if (IsRouterRloc16(GetRloc16()))
240-
{
241-
if (BecomeRouter(ThreadStatusTlv::kTooFewRouters) != kErrorNone)
234+
if (RestorePrevRole() == kErrorNone)
242235
{
243-
Attach(kAnyPartition);
236+
ExitNow();
244237
}
238+
break;
239+
240+
case kAnnounceAttach:
241+
break;
245242
}
246-
#endif
247-
else
248-
{
249-
IgnoreError(SendChildUpdateRequestToParent());
250-
}
243+
244+
Attach(kAnyPartition);
251245

252246
exit:
253247
return error;
@@ -286,6 +280,40 @@ void Mle::Stop(StopMode aMode)
286280
}
287281
}
288282

283+
Error Mle::RestorePrevRole(void)
284+
{
285+
// Restores the device to its previously saved role after MLE
286+
// start.
287+
//
288+
// Returns `kErrorNone` if the restoration process begins
289+
// successfully. An error is returned if:
290+
// - No previous role was saved.
291+
// - The saved role info is inconsistent (e.g., RLOC16 indicates a
292+
// router/leader, but `mLastSavedRole` doesn't match).
293+
// - The last role is "Child," but no valid parent is available.
294+
295+
Error error = kErrorFailed;
296+
297+
VerifyOrExit(GetRloc16() != kInvalidRloc16);
298+
299+
if (IsRouterRloc16(GetRloc16()))
300+
{
301+
#if OPENTHREAD_FTD
302+
VerifyOrExit(mLastSavedRole == kRoleRouter || mLastSavedRole == kRoleLeader);
303+
error = BecomeRouter(ThreadStatusTlv::kTooFewRouters);
304+
#endif
305+
ExitNow();
306+
}
307+
308+
VerifyOrExit(mLastSavedRole == kRoleChild);
309+
VerifyOrExit(mParent.IsStateValidOrRestoring());
310+
IgnoreError(SendChildUpdateRequestToParent());
311+
error = kErrorNone;
312+
313+
exit:
314+
return error;
315+
}
316+
289317
const Counters &Mle::GetCounters(void)
290318
{
291319
UpdateRoleTimeCounters(mRole);

src/core/thread/mle.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,6 +1958,7 @@ class Mle : public InstanceLocator, private NonCopyable
19581958

19591959
Error Start(StartMode aMode);
19601960
void Stop(StopMode aMode);
1961+
Error RestorePrevRole(void);
19611962
TxMessage *NewMleMessage(Command aCommand);
19621963
void SetRole(DeviceRole aRole);
19631964
void Attach(AttachMode aMode);

0 commit comments

Comments
 (0)