mirror of
https://github.com/espressif/openthread.git
synced 2026-08-06 10:47:46 +00:00
[link-metrics] simplify preparation of MLE Data Request (#8142)
This commit simplifies the preparation of MLE Data Request message which include a Link Metrics Query TLV and its sub-TLVs.
This commit is contained in:
@@ -64,25 +64,29 @@ LinkMetrics::LinkMetrics(Instance &aInstance)
|
||||
|
||||
Error LinkMetrics::Query(const Ip6::Address &aDestination, uint8_t aSeriesId, const Metrics *aMetrics)
|
||||
{
|
||||
Error error;
|
||||
TypeIdFlags typeIdFlags[kMaxTypeIdFlags];
|
||||
uint8_t typeIdFlagsCount = 0;
|
||||
Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination);
|
||||
static const uint8_t kTlvs[] = {Mle::Tlv::kLinkMetricsReport};
|
||||
|
||||
Error error;
|
||||
Neighbor *neighbor = GetNeighborFromLinkLocalAddr(aDestination);
|
||||
QueryInfo info;
|
||||
|
||||
VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
|
||||
VerifyOrExit(neighbor->IsThreadVersion1p2OrHigher(), error = kErrorNotCapable);
|
||||
|
||||
info.Clear();
|
||||
info.mSeriesId = aSeriesId;
|
||||
|
||||
if (aMetrics != nullptr)
|
||||
{
|
||||
typeIdFlagsCount = TypeIdFlagsFromMetrics(typeIdFlags, *aMetrics);
|
||||
info.mTypeIdCount = TypeIdFlagsFromMetrics(info.mTypeIds, *aMetrics);
|
||||
}
|
||||
|
||||
if (aSeriesId != 0)
|
||||
{
|
||||
VerifyOrExit(typeIdFlagsCount == 0, error = kErrorInvalidArgs);
|
||||
VerifyOrExit(info.mTypeIdCount == 0, error = kErrorInvalidArgs);
|
||||
}
|
||||
|
||||
error = SendLinkMetricsQuery(aDestination, aSeriesId, typeIdFlags, typeIdFlagsCount);
|
||||
error = Get<Mle::MleRouter>().SendDataRequest(aDestination, kTlvs, sizeof(kTlvs), /* aDelay */ 0, info);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -560,52 +564,32 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error LinkMetrics::SendLinkMetricsQuery(const Ip6::Address &aDestination,
|
||||
uint8_t aSeriesId,
|
||||
const TypeIdFlags * aTypeIdFlags,
|
||||
uint8_t aTypeIdFlagsCount)
|
||||
Error LinkMetrics::AppendLinkMetricsQueryTlv(Message &aMessage, const QueryInfo &aInfo)
|
||||
{
|
||||
// LinkMetricsQuery Tlv + LinkMetricsQueryId sub-TLV (value-length: 1 byte) +
|
||||
// LinkMetricsQueryOptions sub-TLV (value-length: `kMaxTypeIdFlags` bytes)
|
||||
constexpr uint16_t kBufferSize = sizeof(Tlv) * 3 + sizeof(uint8_t) + sizeof(TypeIdFlags) * kMaxTypeIdFlags;
|
||||
Error error = kErrorNone;
|
||||
Tlv tlv;
|
||||
|
||||
Error error = kErrorNone;
|
||||
QueryOptionsSubTlv queryOptionsTlv;
|
||||
uint8_t length = 0;
|
||||
static const uint8_t tlvs[] = {Mle::Tlv::kLinkMetricsReport};
|
||||
uint8_t buf[kBufferSize];
|
||||
Tlv * tlv = reinterpret_cast<Tlv *>(buf);
|
||||
Tlv subTlv;
|
||||
// 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.
|
||||
|
||||
// Link Metrics Query TLV
|
||||
tlv->SetType(Mle::Tlv::kLinkMetricsQuery);
|
||||
length += sizeof(Tlv);
|
||||
tlv.SetType(Mle::Tlv::kLinkMetricsQuery);
|
||||
tlv.SetLength(sizeof(Tlv) + sizeof(uint8_t) + ((aInfo.mTypeIdCount == 0) ? 0 : (sizeof(Tlv) + aInfo.mTypeIdCount)));
|
||||
|
||||
// Link Metrics Query ID sub-TLV
|
||||
subTlv.SetType(SubTlv::kQueryId);
|
||||
subTlv.SetLength(sizeof(uint8_t));
|
||||
memcpy(buf + length, &subTlv, sizeof(subTlv));
|
||||
length += sizeof(subTlv);
|
||||
memcpy(buf + length, &aSeriesId, sizeof(aSeriesId));
|
||||
length += sizeof(aSeriesId);
|
||||
SuccessOrExit(error = aMessage.Append(tlv));
|
||||
|
||||
// Link Metrics Query Options sub-TLV
|
||||
if (aTypeIdFlagsCount > 0)
|
||||
SuccessOrExit(error = Tlv::Append<QueryIdSubTlv>(aMessage, aInfo.mSeriesId));
|
||||
|
||||
if (aInfo.mTypeIdCount != 0)
|
||||
{
|
||||
QueryOptionsSubTlv queryOptionsTlv;
|
||||
|
||||
queryOptionsTlv.Init();
|
||||
queryOptionsTlv.SetLength(aTypeIdFlagsCount * sizeof(TypeIdFlags));
|
||||
|
||||
memcpy(buf + length, &queryOptionsTlv, sizeof(queryOptionsTlv));
|
||||
length += sizeof(queryOptionsTlv);
|
||||
memcpy(buf + length, aTypeIdFlags, queryOptionsTlv.GetLength());
|
||||
length += queryOptionsTlv.GetLength();
|
||||
queryOptionsTlv.SetLength(aInfo.mTypeIdCount);
|
||||
SuccessOrExit(error = aMessage.Append(queryOptionsTlv));
|
||||
SuccessOrExit(error = aMessage.AppendBytes(aInfo.mTypeIds, aInfo.mTypeIdCount));
|
||||
}
|
||||
|
||||
// Set Length for Link Metrics Report TLV
|
||||
tlv->SetLength(length - sizeof(Tlv));
|
||||
|
||||
SuccessOrExit(error = Get<Mle::MleRouter>().SendDataRequest(aDestination, tlvs, sizeof(tlvs), 0, buf, length));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,17 @@ public:
|
||||
typedef otLinkMetricsMgmtResponseCallback MgmtResponseCallback;
|
||||
typedef otLinkMetricsEnhAckProbingIeReportCallback EnhAckProbingIeReportCallback;
|
||||
|
||||
/**
|
||||
* This structure provides the info used for appending MLE Link Metric Query TLV.
|
||||
*
|
||||
*/
|
||||
struct QueryInfo : public Clearable<QueryInfo>
|
||||
{
|
||||
uint8_t mSeriesId; ///< Series ID.
|
||||
TypeIdFlags mTypeIds[kMaxTypeIdFlags]; ///< Type ID flags.
|
||||
uint8_t mTypeIdCount; ///< Number of entries in `mTypeIds[]`.
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes an instance of the LinkMetrics class.
|
||||
*
|
||||
@@ -264,6 +275,18 @@ public:
|
||||
*/
|
||||
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);
|
||||
|
||||
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;
|
||||
@@ -277,11 +300,6 @@ private:
|
||||
static constexpr int32_t kMinRssi = -130;
|
||||
static constexpr int32_t kMaxRssi = 0;
|
||||
|
||||
Error SendLinkMetricsQuery(const Ip6::Address &aDestination,
|
||||
uint8_t aSeriesId,
|
||||
const TypeIdFlags * aTypeIdFlags,
|
||||
uint8_t aTypeIdFlagsCount);
|
||||
|
||||
Status ConfigureForwardTrackingSeries(uint8_t aSeriesId,
|
||||
uint8_t aSeriesFlags,
|
||||
const Metrics &aMetrics,
|
||||
|
||||
+13
-8
@@ -1797,12 +1797,15 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Mle::SendDataRequest(const Ip6::Address &aDestination,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
uint16_t aDelay,
|
||||
const uint8_t * aExtraTlvs,
|
||||
uint8_t aExtraTlvsLength)
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
Error Mle::SendDataRequest(const Ip6::Address & aDestination,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
uint16_t aDelay,
|
||||
const LinkMetrics::LinkMetrics::QueryInfo *aQueryInfo)
|
||||
#else
|
||||
Error Mle::SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aDelay)
|
||||
#endif
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
TxMessage *message;
|
||||
@@ -1812,10 +1815,12 @@ Error Mle::SendDataRequest(const Ip6::Address &aDestination,
|
||||
VerifyOrExit((message = NewMleMessage(kCommandDataRequest)) != nullptr, error = kErrorNoBufs);
|
||||
SuccessOrExit(error = message->AppendTlvRequestTlv(aTlvs, aTlvsLength));
|
||||
|
||||
if (aExtraTlvs != nullptr && aExtraTlvsLength > 0)
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
if (aQueryInfo != nullptr)
|
||||
{
|
||||
SuccessOrExit(error = message->AppendBytes(aExtraTlvs, aExtraTlvsLength));
|
||||
SuccessOrExit(error = Get<LinkMetrics::LinkMetrics>().AppendLinkMetricsQueryTlv(*message, *aQueryInfo));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aDelay)
|
||||
{
|
||||
|
||||
+23
-10
@@ -1447,26 +1447,29 @@ protected:
|
||||
*/
|
||||
Mac::ShortAddress GetNextHop(uint16_t aDestination) const;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
|
||||
/**
|
||||
* This method generates an MLE Data Request message.
|
||||
* This method generates an MLE Data Request message which includes a Link Metrics Query TLV.
|
||||
*
|
||||
* @param[in] aDestination A reference to the IPv6 address of the destination.
|
||||
* @param[in] aTlvs A pointer to requested TLV types.
|
||||
* @param[in] aTlvsLength The number of TLV types in @p aTlvs.
|
||||
* @param[in] aDelay Delay in milliseconds before the Data Request message is sent.
|
||||
* @param[in] aExtraTlvs A pointer to extra TLVs.
|
||||
* @param[in] aExtraTlvsLength Length of extra TLVs.
|
||||
* @param[in] aQueryInfo A Link Metrics query info.
|
||||
*
|
||||
* @retval kErrorNone Successfully generated an MLE Data Request message.
|
||||
* @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message.
|
||||
*
|
||||
*/
|
||||
Error SendDataRequest(const Ip6::Address &aDestination,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
uint16_t aDelay,
|
||||
const uint8_t * aExtraTlvs,
|
||||
uint8_t aExtraTlvsLength);
|
||||
Error SendDataRequest(const Ip6::Address & aDestination,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
uint16_t aDelay,
|
||||
const LinkMetrics::LinkMetrics::QueryInfo &aQueryInfo)
|
||||
{
|
||||
return SendDataRequest(aDestination, aTlvs, aTlvsLength, aDelay, &aQueryInfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method generates an MLE Data Request message.
|
||||
@@ -1484,7 +1487,7 @@ protected:
|
||||
template <uint8_t kArrayLength>
|
||||
Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t (&aTlvs)[kArrayLength], uint16_t aDelay = 0)
|
||||
{
|
||||
return SendDataRequest(aDestination, aTlvs, kArrayLength, aDelay, nullptr, 0);
|
||||
return SendDataRequest(aDestination, aTlvs, kArrayLength, aDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1888,6 +1891,16 @@ private:
|
||||
bool IsDetachingGracefully(void) { return mDetachGracefullyTimer.IsRunning(); }
|
||||
Error SendChildUpdateRequest(bool aAppendChallenge, uint32_t aTimeout);
|
||||
|
||||
#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);
|
||||
#else
|
||||
Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aDelay);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
static void HandleDetachGracefullyAddressReleaseResponse(void * aContext,
|
||||
otMessage * aMessage,
|
||||
|
||||
Reference in New Issue
Block a user