From f2c081b5aebe013c7cceaab71affac143c8634ec Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Thu, 9 Apr 2026 15:54:31 -0700 Subject: [PATCH] [mle] improve address registration in `SendChildUpdateResponse()` (#12863) This commit improves the address registration behavior in `Mle::SendChildUpdateResponse()` for non-FTD devices. Previously, the device would always append only the mesh-local address and then unconditionally attempt to send a follow-up Child Update Request. The updated logic now checks if the parent's request included a Challenge TLV. If not, all addresses are appended directly to the response, eliminating the extra message exchange. If a Challenge is present (indicating the parent is restoring its link), only the mesh-local address is included to prevent message fragmentation. In this case, if the device is attached and has unregistered addresses, a follow-up Child Update Request is scheduled via `mDelayedSender`. The previous implementation indirectly assumed the parent would only request the `Address Registration` TLV when restoring its link (the current behavior of OpenThread parents). However, such behavior on the parent is not strictly required and could change. This update on the child side ensures robust address registration regardless of the parent's specific behavior. --- src/core/thread/mle.cpp | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index df62f71e1..77e84c7db 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1303,7 +1303,6 @@ Error Mle::SendChildUpdateResponse(const ChildUpdateResponseInfo &aInfo) { Error error = kErrorNone; TxMessage *message; - bool checkAddress = false; VerifyOrExit((message = NewMleMessage(kCommandChildUpdateResponse)) != nullptr, error = kErrorNoBufs); @@ -1330,13 +1329,30 @@ Error Mle::SendChildUpdateResponse(const ChildUpdateResponseInfo &aInfo) case Tlv::kAddressRegistration: if (!IsFullThreadDevice()) { - // We only register the mesh-local address in the "Child - // Update Response" message and if there are additional - // addresses to register we follow up with a "Child Update - // Request". + AddressRegistrationMode addrRegMode = kAppendAllAddresses; - SuccessOrExit(error = message->AppendAddressRegistrationTlv(kAppendMeshLocalOnly)); - checkAddress = true; + if (!aInfo.mChallenge.IsEmpty()) + { + // If the parent is restoring its link, its request + // will include a Challenge. In this case, we only + // register the mesh-local address in the response + // message (to ensure it does not get fragmented). + // If there are additional addresses to register + // and the child itself is attached (it is not + // itself restoring its link to the parent), we + // schedule a follow-up "Child Update Request" to + // register the remaining addresses. + + addrRegMode = kAppendMeshLocalOnly; + + if (IsAttached() && HasUnregisteredAddress()) + { + mDelayedSender.RemoveScheduledChildUpdateRequestToParent(); + mDelayedSender.ScheduleChildUpdateRequestToParent(0); + } + } + + SuccessOrExit(error = message->AppendAddressRegistrationTlv(addrRegMode)); } break; @@ -1372,11 +1388,6 @@ Error Mle::SendChildUpdateResponse(const ChildUpdateResponseInfo &aInfo) Log(kMessageSend, kTypeChildUpdateResponseAsChild, aInfo.mDestination); - if (checkAddress && HasUnregisteredAddress()) - { - IgnoreError(SendChildUpdateRequestToParent()); - } - exit: FreeMessageOnError(message, error); return error;