Skip to content

Commit 2b3b56d

Browse files
authored
[mle] separate role transition and leader age checks (openthread#12853)
This commit updates `Mle::HandleTimeTick()` to separate the processing of role transitions and the checking of the leader's age into two distinct `switch` statements. Previously, these two checks were combined in a single `switch` statement with complex fall-through logic. This structure contained two issues: 1. For a device in the `kRoleChild` state, if the role transition timeout expired, the code would execute `ExitNow()`. This unintentionally skipped the leader age check and the rest of the operations in `Mle::HandleTimeTick()`, such as updating the `ChildTable` and `RouterTable`. 2. A non-router-eligible child would incorrectly fall through and perform the leader age check. The new logic adds an explicit check using `IsRouterEligible()` to ensure only router-eligible children monitor the leader's age. By separating the logic into two blocks, the code is simplified and we avoid the brittle fall-through behavior and ensure that all time tick operations are consistently executed regardless of the device's role or role transition state.
1 parent 2a120a9 commit 2b3b56d

1 file changed

Lines changed: 45 additions & 28 deletions

File tree

src/core/thread/mle_ftd.cpp

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,8 +1533,6 @@ bool Mle::HasNeighborWithGoodLinkQuality(void) const
15331533

15341534
void Mle::HandleTimeTick(void)
15351535
{
1536-
bool roleTransitionTimeoutExpired = false;
1537-
15381536
VerifyOrExit(IsFullThreadDevice(), Get<TimeTicker>().UnregisterReceiver(TimeTicker::kMle));
15391537

15401538
if (mPreviousPartitionIdTimeout > 0)
@@ -1555,16 +1553,18 @@ void Mle::HandleTimeTick(void)
15551553
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
15561554
// Role transitions
15571555

1558-
roleTransitionTimeoutExpired = mRouterRoleTransition.HandleTimeTick();
1559-
1560-
switch (mRole)
1556+
if (mRouterRoleTransition.HandleTimeTick())
15611557
{
1562-
case kRoleDetached:
1563-
break;
1558+
// `mRouterRoleTransition.HandleTimeTick()` returns `true`
1559+
// if role transition timeout expires.
15641560

1565-
case kRoleChild:
1566-
if (roleTransitionTimeoutExpired)
1561+
switch (mRole)
15671562
{
1563+
case kRoleDisabled:
1564+
case kRoleDetached:
1565+
break;
1566+
1567+
case kRoleChild:
15681568
if (mRouterTable.GetActiveRouterCount() < mRouterUpgradeThreshold && HasNeighborWithGoodLinkQuality())
15691569
{
15701570
IgnoreError(BecomeRouter(kReasonTooFewRouters));
@@ -1581,39 +1581,56 @@ void Mle::HandleTimeTick(void)
15811581
mAdvertiseTrickleTimer.Start(TrickleTimer::kModePlainTimer, kReedAdvIntervalMin, kReedAdvIntervalMax);
15821582
}
15831583

1584-
ExitNow();
1585-
}
1584+
break;
15861585

1587-
OT_FALL_THROUGH;
1586+
case kRoleRouter:
1587+
if (mRouterTable.GetActiveRouterCount() > mRouterDowngradeThreshold)
1588+
{
1589+
LogNote("Downgrade to REED");
1590+
mAttacher.Attach(kDowngradeToReed);
1591+
}
15881592

1589-
case kRoleRouter:
1590-
LogDebg("Leader age %lu", ToUlong(mRouterTable.GetLeaderAge()));
1593+
OT_FALL_THROUGH;
15911594

1592-
if ((mRouterTable.GetActiveRouterCount() > 0) && (mRouterTable.GetLeaderAge() >= mNetworkIdTimeout))
1593-
{
1594-
LogInfo("Leader age timeout");
1595-
mAttacher.Attach(kSamePartition);
1595+
case kRoleLeader:
1596+
if (!IsRouterEligible())
1597+
{
1598+
LogInfo("No longer router eligible");
1599+
IgnoreError(BecomeDetached());
1600+
}
1601+
1602+
break;
15961603
}
1604+
}
1605+
1606+
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1607+
// Check Leader's age
1608+
1609+
switch (mRole)
1610+
{
1611+
case kRoleDisabled:
1612+
case kRoleDetached:
1613+
case kRoleLeader:
1614+
break;
15971615

1598-
if (roleTransitionTimeoutExpired && mRouterTable.GetActiveRouterCount() > mRouterDowngradeThreshold)
1616+
case kRoleChild:
1617+
if (!IsRouterEligible())
15991618
{
1600-
LogNote("Downgrade to REED");
1601-
mAttacher.Attach(kDowngradeToReed);
1619+
break;
16021620
}
16031621

16041622
OT_FALL_THROUGH;
16051623

1606-
case kRoleLeader:
1607-
if (roleTransitionTimeoutExpired && !IsRouterEligible())
1624+
case kRoleRouter:
1625+
LogDebg("Leader age %lu", ToUlong(mRouterTable.GetLeaderAge()));
1626+
1627+
if ((mRouterTable.GetActiveRouterCount() > 0) && (mRouterTable.GetLeaderAge() >= mNetworkIdTimeout))
16081628
{
1609-
LogInfo("No longer router eligible");
1610-
IgnoreError(BecomeDetached());
1629+
LogInfo("Leader age timeout");
1630+
mAttacher.Attach(kSamePartition);
16111631
}
16121632

16131633
break;
1614-
1615-
case kRoleDisabled:
1616-
OT_ASSERT(false);
16171634
}
16181635

16191636
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

0 commit comments

Comments
 (0)