From 612f21e776c98397d8088412202bee5e2b5667b4 Mon Sep 17 00:00:00 2001 From: Li Cao Date: Fri, 5 May 2023 11:58:06 +0800 Subject: [PATCH] [link-metrics] refactor link metrics module (#8966) This commit breaks Link Metrics Initiator and Subject into two classes and fixes incorrect swtich guard. For example, code for Initiator was guarded by macro of Subject. --- src/core/api/link_metrics_api.cpp | 33 +- src/core/common/instance.cpp | 7 +- src/core/common/instance.hpp | 16 +- src/core/mac/mac.cpp | 8 +- src/core/thread/link_metrics.cpp | 904 +++++++++++++++--------------- src/core/thread/link_metrics.hpp | 284 +++++----- src/core/thread/mle.cpp | 30 +- src/core/thread/mle.hpp | 26 +- src/core/thread/mle_router.cpp | 2 +- src/core/thread/topology.cpp | 2 +- tests/unit/test_link_quality.cpp | 20 +- 11 files changed, 690 insertions(+), 642 deletions(-) diff --git a/src/core/api/link_metrics_api.cpp b/src/core/api/link_metrics_api.cpp index 1ee6acb08..548876d27 100644 --- a/src/core/api/link_metrics_api.cpp +++ b/src/core/api/link_metrics_api.cpp @@ -33,8 +33,7 @@ #include "openthread-core-config.h" -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE #include #include "common/as_core_type.hpp" @@ -49,10 +48,10 @@ otError otLinkMetricsQuery(otInstance *aInstance, otLinkMetricsReportCallback aCallback, void *aCallbackContext) { - AsCoreType(aInstance).Get().SetReportCallback(aCallback, aCallbackContext); + AsCoreType(aInstance).Get().SetReportCallback(aCallback, aCallbackContext); - return AsCoreType(aInstance).Get().Query(AsCoreType(aDestination), aSeriesId, - AsCoreTypePtr(aLinkMetricsFlags)); + return AsCoreType(aInstance).Get().Query(AsCoreType(aDestination), aSeriesId, + AsCoreTypePtr(aLinkMetricsFlags)); } #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE @@ -64,12 +63,12 @@ otError otLinkMetricsConfigForwardTrackingSeries(otInstance otLinkMetricsMgmtResponseCallback aCallback, void *aCallbackContext) { - LinkMetrics::LinkMetrics &linkMetrics = AsCoreType(aInstance).Get(); + LinkMetrics::Initiator &initiator = AsCoreType(aInstance).Get(); - linkMetrics.SetMgmtResponseCallback(aCallback, aCallbackContext); + initiator.SetMgmtResponseCallback(aCallback, aCallbackContext); - return linkMetrics.SendMgmtRequestForwardTrackingSeries( - AsCoreType(aDestination), aSeriesId, AsCoreType(&aSeriesFlags), AsCoreTypePtr(aLinkMetricsFlags)); + return initiator.SendMgmtRequestForwardTrackingSeries(AsCoreType(aDestination), aSeriesId, + AsCoreType(&aSeriesFlags), AsCoreTypePtr(aLinkMetricsFlags)); } otError otLinkMetricsConfigEnhAckProbing(otInstance *aInstance, @@ -81,13 +80,13 @@ otError otLinkMetricsConfigEnhAckProbing(otInstance otLinkMetricsEnhAckProbingIeReportCallback aEnhAckCallback, void *aEnhAckCallbackContext) { - LinkMetrics::LinkMetrics &linkMetrics = AsCoreType(aInstance).Get(); + LinkMetrics::Initiator &initiator = AsCoreType(aInstance).Get(); - linkMetrics.SetMgmtResponseCallback(aCallback, aCallbackContext); - linkMetrics.SetEnhAckProbingCallback(aEnhAckCallback, aEnhAckCallbackContext); + initiator.SetMgmtResponseCallback(aCallback, aCallbackContext); + initiator.SetEnhAckProbingCallback(aEnhAckCallback, aEnhAckCallbackContext); - return linkMetrics.SendMgmtRequestEnhAckProbing(AsCoreType(aDestination), MapEnum(aEnhAckFlags), - AsCoreTypePtr(aLinkMetricsFlags)); + return initiator.SendMgmtRequestEnhAckProbing(AsCoreType(aDestination), MapEnum(aEnhAckFlags), + AsCoreTypePtr(aLinkMetricsFlags)); } otError otLinkMetricsSendLinkProbe(otInstance *aInstance, @@ -95,10 +94,10 @@ otError otLinkMetricsSendLinkProbe(otInstance *aInstance, uint8_t aSeriesId, uint8_t aLength) { - LinkMetrics::LinkMetrics &linkMetrics = AsCoreType(aInstance).Get(); + LinkMetrics::Initiator &initiator = AsCoreType(aInstance).Get(); - return linkMetrics.SendLinkProbe(AsCoreType(aDestination), aSeriesId, aLength); + return initiator.SendLinkProbe(AsCoreType(aDestination), aSeriesId, aLength); } #endif -#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp index 94b905076..d0aebecd3 100644 --- a/src/core/common/instance.cpp +++ b/src/core/common/instance.cpp @@ -189,8 +189,11 @@ Instance::Instance(void) #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE , mTimeSync(*this) #endif -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - , mLinkMetrics(*this) +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + , mInitiator(*this) +#endif +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + , mSubject(*this) #endif #if OPENTHREAD_CONFIG_COAP_API_ENABLE , mApplicationCoap(*this) diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index d7c171dcb..8ce6eba09 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -563,8 +563,12 @@ private: TimeSync mTimeSync; #endif -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - LinkMetrics::LinkMetrics mLinkMetrics; +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + LinkMetrics::Initiator mInitiator; +#endif + +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + LinkMetrics::Subject mSubject; #endif #if OPENTHREAD_CONFIG_COAP_API_ENABLE @@ -930,8 +934,12 @@ template <> inline MlrManager &Instance::Get(void) { return mMlrManager; } template <> inline DuaManager &Instance::Get(void) { return mDuaManager; } #endif -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE -template <> inline LinkMetrics::LinkMetrics &Instance::Get(void) { return mLinkMetrics; } +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE +template <> inline LinkMetrics::Initiator &Instance::Get(void) { return mInitiator; } +#endif + +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +template <> inline LinkMetrics::Subject &Instance::Get(void) { return mSubject; } #endif #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 6997fd01b..a29ee3fc5 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -1201,6 +1201,8 @@ void Mac::RecordFrameTransmitStatus(const TxFrame &aFrame, #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE neighbor->AggregateLinkMetrics(/* aSeriesId */ 0, aAckFrame->GetType(), aAckFrame->GetLqi(), aAckFrame->GetRssi()); +#endif +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE ProcessEnhAckProbing(*aAckFrame, *neighbor); #endif #if OPENTHREAD_FTD @@ -2304,7 +2306,7 @@ exit: } #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE void Mac::ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor) { constexpr uint8_t kEnhAckProbingIeMaxLen = 2; @@ -2320,11 +2322,11 @@ void Mac::ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor) dataLen = enhAckProbingIe->GetLength() - sizeof(VendorIeHeader); VerifyOrExit(dataLen <= kEnhAckProbingIeMaxLen); - Get().ProcessEnhAckIeData(data, dataLen, aNeighbor); + Get().ProcessEnhAckIeData(data, dataLen, aNeighbor); exit: return; } -#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE void Mac::SetRadioFilterEnabled(bool aFilterEnabled) diff --git a/src/core/thread/link_metrics.cpp b/src/core/thread/link_metrics.cpp index a7ad64b0b..cfe784c4f 100644 --- a/src/core/thread/link_metrics.cpp +++ b/src/core/thread/link_metrics.cpp @@ -51,12 +51,22 @@ namespace LinkMetrics { RegisterLogModule("LinkMetrics"); -LinkMetrics::LinkMetrics(Instance &aInstance) +static constexpr uint8_t kQueryIdSingleProbe = 0; // This query ID represents Single Probe. +static constexpr uint8_t kSeriesIdAllSeries = 255; // This series ID represents all series. + +// Constants for scaling Link Margin and RSSI to raw value +static constexpr uint8_t kMaxLinkMargin = 130; +static constexpr int32_t kMinRssi = -130; +static constexpr int32_t kMaxRssi = 0; + +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + +Initiator::Initiator(Instance &aInstance) : InstanceLocator(aInstance) { } -Error LinkMetrics::Query(const Ip6::Address &aDestination, uint8_t aSeriesId, const Metrics *aMetrics) +Error Initiator::Query(const Ip6::Address &aDestination, uint8_t aSeriesId, const Metrics *aMetrics) { Error error; Neighbor *neighbor; @@ -77,325 +87,43 @@ Error LinkMetrics::Query(const Ip6::Address &aDestination, uint8_t aSeriesId, co VerifyOrExit(info.mTypeIdCount == 0, error = kErrorInvalidArgs); } - error = Get().SendDataRequestForLinkMetricsReport(aDestination, info); + error = Get().SendDataRequestForLinkMetricsReport(aDestination, info); exit: return error; } -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE -Error LinkMetrics::SendMgmtRequestForwardTrackingSeries(const Ip6::Address &aDestination, - uint8_t aSeriesId, - const SeriesFlags &aSeriesFlags, - const Metrics *aMetrics) +Error Initiator::AppendLinkMetricsQueryTlv(Message &aMessage, const QueryInfo &aInfo) { - Error error; - Neighbor *neighbor; - uint8_t typeIdCount = 0; - FwdProbingRegSubTlv fwdProbingSubTlv; + Error error = kErrorNone; + Tlv tlv; - SuccessOrExit(error = FindNeighbor(aDestination, neighbor)); + // The MLE Link Metrics Query TLV has two sub-TLVs: + // - Query ID sub-TLV with series ID as value. + // - Query Options sub-TLV with Type IDs as value. - VerifyOrExit(aSeriesId > kQueryIdSingleProbe, error = kErrorInvalidArgs); + tlv.SetType(Mle::Tlv::kLinkMetricsQuery); + tlv.SetLength(sizeof(Tlv) + sizeof(uint8_t) + ((aInfo.mTypeIdCount == 0) ? 0 : (sizeof(Tlv) + aInfo.mTypeIdCount))); - fwdProbingSubTlv.Init(); - fwdProbingSubTlv.SetSeriesId(aSeriesId); - fwdProbingSubTlv.SetSeriesFlagsMask(aSeriesFlags.ConvertToMask()); - - if (aMetrics != nullptr) - { - typeIdCount = aMetrics->ConvertToTypeIds(fwdProbingSubTlv.GetTypeIds()); - } - - fwdProbingSubTlv.SetLength(sizeof(aSeriesId) + sizeof(uint8_t) + typeIdCount); - - error = Get().SendLinkMetricsManagementRequest(aDestination, fwdProbingSubTlv); - -exit: - LogDebg("SendMgmtRequestForwardTrackingSeries, error:%s, Series ID:%u", ErrorToString(error), aSeriesId); - return error; -} - -Error LinkMetrics::SendMgmtRequestEnhAckProbing(const Ip6::Address &aDestination, - const EnhAckFlags aEnhAckFlags, - const Metrics *aMetrics) -{ - Error error; - Neighbor *neighbor; - uint8_t typeIdCount = 0; - EnhAckConfigSubTlv enhAckConfigSubTlv; - - SuccessOrExit(error = FindNeighbor(aDestination, neighbor)); - - if (aEnhAckFlags == kEnhAckClear) - { - VerifyOrExit(aMetrics == nullptr, error = kErrorInvalidArgs); - } - - enhAckConfigSubTlv.Init(); - enhAckConfigSubTlv.SetEnhAckFlags(aEnhAckFlags); - - if (aMetrics != nullptr) - { - typeIdCount = aMetrics->ConvertToTypeIds(enhAckConfigSubTlv.GetTypeIds()); - } - - enhAckConfigSubTlv.SetLength(EnhAckConfigSubTlv::kMinLength + typeIdCount); - - error = Get().SendLinkMetricsManagementRequest(aDestination, enhAckConfigSubTlv); - - if (aMetrics != nullptr) - { - neighbor->SetEnhAckProbingMetrics(*aMetrics); - } - else - { - Metrics metrics; - - metrics.Clear(); - neighbor->SetEnhAckProbingMetrics(metrics); - } - -exit: - return error; -} - -Error LinkMetrics::SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength) -{ - Error error; - uint8_t buf[kLinkProbeMaxLen]; - Neighbor *neighbor; - - SuccessOrExit(error = FindNeighbor(aDestination, neighbor)); - - VerifyOrExit(aLength <= LinkMetrics::kLinkProbeMaxLen && aSeriesId != kQueryIdSingleProbe && - aSeriesId != kSeriesIdAllSeries, - error = kErrorInvalidArgs); - - error = Get().SendLinkProbe(aDestination, aSeriesId, buf, aLength); -exit: - LogDebg("SendLinkProbe, error:%s, Series ID:%u", ErrorToString(error), aSeriesId); - return error; -} -#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE - -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE -Error LinkMetrics::AppendReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor) -{ - Error error = kErrorNone; - Tlv tlv; - uint8_t queryId; - bool hasQueryId = false; - uint16_t length; - uint16_t offset; - uint16_t endOffset; - MetricsValues values; - - values.Clear(); - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Parse MLE Link Metrics Query TLV and its sub-TLVs from - // `aRequestMessage`. - - SuccessOrExit(error = Tlv::FindTlvValueOffset(aRequestMessage, Mle::Tlv::Type::kLinkMetricsQuery, offset, length)); - - endOffset = offset + length; - - while (offset < endOffset) - { - SuccessOrExit(error = aRequestMessage.Read(offset, tlv)); - - switch (tlv.GetType()) - { - case SubTlv::kQueryId: - SuccessOrExit(error = Tlv::Read(aRequestMessage, offset, queryId)); - hasQueryId = true; - break; - - case SubTlv::kQueryOptions: - SuccessOrExit(error = ReadTypeIdsFromMessage(aRequestMessage, offset + sizeof(tlv), - static_cast(offset + tlv.GetSize()), - values.GetMetrics())); - break; - - default: - break; - } - - offset += static_cast(tlv.GetSize()); - } - - VerifyOrExit(hasQueryId, error = kErrorParse); - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Append MLE Link Metrics Report TLV and its sub-TLVs to - // `aMessage`. - - offset = aMessage.GetLength(); - tlv.SetType(Mle::Tlv::kLinkMetricsReport); SuccessOrExit(error = aMessage.Append(tlv)); - if (queryId == kQueryIdSingleProbe) + SuccessOrExit(error = Tlv::Append(aMessage, aInfo.mSeriesId)); + + if (aInfo.mTypeIdCount != 0) { - values.mPduCountValue = aRequestMessage.GetPsduCount(); - values.mLqiValue = aRequestMessage.GetAverageLqi(); - values.mLinkMarginValue = Get().ComputeLinkMargin(aRequestMessage.GetAverageRss()); - values.mRssiValue = aRequestMessage.GetAverageRss(); - SuccessOrExit(error = AppendReportSubTlvToMessage(aMessage, values)); - } - else - { - SeriesInfo *seriesInfo = aNeighbor.GetForwardTrackingSeriesInfo(queryId); + QueryOptionsSubTlv queryOptionsTlv; - if (seriesInfo == nullptr) - { - SuccessOrExit(error = Tlv::Append(aMessage, kStatusSeriesIdNotRecognized)); - } - else if (seriesInfo->GetPduCount() == 0) - { - SuccessOrExit(error = Tlv::Append(aMessage, kStatusNoMatchingFramesReceived)); - } - else - { - values.SetMetrics(seriesInfo->GetLinkMetrics()); - values.mPduCountValue = seriesInfo->GetPduCount(); - values.mLqiValue = seriesInfo->GetAverageLqi(); - values.mLinkMarginValue = Get().ComputeLinkMargin(seriesInfo->GetAverageRss()); - values.mRssiValue = seriesInfo->GetAverageRss(); - SuccessOrExit(error = AppendReportSubTlvToMessage(aMessage, values)); - } - } - - // Update the TLV length in message. - length = aMessage.GetLength() - offset - sizeof(Tlv); - tlv.SetLength(static_cast(length)); - aMessage.Write(offset, tlv); - -exit: - LogDebg("AppendReport, error:%s", ErrorToString(error)); - return error; -} - -Error LinkMetrics::HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus) -{ - Error error = kErrorNone; - uint16_t offset; - uint16_t endOffset; - uint16_t tlvEndOffset; - uint16_t length; - FwdProbingRegSubTlv fwdProbingSubTlv; - EnhAckConfigSubTlv enhAckConfigSubTlv; - Metrics metrics; - - SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, length)); - endOffset = offset + length; - - // Set sub-TLV lengths to zero to indicate that we have - // not yet seen them in the message. - fwdProbingSubTlv.SetLength(0); - enhAckConfigSubTlv.SetLength(0); - - for (; offset < endOffset; offset = tlvEndOffset) - { - Tlv tlv; - uint16_t minTlvSize; - Tlv *subTlv; - - SuccessOrExit(error = aMessage.Read(offset, tlv)); - - VerifyOrExit(offset + tlv.GetSize() <= endOffset, error = kErrorParse); - tlvEndOffset = static_cast(offset + tlv.GetSize()); - - switch (tlv.GetType()) - { - case SubTlv::kFwdProbingReg: - subTlv = &fwdProbingSubTlv; - minTlvSize = sizeof(Tlv) + FwdProbingRegSubTlv::kMinLength; - break; - - case SubTlv::kEnhAckConfig: - subTlv = &enhAckConfigSubTlv; - minTlvSize = sizeof(Tlv) + EnhAckConfigSubTlv::kMinLength; - break; - - default: - continue; - } - - // Ensure message contains only one sub-TLV. - VerifyOrExit(fwdProbingSubTlv.GetLength() == 0, error = kErrorParse); - VerifyOrExit(enhAckConfigSubTlv.GetLength() == 0, error = kErrorParse); - - VerifyOrExit(tlv.GetSize() >= minTlvSize, error = kErrorParse); - - // Read `subTlv` with its `minTlvSize`, followed by the Type IDs. - SuccessOrExit(error = aMessage.Read(offset, subTlv, minTlvSize)); - SuccessOrExit(error = ReadTypeIdsFromMessage(aMessage, offset + minTlvSize, tlvEndOffset, metrics)); - } - - if (fwdProbingSubTlv.GetLength() != 0) - { - aStatus = ConfigureForwardTrackingSeries(fwdProbingSubTlv.GetSeriesId(), fwdProbingSubTlv.GetSeriesFlagsMask(), - metrics, aNeighbor); - } - - if (enhAckConfigSubTlv.GetLength() != 0) - { - aStatus = ConfigureEnhAckProbing(enhAckConfigSubTlv.GetEnhAckFlags(), metrics, aNeighbor); + queryOptionsTlv.Init(); + queryOptionsTlv.SetLength(aInfo.mTypeIdCount); + SuccessOrExit(error = aMessage.Append(queryOptionsTlv)); + SuccessOrExit(error = aMessage.AppendBytes(aInfo.mTypeIds, aInfo.mTypeIdCount)); } exit: return error; } -#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE -Error LinkMetrics::HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress) -{ - Error error = kErrorNone; - uint16_t offset; - uint16_t endOffset; - uint16_t length; - uint8_t status; - bool hasStatus = false; - - VerifyOrExit(mMgmtResponseCallback.IsSet()); - - SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, length)); - endOffset = offset + length; - - while (offset < endOffset) - { - Tlv tlv; - - SuccessOrExit(error = aMessage.Read(offset, tlv)); - - switch (tlv.GetType()) - { - case StatusSubTlv::kType: - VerifyOrExit(!hasStatus, error = kErrorParse); - SuccessOrExit(error = Tlv::Read(aMessage, offset, status)); - hasStatus = true; - break; - - default: - break; - } - - offset += sizeof(Tlv) + tlv.GetLength(); - } - - VerifyOrExit(hasStatus, error = kErrorParse); - - mMgmtResponseCallback.Invoke(&aAddress, status); - -exit: - return error; -} - -void LinkMetrics::HandleReport(const Message &aMessage, - uint16_t aOffset, - uint16_t aLength, - const Ip6::Address &aAddress) +void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t aLength, const Ip6::Address &aAddress) { Error error = kErrorNone; uint16_t offset = aOffset; @@ -497,21 +225,143 @@ exit: LogDebg("HandleReport, error:%s", ErrorToString(error)); } -Error LinkMetrics::HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId) +Error Initiator::SendMgmtRequestForwardTrackingSeries(const Ip6::Address &aDestination, + uint8_t aSeriesId, + const SeriesFlags &aSeriesFlags, + const Metrics *aMetrics) { - Error error = kErrorNone; - uint16_t offset; - uint16_t length; + Error error; + Neighbor *neighbor; + uint8_t typeIdCount = 0; + FwdProbingRegSubTlv fwdProbingSubTlv; - SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkProbe, offset, length)); - VerifyOrExit(length >= sizeof(aSeriesId), error = kErrorParse); - error = aMessage.Read(offset, aSeriesId); + SuccessOrExit(error = FindNeighbor(aDestination, neighbor)); + + VerifyOrExit(aSeriesId > kQueryIdSingleProbe, error = kErrorInvalidArgs); + + fwdProbingSubTlv.Init(); + fwdProbingSubTlv.SetSeriesId(aSeriesId); + fwdProbingSubTlv.SetSeriesFlagsMask(aSeriesFlags.ConvertToMask()); + + if (aMetrics != nullptr) + { + typeIdCount = aMetrics->ConvertToTypeIds(fwdProbingSubTlv.GetTypeIds()); + } + + fwdProbingSubTlv.SetLength(sizeof(aSeriesId) + sizeof(uint8_t) + typeIdCount); + + error = Get().SendLinkMetricsManagementRequest(aDestination, fwdProbingSubTlv); + +exit: + LogDebg("SendMgmtRequestForwardTrackingSeries, error:%s, Series ID:%u", ErrorToString(error), aSeriesId); + return error; +} + +Error Initiator::SendMgmtRequestEnhAckProbing(const Ip6::Address &aDestination, + EnhAckFlags aEnhAckFlags, + const Metrics *aMetrics) +{ + Error error; + Neighbor *neighbor; + uint8_t typeIdCount = 0; + EnhAckConfigSubTlv enhAckConfigSubTlv; + + SuccessOrExit(error = FindNeighbor(aDestination, neighbor)); + + if (aEnhAckFlags == kEnhAckClear) + { + VerifyOrExit(aMetrics == nullptr, error = kErrorInvalidArgs); + } + + enhAckConfigSubTlv.Init(); + enhAckConfigSubTlv.SetEnhAckFlags(aEnhAckFlags); + + if (aMetrics != nullptr) + { + typeIdCount = aMetrics->ConvertToTypeIds(enhAckConfigSubTlv.GetTypeIds()); + } + + enhAckConfigSubTlv.SetLength(EnhAckConfigSubTlv::kMinLength + typeIdCount); + + error = Get().SendLinkMetricsManagementRequest(aDestination, enhAckConfigSubTlv); + + if (aMetrics != nullptr) + { + neighbor->SetEnhAckProbingMetrics(*aMetrics); + } + else + { + Metrics metrics; + + metrics.Clear(); + neighbor->SetEnhAckProbingMetrics(metrics); + } exit: return error; } -void LinkMetrics::ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLength, const Neighbor &aNeighbor) +Error Initiator::HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress) +{ + Error error = kErrorNone; + uint16_t offset; + uint16_t endOffset; + uint16_t length; + uint8_t status; + bool hasStatus = false; + + VerifyOrExit(mMgmtResponseCallback.IsSet()); + + SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, length)); + endOffset = offset + length; + + while (offset < endOffset) + { + Tlv tlv; + + SuccessOrExit(error = aMessage.Read(offset, tlv)); + + switch (tlv.GetType()) + { + case StatusSubTlv::kType: + VerifyOrExit(!hasStatus, error = kErrorParse); + SuccessOrExit(error = Tlv::Read(aMessage, offset, status)); + hasStatus = true; + break; + + default: + break; + } + + offset += sizeof(Tlv) + tlv.GetLength(); + } + + VerifyOrExit(hasStatus, error = kErrorParse); + + mMgmtResponseCallback.Invoke(&aAddress, status); + +exit: + return error; +} + +Error Initiator::SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength) +{ + Error error; + uint8_t buf[kLinkProbeMaxLen]; + Neighbor *neighbor; + + SuccessOrExit(error = FindNeighbor(aDestination, neighbor)); + + VerifyOrExit(aLength <= kLinkProbeMaxLen && aSeriesId != kQueryIdSingleProbe && aSeriesId != kSeriesIdAllSeries, + error = kErrorInvalidArgs); + + error = Get().SendLinkProbe(aDestination, aSeriesId, buf, aLength); +exit: + LogDebg("SendLinkProbe, error:%s, Series ID:%u", ErrorToString(error), aSeriesId); + return error; +} + +void Initiator::ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLength, const Neighbor &aNeighbor) { MetricsValues values; uint8_t idx = 0; @@ -539,108 +389,7 @@ exit: return; } -Error LinkMetrics::AppendLinkMetricsQueryTlv(Message &aMessage, const QueryInfo &aInfo) -{ - Error error = kErrorNone; - Tlv tlv; - - // The MLE Link Metrics Query TLV has two sub-TLVs: - // - Query ID sub-TLV with series ID as value. - // - Query Options sub-TLV with Type IDs as value. - - tlv.SetType(Mle::Tlv::kLinkMetricsQuery); - tlv.SetLength(sizeof(Tlv) + sizeof(uint8_t) + ((aInfo.mTypeIdCount == 0) ? 0 : (sizeof(Tlv) + aInfo.mTypeIdCount))); - - SuccessOrExit(error = aMessage.Append(tlv)); - - SuccessOrExit(error = Tlv::Append(aMessage, aInfo.mSeriesId)); - - if (aInfo.mTypeIdCount != 0) - { - QueryOptionsSubTlv queryOptionsTlv; - - queryOptionsTlv.Init(); - queryOptionsTlv.SetLength(aInfo.mTypeIdCount); - SuccessOrExit(error = aMessage.Append(queryOptionsTlv)); - SuccessOrExit(error = aMessage.AppendBytes(aInfo.mTypeIds, aInfo.mTypeIdCount)); - } - -exit: - return error; -} - -Status LinkMetrics::ConfigureForwardTrackingSeries(uint8_t aSeriesId, - uint8_t aSeriesFlagsMask, - const Metrics &aMetrics, - Neighbor &aNeighbor) -{ - Status status = kStatusSuccess; - - VerifyOrExit(0 < aSeriesId, status = kStatusOtherError); - - if (aSeriesFlagsMask == 0) // Remove the series - { - if (aSeriesId == kSeriesIdAllSeries) // Remove all - { - aNeighbor.RemoveAllForwardTrackingSeriesInfo(); - } - else - { - SeriesInfo *seriesInfo = aNeighbor.RemoveForwardTrackingSeriesInfo(aSeriesId); - VerifyOrExit(seriesInfo != nullptr, status = kStatusSeriesIdNotRecognized); - mSeriesInfoPool.Free(*seriesInfo); - } - } - else // Add a new series - { - SeriesInfo *seriesInfo = aNeighbor.GetForwardTrackingSeriesInfo(aSeriesId); - VerifyOrExit(seriesInfo == nullptr, status = kStatusSeriesIdAlreadyRegistered); - seriesInfo = mSeriesInfoPool.Allocate(); - VerifyOrExit(seriesInfo != nullptr, status = kStatusCannotSupportNewSeries); - - seriesInfo->Init(aSeriesId, aSeriesFlagsMask, aMetrics); - - aNeighbor.AddForwardTrackingSeriesInfo(*seriesInfo); - } - -exit: - return status; -} - -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE -Status LinkMetrics::ConfigureEnhAckProbing(uint8_t aEnhAckFlags, const Metrics &aMetrics, Neighbor &aNeighbor) -{ - Status status = kStatusSuccess; - Error error = kErrorNone; - - VerifyOrExit(!aMetrics.mReserved, status = kStatusOtherError); - - if (aEnhAckFlags == kEnhAckRegister) - { - VerifyOrExit(!aMetrics.mPduCount, status = kStatusOtherError); - VerifyOrExit(aMetrics.mLqi || aMetrics.mLinkMargin || aMetrics.mRssi, status = kStatusOtherError); - VerifyOrExit(!(aMetrics.mLqi && aMetrics.mLinkMargin && aMetrics.mRssi), status = kStatusOtherError); - - error = Get().ConfigureEnhAckProbing(aMetrics, aNeighbor.GetRloc16(), aNeighbor.GetExtAddress()); - } - else if (aEnhAckFlags == kEnhAckClear) - { - VerifyOrExit(!aMetrics.mLqi && !aMetrics.mLinkMargin && !aMetrics.mRssi, status = kStatusOtherError); - error = Get().ConfigureEnhAckProbing(aMetrics, aNeighbor.GetRloc16(), aNeighbor.GetExtAddress()); - } - else - { - status = kStatusOtherError; - } - - VerifyOrExit(error == kErrorNone, status = kStatusOtherError); - -exit: - return status; -} -#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - -Error LinkMetrics::FindNeighbor(const Ip6::Address &aDestination, Neighbor *&aNeighbor) const +Error Initiator::FindNeighbor(const Ip6::Address &aDestination, Neighbor *&aNeighbor) { Error error = kErrorUnknownNeighbor; Mac::Address macAddress; @@ -660,10 +409,241 @@ exit: return error; } -Error LinkMetrics::ReadTypeIdsFromMessage(const Message &aMessage, - uint16_t aStartOffset, - uint16_t aEndOffset, - Metrics &aMetrics) +#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +Subject::Subject(Instance &aInstance) + : InstanceLocator(aInstance) +{ +} + +Error Subject::AppendReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor) +{ + Error error = kErrorNone; + Tlv tlv; + uint8_t queryId; + bool hasQueryId = false; + uint16_t length; + uint16_t offset; + uint16_t endOffset; + MetricsValues values; + + values.Clear(); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Parse MLE Link Metrics Query TLV and its sub-TLVs from + // `aRequestMessage`. + + SuccessOrExit(error = Tlv::FindTlvValueOffset(aRequestMessage, Mle::Tlv::Type::kLinkMetricsQuery, offset, length)); + + endOffset = offset + length; + + while (offset < endOffset) + { + SuccessOrExit(error = aRequestMessage.Read(offset, tlv)); + + switch (tlv.GetType()) + { + case SubTlv::kQueryId: + SuccessOrExit(error = Tlv::Read(aRequestMessage, offset, queryId)); + hasQueryId = true; + break; + + case SubTlv::kQueryOptions: + SuccessOrExit(error = ReadTypeIdsFromMessage(aRequestMessage, offset + sizeof(tlv), + static_cast(offset + tlv.GetSize()), + values.GetMetrics())); + break; + + default: + break; + } + + offset += static_cast(tlv.GetSize()); + } + + VerifyOrExit(hasQueryId, error = kErrorParse); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Append MLE Link Metrics Report TLV and its sub-TLVs to + // `aMessage`. + + offset = aMessage.GetLength(); + tlv.SetType(Mle::Tlv::kLinkMetricsReport); + SuccessOrExit(error = aMessage.Append(tlv)); + + if (queryId == kQueryIdSingleProbe) + { + values.mPduCountValue = aRequestMessage.GetPsduCount(); + values.mLqiValue = aRequestMessage.GetAverageLqi(); + values.mLinkMarginValue = Get().ComputeLinkMargin(aRequestMessage.GetAverageRss()); + values.mRssiValue = aRequestMessage.GetAverageRss(); + SuccessOrExit(error = AppendReportSubTlvToMessage(aMessage, values)); + } + else + { + SeriesInfo *seriesInfo = aNeighbor.GetForwardTrackingSeriesInfo(queryId); + + if (seriesInfo == nullptr) + { + SuccessOrExit(error = Tlv::Append(aMessage, kStatusSeriesIdNotRecognized)); + } + else if (seriesInfo->GetPduCount() == 0) + { + SuccessOrExit(error = Tlv::Append(aMessage, kStatusNoMatchingFramesReceived)); + } + else + { + values.SetMetrics(seriesInfo->GetLinkMetrics()); + values.mPduCountValue = seriesInfo->GetPduCount(); + values.mLqiValue = seriesInfo->GetAverageLqi(); + values.mLinkMarginValue = Get().ComputeLinkMargin(seriesInfo->GetAverageRss()); + values.mRssiValue = seriesInfo->GetAverageRss(); + SuccessOrExit(error = AppendReportSubTlvToMessage(aMessage, values)); + } + } + + // Update the TLV length in message. + length = aMessage.GetLength() - offset - sizeof(Tlv); + tlv.SetLength(static_cast(length)); + aMessage.Write(offset, tlv); + +exit: + LogDebg("AppendReport, error:%s", ErrorToString(error)); + return error; +} + +Error Subject::HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus) +{ + Error error = kErrorNone; + uint16_t offset; + uint16_t endOffset; + uint16_t tlvEndOffset; + uint16_t length; + FwdProbingRegSubTlv fwdProbingSubTlv; + EnhAckConfigSubTlv enhAckConfigSubTlv; + Metrics metrics; + + SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, length)); + endOffset = offset + length; + + // Set sub-TLV lengths to zero to indicate that we have + // not yet seen them in the message. + fwdProbingSubTlv.SetLength(0); + enhAckConfigSubTlv.SetLength(0); + + for (; offset < endOffset; offset = tlvEndOffset) + { + Tlv tlv; + uint16_t minTlvSize; + Tlv *subTlv; + + SuccessOrExit(error = aMessage.Read(offset, tlv)); + + VerifyOrExit(offset + tlv.GetSize() <= endOffset, error = kErrorParse); + tlvEndOffset = static_cast(offset + tlv.GetSize()); + + switch (tlv.GetType()) + { + case SubTlv::kFwdProbingReg: + subTlv = &fwdProbingSubTlv; + minTlvSize = sizeof(Tlv) + FwdProbingRegSubTlv::kMinLength; + break; + + case SubTlv::kEnhAckConfig: + subTlv = &enhAckConfigSubTlv; + minTlvSize = sizeof(Tlv) + EnhAckConfigSubTlv::kMinLength; + break; + + default: + continue; + } + + // Ensure message contains only one sub-TLV. + VerifyOrExit(fwdProbingSubTlv.GetLength() == 0, error = kErrorParse); + VerifyOrExit(enhAckConfigSubTlv.GetLength() == 0, error = kErrorParse); + + VerifyOrExit(tlv.GetSize() >= minTlvSize, error = kErrorParse); + + // Read `subTlv` with its `minTlvSize`, followed by the Type IDs. + SuccessOrExit(error = aMessage.Read(offset, subTlv, minTlvSize)); + SuccessOrExit(error = ReadTypeIdsFromMessage(aMessage, offset + minTlvSize, tlvEndOffset, metrics)); + } + + if (fwdProbingSubTlv.GetLength() != 0) + { + aStatus = ConfigureForwardTrackingSeries(fwdProbingSubTlv.GetSeriesId(), fwdProbingSubTlv.GetSeriesFlagsMask(), + metrics, aNeighbor); + } + + if (enhAckConfigSubTlv.GetLength() != 0) + { + aStatus = ConfigureEnhAckProbing(enhAckConfigSubTlv.GetEnhAckFlags(), metrics, aNeighbor); + } + +exit: + return error; +} + +Error Subject::HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId) +{ + Error error = kErrorNone; + uint16_t offset; + uint16_t length; + + SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkProbe, offset, length)); + VerifyOrExit(length >= sizeof(aSeriesId), error = kErrorParse); + error = aMessage.Read(offset, aSeriesId); + +exit: + return error; +} + +Error Subject::AppendReportSubTlvToMessage(Message &aMessage, const MetricsValues &aValues) +{ + Error error = kErrorNone; + ReportSubTlv reportTlv; + + reportTlv.Init(); + + if (aValues.mMetrics.mPduCount) + { + reportTlv.SetMetricsTypeId(TypeId::kPdu); + reportTlv.SetMetricsValue32(aValues.mPduCountValue); + SuccessOrExit(error = reportTlv.AppendTo(aMessage)); + } + + if (aValues.mMetrics.mLqi) + { + reportTlv.SetMetricsTypeId(TypeId::kLqi); + reportTlv.SetMetricsValue8(aValues.mLqiValue); + SuccessOrExit(error = reportTlv.AppendTo(aMessage)); + } + + if (aValues.mMetrics.mLinkMargin) + { + reportTlv.SetMetricsTypeId(TypeId::kLinkMargin); + reportTlv.SetMetricsValue8(ScaleLinkMarginToRawValue(aValues.mLinkMarginValue)); + SuccessOrExit(error = reportTlv.AppendTo(aMessage)); + } + + if (aValues.mMetrics.mRssi) + { + reportTlv.SetMetricsTypeId(TypeId::kRssi); + reportTlv.SetMetricsValue8(ScaleRssiToRawValue(aValues.mRssiValue)); + SuccessOrExit(error = reportTlv.AppendTo(aMessage)); + } + +exit: + return error; +} + +void Subject::Free(SeriesInfo &aSeriesInfo) { mSeriesInfoPool.Free(aSeriesInfo); } + +Error Subject::ReadTypeIdsFromMessage(const Message &aMessage, + uint16_t aStartOffset, + uint16_t aEndOffset, + Metrics &aMetrics) { Error error = kErrorNone; @@ -714,46 +694,78 @@ exit: return error; } -Error LinkMetrics::AppendReportSubTlvToMessage(Message &aMessage, const MetricsValues &aValues) +Status Subject::ConfigureForwardTrackingSeries(uint8_t aSeriesId, + uint8_t aSeriesFlagsMask, + const Metrics &aMetrics, + Neighbor &aNeighbor) { - Error error = kErrorNone; - ReportSubTlv reportTlv; + Status status = kStatusSuccess; - reportTlv.Init(); + VerifyOrExit(0 < aSeriesId, status = kStatusOtherError); - if (aValues.mMetrics.mPduCount) + if (aSeriesFlagsMask == 0) // Remove the series { - reportTlv.SetMetricsTypeId(TypeId::kPdu); - reportTlv.SetMetricsValue32(aValues.mPduCountValue); - SuccessOrExit(error = reportTlv.AppendTo(aMessage)); + if (aSeriesId == kSeriesIdAllSeries) // Remove all + { + aNeighbor.RemoveAllForwardTrackingSeriesInfo(); + } + else + { + SeriesInfo *seriesInfo = aNeighbor.RemoveForwardTrackingSeriesInfo(aSeriesId); + VerifyOrExit(seriesInfo != nullptr, status = kStatusSeriesIdNotRecognized); + mSeriesInfoPool.Free(*seriesInfo); + } } - - if (aValues.mMetrics.mLqi) + else // Add a new series { - reportTlv.SetMetricsTypeId(TypeId::kLqi); - reportTlv.SetMetricsValue8(aValues.mLqiValue); - SuccessOrExit(error = reportTlv.AppendTo(aMessage)); - } + SeriesInfo *seriesInfo = aNeighbor.GetForwardTrackingSeriesInfo(aSeriesId); + VerifyOrExit(seriesInfo == nullptr, status = kStatusSeriesIdAlreadyRegistered); + seriesInfo = mSeriesInfoPool.Allocate(); + VerifyOrExit(seriesInfo != nullptr, status = kStatusCannotSupportNewSeries); - if (aValues.mMetrics.mLinkMargin) - { - reportTlv.SetMetricsTypeId(TypeId::kLinkMargin); - reportTlv.SetMetricsValue8(ScaleLinkMarginToRawValue(aValues.mLinkMarginValue)); - SuccessOrExit(error = reportTlv.AppendTo(aMessage)); - } + seriesInfo->Init(aSeriesId, aSeriesFlagsMask, aMetrics); - if (aValues.mMetrics.mRssi) - { - reportTlv.SetMetricsTypeId(TypeId::kRssi); - reportTlv.SetMetricsValue8(ScaleRssiToRawValue(aValues.mRssiValue)); - SuccessOrExit(error = reportTlv.AppendTo(aMessage)); + aNeighbor.AddForwardTrackingSeriesInfo(*seriesInfo); } exit: - return error; + return status; } -uint8_t LinkMetrics::ScaleLinkMarginToRawValue(uint8_t aLinkMargin) +Status Subject::ConfigureEnhAckProbing(uint8_t aEnhAckFlags, const Metrics &aMetrics, Neighbor &aNeighbor) +{ + Status status = kStatusSuccess; + Error error = kErrorNone; + + VerifyOrExit(!aMetrics.mReserved, status = kStatusOtherError); + + if (aEnhAckFlags == kEnhAckRegister) + { + VerifyOrExit(!aMetrics.mPduCount, status = kStatusOtherError); + VerifyOrExit(aMetrics.mLqi || aMetrics.mLinkMargin || aMetrics.mRssi, status = kStatusOtherError); + VerifyOrExit(!(aMetrics.mLqi && aMetrics.mLinkMargin && aMetrics.mRssi), status = kStatusOtherError); + + error = Get().ConfigureEnhAckProbing(aMetrics, aNeighbor.GetRloc16(), aNeighbor.GetExtAddress()); + } + else if (aEnhAckFlags == kEnhAckClear) + { + VerifyOrExit(!aMetrics.mLqi && !aMetrics.mLinkMargin && !aMetrics.mRssi, status = kStatusOtherError); + error = Get().ConfigureEnhAckProbing(aMetrics, aNeighbor.GetRloc16(), aNeighbor.GetExtAddress()); + } + else + { + status = kStatusOtherError; + } + + VerifyOrExit(error == kErrorNone, status = kStatusOtherError); + +exit: + return status; +} + +#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + +uint8_t ScaleLinkMarginToRawValue(uint8_t aLinkMargin) { // Linearly scale Link Margin from [0, 130] to [0, 255]. // `kMaxLinkMargin = 130`. @@ -767,7 +779,7 @@ uint8_t LinkMetrics::ScaleLinkMarginToRawValue(uint8_t aLinkMargin) return static_cast(value); } -uint8_t LinkMetrics::ScaleRawValueToLinkMargin(uint8_t aRawValue) +uint8_t ScaleRawValueToLinkMargin(uint8_t aRawValue) { // Scale back raw value of [0, 255] to Link Margin from [0, 130]. @@ -778,7 +790,7 @@ uint8_t LinkMetrics::ScaleRawValueToLinkMargin(uint8_t aRawValue) return static_cast(value); } -uint8_t LinkMetrics::ScaleRssiToRawValue(int8_t aRssi) +uint8_t ScaleRssiToRawValue(int8_t aRssi) { // Linearly scale RSSI from [-130, 0] to [0, 255]. // `kMinRssi = -130`, `kMaxRssi = 0`. @@ -792,7 +804,7 @@ uint8_t LinkMetrics::ScaleRssiToRawValue(int8_t aRssi) return static_cast(value); } -int8_t LinkMetrics::ScaleRawValueToRssi(uint8_t aRawValue) +int8_t ScaleRawValueToRssi(uint8_t aRawValue) { int32_t value = aRawValue; diff --git a/src/core/thread/link_metrics.hpp b/src/core/thread/link_metrics.hpp index aef44320c..0dcdd991f 100644 --- a/src/core/thread/link_metrics.hpp +++ b/src/core/thread/link_metrics.hpp @@ -71,16 +71,18 @@ namespace LinkMetrics { * @{ */ +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + /** - * This class implements Thread Link Metrics query and management. + * This class implements the Thread Link Metrics Initiator. + * + * The Initiator makes queries, configures Link Metrics probing at the Subject and generates reports of the results. * */ -class LinkMetrics : public InstanceLocator, private NonCopyable +class Initiator : public InstanceLocator, private NonCopyable { - friend class ot::Neighbor; - friend class ot::UnitTester; - public: + // Initiator callbacks typedef otLinkMetricsReportCallback ReportCallback; typedef otLinkMetricsMgmtResponseCallback MgmtResponseCallback; typedef otLinkMetricsEnhAckProbingIeReportCallback EnhAckProbingIeReportCallback; @@ -97,12 +99,12 @@ public: }; /** - * This constructor initializes an instance of the LinkMetrics class. + * This constructor initializes an instance of the Initiator class. * * @param[in] aInstance A reference to the OpenThread interface. * */ - explicit LinkMetrics(Instance &aInstance); + explicit Initiator(Instance &aInstance); /** * This method sends an MLE Data Request containing Link Metrics Query TLV to query Link Metrics data. @@ -121,7 +123,38 @@ public: */ Error Query(const Ip6::Address &aDestination, uint8_t aSeriesId, const Metrics *aMetrics); -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + /** + * This method appends MLE Link Metrics Query TLV to a given message. + * + * @param[in] aMessage The message to append to. + * @param[in] aInfo The link metrics query info to use to prepare the message. + * + * @retval kErrorNone Successfully appended the TLV to the message. + * @retval kErrorNoBufs Insufficient buffers available to append the TLV. + * + */ + Error AppendLinkMetricsQueryTlv(Message &aMessage, const QueryInfo &aInfo); + + /** + * This method registers a callback to handle Link Metrics report received. + * + * @param[in] aCallback A pointer to a function that is called when a Link Metrics report is received. + * @param[in] aContext A pointer to application-specific context. + * + */ + void SetReportCallback(ReportCallback aCallback, void *aContext) { mReportCallback.Set(aCallback, aContext); } + + /** + * This method handles the received Link Metrics report contained in @p aMessage. + * + * @param[in] aMessage A reference to the message. + * @param[in] aOffset The offset in bytes where the metrics report sub-TLVs start. + * @param[in] aLength The length of the metrics report sub-TLVs in bytes. + * @param[in] aAddress A reference to the source address of the message. + * + */ + void HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t aLength, const Ip6::Address &aAddress); + /** * This method sends an MLE Link Metrics Management Request to configure/clear a Forward Tracking Series. * @@ -141,6 +174,18 @@ public: const SeriesFlags &aSeriesFlags, const Metrics *aMetrics); + /** + * This method registers a callback to handle Link Metrics Management Response received. + * + * @param[in] aCallback A pointer to a function that is called when a Link Metrics Management Response is received. + * @param[in] aContext A pointer to application-specific context. + * + */ + void SetMgmtResponseCallback(MgmtResponseCallback aCallback, void *aContext) + { + mMgmtResponseCallback.Set(aCallback, aContext); + } + /** * This method sends an MLE Link Metrics Management Request to configure/clear a Enhanced-ACK Based Probing. * @@ -161,48 +206,16 @@ public: const Metrics *aMetrics); /** - * This method sends an MLE Link Probe message. + * This method registers a callback to handle Link Metrics when Enh-ACK Probing IE is received. * - * @param[in] aDestination A reference to the IPv6 address of the destination. - * @param[in] aSeriesId The Series ID which the Probe message targets at. - * @param[in] aLength The length of the data payload in Link Probe TLV, [0, 64]. - * - * @retval kErrorNone Successfully sent a Link Probe message. - * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Probe message. - * @retval kErrorInvalidArgs @p aSeriesId or @p aLength is not within the valid range. - * @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found. + * @param[in] aCallback A pointer to a function that is called when Enh-ACK Probing IE is received is received. + * @param[in] aContext A pointer to application-specific context. * */ - Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength); -#endif - -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - /** - * This method appends a Link Metrics Report to a message according to the Link Metrics query. - * - * @param[out] aMessage A reference to the message to append report. - * @param[in] aRequestMessage A reference to the message of the Data Request. - * @param[in] aNeighbor A reference to the neighbor who queries the report. - * - * @retval kErrorNone Successfully appended the Thread Discovery TLV. - * @retval kErrorParse Cannot parse query sub TLV successfully. - * @retval kErrorInvalidArgs QueryId is invalid or any Type ID is invalid. - * - */ - Error AppendReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor); -#endif - /** - * This method handles the received Link Metrics Management Request contained in @p aMessage and return a status. - * - * @param[in] aMessage A reference to the message that contains the Link Metrics Management Request. - * @param[in] aNeighbor A reference to the neighbor who sends the request. - * @param[out] aStatus A reference to the status which indicates the handling result. - * - * @retval kErrorNone Successfully handled the Link Metrics Management Request. - * @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully. - * - */ - Error HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus); + void SetEnhAckProbingCallback(EnhAckProbingIeReportCallback aCallback, void *aContext) + { + mEnhAckProbingIeReportCallback.Set(aCallback, aContext); + } /** * This method handles the received Link Metrics Management Response contained in @p aMessage. @@ -217,15 +230,89 @@ public: Error HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress); /** - * This method handles the received Link Metrics report contained in @p aMessage. + * This method sends an MLE Link Probe message. * - * @param[in] aMessage A reference to the message. - * @param[in] aOffset The offset in bytes where the metrics report sub-TLVs start. - * @param[in] aLength The length of the metrics report sub-TLVs in bytes. - * @param[in] aAddress A reference to the source address of the message. + * @param[in] aDestination A reference to the IPv6 address of the destination. + * @param[in] aSeriesId The Series ID which the Probe message targets at. + * @param[in] aLength The length of the data payload in Link Probe TLV, [0, 64]. + * + * @retval kErrorNone Successfully sent a Link Probe message. + * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Probe message. + * @retval kErrorInvalidArgs @p aSeriesId or @p aLength is not within the valid range. + * @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found. * */ - void HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t aLength, const Ip6::Address &aAddress); + Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength); + + /** + * This method processes received Enh-ACK Probing IE data. + * + * @param[in] aData A pointer to buffer containing the Enh-ACK Probing IE data. + * @param[in] aLength The length of @p aData. + * @param[in] aNeighbor The neighbor from which the Enh-ACK Probing IE was received. + * + */ + void ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLength, const Neighbor &aNeighbor); + +private: + static constexpr uint8_t kLinkProbeMaxLen = 64; // Max length of data payload in Link Probe TLV. + + Error FindNeighbor(const Ip6::Address &aDestination, Neighbor *&aNeighbor); + + Callback mReportCallback; + Callback mMgmtResponseCallback; + Callback mEnhAckProbingIeReportCallback; +}; + +#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + +/** + * This class implements the Thread Link Metrics Subject. + * + * The Subject reponds queries with reports, handles Link Metrics Management Requests and Link Probe Messages. + * + */ +class Subject : public InstanceLocator, private NonCopyable +{ +public: + typedef otLinkMetricsEnhAckProbingIeReportCallback EnhAckProbingIeReportCallback; + + /** + * This constructor initializes an instance of the Subject class. + * + * @param[in] aInstance A reference to the OpenThread interface. + * + */ + explicit Subject(Instance &aInstance); + + /** + * This method appends a Link Metrics Report to a message according to the Link Metrics query. + * + * @param[out] aMessage A reference to the message to append report. + * @param[in] aRequestMessage A reference to the message of the Data Request. + * @param[in] aNeighbor A reference to the neighbor who queries the report. + * + * @retval kErrorNone Successfully appended the Thread Discovery TLV. + * @retval kErrorParse Cannot parse query sub TLV successfully. + * @retval kErrorInvalidArgs QueryId is invalid or any Type ID is invalid. + * + */ + Error AppendReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor); + + /** + * This method handles the received Link Metrics Management Request contained in @p aMessage and return a status. + * + * @param[in] aMessage A reference to the message that contains the Link Metrics Management Request. + * @param[in] aNeighbor A reference to the neighbor who sends the request. + * @param[out] aStatus A reference to the status which indicates the handling result. + * + * @retval kErrorNone Successfully handled the Link Metrics Management Request. + * @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully. + * + */ + Error HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus); /** * This method handles the Link Probe contained in @p aMessage. @@ -240,100 +327,39 @@ public: Error HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId); /** - * This method registers a callback to handle Link Metrics report received. + * This method frees a SeriesInfo entry that was allocated from the Subject object. * - * @param[in] aCallback A pointer to a function that is called when a Link Metrics report is received. - * @param[in] aContext A pointer to application-specific context. + * @param[in] aSeries A reference to the SeriesInfo to free. * */ - void SetReportCallback(ReportCallback aCallback, void *aContext) { mReportCallback.Set(aCallback, aContext); } - - /** - * This method registers a callback to handle Link Metrics Management Response received. - * - * @param[in] aCallback A pointer to a function that is called when a Link Metrics Management Response is received. - * @param[in] aContext A pointer to application-specific context. - * - */ - void SetMgmtResponseCallback(MgmtResponseCallback aCallback, void *aContext) - { - mMgmtResponseCallback.Set(aCallback, aContext); - } - - /** - * This method registers a callback to handle Link Metrics when Enh-ACK Probing IE is received. - * - * @param[in] aCallback A pointer to a function that is called when Enh-ACK Probing IE is received is received. - * @param[in] aContext A pointer to application-specific context. - * - */ - void SetEnhAckProbingCallback(EnhAckProbingIeReportCallback aCallback, void *aContext) - { - mEnhAckProbingIeReportCallback.Set(aCallback, aContext); - } - - /** - * This method processes received Enh-ACK Probing IE data. - * - * @param[in] aData A pointer to buffer containing the Enh-ACK Probing IE data. - * @param[in] aLength The length of @p aData. - * @param[in] aNeighbor The neighbor from which the Enh-ACK Probing IE was received. - * - */ - void ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLength, const Neighbor &aNeighbor); - - /** - * This method appends MLE Link Metrics Query TLV to a given message. - * - * @param[in] aMessage The message to append to. - * @param[in] aInfo The link metrics query info to use to prepare the message. - * - * @retval kErrorNone Successfully appended the TLV to the message. - * @retval kErrorNoBufs Insufficient buffers available to append the TLV. - * - */ - Error AppendLinkMetricsQueryTlv(Message &aMessage, const QueryInfo &aInfo); + void Free(SeriesInfo &aSeriesInfo); private: // Max number of SeriesInfo that could be allocated by the pool. static constexpr uint16_t kMaxSeriesSupported = OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED; - static constexpr uint8_t kQueryIdSingleProbe = 0; // This query ID represents Single Probe. - static constexpr uint8_t kSeriesIdAllSeries = 255; // This series ID represents all series. - static constexpr uint8_t kLinkProbeMaxLen = 64; // Max length of data payload in Link Probe TLV. - - // Constants for scaling Link Margin and RSSI to raw value - static constexpr uint8_t kMaxLinkMargin = 130; - static constexpr int32_t kMinRssi = -130; - static constexpr int32_t kMaxRssi = 0; - - Status ConfigureForwardTrackingSeries(uint8_t aSeriesId, - uint8_t aSeriesFlags, - const Metrics &aMetrics, - Neighbor &aNeighbor); - - Status ConfigureEnhAckProbing(uint8_t aEnhAckFlags, const Metrics &aMetrics, Neighbor &aNeighbor); - - Error FindNeighbor(const Ip6::Address &aDestination, Neighbor *&aNeighbor) const; - static Error ReadTypeIdsFromMessage(const Message &aMessage, uint16_t aStartOffset, uint16_t aEndOffset, Metrics &aMetrics); static Error AppendReportSubTlvToMessage(Message &aMessage, const MetricsValues &aValues); - static uint8_t ScaleLinkMarginToRawValue(uint8_t aLinkMargin); - static uint8_t ScaleRawValueToLinkMargin(uint8_t aRawValue); - static uint8_t ScaleRssiToRawValue(int8_t aRssi); - static int8_t ScaleRawValueToRssi(uint8_t aRawValue); - - Callback mReportCallback; - Callback mMgmtResponseCallback; - Callback mEnhAckProbingIeReportCallback; + Status ConfigureForwardTrackingSeries(uint8_t aSeriesId, + uint8_t aSeriesFlags, + const Metrics &aMetrics, + Neighbor &aNeighbor); + Status ConfigureEnhAckProbing(uint8_t aEnhAckFlags, const Metrics &aMetrics, Neighbor &aNeighbor); Pool mSeriesInfoPool; }; +#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + +uint8_t ScaleLinkMarginToRawValue(uint8_t aLinkMargin); +uint8_t ScaleRawValueToLinkMargin(uint8_t aRawValue); +uint8_t ScaleRssiToRawValue(int8_t aRssi); +int8_t ScaleRawValueToRssi(uint8_t aRawValue); + /** * @} */ diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 440f44d69..bd6510185 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1857,20 +1857,20 @@ Error Mle::SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t return SendDataRequest(aDestination, kTlvs, mRequestRouteTlv ? 2 : 1, aDelay); } -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE -Error Mle::SendDataRequestForLinkMetricsReport(const Ip6::Address &aDestination, - const LinkMetrics::LinkMetrics::QueryInfo &aQueryInfo) +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE +Error Mle::SendDataRequestForLinkMetricsReport(const Ip6::Address &aDestination, + const LinkMetrics::Initiator::QueryInfo &aQueryInfo) { static const uint8_t kTlvs[] = {Tlv::kLinkMetricsReport}; return SendDataRequest(aDestination, kTlvs, sizeof(kTlvs), /* aDelay */ 0, &aQueryInfo); } -Error Mle::SendDataRequest(const Ip6::Address &aDestination, - const uint8_t *aTlvs, - uint8_t aTlvsLength, - uint16_t aDelay, - const LinkMetrics::LinkMetrics::QueryInfo *aQueryInfo) +Error Mle::SendDataRequest(const Ip6::Address &aDestination, + const uint8_t *aTlvs, + uint8_t aTlvsLength, + uint16_t aDelay, + const LinkMetrics::Initiator::QueryInfo *aQueryInfo) #else Error Mle::SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aDelay) #endif @@ -1883,10 +1883,10 @@ Error Mle::SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlv VerifyOrExit((message = NewMleMessage(kCommandDataRequest)) != nullptr, error = kErrorNoBufs); SuccessOrExit(error = message->AppendTlvRequestTlv(aTlvs, aTlvsLength)); -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE if (aQueryInfo != nullptr) { - SuccessOrExit(error = Get().AppendLinkMetricsQueryTlv(*message, *aQueryInfo)); + SuccessOrExit(error = Get().AppendLinkMetricsQueryTlv(*message, *aQueryInfo)); } #endif @@ -2840,8 +2840,8 @@ void Mle::HandleDataResponse(RxInfo &aRxInfo) if (Tlv::FindTlvValueOffset(aRxInfo.mMessage, Tlv::kLinkMetricsReport, offset, length) == kErrorNone) { - Get().HandleReport(aRxInfo.mMessage, offset, length, - aRxInfo.mMessageInfo.GetPeerAddr()); + Get().HandleReport(aRxInfo.mMessage, offset, length, + aRxInfo.mMessageInfo.GetPeerAddr()); } } #endif @@ -3779,7 +3779,7 @@ void Mle::HandleLinkMetricsManagementRequest(RxInfo &aRxInfo) VerifyOrExit(aRxInfo.mNeighbor != nullptr, error = kErrorInvalidState); SuccessOrExit( - error = Get().HandleManagementRequest(aRxInfo.mMessage, *aRxInfo.mNeighbor, status)); + error = Get().HandleManagementRequest(aRxInfo.mMessage, *aRxInfo.mNeighbor, status)); error = SendLinkMetricsManagementResponse(aRxInfo.mMessageInfo.GetPeerAddr(), status); @@ -3801,7 +3801,7 @@ void Mle::HandleLinkMetricsManagementResponse(RxInfo &aRxInfo) VerifyOrExit(aRxInfo.mNeighbor != nullptr, error = kErrorInvalidState); error = - Get().HandleManagementResponse(aRxInfo.mMessage, aRxInfo.mMessageInfo.GetPeerAddr()); + Get().HandleManagementResponse(aRxInfo.mMessage, aRxInfo.mMessageInfo.GetPeerAddr()); aRxInfo.mClass = RxInfo::kPeerMessage; @@ -3818,7 +3818,7 @@ void Mle::HandleLinkProbe(RxInfo &aRxInfo) Log(kMessageReceive, kTypeLinkProbe, aRxInfo.mMessageInfo.GetPeerAddr()); - SuccessOrExit(error = Get().HandleLinkProbe(aRxInfo.mMessage, seriesId)); + SuccessOrExit(error = Get().HandleLinkProbe(aRxInfo.mMessage, seriesId)); aRxInfo.mNeighbor->AggregateLinkMetrics(seriesId, LinkMetrics::SeriesInfo::kSeriesTypeLinkProbe, aRxInfo.mMessage.GetAverageLqi(), aRxInfo.mMessage.GetAverageRss()); diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 163a4af95..f33b52552 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -103,8 +103,8 @@ class Mle : public InstanceLocator, private NonCopyable friend class DiscoverScanner; friend class ot::Notifier; friend class ot::SupervisionListener; -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - friend class ot::LinkMetrics::LinkMetrics; +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + friend class ot::LinkMetrics::Initiator; #endif public: @@ -1536,7 +1536,7 @@ protected: */ Error SendDataRequest(const Ip6::Address &aDestination); -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE /** * This method generates an MLE Data Request message which request Link Metrics Report TLV. * @@ -1547,8 +1547,8 @@ protected: * @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message. * */ - Error SendDataRequestForLinkMetricsReport(const Ip6::Address &aDestination, - const LinkMetrics::LinkMetrics::QueryInfo &aQueryInfo); + Error SendDataRequestForLinkMetricsReport(const Ip6::Address &aDestination, + const LinkMetrics::Initiator::QueryInfo &aQueryInfo); #endif /** @@ -1976,12 +1976,12 @@ private: Error SendChildUpdateRequest(ChildUpdateRequestMode aMode); Error SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay); -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - Error SendDataRequest(const Ip6::Address &aDestination, - const uint8_t *aTlvs, - uint8_t aTlvsLength, - uint16_t aDelay, - const LinkMetrics::LinkMetrics::QueryInfo *aQueryInfo = nullptr); +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE + Error SendDataRequest(const Ip6::Address &aDestination, + const uint8_t *aTlvs, + uint8_t aTlvsLength, + uint16_t aDelay, + const LinkMetrics::Initiator::QueryInfo *aQueryInfo = nullptr); #else Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aDelay); #endif @@ -2003,12 +2003,10 @@ private: void HandleAnnounce(RxInfo &aRxInfo); #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE void HandleLinkMetricsManagementRequest(RxInfo &aRxInfo); + void HandleLinkProbe(RxInfo &aRxInfo); #endif #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE void HandleLinkMetricsManagementResponse(RxInfo &aRxInfo); -#endif -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - void HandleLinkProbe(RxInfo &aRxInfo); #endif Error HandleLeaderData(RxInfo &aRxInfo); void ProcessAnnounce(void); diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 052c93e53..bade0cb64 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -3167,7 +3167,7 @@ void MleRouter::SendDataResponse(const Ip6::Address &aDestination, OT_ASSERT(aRequestMessage != nullptr); neighbor = mNeighborTable.FindNeighbor(aDestination); VerifyOrExit(neighbor != nullptr, error = kErrorInvalidState); - SuccessOrExit(error = Get().AppendReport(*message, *aRequestMessage, *neighbor)); + SuccessOrExit(error = Get().AppendReport(*message, *aRequestMessage, *neighbor)); break; #endif } diff --git a/src/core/thread/topology.cpp b/src/core/thread/topology.cpp index 8b6e65880..10959f86f 100644 --- a/src/core/thread/topology.cpp +++ b/src/core/thread/topology.cpp @@ -208,7 +208,7 @@ void Neighbor::RemoveAllForwardTrackingSeriesInfo(void) while (!mLinkMetricsSeriesInfoList.IsEmpty()) { LinkMetrics::SeriesInfo *seriesInfo = mLinkMetricsSeriesInfoList.Pop(); - Get().mSeriesInfoPool.Free(*seriesInfo); + Get().Free(*seriesInfo); } } #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE diff --git a/tests/unit/test_link_quality.cpp b/tests/unit/test_link_quality.cpp index a1155efd3..0f2e9eb76 100644 --- a/tests/unit/test_link_quality.cpp +++ b/tests/unit/test_link_quality.cpp @@ -494,13 +494,13 @@ public: printf("\nLinkMargin : %-3u -> Scaled : %.1f (rounded:%u)", linkMargin, scaled, scaledAsU8); - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleLinkMarginToRawValue(linkMargin) == scaledAsU8); - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleRawValueToLinkMargin(scaledAsU8) == linkMargin); + VerifyOrQuit(LinkMetrics::ScaleLinkMarginToRawValue(linkMargin) == scaledAsU8); + VerifyOrQuit(LinkMetrics::ScaleRawValueToLinkMargin(scaledAsU8) == linkMargin); } - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleLinkMarginToRawValue(131) == 255); - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleLinkMarginToRawValue(150) == 255); - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleLinkMarginToRawValue(255) == 255); + VerifyOrQuit(LinkMetrics::ScaleLinkMarginToRawValue(131) == 255); + VerifyOrQuit(LinkMetrics::ScaleLinkMarginToRawValue(150) == 255); + VerifyOrQuit(LinkMetrics::ScaleLinkMarginToRawValue(255) == 255); // Test RSSI scaling from [-130, 0] -> [0, 255] @@ -511,13 +511,13 @@ public: printf("\nRSSI : %-3d -> Scaled :%.1f (rounded:%u)", rssi, scaled, scaledAsU8); - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleRssiToRawValue(rssi) == scaledAsU8); - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleRawValueToRssi(scaledAsU8) == rssi); + VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(rssi) == scaledAsU8); + VerifyOrQuit(LinkMetrics::ScaleRawValueToRssi(scaledAsU8) == rssi); } - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleRssiToRawValue(1) == 255); - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleRssiToRawValue(10) == 255); - VerifyOrQuit(LinkMetrics::LinkMetrics::ScaleRssiToRawValue(127) == 255); + VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(1) == 255); + VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(10) == 255); + VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(127) == 255); } };