From a30cbda8ae3ebb02f2557aa9c1ea460729324c08 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 27 Aug 2024 11:14:50 -0700 Subject: [PATCH] [mle] include Link Margin TLV in Child Update messages (#10626) This commit adds code to include the Link Margin TLV in MLE Child Update Request or Response messages sent by a parent to a child. This allows the child to learn and update its "link quality out" to its parent. The change is designed to be backward compatible. Child devices running older firmware will simply disregard this additional TLV. When processing the message, the presence of the Link Margin TLV is checked (it is optional). --- src/core/thread/mle.cpp | 24 ++++++++++++++++++++++++ src/core/thread/mle_router.cpp | 11 ++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index efe9e593b..6b64959f1 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -3394,6 +3394,7 @@ void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo) RxChallenge challenge; TlvList requestedTlvList; TlvList tlvList; + uint8_t linkMarginOut; SuccessOrExit(error = Tlv::Find(aRxInfo.mMessage, sourceAddress)); @@ -3436,6 +3437,17 @@ void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo) SuccessOrExit(error = HandleLeaderData(aRxInfo)); + switch (Tlv::Find(aRxInfo.mMessage, linkMarginOut)) + { + case kErrorNone: + mParent.SetLinkQualityOut(LinkQualityForLinkMargin(linkMarginOut)); + break; + case kErrorNotFound: + break; + default: + ExitNow(error = kErrorParse); + } + #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE { Mac::CslAccuracy cslAccuracy; @@ -3494,6 +3506,7 @@ void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo) uint32_t mleFrameCounter; uint16_t sourceAddress; uint32_t timeout; + uint8_t linkMarginOut; Log(kMessageReceive, kTypeChildUpdateResponseAsChild, aRxInfo.mMessageInfo.GetPeerAddr()); @@ -3616,6 +3629,17 @@ void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo) OT_ASSERT(false); } + switch (Tlv::Find(aRxInfo.mMessage, linkMarginOut)) + { + case kErrorNone: + mParent.SetLinkQualityOut(LinkQualityForLinkMargin(linkMarginOut)); + break; + case kErrorNotFound: + break; + default: + ExitNow(error = kErrorParse); + } + aRxInfo.mClass = response.IsEmpty() ? RxInfo::kPeerMessage : RxInfo::kAuthoritativeMessage; exit: diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index fcb4595de..087be21bc 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -2211,6 +2211,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo) child->SetDeviceMode(mode); tlvList.Add(Tlv::kMode); + tlvList.Add(Tlv::kLinkMargin); // Parent MUST include Leader Data TLV in Child Update Response tlvList.Add(Tlv::kLeaderData); @@ -2921,7 +2922,11 @@ Error MleRouter::SendChildUpdateRequest(Child &aChild) SuccessOrExit(error = message->AppendNetworkDataTlv(aChild.GetNetworkDataType())); SuccessOrExit(error = message->AppendActiveAndPendingTimestampTlvs()); - if (!aChild.IsStateValid()) + if (aChild.IsStateValid()) + { + SuccessOrExit(error = message->AppendLinkMarginTlv(aChild.GetLinkInfo().GetLinkMargin())); + } + else { SuccessOrExit(error = message->AppendTlvRequestTlv(kTlvs)); @@ -3029,6 +3034,10 @@ void MleRouter::SendChildUpdateResponse(Child *aChild, SuccessOrExit(error = message->AppendTimeoutTlv(aChild->GetTimeout())); break; + case Tlv::kLinkMargin: + SuccessOrExit(error = message->AppendLinkMarginTlv(aChild->GetLinkInfo().GetLinkMargin())); + break; + case Tlv::kSupervisionInterval: SuccessOrExit(error = message->AppendSupervisionIntervalTlv(aChild->GetSupervisionInterval())); break;