mirror of
https://github.com/espressif/openthread.git
synced 2026-09-02 23:30:07 +00:00
[mle] allow processing of "Child Update Request" while restoring child role (#12007)
This change modifies `HandleChildUpdateRequest()` to allow a detached child that is restoring its previous role to process a "Child Update Request" from its former parent. When in this state, the device will respond to the request but will not save any of the content (TLVs) from the message, as the child has not yet established trust with any device (including its former parent) and therefore cannot authenticate the freshness of the received request. This change handles the scenario where a child and its parent may be reset simultaneously. It allows the parent to first restore its link with the child through a "Child Update" exchange, which can then be followed by the child sending its own "Child Update Request" to re-establish the link. Without this change, a communication impasse could occur where the parent rejects the child's request (as the child is not yet valid), and the child ignores the parent's request (as it is not yet attached). This change prevents devices from resorting to a full re-attachment, thereby improving network resilience and recovery time. A new test is added to emulate this scenario and verify that the child restores its role correctly without performing a full attach.
This commit is contained in:
+31
-19
@@ -2181,31 +2181,40 @@ exit:
|
||||
|
||||
void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
VerifyOrExit(IsAttached());
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
if (IsRouterOrLeader())
|
||||
{
|
||||
HandleChildUpdateRequestOnParent(aRxInfo);
|
||||
ExitNow();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
HandleChildUpdateRequestOnChild(aRxInfo);
|
||||
|
||||
exit:
|
||||
return;
|
||||
{
|
||||
HandleChildUpdateRequestOnChild(aRxInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void Mle::HandleChildUpdateRequestOnChild(RxInfo &aRxInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error = kErrorNone;
|
||||
bool canTrustMessage = aRxInfo.IsNeighborStateValid();
|
||||
uint16_t sourceAddress;
|
||||
RxChallenge challenge;
|
||||
TlvList requestedTlvList;
|
||||
TlvList tlvList;
|
||||
uint8_t linkMarginOut;
|
||||
|
||||
if (!IsAttached())
|
||||
{
|
||||
// If detached and trying to restore our role as a child, we
|
||||
// allow processing of a received "Child Update Request"
|
||||
// and send a response. But since we have not yet established
|
||||
// trust with any device (including our former parent),
|
||||
// we will not save any of the content (TLVs) from the
|
||||
// message (`canTrustMessage` will be `false`).
|
||||
|
||||
VerifyOrExit(mPrevRoleRestorer.IsRestoringChildRole());
|
||||
}
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
|
||||
|
||||
Log(kMessageReceive, kTypeChildUpdateRequestAsChild, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);
|
||||
@@ -2245,17 +2254,20 @@ void Mle::HandleChildUpdateRequestOnChild(RxInfo &aRxInfo)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
SuccessOrExit(error = HandleLeaderData(aRxInfo));
|
||||
|
||||
switch (Tlv::Find<LinkMarginTlv>(aRxInfo.mMessage, linkMarginOut))
|
||||
if (canTrustMessage)
|
||||
{
|
||||
case kErrorNone:
|
||||
mParent.SetLinkQualityOut(LinkQualityForLinkMargin(linkMarginOut));
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
break;
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
SuccessOrExit(error = HandleLeaderData(aRxInfo));
|
||||
|
||||
switch (Tlv::Find<LinkMarginTlv>(aRxInfo.mMessage, linkMarginOut))
|
||||
{
|
||||
case kErrorNone:
|
||||
mParent.SetLinkQualityOut(LinkQualityForLinkMargin(linkMarginOut));
|
||||
break;
|
||||
case kErrorNotFound:
|
||||
break;
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
|
||||
Reference in New Issue
Block a user