mirror of
https://github.com/espressif/openthread.git
synced 2026-08-21 01:49:52 +00:00
[mle] block router downgrade if triggered by child ID request (#12725)
This commit updates the `Mle` router role downgrade logic. When a REED transitions to a router in response to a Child ID Request, it indicates that the attaching child has no other viable parent options. To ensure this child remains connected to the mesh, this commit prevents the newly promoted router from downgrading back to a REED. A new flag `mBlockDowngrade` is added to `Mle`, and a matching property `mBlockParentDowngrade` is added to `Child` to track if it is blocking its parent's downgrade. The downgrade restriction is lifted under specific conditions: when the device detaches, when a new router is added to the network (providing a potential alternative parent for the child), or when all children blocking the downgrade are removed. A new nexus test `test_mle_blocking_downgrade` is added to validate the new behavior.
This commit is contained in:
@@ -478,8 +478,15 @@ uint32_t Mle::DetermineAdvertiseIntervalMax(void) const
|
||||
return interval;
|
||||
}
|
||||
|
||||
void Mle::UpdateAdvertiseInterval(void)
|
||||
void Mle::HandleRouterTableEvent(RouterTable::Events aEvents)
|
||||
{
|
||||
// Callback from `RouterTable` when there is a change.
|
||||
|
||||
if (aEvents & RouterTable::kEventRouterAdded)
|
||||
{
|
||||
mBlockDowngrade = false;
|
||||
}
|
||||
|
||||
if (IsRouterOrLeader() && mAdvertiseTrickleTimer.IsRunning())
|
||||
{
|
||||
mAdvertiseTrickleTimer.SetIntervalMax(DetermineAdvertiseIntervalMax());
|
||||
@@ -3420,6 +3427,20 @@ void Mle::HandleAddressSolicitResponse(Coap::Msg *aMsg, Error aResult)
|
||||
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateChildIdRequest))
|
||||
{
|
||||
IgnoreError(SendChildIdResponse(child));
|
||||
|
||||
// The transition to the router role was triggered by a Child
|
||||
// ID Request. This indicates that the child has no other
|
||||
// parent option. We set the flags to prevent the parent
|
||||
// router from downgrading back to a REED to ensure this
|
||||
// child remains connected.
|
||||
//
|
||||
// The `mBlockDowngrade` is cleared in various situations:
|
||||
// - From `SetStateDetached()` (e.g. partition change).
|
||||
// - If a new router is added (new possible parent).
|
||||
// - If all children blocking downgrade are disconnected.
|
||||
|
||||
child.SetBlockParentDowngrade(true);
|
||||
mBlockDowngrade = true;
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -3724,6 +3745,7 @@ bool Mle::ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const
|
||||
|
||||
VerifyOrExit(IsRouter());
|
||||
VerifyOrExit(mRouterTable.IsAllocated(aNeighborId));
|
||||
VerifyOrExit(!mBlockDowngrade);
|
||||
|
||||
VerifyOrExit(!mRouterRoleTransition.IsPending());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user