From ae54e4a133a39df270f26a9ff398614ae92ce8b8 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 27 Oct 2025 10:57:47 -0700 Subject: [PATCH] [mle] centralize `ChildUpdate` reject response logic (#12066) Introduces a new private method `Mle::SendChildUpdateRejectResponse()` to consolidate the logic for sending a reject response to a "Child Update Request". This new method creates a response containing the Source Address TLV, Status TLV, and (if applicable) Response TLV. The new method is now used in `Mle::HandleChildUpdateRequestOnChild()` when the device is not a parent of the sender, and in `Mle::HandleChildUpdateRequestOnParent()` when a request from an unknown child is received. This change removes duplicated code from both locations. --- src/core/thread/mle.cpp | 38 +++++++++++++++++++++---------------- src/core/thread/mle.hpp | 1 + src/core/thread/mle_ftd.cpp | 3 +-- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index af224ef29..f74d2801a 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1264,6 +1264,25 @@ exit: return error; } +Error Mle::SendChildUpdateRejectResponse(const RxChallenge &aChallenge, const Ip6::Address &aDestination) +{ + // Send a reject response which only includes a Source Address TLV, + // a Status TLV, and a Response TLV when request contained a + // Challenge TLV. + + TlvList tlvList; + + tlvList.Add(Tlv::kSourceAddress); + tlvList.Add(Tlv::kStatus); + + if (!aChallenge.IsEmpty()) + { + tlvList.Add(Tlv::kResponse); + } + + return SendChildUpdateResponse(tlvList, aChallenge, aDestination); +} + Error Mle::SendChildUpdateResponse(const TlvList &aTlvList, const RxChallenge &aChallenge, const Ip6::Address &aDestination) @@ -2315,19 +2334,8 @@ void Mle::HandleChildUpdateRequestOnChild(RxInfo &aRxInfo) else { // This device is not a child of the Child Update Request source. - // - // Send a reject response which only includes a Source Address TLV, - // a Status TLV, and a Response TLV when request contained a - // Challenge TLV. - - tlvList.Clear(); - tlvList.Add(Tlv::kSourceAddress); - tlvList.Add(Tlv::kStatus); - - if (!challenge.IsEmpty()) - { - tlvList.Add(Tlv::kResponse); - } + error = SendChildUpdateRejectResponse(challenge, aRxInfo.mMessageInfo.GetPeerAddr()); + ExitNow(); } aRxInfo.mClass = RxInfo::kPeerMessage; @@ -2340,9 +2348,7 @@ void Mle::HandleChildUpdateRequestOnChild(RxInfo &aRxInfo) } #endif - // Send the response to the requester, regardless if it's this - // device's parent or not. - SuccessOrExit(error = SendChildUpdateResponse(tlvList, challenge, aRxInfo.mMessageInfo.GetPeerAddr())); + error = SendChildUpdateResponse(tlvList, challenge, aRxInfo.mMessageInfo.GetPeerAddr()); exit: LogProcessError(kTypeChildUpdateRequestAsChild, error); diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index eba1b5b09..cc4656d79 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -2262,6 +2262,7 @@ private: void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); void ReestablishLinkWithNeighbor(Neighbor &aNeighbor); Error SendChildUpdateRequestToParent(ChildUpdateRequestMode aMode); + Error SendChildUpdateRejectResponse(const RxChallenge &aChallenge, const Ip6::Address &aDestination); Error SendChildUpdateResponse(const TlvList &aTlvList, const RxChallenge &aChallenge, const Ip6::Address &aDestination); diff --git a/src/core/thread/mle_ftd.cpp b/src/core/thread/mle_ftd.cpp index 54c2743f1..07568309d 100644 --- a/src/core/thread/mle_ftd.cpp +++ b/src/core/thread/mle_ftd.cpp @@ -2255,8 +2255,7 @@ void Mle::HandleChildUpdateRequestOnParent(RxInfo &aRxInfo) // Status TLV (error). if (mode.IsRxOnWhenIdle()) { - tlvList.Add(Tlv::kStatus); - SendChildUpdateResponseToChild(nullptr, aRxInfo.mMessageInfo, tlvList, challenge); + IgnoreError(SendChildUpdateRejectResponse(challenge, aRxInfo.mMessageInfo.GetPeerAddr())); } ExitNow();