diff --git a/src/core/thread/link_metrics.cpp b/src/core/thread/link_metrics.cpp index 90ac4872d..40bf0db0e 100644 --- a/src/core/thread/link_metrics.cpp +++ b/src/core/thread/link_metrics.cpp @@ -94,37 +94,28 @@ Error LinkMetrics::SendMgmtRequestForwardTrackingSeries(const Ip6::Address & const SeriesFlags::Info &aSeriesFlags, const Metrics * aMetrics) { - Error error = kErrorNone; - uint8_t subTlvs[sizeof(Tlv) + sizeof(uint8_t) * 2 + sizeof(TypeIdFlags) * kMaxTypeIdFlags]; - Tlv * fwdProbingSubTlv = reinterpret_cast(subTlvs); - SeriesFlags *seriesFlags = reinterpret_cast(subTlvs + sizeof(Tlv) + sizeof(aSeriesId)); - uint8_t typeIdFlagsOffset = sizeof(Tlv) + sizeof(uint8_t) * 2; - uint8_t typeIdFlagsCount = 0; - Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination); + Error error = kErrorNone; + Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination); + uint8_t typeIdCount = 0; + FwdProbingRegSubTlv fwdProbingSubTlv; VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor); VerifyOrExit(neighbor->IsThreadVersion1p2OrHigher(), error = kErrorNotCapable); - // Directly transform `aMetrics` into TypeIdFlags and put them into `subTlvs` - if (aMetrics != nullptr) - { - typeIdFlagsCount = - TypeIdFlagsFromMetrics(reinterpret_cast(subTlvs + typeIdFlagsOffset), *aMetrics); - } - VerifyOrExit(aSeriesId > kQueryIdSingleProbe, error = kErrorInvalidArgs); - fwdProbingSubTlv->SetType(SubTlv::kFwdProbingReg); + fwdProbingSubTlv.Init(); + fwdProbingSubTlv.SetSeriesId(aSeriesId); + fwdProbingSubTlv.GetSeriesFlags().SetFrom(aSeriesFlags); - // SeriesId + SeriesFlags + typeIdFlagsCount * TypeIdFlags - fwdProbingSubTlv->SetLength(sizeof(uint8_t) * 2 + sizeof(TypeIdFlags) * typeIdFlagsCount); + if (aMetrics != nullptr) + { + typeIdCount = TypeIdFlagsFromMetrics(fwdProbingSubTlv.GetTypeIds(), *aMetrics); + } - memcpy(subTlvs + sizeof(Tlv), &aSeriesId, sizeof(aSeriesId)); + fwdProbingSubTlv.SetLength(sizeof(aSeriesId) + sizeof(SeriesFlags) + typeIdCount * sizeof(TypeIdFlags)); - seriesFlags->SetFrom(aSeriesFlags); - - error = Get().SendLinkMetricsManagementRequest(aDestination, subTlvs, - static_cast(fwdProbingSubTlv->GetSize())); + error = Get().SendLinkMetricsManagementRequest(aDestination, fwdProbingSubTlv); exit: LogDebg("SendMgmtRequestForwardTrackingSeries, error:%s, Series ID:%u", ErrorToString(error), aSeriesId); @@ -135,10 +126,10 @@ Error LinkMetrics::SendMgmtRequestEnhAckProbing(const Ip6::Address &aDestination const EnhAckFlags aEnhAckFlags, const Metrics * aMetrics) { - Error error = kErrorNone; + Error error = kErrorNone; + Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination); + uint8_t typeIdCount = 0; EnhAckConfigSubTlv enhAckConfigSubTlv; - Mac::Address macAddress; - Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination); VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor); VerifyOrExit(neighbor->IsThreadVersion1p2OrHigher(), error = kErrorNotCapable); @@ -148,16 +139,17 @@ Error LinkMetrics::SendMgmtRequestEnhAckProbing(const Ip6::Address &aDestination VerifyOrExit(aMetrics == nullptr, error = kErrorInvalidArgs); } + enhAckConfigSubTlv.Init(); enhAckConfigSubTlv.SetEnhAckFlags(aEnhAckFlags); if (aMetrics != nullptr) { - enhAckConfigSubTlv.SetTypeIdFlags(*aMetrics); + typeIdCount = TypeIdFlagsFromMetrics(enhAckConfigSubTlv.GetTypeIds(), *aMetrics); } - error = Get().SendLinkMetricsManagementRequest( - aDestination, reinterpret_cast(&enhAckConfigSubTlv), - static_cast(enhAckConfigSubTlv.GetSize())); + enhAckConfigSubTlv.SetLength(EnhAckConfigSubTlv::kMinLength + typeIdCount * sizeof(TypeIdFlags)); + + error = Get().SendLinkMetricsManagementRequest(aDestination, enhAckConfigSubTlv); if (aMetrics != nullptr) { diff --git a/src/core/thread/link_metrics.hpp b/src/core/thread/link_metrics.hpp index f5d08f6d9..288c6634d 100644 --- a/src/core/thread/link_metrics.hpp +++ b/src/core/thread/link_metrics.hpp @@ -265,8 +265,6 @@ public: void ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLength, const Neighbor &aNeighbor); private: - static constexpr uint8_t kMaxTypeIdFlags = 4; - // Max number of SeriesInfo that could be allocated by the pool. static constexpr uint16_t kMaxSeriesSupported = OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED; diff --git a/src/core/thread/link_metrics_tlvs.hpp b/src/core/thread/link_metrics_tlvs.hpp index b9b32aff1..dbbd42369 100644 --- a/src/core/thread/link_metrics_tlvs.hpp +++ b/src/core/thread/link_metrics_tlvs.hpp @@ -209,15 +209,86 @@ public: } OT_TOOL_PACKED_END; +/** + * This class defines Link Metrics Forward Probing Registration Sub-TLV. + * + */ +OT_TOOL_PACKED_BEGIN +class FwdProbingRegSubTlv : public Tlv, public TlvInfo +{ +public: + static constexpr uint8_t kMinLength = sizeof(uint8_t) + sizeof(SeriesFlags); ///< Minimum expected TLV length + + /** + * This method initializes the TLV. + * + */ + void Init(void) + { + SetType(SubTlv::kFwdProbingReg); + SetLength(kMinLength); + } + + /** + * This method indicates whether or not the TLV appears to be well-formed. + * + * @retval true The TLV appears to be well-formed. + * @retval false The TLV does not appear to be well-formed. + * + */ + bool IsValid(void) const { return GetLength() >= kMinLength; } + + /** + * This method gets the Forward Series ID value. + * + * @returns The Forward Series ID. + * + */ + uint8_t GetSeriesId(void) const { return mSeriesId; } + + /** + * This method sets the Forward Series ID value. + * + * @param[in] aSeriesId The Forward Series ID. + * + */ + void SetSeriesId(uint8_t aSeriesId) { mSeriesId = aSeriesId; } + + /** + * This method gets the Forward Series Flags. + * + * @returns The Forward Series Flags. + * + */ + SeriesFlags &GetSeriesFlags(void) { return mSeriesFlags; } + + /** + * This method sets the Forward Series Flags. + * + * @param[in] aSeriesFlags The Forward Series Flags. + * + */ + void SetSeriesFlags(const SeriesFlags &aSeriesFlags) { mSeriesFlags = aSeriesFlags; } + + /** + * This method gets the start of Type ID Flags array. + * + * @returns The start of Type ID Flags array. Array has `kMaxTypeIdFlags` max length. + * + */ + TypeIdFlags *GetTypeIds(void) { return mTypeIds; } + +private: + uint8_t mSeriesId; + SeriesFlags mSeriesFlags; + TypeIdFlags mTypeIds[kMaxTypeIdFlags]; +} OT_TOOL_PACKED_END; + OT_TOOL_PACKED_BEGIN class EnhAckConfigSubTlv : public Tlv, public TlvInfo { public: - /** - * Default constructor - * - */ - EnhAckConfigSubTlv(void) { Init(); } + static constexpr uint8_t kMinLength = sizeof(uint8_t); ///< Minimum TLV length (only `EnhAckFlags`). /** * This method initializes the TLV. @@ -226,43 +297,45 @@ public: void Init(void) { SetType(SubTlv::kEnhAckConfig); - SetLength(sizeof(EnhAckFlags)); + SetLength(kMinLength); } + /** + * This method indicates whether or not the TLV appears to be well-formed. + * + * @retval true The TLV appears to be well-formed. + * @retval false The TLV does not appear to be well-formed. + * + */ + bool IsValid(void) const { return GetLength() >= kMinLength; } + + /** + * This method gets the Enhanced ACK Flags. + * + * @returns The Enhanced ACK Flags. + * + */ + uint8_t GetEnhAckFlags(void) const { return mEnhAckFlags; } + /** * This method sets Enhanced ACK Flags. * * @param[in] aEnhAckFlags The value of Enhanced ACK Flags. * */ - void SetEnhAckFlags(EnhAckFlags aEnhAckFlags) - { - memcpy(mSubTlvs + kEnhAckFlagsOffset, &aEnhAckFlags, sizeof(aEnhAckFlags)); - } + void SetEnhAckFlags(EnhAckFlags aEnhAckFlags) { mEnhAckFlags = aEnhAckFlags; } /** - * This method sets Type ID Flags. + * This method gets the start of Type ID Flags array. * - * @param[in] aMetrics A metrics flags to indicate the Type ID Flags. + * @returns The start of Type ID Flags array. Array has `kMaxTypeIdFlags` max length. * */ - void SetTypeIdFlags(const Metrics &aMetrics) - { - uint8_t count; - - count = TypeIdFlagsFromMetrics(reinterpret_cast(mSubTlvs + kTypeIdFlagsOffset), aMetrics); - - OT_ASSERT(count <= kMaxTypeIdFlagsEnhAck); - - SetLength(sizeof(EnhAckFlags) + sizeof(TypeIdFlags) * count); - } + TypeIdFlags *GetTypeIds(void) { return mTypeIds; } private: - static constexpr uint8_t kMaxTypeIdFlagsEnhAck = 3; - static constexpr uint8_t kEnhAckFlagsOffset = 0; - static constexpr uint16_t kTypeIdFlagsOffset = sizeof(TypeIdFlags); - - uint8_t mSubTlvs[sizeof(EnhAckFlags) + sizeof(TypeIdFlags) * kMaxTypeIdFlagsEnhAck]; + uint8_t mEnhAckFlags; + TypeIdFlags mTypeIds[kMaxTypeIdFlags]; } OT_TOOL_PACKED_END; } // namespace LinkMetrics diff --git a/src/core/thread/link_metrics_types.hpp b/src/core/thread/link_metrics_types.hpp index ad99fc26d..505d84d4f 100644 --- a/src/core/thread/link_metrics_types.hpp +++ b/src/core/thread/link_metrics_types.hpp @@ -445,6 +445,8 @@ enum EnhAckFlags : uint8_t kEnhAckRegister = OT_LINK_METRICS_ENH_ACK_REGISTER, ///< Register. }; +constexpr uint8_t kMaxTypeIdFlags = 4; ///< Maximum number of TypeIdFlags in a `Metrics` + uint8_t TypeIdFlagsFromMetrics(TypeIdFlags aTypeIdFlags[], const Metrics &aMetrics); /** diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 007189561..ffa0a5c60 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -4248,22 +4248,21 @@ const char *Mle::ReattachStateToString(ReattachState aState) // LCOV_EXCL_STOP #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE -Error Mle::SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const uint8_t *aSubTlvs, uint8_t aLength) +Error Mle::SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const ot::Tlv &aSubTlv) { - Error error = kErrorNone; - TxMessage *message; + Error error = kErrorNone; + TxMessage *message = NewMleMessage(kCommandLinkMetricsManagementRequest); Tlv tlv; - VerifyOrExit((message = NewMleMessage(kCommandLinkMetricsManagementRequest)) != nullptr, error = kErrorNoBufs); + VerifyOrExit(message != nullptr, error = kErrorNoBufs); - // Link Metrics Management TLV tlv.SetType(Tlv::kLinkMetricsManagement); - tlv.SetLength(aLength); + tlv.SetLength(static_cast(aSubTlv.GetSize())); - SuccessOrExit(error = message->AppendBytes(&tlv, sizeof(tlv))); - SuccessOrExit(error = message->AppendBytes(aSubTlvs, aLength)); + SuccessOrExit(error = message->Append(tlv)); + SuccessOrExit(error = aSubTlv.AppendTo(*message)); - SuccessOrExit(error = message->SendTo(aDestination)); + error = message->SendTo(aDestination); exit: FreeMessageOnError(message, error); diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 4de09fe29..961065026 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1650,14 +1650,13 @@ protected: * This method sends a Link Metrics Management Request message. * * @param[in] aDestination A reference to the IPv6 address of the destination. - * @param[in] aSubTlvs A pointer to the buffer of the sub-TLVs in the message. - * @param[in] aLength The overall length of @p aSubTlvs. + * @param[in] aSubTlv A reference to the sub-TLV to include. * * @retval kErrorNone Successfully sent a Link Metrics Management Request. * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message. * */ - Error SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const uint8_t *aSubTlvs, uint8_t aLength); + Error SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const ot::Tlv &aSubTlv); /** * This method sends an MLE Link Probe message.