[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:
Abtin Keshavarzian
2022-09-13 08:44:45 -07:00
committed by GitHub
parent dd02babfeb
commit 531339b65d
4 changed files with 87 additions and 67 deletions
+28 -44
View File
@@ -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;
}
+23 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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,