[link-metrics] renames, using namespace, and style changes (#6848)

This commit contains style changes, simplifications, and renames in
Link Metrics modules.  It moves all the definitions under a new
namespace `LinkMetrics` which allows the use of shorter and simpler
names for types, methods, and constants (omit the `LinkMetrics`
prefix from names). For example, `LinkMetricsTypeIdFlags` and
`LinkMetricsSeriesInfo` are renamed to simpler `TypeIdFlags` and
`SeriesInfo` respectively.
This commit is contained in:
Abtin Keshavarzian
2021-07-27 18:24:32 -07:00
committed by GitHub
parent b46f7b60e3
commit e8b085e09c
12 changed files with 703 additions and 612 deletions
+20 -16
View File
@@ -51,10 +51,11 @@ otError otLinkMetricsQuery(otInstance * aInstance,
{
OT_ASSERT(aDestination != nullptr);
static_cast<Instance *>(aInstance)->Get<LinkMetrics>().SetLinkMetricsReportCallback(aCallback, aCallbackContext);
static_cast<Instance *>(aInstance)->Get<LinkMetrics::LinkMetrics>().SetReportCallback(aCallback, aCallbackContext);
return static_cast<Instance *>(aInstance)->Get<LinkMetrics>().LinkMetricsQuery(
static_cast<const Ip6::Address &>(*aDestination), aSeriesId, aLinkMetricsFlags);
return static_cast<Instance *>(aInstance)->Get<LinkMetrics::LinkMetrics>().Query(
static_cast<const Ip6::Address &>(*aDestination), aSeriesId,
static_cast<const LinkMetrics::Metrics *>(aLinkMetricsFlags));
}
otError otLinkMetricsConfigForwardTrackingSeries(otInstance * aInstance,
@@ -67,17 +68,19 @@ otError otLinkMetricsConfigForwardTrackingSeries(otInstance *
{
OT_ASSERT(aDestination != nullptr);
static_cast<Instance *>(aInstance)->Get<LinkMetrics>().SetLinkMetricsMgmtResponseCallback(aCallback,
aCallbackContext);
LinkMetrics::LinkMetrics &linkMetrics = static_cast<Instance *>(aInstance)->Get<LinkMetrics::LinkMetrics>();
return static_cast<Instance *>(aInstance)->Get<LinkMetrics>().SendMgmtRequestForwardTrackingSeries(
static_cast<const Ip6::Address &>(*aDestination), aSeriesId, aSeriesFlags, aLinkMetricsFlags);
linkMetrics.SetMgmtResponseCallback(aCallback, aCallbackContext);
return linkMetrics.SendMgmtRequestForwardTrackingSeries(
static_cast<const Ip6::Address &>(*aDestination), aSeriesId, aSeriesFlags,
static_cast<const LinkMetrics::Metrics *>(aLinkMetricsFlags));
}
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
otError otLinkMetricsConfigEnhAckProbing(otInstance * aInstance,
const otIp6Address * aDestination,
const otLinkMetricsEnhAckFlags aEnhAckFlags,
otLinkMetricsEnhAckFlags aEnhAckFlags,
const otLinkMetrics * aLinkMetricsFlags,
otLinkMetricsMgmtResponseCallback aCallback,
void * aCallbackContext,
@@ -86,13 +89,14 @@ otError otLinkMetricsConfigEnhAckProbing(otInstance *
{
OT_ASSERT(aDestination != nullptr);
static_cast<Instance *>(aInstance)->Get<LinkMetrics>().SetLinkMetricsMgmtResponseCallback(aCallback,
aCallbackContext);
static_cast<Instance *>(aInstance)->Get<LinkMetrics>().SetLinkMetricsEnhAckProbingCallback(aEnhAckCallback,
aEnhAckCallbackContext);
LinkMetrics::LinkMetrics &linkMetrics = static_cast<Instance *>(aInstance)->Get<LinkMetrics::LinkMetrics>();
return static_cast<Instance *>(aInstance)->Get<LinkMetrics>().SendMgmtRequestEnhAckProbing(
static_cast<const Ip6::Address &>(*aDestination), aEnhAckFlags, aLinkMetricsFlags);
linkMetrics.SetMgmtResponseCallback(aCallback, aCallbackContext);
linkMetrics.SetEnhAckProbingCallback(aEnhAckCallback, aEnhAckCallbackContext);
return linkMetrics.SendMgmtRequestEnhAckProbing(static_cast<const Ip6::Address &>(*aDestination),
static_cast<LinkMetrics::EnhAckFlags>(aEnhAckFlags),
static_cast<const LinkMetrics::Metrics *>(aLinkMetricsFlags));
}
otError otLinkMetricsSendLinkProbe(otInstance * aInstance,
@@ -101,9 +105,9 @@ otError otLinkMetricsSendLinkProbe(otInstance * aInstance,
uint8_t aLength)
{
OT_ASSERT(aDestination != nullptr);
LinkMetrics::LinkMetrics &linkMetrics = static_cast<Instance *>(aInstance)->Get<LinkMetrics::LinkMetrics>();
return static_cast<Instance *>(aInstance)->Get<LinkMetrics>().SendLinkProbe(
static_cast<const Ip6::Address &>(*aDestination), aSeriesId, aLength);
return linkMetrics.SendLinkProbe(static_cast<const Ip6::Address &>(*aDestination), aSeriesId, aLength);
}
#endif
+1 -1
View File
@@ -899,7 +899,7 @@ template <> inline DuaManager &Instance::Get(void)
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
template <> inline LinkMetrics &Instance::Get(void)
template <> inline LinkMetrics::LinkMetrics &Instance::Get(void)
{
return mThreadNetif.mLinkMetrics;
}
+1 -1
View File
@@ -2449,7 +2449,7 @@ void Mac::ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor)
dataLen = enhAckProbingIe->GetLength() - sizeof(VendorIeHeader);
VerifyOrExit(dataLen <= kEnhAckProbingIeMaxLen);
Get<LinkMetrics>().ProcessEnhAckIeData(data, dataLen, aNeighbor);
Get<LinkMetrics::LinkMetrics>().ProcessEnhAckIeData(data, dataLen, aNeighbor);
exit:
return;
}
+272 -289
View File
@@ -39,27 +39,24 @@
#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/logging.hpp"
#include "mac/mac.hpp"
#include "thread/link_metrics_tlvs.hpp"
#include "thread/neighbor_table.hpp"
namespace ot {
namespace LinkMetrics {
void LinkMetricsSeriesInfo::Init(uint8_t aSeriesId,
const SeriesFlags & aSeriesFlags,
const otLinkMetrics &aLinkMetricsFlags)
void SeriesInfo::Init(uint8_t aSeriesId, const SeriesFlags &aSeriesFlags, const Metrics &aMetrics)
{
mSeriesId = aSeriesId;
mSeriesFlags = aSeriesFlags;
mLinkMetrics.mPduCount = aLinkMetricsFlags.mPduCount;
mLinkMetrics.mLqi = aLinkMetricsFlags.mLqi;
mLinkMetrics.mLinkMargin = aLinkMetricsFlags.mLinkMargin;
mLinkMetrics.mRssi = aLinkMetricsFlags.mRssi;
mSeriesId = aSeriesId;
mSeriesFlags = aSeriesFlags;
mMetrics = aMetrics;
mRssAverager.Clear();
mLqiAverager.Clear();
mPduCount = 0;
}
void LinkMetricsSeriesInfo::AggregateLinkMetrics(uint8_t aFrameType, uint8_t aLqi, int8_t aRss)
void SeriesInfo::AggregateLinkMetrics(uint8_t aFrameType, uint8_t aLqi, int8_t aRss)
{
if (IsFrameTypeMatch(aFrameType))
{
@@ -69,15 +66,7 @@ void LinkMetricsSeriesInfo::AggregateLinkMetrics(uint8_t aFrameType, uint8_t aLq
}
}
void LinkMetricsSeriesInfo::GetLinkMetrics(otLinkMetrics &aLinkMetrics) const
{
aLinkMetrics.mPduCount = mLinkMetrics.mPduCount;
aLinkMetrics.mLqi = mLinkMetrics.mLqi;
aLinkMetrics.mLinkMargin = mLinkMetrics.mLinkMargin;
aLinkMetrics.mRssi = mLinkMetrics.mRssi;
}
bool LinkMetricsSeriesInfo::IsFrameTypeMatch(uint8_t aFrameType) const
bool SeriesInfo::IsFrameTypeMatch(uint8_t aFrameType) const
{
bool match = false;
@@ -106,26 +95,28 @@ exit:
LinkMetrics::LinkMetrics(Instance &aInstance)
: InstanceLocator(aInstance)
, mLinkMetricsReportCallback(nullptr)
, mLinkMetricsReportCallbackContext(nullptr)
, mReportCallback(nullptr)
, mReportCallbackContext(nullptr)
, mMgmtResponseCallback(nullptr)
, mMgmtResponseCallbackContext(nullptr)
, mEnhAckProbingIeReportCallback(nullptr)
, mEnhAckProbingIeReportCallbackContext(nullptr)
{
}
Error LinkMetrics::LinkMetricsQuery(const Ip6::Address & aDestination,
uint8_t aSeriesId,
const otLinkMetrics *aLinkMetricsFlags)
Error LinkMetrics::Query(const Ip6::Address &aDestination, uint8_t aSeriesId, const Metrics *aMetrics)
{
Error error;
LinkMetricsTypeIdFlags typeIdFlags[kMaxTypeIdFlags];
uint8_t typeIdFlagsCount = 0;
Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination);
Error error;
TypeIdFlags typeIdFlags[kMaxTypeIdFlags];
uint8_t typeIdFlagsCount = 0;
Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination);
VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
if (aLinkMetricsFlags != nullptr)
if (aMetrics != nullptr)
{
typeIdFlagsCount = TypeIdFlagsFromLinkMetricsFlags(typeIdFlags, *aLinkMetricsFlags);
typeIdFlagsCount = TypeIdFlagsFromMetrics(typeIdFlags, *aMetrics);
}
if (aSeriesId != 0)
@@ -140,14 +131,14 @@ exit:
}
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
Error LinkMetrics::SendMgmtRequestForwardTrackingSeries(const Ip6::Address & aDestination,
uint8_t aSeriesId,
const otLinkMetricsSeriesFlags &aSeriesFlags,
const otLinkMetrics * aLinkMetricsFlags)
Error LinkMetrics::SendMgmtRequestForwardTrackingSeries(const Ip6::Address & aDestination,
uint8_t aSeriesId,
const SeriesFlags::Info &aSeriesFlags,
const Metrics * aMetrics)
{
Error error = kErrorNone;
uint8_t subTlvs[sizeof(Tlv) + sizeof(uint8_t) * 2 + sizeof(LinkMetricsTypeIdFlags) * kMaxTypeIdFlags];
Tlv * forwardProbingRegistrationSubTlv = reinterpret_cast<Tlv *>(subTlvs);
uint8_t subTlvs[sizeof(Tlv) + sizeof(uint8_t) * 2 + sizeof(TypeIdFlags) * kMaxTypeIdFlags];
Tlv * fwdProbingSubTlv = reinterpret_cast<Tlv *>(subTlvs);
SeriesFlags *seriesFlags = reinterpret_cast<SeriesFlags *>(subTlvs + sizeof(Tlv) + sizeof(aSeriesId));
uint8_t typeIdFlagsOffset = sizeof(Tlv) + sizeof(uint8_t) * 2;
uint8_t typeIdFlagsCount = 0;
@@ -156,70 +147,68 @@ Error LinkMetrics::SendMgmtRequestForwardTrackingSeries(const Ip6::Address &
VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
// Directly transform `aLinkMetricsFlags` into LinkMetricsTypeIdFlags and put them into `subTlvs`
if (aLinkMetricsFlags != nullptr)
// Directly transform `aMetrics` into TypeIdFlags and put them into `subTlvs`
if (aMetrics != nullptr)
{
typeIdFlagsCount = TypeIdFlagsFromLinkMetricsFlags(
reinterpret_cast<LinkMetricsTypeIdFlags *>(subTlvs + typeIdFlagsOffset), *aLinkMetricsFlags);
typeIdFlagsCount =
TypeIdFlagsFromMetrics(reinterpret_cast<TypeIdFlags *>(subTlvs + typeIdFlagsOffset), *aMetrics);
}
VerifyOrExit(aSeriesId > kQueryIdSingleProbe, error = kErrorInvalidArgs);
forwardProbingRegistrationSubTlv->SetType(kForwardProbingRegistration);
forwardProbingRegistrationSubTlv->SetLength(
sizeof(uint8_t) * 2 +
sizeof(LinkMetricsTypeIdFlags) *
typeIdFlagsCount); // SeriesId + SeriesFlags + typeIdFlagsCount * LinkMetricsTypeIdFlags
fwdProbingSubTlv->SetType(SubTlv::kFwdProbingReg);
// SeriesId + SeriesFlags + typeIdFlagsCount * TypeIdFlags
fwdProbingSubTlv->SetLength(sizeof(uint8_t) * 2 + sizeof(TypeIdFlags) * typeIdFlagsCount);
memcpy(subTlvs + sizeof(Tlv), &aSeriesId, sizeof(aSeriesId));
seriesFlags->SetFromOtSeriesFlags(aSeriesFlags);
seriesFlags->SetFrom(aSeriesFlags);
error = Get<Mle::MleRouter>().SendLinkMetricsManagementRequest(aDestination, subTlvs,
forwardProbingRegistrationSubTlv->GetSize());
error = Get<Mle::MleRouter>().SendLinkMetricsManagementRequest(aDestination, subTlvs, fwdProbingSubTlv->GetSize());
exit:
otLogDebgMle("SendMgmtRequestForwardTrackingSeries, error:%s, Series ID:%u", ErrorToString(error), aSeriesId);
return error;
}
Error LinkMetrics::SendMgmtRequestEnhAckProbing(const Ip6::Address & aDestination,
const otLinkMetricsEnhAckFlags aEnhAckFlags,
const otLinkMetrics * aLinkMetricsFlags)
Error LinkMetrics::SendMgmtRequestEnhAckProbing(const Ip6::Address &aDestination,
const EnhAckFlags aEnhAckFlags,
const Metrics * aMetrics)
{
Error error = kErrorNone;
EnhAckLinkMetricsConfigurationSubTlv enhAckLinkMetricsConfigurationSubTlv;
Mac::Address macAddress;
Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination);
Error error = kErrorNone;
EnhAckConfigSubTlv enhAckConfigSubTlv;
Mac::Address macAddress;
Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination);
VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
if (aEnhAckFlags == OT_LINK_METRICS_ENH_ACK_CLEAR)
if (aEnhAckFlags == kEnhAckClear)
{
VerifyOrExit(aLinkMetricsFlags == nullptr, error = kErrorInvalidArgs);
VerifyOrExit(aMetrics == nullptr, error = kErrorInvalidArgs);
}
enhAckLinkMetricsConfigurationSubTlv.SetEnhAckFlags(aEnhAckFlags);
enhAckConfigSubTlv.SetEnhAckFlags(aEnhAckFlags);
if (aLinkMetricsFlags != nullptr)
if (aMetrics != nullptr)
{
enhAckLinkMetricsConfigurationSubTlv.SetTypeIdFlags(aLinkMetricsFlags);
enhAckConfigSubTlv.SetTypeIdFlags(*aMetrics);
}
error = Get<Mle::MleRouter>().SendLinkMetricsManagementRequest(
aDestination, reinterpret_cast<const uint8_t *>(&enhAckLinkMetricsConfigurationSubTlv),
enhAckLinkMetricsConfigurationSubTlv.GetSize());
aDestination, reinterpret_cast<const uint8_t *>(&enhAckConfigSubTlv), enhAckConfigSubTlv.GetSize());
if (aLinkMetricsFlags != nullptr)
if (aMetrics != nullptr)
{
neighbor->SetEnhAckProbingMetrics(*aLinkMetricsFlags);
neighbor->SetEnhAckProbingMetrics(*aMetrics);
}
else
{
otLinkMetrics linkMetrics;
memset(&linkMetrics, 0, sizeof(linkMetrics));
neighbor->SetEnhAckProbingMetrics(linkMetrics);
Metrics metrics;
metrics.Clear();
neighbor->SetEnhAckProbingMetrics(metrics);
}
exit:
@@ -247,19 +236,19 @@ exit:
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
Error LinkMetrics::AppendLinkMetricsReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor)
Error LinkMetrics::AppendReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor)
{
Error error = kErrorNone;
Tlv tlv;
uint8_t queryId;
bool hasQueryId = false;
uint8_t length = 0;
uint16_t startOffset = aMessage.GetLength();
uint16_t offset;
uint16_t endOffset;
otLinkMetricsValues linkMetricsValues;
Error error = kErrorNone;
Tlv tlv;
uint8_t queryId;
bool hasQueryId = false;
uint8_t length = 0;
uint16_t startOffset = aMessage.GetLength();
uint16_t offset;
uint16_t endOffset;
MetricsValues values;
memset(&linkMetricsValues, 0, sizeof(linkMetricsValues));
values.Clear();
SuccessOrExit(error = Tlv::FindTlvValueOffset(aRequestMessage, Mle::Tlv::Type::kLinkMetricsQuery, offset,
endOffset)); // `endOffset` is used to store tlv length here
@@ -272,15 +261,15 @@ Error LinkMetrics::AppendLinkMetricsReport(Message &aMessage, const Message &aRe
switch (tlv.GetType())
{
case kLinkMetricsQueryId:
SuccessOrExit(error = Tlv::Read<LinkMetricsQueryIdTlv>(aRequestMessage, offset, queryId));
case SubTlv::kQueryId:
SuccessOrExit(error = Tlv::Read<QueryIdSubTlv>(aRequestMessage, offset, queryId));
hasQueryId = true;
break;
case kLinkMetricsQueryOptions:
case SubTlv::kQueryOptions:
SuccessOrExit(error = ReadTypeIdFlagsFromMessage(aRequestMessage, offset + sizeof(tlv),
static_cast<uint16_t>(offset + tlv.GetSize()),
linkMetricsValues.mMetrics));
values.GetMetrics()));
break;
default:
@@ -298,41 +287,41 @@ Error LinkMetrics::AppendLinkMetricsReport(Message &aMessage, const Message &aRe
if (queryId == kQueryIdSingleProbe)
{
linkMetricsValues.mPduCountValue = aRequestMessage.GetPsduCount();
linkMetricsValues.mLqiValue = aRequestMessage.GetAverageLqi();
linkMetricsValues.mLinkMarginValue =
values.mPduCountValue = aRequestMessage.GetPsduCount();
values.mLqiValue = aRequestMessage.GetAverageLqi();
// Linearly scale Link Margin from [0, 130] to [0, 255]
values.mLinkMarginValue =
LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), aRequestMessage.GetAverageRss()) *
255 / 130; // Linear scale Link Margin from [0, 130] to [0, 255]
linkMetricsValues.mRssiValue =
(aRequestMessage.GetAverageRss() + 130) * 255 / 130; // Linear scale rss from [-130, 0] to [0, 255]
255 / 130;
// Linearly scale rss from [-130, 0] to [0, 255]
values.mRssiValue = (aRequestMessage.GetAverageRss() + 130) * 255 / 130;
SuccessOrExit(error = AppendReportSubTlvToMessage(aMessage, length, linkMetricsValues));
SuccessOrExit(error = AppendReportSubTlvToMessage(aMessage, length, values));
}
else
{
LinkMetricsSeriesInfo *seriesInfo = aNeighbor.GetForwardTrackingSeriesInfo(queryId);
SeriesInfo *seriesInfo = aNeighbor.GetForwardTrackingSeriesInfo(queryId);
if (seriesInfo == nullptr)
{
SuccessOrExit(error =
AppendStatusSubTlvToMessage(aMessage, length, kLinkMetricsStatusSeriesIdNotRecognized));
SuccessOrExit(error = AppendStatusSubTlvToMessage(aMessage, length, kStatusSeriesIdNotRecognized));
}
else if (seriesInfo->GetPduCount() == 0)
{
SuccessOrExit(
error = AppendStatusSubTlvToMessage(aMessage, length, kLinkMetricsStatusNoMatchingFramesReceived));
SuccessOrExit(error = AppendStatusSubTlvToMessage(aMessage, length, kStatusNoMatchingFramesReceived));
}
else
{
seriesInfo->GetLinkMetrics(linkMetricsValues.mMetrics);
linkMetricsValues.mPduCountValue = seriesInfo->GetPduCount();
linkMetricsValues.mLqiValue = seriesInfo->GetAverageLqi();
linkMetricsValues.mLinkMarginValue =
LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(),
seriesInfo->GetAverageRss()) *
255 / 130; // Linear scale Link Margin from [0, 130] to [0, 255]
linkMetricsValues.mRssiValue =
(seriesInfo->GetAverageRss() + 130) * 255 / 130; // Linear scale RSSI from [-130, 0] to [0, 255]
SuccessOrExit(error = AppendReportSubTlvToMessage(aMessage, length, linkMetricsValues));
values.SetMetrics(seriesInfo->GetLinkMetrics());
values.mPduCountValue = seriesInfo->GetPduCount();
values.mLqiValue = seriesInfo->GetAverageLqi();
// Linearly scale Link Margin from [0, 130] to [0, 255]
values.mLinkMarginValue =
LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), seriesInfo->GetAverageRss()) *
255 / 130;
// Linearly scale RSSI from [-130, 0] to [0, 255]
values.mRssiValue = (seriesInfo->GetAverageRss() + 130) * 255 / 130;
SuccessOrExit(error = AppendReportSubTlvToMessage(aMessage, length, values));
}
}
@@ -340,38 +329,37 @@ Error LinkMetrics::AppendLinkMetricsReport(Message &aMessage, const Message &aRe
aMessage.Write(startOffset, tlv);
exit:
otLogDebgMle("AppendLinkMetricsReport, error:%s", ErrorToString(error));
otLogDebgMle("AppendReport, error:%s", ErrorToString(error));
return error;
}
Error LinkMetrics::HandleLinkMetricsManagementRequest(const Message & aMessage,
Neighbor & aNeighbor,
LinkMetricsStatus &aStatus)
Error LinkMetrics::HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus)
{
Error error = kErrorNone;
Tlv tlv;
uint8_t seriesId;
SeriesFlags seriesFlags;
LinkMetricsEnhAckFlags enhAckFlags;
otLinkMetrics linkMetrics;
bool hasForwardProbingRegistrationTlv = false;
bool hasEnhAckProbingTlv = false;
uint16_t offset;
uint16_t length;
uint16_t index = 0;
Error error = kErrorNone;
Tlv tlv;
uint8_t seriesId;
SeriesFlags seriesFlags;
EnhAckFlags enhAckFlags;
Metrics metrics;
bool hasForwardProbingRegistrationTlv = false;
bool hasEnhAckProbingTlv = false;
uint16_t offset;
uint16_t length;
uint16_t index = 0;
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, length));
while (index < length)
{
uint16_t pos = offset + index;
SuccessOrExit(aMessage.Read(pos, tlv));
pos += sizeof(tlv);
switch (tlv.GetType())
{
case kForwardProbingRegistration:
case SubTlv::kFwdProbingReg:
VerifyOrExit(!hasForwardProbingRegistrationTlv && !hasEnhAckProbingTlv, error = kErrorParse);
VerifyOrExit(tlv.GetLength() >= sizeof(seriesId) + sizeof(seriesFlags), error = kErrorParse);
SuccessOrExit(aMessage.Read(pos, seriesId));
@@ -379,17 +367,17 @@ Error LinkMetrics::HandleLinkMetricsManagementRequest(const Message & aMessag
SuccessOrExit(aMessage.Read(pos, seriesFlags));
pos += sizeof(seriesFlags);
SuccessOrExit(error = ReadTypeIdFlagsFromMessage(
aMessage, pos, static_cast<uint16_t>(offset + index + tlv.GetSize()), linkMetrics));
aMessage, pos, static_cast<uint16_t>(offset + index + tlv.GetSize()), metrics));
hasForwardProbingRegistrationTlv = true;
break;
case kEnhancedACKConfiguration:
case SubTlv::kEnhAckConfig:
VerifyOrExit(!hasForwardProbingRegistrationTlv && !hasEnhAckProbingTlv, error = kErrorParse);
VerifyOrExit(tlv.GetLength() >= sizeof(LinkMetricsEnhAckFlags), error = kErrorParse);
VerifyOrExit(tlv.GetLength() >= sizeof(EnhAckFlags), error = kErrorParse);
SuccessOrExit(aMessage.Read(pos, enhAckFlags));
pos += sizeof(enhAckFlags);
SuccessOrExit(error = ReadTypeIdFlagsFromMessage(
aMessage, pos, static_cast<uint16_t>(offset + index + tlv.GetSize()), linkMetrics));
aMessage, pos, static_cast<uint16_t>(offset + index + tlv.GetSize()), metrics));
hasEnhAckProbingTlv = true;
break;
@@ -402,11 +390,11 @@ Error LinkMetrics::HandleLinkMetricsManagementRequest(const Message & aMessag
if (hasForwardProbingRegistrationTlv)
{
aStatus = ConfigureForwardTrackingSeries(seriesId, seriesFlags, linkMetrics, aNeighbor);
aStatus = ConfigureForwardTrackingSeries(seriesId, seriesFlags, metrics, aNeighbor);
}
else if (hasEnhAckProbingTlv)
{
aStatus = ConfigureEnhAckProbing(enhAckFlags, linkMetrics, aNeighbor);
aStatus = ConfigureEnhAckProbing(enhAckFlags, metrics, aNeighbor);
}
exit:
@@ -414,17 +402,17 @@ exit:
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
Error LinkMetrics::HandleLinkMetricsManagementResponse(const Message &aMessage, const Ip6::Address &aAddress)
Error LinkMetrics::HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress)
{
Error error = kErrorNone;
Tlv tlv;
uint16_t offset;
uint16_t length;
uint16_t index = 0;
LinkMetricsStatus status;
bool hasStatus = false;
Error error = kErrorNone;
Tlv tlv;
uint16_t offset;
uint16_t length;
uint16_t index = 0;
Status status;
bool hasStatus = false;
VerifyOrExit(mLinkMetricsMgmtResponseCallback != nullptr);
VerifyOrExit(mMgmtResponseCallback != nullptr);
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, length));
@@ -434,7 +422,7 @@ Error LinkMetrics::HandleLinkMetricsManagementResponse(const Message &aMessage,
switch (tlv.GetType())
{
case kLinkMetricsStatus:
case SubTlv::kStatus:
VerifyOrExit(!hasStatus, error = kErrorParse);
VerifyOrExit(tlv.GetLength() == sizeof(status), error = kErrorParse);
SuccessOrExit(aMessage.Read(offset + index + sizeof(tlv), status));
@@ -450,98 +438,100 @@ Error LinkMetrics::HandleLinkMetricsManagementResponse(const Message &aMessage,
VerifyOrExit(hasStatus, error = kErrorParse);
mLinkMetricsMgmtResponseCallback(&aAddress, status, mLinkMetricsMgmtResponseCallbackContext);
mMgmtResponseCallback(&aAddress, status, mMgmtResponseCallbackContext);
exit:
return error;
}
void LinkMetrics::HandleLinkMetricsReport(const Message & aMessage,
uint16_t aOffset,
uint16_t aLength,
const Ip6::Address &aAddress)
void LinkMetrics::HandleReport(const Message & aMessage,
uint16_t aOffset,
uint16_t aLength,
const Ip6::Address &aAddress)
{
Error error = kErrorNone;
otLinkMetricsValues metricsValues;
uint8_t metricsRawValue;
uint16_t pos = aOffset;
uint16_t endPos = aOffset + aLength;
Tlv tlv;
LinkMetricsTypeIdFlags typeIdFlags;
bool hasStatus = false;
bool hasReport = false;
LinkMetricsStatus status;
Error error = kErrorNone;
MetricsValues values;
uint8_t rawValue;
uint16_t pos = aOffset;
uint16_t endPos = aOffset + aLength;
Tlv tlv;
TypeIdFlags typeIdFlags;
bool hasStatus = false;
bool hasReport = false;
Status status;
OT_UNUSED_VARIABLE(error);
VerifyOrExit(mLinkMetricsReportCallback != nullptr);
VerifyOrExit(mReportCallback != nullptr);
memset(&metricsValues, 0, sizeof(metricsValues));
values.Clear();
while (pos < endPos)
{
SuccessOrExit(aMessage.Read(pos, tlv));
VerifyOrExit(tlv.GetType() == kLinkMetricsReportSub);
VerifyOrExit(tlv.GetType() == SubTlv::kReport);
pos += sizeof(Tlv);
VerifyOrExit(pos + tlv.GetLength() <= endPos, error = kErrorParse);
switch (tlv.GetType())
{
case kLinkMetricsStatus:
VerifyOrExit(!hasStatus && !hasReport,
error = kErrorDrop); // There should be either: one Status TLV or some Report-Sub TLVs
case SubTlv::kStatus:
// There should be either: one Status TLV or some Report-Sub TLVs
VerifyOrExit(!hasStatus && !hasReport, error = kErrorDrop);
VerifyOrExit(tlv.GetLength() == sizeof(status), error = kErrorParse);
SuccessOrExit(aMessage.Read(pos, status));
hasStatus = true;
pos += sizeof(status);
break;
case kLinkMetricsReportSub:
VerifyOrExit(!hasStatus,
error = kErrorDrop); // There shouldn't be any Report-Sub TLV when there's a Status TLV
case SubTlv::kReport:
// There shouldn't be any Report-Sub TLV when there's a Status TLV
VerifyOrExit(!hasStatus, error = kErrorDrop);
VerifyOrExit(tlv.GetLength() > sizeof(typeIdFlags), error = kErrorParse);
SuccessOrExit(aMessage.Read(pos, typeIdFlags));
if (typeIdFlags.IsExtendedFlagSet())
{
pos += tlv.GetLength(); // Skip the whole sub-TLV if `E` flag is set
continue;
}
hasReport = true;
pos += sizeof(LinkMetricsTypeIdFlags);
pos += sizeof(TypeIdFlags);
switch (typeIdFlags.GetRawValue())
{
case kTypeIdFlagPdu:
metricsValues.mMetrics.mPduCount = true;
SuccessOrExit(aMessage.Read(pos, metricsValues.mPduCountValue));
case TypeIdFlags::kPdu:
values.GetMetrics().mPduCount = true;
SuccessOrExit(aMessage.Read(pos, values.mPduCountValue));
pos += sizeof(uint32_t);
otLogDebgMle(" - PDU Counter: %d (Count/Summation)", metricsValues.mPduCountValue);
otLogDebgMle(" - PDU Counter: %d (Count/Summation)", values.mPduCountValue);
break;
case kTypeIdFlagLqi:
metricsValues.mMetrics.mLqi = true;
SuccessOrExit(aMessage.Read(pos, metricsValues.mLqiValue));
case TypeIdFlags::kLqi:
values.GetMetrics().mLqi = true;
SuccessOrExit(aMessage.Read(pos, values.mLqiValue));
pos += sizeof(uint8_t);
otLogDebgMle(" - LQI: %d (Exponential Moving Average)", metricsValues.mLqiValue);
otLogDebgMle(" - LQI: %d (Exponential Moving Average)", values.mLqiValue);
break;
case kTypeIdFlagLinkMargin:
metricsValues.mMetrics.mLinkMargin = true;
SuccessOrExit(aMessage.Read(pos, metricsRawValue));
metricsValues.mLinkMarginValue =
metricsRawValue * 130 / 255; // Reverse operation for linear scale, map from [0, 255] to [0, 130]
case TypeIdFlags::kLinkMargin:
values.GetMetrics().mLinkMargin = true;
SuccessOrExit(aMessage.Read(pos, rawValue));
// Reverse operation for linear scale, map from [0, 255] to [0, 130]
values.mLinkMarginValue = rawValue * 130 / 255;
pos += sizeof(uint8_t);
otLogDebgMle(" - Margin: %d (dB) (Exponential Moving Average)", metricsValues.mLinkMarginValue);
otLogDebgMle(" - Margin: %d (dB) (Exponential Moving Average)", values.mLinkMarginValue);
break;
case kTypeIdFlagRssi:
metricsValues.mMetrics.mRssi = true;
SuccessOrExit(aMessage.Read(pos, metricsRawValue));
metricsValues.mRssiValue = metricsRawValue * 130 / 255 -
130; // Reverse operation for linear scale, map from [0, 255] to [-130, 0]
case TypeIdFlags::kRssi:
values.GetMetrics().mRssi = true;
SuccessOrExit(aMessage.Read(pos, rawValue));
// Reverse operation for linear scale, map from [0, 255] to [-130, 0]
values.mRssiValue = rawValue * 130 / 255 - 130;
pos += sizeof(uint8_t);
otLogDebgMle(" - RSSI: %d (dBm) (Exponential Moving Average)", metricsValues.mRssiValue);
otLogDebgMle(" - RSSI: %d (dBm) (Exponential Moving Average)", values.mRssiValue);
break;
default:
@@ -553,16 +543,15 @@ void LinkMetrics::HandleLinkMetricsReport(const Message & aMessage,
if (hasStatus)
{
mLinkMetricsReportCallback(&aAddress, nullptr, status, mLinkMetricsReportCallbackContext);
mReportCallback(&aAddress, nullptr, status, mReportCallbackContext);
}
else if (hasReport)
{
mLinkMetricsReportCallback(&aAddress, &metricsValues, OT_LINK_METRICS_STATUS_SUCCESS,
mLinkMetricsReportCallbackContext);
mReportCallback(&aAddress, &values, OT_LINK_METRICS_STATUS_SUCCESS, mReportCallbackContext);
}
exit:
otLogDebgMle("HandleLinkMetricsReport, error:%s", ErrorToString(error));
otLogDebgMle("HandleReport, error:%s", ErrorToString(error));
return;
}
@@ -574,84 +563,82 @@ Error LinkMetrics::HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId)
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkProbe, offset, length));
VerifyOrExit(length >= sizeof(aSeriesId), error = kErrorParse);
SuccessOrExit(error = aMessage.Read(offset, aSeriesId));
VerifyOrExit(aSeriesId >= kQueryIdSingleProbe && aSeriesId <= kSeriesIdAllSeries, error = kErrorInvalidArgs);
error = aMessage.Read(offset, aSeriesId);
exit:
return error;
}
void LinkMetrics::SetLinkMetricsReportCallback(otLinkMetricsReportCallback aCallback, void *aCallbackContext)
void LinkMetrics::SetReportCallback(ReportCallback aCallback, void *aContext)
{
mLinkMetricsReportCallback = aCallback;
mLinkMetricsReportCallbackContext = aCallbackContext;
mReportCallback = aCallback;
mReportCallbackContext = aContext;
}
void LinkMetrics::SetLinkMetricsMgmtResponseCallback(otLinkMetricsMgmtResponseCallback aCallback,
void * aCallbackContext)
void LinkMetrics::SetMgmtResponseCallback(MgmtResponseCallback aCallback, void *aContext)
{
mLinkMetricsMgmtResponseCallback = aCallback;
mLinkMetricsMgmtResponseCallbackContext = aCallbackContext;
mMgmtResponseCallback = aCallback;
mMgmtResponseCallbackContext = aContext;
}
void LinkMetrics::SetLinkMetricsEnhAckProbingCallback(otLinkMetricsEnhAckProbingIeReportCallback aCallback,
void * aCallbackContext)
void LinkMetrics::SetEnhAckProbingCallback(EnhAckProbingIeReportCallback aCallback, void *aContext)
{
mLinkMetricsEnhAckProbingIeReportCallback = aCallback;
mLinkMetricsEnhAckProbingIeReportCallbackContext = aCallbackContext;
mEnhAckProbingIeReportCallback = aCallback;
mEnhAckProbingIeReportCallbackContext = aContext;
}
void LinkMetrics::ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLen, const Neighbor &aNeighbor)
void LinkMetrics::ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLength, const Neighbor &aNeighbor)
{
otLinkMetricsValues linkMetricsValues;
uint8_t idx = 0;
MetricsValues values;
uint8_t idx = 0;
VerifyOrExit(mLinkMetricsEnhAckProbingIeReportCallback != nullptr);
VerifyOrExit(mEnhAckProbingIeReportCallback != nullptr);
linkMetricsValues.mMetrics = aNeighbor.GetEnhAckProbingMetrics();
values.SetMetrics(aNeighbor.GetEnhAckProbingMetrics());
if (linkMetricsValues.mMetrics.mLqi && idx < aLen)
if (values.GetMetrics().mLqi && idx < aLength)
{
linkMetricsValues.mLqiValue = aData[idx++];
values.mLqiValue = aData[idx++];
}
if (linkMetricsValues.mMetrics.mLinkMargin && idx < aLen)
if (values.GetMetrics().mLinkMargin && idx < aLength)
{
linkMetricsValues.mLinkMarginValue = aData[idx++];
values.mLinkMarginValue = aData[idx++];
}
if (linkMetricsValues.mMetrics.mRssi && idx < aLen)
if (values.GetMetrics().mRssi && idx < aLength)
{
linkMetricsValues.mRssiValue = aData[idx++];
values.mRssiValue = aData[idx++];
}
mLinkMetricsEnhAckProbingIeReportCallback(aNeighbor.GetRloc16(), &aNeighbor.GetExtAddress(), &linkMetricsValues,
mLinkMetricsEnhAckProbingIeReportCallbackContext);
mEnhAckProbingIeReportCallback(aNeighbor.GetRloc16(), &aNeighbor.GetExtAddress(), &values,
mEnhAckProbingIeReportCallbackContext);
exit:
return;
}
Error LinkMetrics::SendLinkMetricsQuery(const Ip6::Address & aDestination,
uint8_t aSeriesId,
const LinkMetricsTypeIdFlags *aTypeIdFlags,
uint8_t aTypeIdFlagsCount)
Error LinkMetrics::SendLinkMetricsQuery(const Ip6::Address &aDestination,
uint8_t aSeriesId,
const TypeIdFlags * aTypeIdFlags,
uint8_t aTypeIdFlagsCount)
{
Error error = kErrorNone;
LinkMetricsQueryOptionsTlv linkMetricsQueryOptionsTlv;
uint8_t length = 0;
static const uint8_t tlvs[] = {Mle::Tlv::kLinkMetricsReport};
uint8_t buf[sizeof(Tlv) * 3 + sizeof(uint8_t) +
sizeof(LinkMetricsTypeIdFlags) *
kMaxTypeIdFlags]; // LinkMetricsQuery Tlv + LinkMetricsQueryId sub-TLV (value-length: 1 byte) +
// LinkMetricsQueryOptions sub-TLV (value-length: `kMaxTypeIdFlags` bytes)
Tlv *tlv = reinterpret_cast<Tlv *>(buf);
Tlv subTlv;
// 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;
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;
// Link Metrics Query TLV
tlv->SetType(Mle::Tlv::kLinkMetricsQuery);
length += sizeof(Tlv);
// Link Metrics Query ID sub-TLV
subTlv.SetType(kLinkMetricsQueryId);
subTlv.SetType(SubTlv::kQueryId);
subTlv.SetLength(sizeof(uint8_t));
memcpy(buf + length, &subTlv, sizeof(subTlv));
length += sizeof(subTlv);
@@ -661,13 +648,13 @@ Error LinkMetrics::SendLinkMetricsQuery(const Ip6::Address & aDestinati
// Link Metrics Query Options sub-TLV
if (aTypeIdFlagsCount > 0)
{
linkMetricsQueryOptionsTlv.Init();
linkMetricsQueryOptionsTlv.SetLength(aTypeIdFlagsCount * sizeof(LinkMetricsTypeIdFlags));
queryOptionsTlv.Init();
queryOptionsTlv.SetLength(aTypeIdFlagsCount * sizeof(TypeIdFlags));
memcpy(buf + length, &linkMetricsQueryOptionsTlv, sizeof(linkMetricsQueryOptionsTlv));
length += sizeof(linkMetricsQueryOptionsTlv);
memcpy(buf + length, aTypeIdFlags, linkMetricsQueryOptionsTlv.GetLength());
length += linkMetricsQueryOptionsTlv.GetLength();
memcpy(buf + length, &queryOptionsTlv, sizeof(queryOptionsTlv));
length += sizeof(queryOptionsTlv);
memcpy(buf + length, aTypeIdFlags, queryOptionsTlv.GetLength());
length += queryOptionsTlv.GetLength();
}
// Set Length for Link Metrics Report TLV
@@ -679,14 +666,14 @@ exit:
return error;
}
LinkMetrics::LinkMetricsStatus LinkMetrics::ConfigureForwardTrackingSeries(uint8_t aSeriesId,
const SeriesFlags & aSeriesFlags,
const otLinkMetrics &aLinkMetrics,
Neighbor & aNeighbor)
Status LinkMetrics::ConfigureForwardTrackingSeries(uint8_t aSeriesId,
const SeriesFlags &aSeriesFlags,
const Metrics & aMetrics,
Neighbor & aNeighbor)
{
LinkMetricsStatus status = kLinkMetricsStatusSuccess;
Status status = kStatusSuccess;
VerifyOrExit(0 < aSeriesId, status = kLinkMetricsStatusOtherError);
VerifyOrExit(0 < aSeriesId, status = kStatusOtherError);
if (aSeriesFlags.GetRawValue() == 0) // Remove the series
{
if (aSeriesId == kSeriesIdAllSeries) // Remove all
@@ -695,19 +682,19 @@ LinkMetrics::LinkMetricsStatus LinkMetrics::ConfigureForwardTrackingSeries(uint8
}
else
{
LinkMetricsSeriesInfo *seriesInfo = aNeighbor.RemoveForwardTrackingSeriesInfo(aSeriesId);
VerifyOrExit(seriesInfo != nullptr, status = kLinkMetricsStatusSeriesIdNotRecognized);
mLinkMetricsSeriesInfoPool.Free(*seriesInfo);
SeriesInfo *seriesInfo = aNeighbor.RemoveForwardTrackingSeriesInfo(aSeriesId);
VerifyOrExit(seriesInfo != nullptr, status = kStatusSeriesIdNotRecognized);
mSeriesInfoPool.Free(*seriesInfo);
}
}
else // Add a new series
{
LinkMetricsSeriesInfo *seriesInfo = aNeighbor.GetForwardTrackingSeriesInfo(aSeriesId);
VerifyOrExit(seriesInfo == nullptr, status = kLinkMetricsStatusSeriesIdAlreadyRegistered);
seriesInfo = mLinkMetricsSeriesInfoPool.Allocate();
VerifyOrExit(seriesInfo != nullptr, status = kLinkMetricsStatusCannotSupportNewSeries);
SeriesInfo *seriesInfo = aNeighbor.GetForwardTrackingSeriesInfo(aSeriesId);
VerifyOrExit(seriesInfo == nullptr, status = kStatusSeriesIdAlreadyRegistered);
seriesInfo = mSeriesInfoPool.Allocate();
VerifyOrExit(seriesInfo != nullptr, status = kStatusCannotSupportNewSeries);
seriesInfo->Init(aSeriesId, aSeriesFlags, aLinkMetrics);
seriesInfo->Init(aSeriesId, aSeriesFlags, aMetrics);
aNeighbor.AddForwardTrackingSeriesInfo(*seriesInfo);
}
@@ -717,37 +704,32 @@ exit:
}
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
LinkMetrics::LinkMetricsStatus LinkMetrics::ConfigureEnhAckProbing(LinkMetricsEnhAckFlags aEnhAckFlags,
const otLinkMetrics & aLinkMetrics,
Neighbor & aNeighbor)
Status LinkMetrics::ConfigureEnhAckProbing(EnhAckFlags aEnhAckFlags, const Metrics &aMetrics, Neighbor &aNeighbor)
{
LinkMetricsStatus status = kLinkMetricsStatusSuccess;
Error error = kErrorNone;
Status status = kStatusSuccess;
Error error = kErrorNone;
VerifyOrExit(!aLinkMetrics.mReserved, status = kLinkMetricsStatusOtherError);
VerifyOrExit(!aMetrics.mReserved, status = kStatusOtherError);
if (aEnhAckFlags == kEnhAckRegister)
{
VerifyOrExit(!aLinkMetrics.mPduCount, status = kLinkMetricsStatusOtherError);
VerifyOrExit(aLinkMetrics.mLqi || aLinkMetrics.mLinkMargin || aLinkMetrics.mRssi,
status = kLinkMetricsStatusOtherError);
VerifyOrExit(!(aLinkMetrics.mLqi && aLinkMetrics.mLinkMargin && aLinkMetrics.mRssi),
status = kLinkMetricsStatusOtherError);
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<Radio>().ConfigureEnhAckProbing(aLinkMetrics, aNeighbor.GetRloc16(), aNeighbor.GetExtAddress());
error = Get<Radio>().ConfigureEnhAckProbing(aMetrics, aNeighbor.GetRloc16(), aNeighbor.GetExtAddress());
}
else if (aEnhAckFlags == kEnhAckClear)
{
VerifyOrExit(!aLinkMetrics.mLqi && !aLinkMetrics.mLinkMargin && !aLinkMetrics.mRssi,
status = kLinkMetricsStatusOtherError);
error = Get<Radio>().ConfigureEnhAckProbing(aLinkMetrics, aNeighbor.GetRloc16(), aNeighbor.GetExtAddress());
VerifyOrExit(!aMetrics.mLqi && !aMetrics.mLinkMargin && !aMetrics.mRssi, status = kStatusOtherError);
error = Get<Radio>().ConfigureEnhAckProbing(aMetrics, aNeighbor.GetRloc16(), aNeighbor.GetExtAddress());
}
else
{
status = kLinkMetricsStatusOtherError;
status = kStatusOtherError;
}
VerifyOrExit(error == kErrorNone, status = kLinkMetricsStatusOtherError);
VerifyOrExit(error == kErrorNone, status = kStatusOtherError);
exit:
return status;
@@ -770,38 +752,38 @@ exit:
Error LinkMetrics::ReadTypeIdFlagsFromMessage(const Message &aMessage,
uint8_t aStartPos,
uint8_t aEndPos,
otLinkMetrics &aLinkMetrics)
Metrics & aMetrics)
{
Error error = kErrorNone;
memset(&aLinkMetrics, 0, sizeof(aLinkMetrics));
memset(&aMetrics, 0, sizeof(aMetrics));
for (uint16_t pos = aStartPos; pos < aEndPos; pos += sizeof(LinkMetricsTypeIdFlags))
for (uint16_t pos = aStartPos; pos < aEndPos; pos += sizeof(TypeIdFlags))
{
LinkMetricsTypeIdFlags typeIdFlags;
TypeIdFlags typeIdFlags;
SuccessOrExit(aMessage.Read(pos, typeIdFlags));
switch (typeIdFlags.GetRawValue())
{
case kTypeIdFlagPdu:
VerifyOrExit(!aLinkMetrics.mPduCount, error = kErrorParse);
aLinkMetrics.mPduCount = true;
case TypeIdFlags::kPdu:
VerifyOrExit(!aMetrics.mPduCount, error = kErrorParse);
aMetrics.mPduCount = true;
break;
case kTypeIdFlagLqi:
VerifyOrExit(!aLinkMetrics.mLqi, error = kErrorParse);
aLinkMetrics.mLqi = true;
case TypeIdFlags::kLqi:
VerifyOrExit(!aMetrics.mLqi, error = kErrorParse);
aMetrics.mLqi = true;
break;
case kTypeIdFlagLinkMargin:
VerifyOrExit(!aLinkMetrics.mLinkMargin, error = kErrorParse);
aLinkMetrics.mLinkMargin = true;
case TypeIdFlags::kLinkMargin:
VerifyOrExit(!aMetrics.mLinkMargin, error = kErrorParse);
aMetrics.mLinkMargin = true;
break;
case kTypeIdFlagRssi:
VerifyOrExit(!aLinkMetrics.mRssi, error = kErrorParse);
aLinkMetrics.mRssi = true;
case TypeIdFlags::kRssi:
VerifyOrExit(!aMetrics.mRssi, error = kErrorParse);
aMetrics.mRssi = true;
break;
default:
@@ -811,7 +793,7 @@ Error LinkMetrics::ReadTypeIdFlagsFromMessage(const Message &aMessage,
}
else
{
aLinkMetrics.mReserved = true;
aMetrics.mReserved = true;
}
break;
}
@@ -821,10 +803,10 @@ exit:
return error;
}
Error LinkMetrics::AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLength, const otLinkMetricsValues &aValues)
Error LinkMetrics::AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLength, const MetricsValues &aValues)
{
Error error = kErrorNone;
LinkMetricsReportSubTlv metric;
Error error = kErrorNone;
ReportSubTlv metric;
aLength = 0;
@@ -832,7 +814,7 @@ Error LinkMetrics::AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLeng
if (aValues.mMetrics.mPduCount)
{
metric.Init();
metric.SetMetricsTypeId(LinkMetricsTypeIdFlags(kTypeIdFlagPdu));
metric.SetMetricsTypeId(TypeIdFlags(TypeIdFlags::kPdu));
metric.SetMetricsValue32(aValues.mPduCountValue);
SuccessOrExit(error = aMessage.AppendBytes(&metric, metric.GetSize()));
aLength += metric.GetSize();
@@ -841,7 +823,7 @@ Error LinkMetrics::AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLeng
if (aValues.mMetrics.mLqi)
{
metric.Init();
metric.SetMetricsTypeId(LinkMetricsTypeIdFlags(kTypeIdFlagLqi));
metric.SetMetricsTypeId(TypeIdFlags(TypeIdFlags::kLqi));
metric.SetMetricsValue8(aValues.mLqiValue);
SuccessOrExit(error = aMessage.AppendBytes(&metric, metric.GetSize()));
aLength += metric.GetSize();
@@ -850,7 +832,7 @@ Error LinkMetrics::AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLeng
if (aValues.mMetrics.mLinkMargin)
{
metric.Init();
metric.SetMetricsTypeId(LinkMetricsTypeIdFlags(kTypeIdFlagLinkMargin));
metric.SetMetricsTypeId(TypeIdFlags(TypeIdFlags::kLinkMargin));
metric.SetMetricsValue8(aValues.mLinkMarginValue);
SuccessOrExit(error = aMessage.AppendBytes(&metric, metric.GetSize()));
aLength += metric.GetSize();
@@ -859,7 +841,7 @@ Error LinkMetrics::AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLeng
if (aValues.mMetrics.mRssi)
{
metric.Init();
metric.SetMetricsTypeId(LinkMetricsTypeIdFlags(kTypeIdFlagRssi));
metric.SetMetricsTypeId(TypeIdFlags(TypeIdFlags::kRssi));
metric.SetMetricsValue8(aValues.mRssiValue);
SuccessOrExit(error = aMessage.AppendBytes(&metric, metric.GetSize()));
aLength += metric.GetSize();
@@ -869,12 +851,12 @@ exit:
return error;
}
Error LinkMetrics::AppendStatusSubTlvToMessage(Message &aMessage, uint8_t &aLength, LinkMetricsStatus aStatus)
Error LinkMetrics::AppendStatusSubTlvToMessage(Message &aMessage, uint8_t &aLength, Status aStatus)
{
Error error = kErrorNone;
Tlv statusTlv;
statusTlv.SetType(kLinkMetricsStatus);
statusTlv.SetType(SubTlv::kStatus);
statusTlv.SetLength(sizeof(uint8_t));
SuccessOrExit(error = aMessage.AppendBytes(&statusTlv, sizeof(statusTlv)));
SuccessOrExit(error = aMessage.AppendBytes(&aStatus, sizeof(aStatus)));
@@ -884,6 +866,7 @@ exit:
return error;
}
} // namespace LinkMetrics
} // namespace ot
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+160 -121
View File
@@ -39,12 +39,13 @@
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
#error \
"Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE and OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE."
#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE" \
"and OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE."
#endif
#include <openthread/link.h>
#include "common/clearable.hpp"
#include "common/locator.hpp"
#include "common/message.hpp"
#include "common/non_copyable.hpp"
@@ -54,9 +55,10 @@
#include "thread/link_quality.hpp"
namespace ot {
class Neighbor;
namespace LinkMetrics {
/**
* @addtogroup core-link-metrics
*
@@ -66,41 +68,74 @@ class Neighbor;
* @{
*/
/**
* This type represents the results (values) for a set of metrics.
*
* @sa otLinkMetricsValues.
*
*/
class MetricsValues : public otLinkMetricsValues, public Clearable<MetricsValues>
{
public:
/**
* This method gets the metrics flags.
*
* @returns The metrics flags.
*
*/
Metrics &GetMetrics(void) { return static_cast<Metrics &>(mMetrics); }
/**
* This method gets the metrics flags.
*
* @returns The metrics flags.
*
*/
const Metrics &GetMetrics(void) const { return static_cast<const Metrics &>(mMetrics); }
/**
* This method set the metrics flags.
*
* @param[in] aMetrics The metrics flags to set from.
*
*/
void SetMetrics(const Metrics &aMetrics) { mMetrics = aMetrics; }
};
/**
* This class represents one Series that is being tracked by the Subject.
*
* When an Initiator successfully configured a Forward Tracking Series, the Subject would use an instance of this class
* to track the information of the Series. The Subject has a `Pool` of `LinkMetricsSeriesInfo`. It would allocate one
* when a new Series comes, and free it when a Series finishes.
* to track the information of the Series. The Subject has a `Pool` of `SeriesInfo`. It would allocate one when a new
* Series comes, and free it when a Series finishes.
*
* This class inherits `LinkedListEntry` and each `Neighbor` has a list of `LinkMetricsSeriesInfo` so that the Subject
* could track per Series initiated by neighbors as long as it has available resources.
* This class inherits `LinkedListEntry` and each `Neighbor` has a list of `SeriesInfo` so that the Subject could track
* per Series initiated by neighbors as long as it has available resources.
*
*/
class LinkMetricsSeriesInfo : public LinkedListEntry<LinkMetricsSeriesInfo>
class SeriesInfo : public LinkedListEntry<SeriesInfo>
{
friend class LinkedList<LinkMetricsSeriesInfo>;
friend class LinkedListEntry<LinkMetricsSeriesInfo>;
friend class LinkedList<SeriesInfo>;
friend class LinkedListEntry<SeriesInfo>;
public:
///< This represents Link Probe when filtering frames to be accounted using Series Flag. There's
///< already `kFcfFrameData`, `kFcfFrameAck` and `kFcfFrameMacCmd`. This item is added so that we can
///< filter a Link Probe for series in the same way as other frames.
enum
{
kSeriesTypeLinkProbe = 0,
};
/**
* This method initializes the object.
*
* @param[in] aSeriesId The Series ID.
* @param[in] aSeriesFlags A reference to the Series Flags which specify what types of frames are to be
* accounted.
* @param[in] aLinkMetricsFlags A reference to flags specifying what metrics to query.
* This constant represents Link Probe when filtering frames to be accounted using Series Flag. There's
* already `kFcfFrameData`, `kFcfFrameAck` and `kFcfFrameMacCmd`. This item is added so that we can
* filter a Link Probe for series in the same way as other frames.
*
*/
void Init(uint8_t aSeriesId, const SeriesFlags &aSeriesFlags, const otLinkMetrics &aLinkMetrics);
static constexpr uint8_t kSeriesTypeLinkProbe = 0;
/**
* This method initializes the SeriesInfo object.
*
* @param[in] aSeriesId The Series ID.
* @param[in] aSeriesFlags The Series Flags which specify what types of frames are to be accounted.
* @param[in] aMetrics Metrics to query.
*
*/
void Init(uint8_t aSeriesId, const SeriesFlags &aSeriesFlags, const Metrics &aMetrics);
/**
* This method gets the Series ID.
@@ -145,42 +180,52 @@ public:
void AggregateLinkMetrics(uint8_t aFrameType, uint8_t aLqi, int8_t aRss);
/**
* This methods gets the Link Metrics Flags.
* This methods gets the metrics.
*
* @param[out] aLinkMetrics A reference to a `LinkMetrics` object to get the values.
* @returns The metrics associated with `SeriesInfo`.
*
*/
void GetLinkMetrics(otLinkMetrics &aLinkMetrics) const;
const Metrics &GetLinkMetrics(void) const { return mMetrics; }
private:
LinkMetricsSeriesInfo *mNext;
uint8_t mSeriesId;
SeriesFlags mSeriesFlags;
otLinkMetrics mLinkMetrics;
RssAverager mRssAverager;
LqiAverager mLqiAverager;
uint32_t mPduCount;
bool Matches(const uint8_t &aSeriesId) const { return mSeriesId == aSeriesId; }
bool IsFrameTypeMatch(uint8_t aFrameType) const;
SeriesInfo *mNext;
uint8_t mSeriesId;
SeriesFlags mSeriesFlags;
Metrics mMetrics;
RssAverager mRssAverager;
LqiAverager mLqiAverager;
uint32_t mPduCount;
};
/**
* This enumeration type represent Link Metrics Status.
*
*/
enum Status : uint8_t
{
kStatusSuccess = OT_LINK_METRICS_STATUS_SUCCESS,
kStatusCannotSupportNewSeries = OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES,
kStatusSeriesIdAlreadyRegistered = OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED,
kStatusSeriesIdNotRecognized = OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED,
kStatusNoMatchingFramesReceived = OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED,
kStatusOtherError = OT_LINK_METRICS_STATUS_OTHER_ERROR,
};
/**
* This class implements Thread Link Metrics query and management.
*
*/
class LinkMetrics : public InstanceLocator, private NonCopyable
{
friend class Neighbor;
friend class ot::Neighbor;
public:
enum LinkMetricsStatus : uint8_t
{
kLinkMetricsStatusSuccess = OT_LINK_METRICS_STATUS_SUCCESS,
kLinkMetricsStatusCannotSupportNewSeries = OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES,
kLinkMetricsStatusSeriesIdAlreadyRegistered = OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED,
kLinkMetricsStatusSeriesIdNotRecognized = OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED,
kLinkMetricsStatusNoMatchingFramesReceived = OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED,
kLinkMetricsStatusOtherError = OT_LINK_METRICS_STATUS_OTHER_ERROR,
};
typedef otLinkMetricsReportCallback ReportCallback;
typedef otLinkMetricsMgmtResponseCallback MgmtResponseCallback;
typedef otLinkMetricsEnhAckProbingIeReportCallback EnhAckProbingIeReportCallback;
/**
* This constructor initializes an instance of the LinkMetrics class.
@@ -197,7 +242,7 @@ public:
*
* @param[in] aDestination A reference to the IPv6 address of the destination.
* @param[in] aSeriesId The Series ID to query, 0 for single probe.
* @param[in] aLinkMetricsFlags A pointer to flags specifying what metrics to query.
* @param[in] aMetrics A pointer to metrics to query.
*
* @retval kErrorNone Successfully sent a Link Metrics query message.
* @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message.
@@ -205,16 +250,15 @@ public:
* @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found.
*
*/
Error LinkMetricsQuery(const Ip6::Address &aDestination, uint8_t aSeriesId, const otLinkMetrics *aLinkMetricsFlags);
Error Query(const Ip6::Address &aDestination, uint8_t aSeriesId, const Metrics *aMetrics);
/**
* This method sends an MLE Link Metrics Management Request to configure/clear a Forward Tracking Series.
*
* @param[in] aDestination A reference to the IPv6 address of the destination.
* @param[in] aSeriesId The Series ID.
* @param[in] aSeriesFlags A reference to the Series Flags which specify what types of frames are to be
* accounted.
* @param[in] aLinkMetricsFlags A pointer to flags specifying what metrics to query.
* @param[in] aSeriesFlags The Series Flags info which specify what types of frames are to be accounted.
* @param[in] aMetrics A pointer to flags specifying what metrics to query.
*
* @retval kErrorNone Successfully sent a Link Metrics Management Request message.
* @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message.
@@ -222,10 +266,10 @@ public:
* @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found.
*
*/
Error SendMgmtRequestForwardTrackingSeries(const Ip6::Address & aDestination,
uint8_t aSeriesId,
const otLinkMetricsSeriesFlags &aSeriesFlags,
const otLinkMetrics * aLinkMetricsFlags);
Error SendMgmtRequestForwardTrackingSeries(const Ip6::Address & aDestination,
uint8_t aSeriesId,
const SeriesFlags::Info &aSeriesFlags,
const Metrics * aMetrics);
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
/**
@@ -234,18 +278,18 @@ public:
* @param[in] aDestination A reference to the IPv6 address of the destination.
* @param[in] aEnhAckFlags Enh-ACK Flags to indicate whether to register or clear the probing. `0` to clear
* and `1` to register. Other values are reserved.
* @param[in] aLinkMetricsFlags A pointer to flags specifying what metrics to query. Should be `NULL` when
* @param[in] aMetrics A pointer to flags specifying what metrics to query. Should be `nullptr` when
* `aEnhAckFlags` is `0`.
*
* @retval kErrorNone Successfully sent a Link Metrics Management Request message.
* @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message.
* @retval kErrorInvalidArgs @p aEnhAckFlags is not a valid value or @p aLinkMetricsFlags isn't correct.
* @retval kErrorInvalidArgs @p aEnhAckFlags is not a valid value or @p aMetrics isn't correct.
* @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found.
*
*/
Error SendMgmtRequestEnhAckProbing(const Ip6::Address & aDestination,
otLinkMetricsEnhAckFlags aEnhAckFlags,
const otLinkMetrics * aLinkMetricsFlags);
Error SendMgmtRequestEnhAckProbing(const Ip6::Address &aDestination,
EnhAckFlags aEnhAckFlags,
const Metrics * aMetrics);
/**
* This method sends an MLE Link Probe message.
@@ -276,7 +320,7 @@ public:
* @retval kErrorInvalidArgs QueryId is invalid or any Type ID is invalid.
*
*/
Error AppendLinkMetricsReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor);
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.
@@ -289,7 +333,7 @@ public:
* @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully.
*
*/
Error HandleLinkMetricsManagementRequest(const Message &aMessage, Neighbor &aNeighbor, LinkMetricsStatus &aStatus);
Error HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus);
/**
* This method handles the received Link Metrics Management Response contained in @p aMessage.
@@ -301,7 +345,7 @@ public:
* @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully.
*
*/
Error HandleLinkMetricsManagementResponse(const Message &aMessage, const Ip6::Address &aAddress);
Error HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress);
/**
* This method handles the received Link Metrics report contained in @p aMessage.
@@ -312,10 +356,7 @@ public:
* @param[in] aAddress A reference to the source address of the message.
*
*/
void HandleLinkMetricsReport(const Message & aMessage,
uint16_t aOffset,
uint16_t aLength,
const Ip6::Address &aAddress);
void HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t aLength, const Ip6::Address &aAddress);
/**
* This method handles the Link Probe contained in @p aMessage.
@@ -332,88 +373,86 @@ public:
/**
* 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] aCallbackContext A pointer to application-specific context.
* @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 SetLinkMetricsReportCallback(otLinkMetricsReportCallback aCallback, void *aCallbackContext);
void SetReportCallback(ReportCallback aCallback, void *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] aCallbackContext A pointer to application-specific context.
* @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 SetLinkMetricsMgmtResponseCallback(otLinkMetricsMgmtResponseCallback aCallback, void *aCallbackContext);
void SetMgmtResponseCallback(MgmtResponseCallback aCallback, void *aContext);
void SetLinkMetricsEnhAckProbingCallback(otLinkMetricsEnhAckProbingIeReportCallback aCallback,
void * aCallbackContext);
void ProcessEnhAckIeData(const uint8_t *aData, uint8_t aLen, const Neighbor &aNeighbor);
/**
* 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);
/**
* 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] aLen 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:
/*
* TypeIdFlagPdu: 0x0_1_000_000 -> 0x40 ==> L bit set, type = 0 (count/summation), metric-enum = 0 (PDU rxed).
* TypeIdFlagLqi: 0x0_0_001_001 -> 0x00 ==> L bit not set, type = 1 (exp ave), metric-enum = 1 (LQI).
* TypeIdFlagLinkMargin: 0x0_0_001_010 -> 0x00 ==> L bit not set, type = 1 (exp ave), metric-enum = 2 (Link Margin).
* TypeIdFlagRssi: 0x0_0_001_011 -> 0x00 ==> L bit not set, type = 1 (exp ave), metric-enum = 3 (RSSI).
*
*/
enum
{
kMaxTypeIdFlags = 4,
static constexpr uint8_t kMaxTypeIdFlags = 4;
kMaxSeriesSupported =
OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED, ///< Max number of LinkMetricsSeriesInfo that could
///< be allocated by the pool.
// Max number of SeriesInfo that could be allocated by the pool.
static constexpr uint16_t kMaxSeriesSupported = OPENTHREAD_CONFIG_MLE_LINK_METRICS_MAX_SERIES_SUPPORTED;
kQueryIdSingleProbe = 0, ///< This query ID represents Single Probe.
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.
kSeriesIdAllSeries = 255, ///< This series ID represents all series.
Error SendLinkMetricsQuery(const Ip6::Address &aDestination,
uint8_t aSeriesId,
const TypeIdFlags * aTypeIdFlags,
uint8_t aTypeIdFlagsCount);
kLinkProbeMaxLen = 64, ///< Max length of data payload in Link Probe TLV.
};
Status ConfigureForwardTrackingSeries(uint8_t aSeriesId,
const SeriesFlags &aSeriesFlags,
const Metrics & aMetrics,
Neighbor & aNeighbor);
otLinkMetricsReportCallback mLinkMetricsReportCallback;
void * mLinkMetricsReportCallbackContext;
otLinkMetricsMgmtResponseCallback mLinkMetricsMgmtResponseCallback;
void * mLinkMetricsMgmtResponseCallbackContext;
otLinkMetricsEnhAckProbingIeReportCallback mLinkMetricsEnhAckProbingIeReportCallback;
void * mLinkMetricsEnhAckProbingIeReportCallbackContext;
Pool<LinkMetricsSeriesInfo, kMaxSeriesSupported> mLinkMetricsSeriesInfoPool;
Error SendLinkMetricsQuery(const Ip6::Address & aDestination,
uint8_t aSeriesId,
const LinkMetricsTypeIdFlags *aTypeIdFlags,
uint8_t aTypeIdFlagsCount);
LinkMetricsStatus ConfigureForwardTrackingSeries(uint8_t aSeriesId,
const SeriesFlags & aSeriesFlags,
const otLinkMetrics &aLinkMetrics,
Neighbor & aNeighbor);
LinkMetricsStatus ConfigureEnhAckProbing(LinkMetricsEnhAckFlags aEnhAckFlags,
const otLinkMetrics & aLinkMetrics,
Neighbor & aNeighbor);
Status ConfigureEnhAckProbing(EnhAckFlags aEnhAckFlags, const Metrics &aMetrics, Neighbor &aNeighbor);
Neighbor *GetNeighborFromLinkLocalAddr(const Ip6::Address &aDestination);
static Error ReadTypeIdFlagsFromMessage(const Message &aMessage,
uint8_t aStartPos,
uint8_t aEndPos,
otLinkMetrics &aLinkMetrics);
Metrics & aMetrics);
static Error AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLength, const MetricsValues &aValues);
static Error AppendStatusSubTlvToMessage(Message &aMessage, uint8_t &aLength, Status aStatus);
static Error AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLength, const otLinkMetricsValues &aValues);
ReportCallback mReportCallback;
void * mReportCallbackContext;
MgmtResponseCallback mMgmtResponseCallback;
void * mMgmtResponseCallbackContext;
EnhAckProbingIeReportCallback mEnhAckProbingIeReportCallback;
void * mEnhAckProbingIeReportCallbackContext;
static Error AppendStatusSubTlvToMessage(Message &aMessage, uint8_t &aLength, LinkMetricsStatus aStatus);
Pool<SeriesInfo, kMaxSeriesSupported> mSeriesInfoPool;
};
/**
* @}
*/
} // namespace LinkMetrics
} // namespace ot
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+207 -144
View File
@@ -41,77 +41,143 @@
#include <openthread/link_metrics.h>
#include "common/clearable.hpp"
#include "common/encoding.hpp"
#include "common/message.hpp"
#include "common/tlvs.hpp"
namespace ot {
namespace LinkMetrics {
/**
* Link Metrics parameters.
* This type represents Link Metric Flags indicating a set of metrics.
*
* @sa otLinkMetrics
*
*/
enum
class Metrics : public otLinkMetrics, public Clearable<Metrics>
{
kLinkMetricsMaxTypeIdFlags = 4, ///< Max count of Link Metrics Type ID Flags.
};
/**
* Link Metrics Sub-TLV types.
* This class defines constants related to Link Metrics Sub-TLVs.
*
*/
enum Type : uint8_t
{
kLinkMetricsReportSub = 0, ///< Link Metrics Report Sub-TLV
kLinkMetricsQueryId = 1, ///< Link Metrics Query ID Sub-TLV
kLinkMetricsQueryOptions = 2, ///< Link Metrics Query Options Sub-TLV
kForwardProbingRegistration = 3, ///< Forward Probing Registration Sub-TLV
kLinkMetricsStatus = 5, ///< Link Metrics Status Sub-TLV
kEnhancedACKConfiguration = 7, ///< Enhanced ACK Configuration Sub-TLV
};
/**
* Valid values for Link Metrics Type Id Flags.
*
*/
enum
{
kTypeIdFlagPdu = 0x40,
kTypeIdFlagLqi = 0x09,
kTypeIdFlagLinkMargin = 0x0a,
kTypeIdFlagRssi = 0x0b,
};
/**
* This class defines Link Metrics Query ID TLV constants and types.
*
*/
typedef UintTlvInfo<kLinkMetricsQueryId, uint8_t> LinkMetricsQueryIdTlv;
/**
* This class implements Link Metrics Type Id Flags generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN class LinkMetricsTypeIdFlags
class SubTlv
{
public:
enum : uint8_t
/**
* Link Metrics Sub-TLV types.
*
*/
enum Type : uint8_t
{
kTypeEnumReserved = 2,
kReport = 0, ///< Report Sub-TLV
kQueryId = 1, ///< Query ID Sub-TLV
kQueryOptions = 2, ///< Query Options Sub-TLV
kFwdProbingReg = 3, ///< Forward Probing Registration Sub-TLV
kStatus = 5, ///< Status Sub-TLV
kEnhAckConfig = 7, ///< Enhanced ACK Configuration Sub-TLV
};
};
/**
* This class defines Link Metrics Query ID Sub-TLV constants and types.
*
*/
typedef UintTlvInfo<SubTlv::kQueryId, uint8_t> QueryIdSubTlv;
/**
* This class implements Link Metrics Type ID Flags generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN class TypeIdFlags
{
static constexpr uint8_t kExtendedFlag = 1 << 7;
static constexpr uint8_t kLengthOffset = 6;
static constexpr uint8_t kLengthFlag = 1 << kLengthOffset;
static constexpr uint8_t kTypeEnumOffset = 3;
static constexpr uint8_t kTypeEnumMask = 7 << kTypeEnumOffset;
static constexpr uint8_t kMetricEnumOffset = 0;
static constexpr uint8_t kMetricEnumMask = 7 << kMetricEnumOffset;
public:
/**
* This enumeration specifies the Length field in Type ID Flags.
*
*/
enum Length
{
kShortLength = 0, ///< Short value length (1 byte value)
kExtendedLength = 1, ///< Extended value length (4 bytes value)
};
/**
* This enumeration specifies the Type values in Type ID Flags.
*
*/
enum TypeEnum : uint8_t
{
kTypeCountSummation = 0, ///< Count or summation
kTypeExpMovingAverage = 1, ///< Exponential moving average.
kTypeReserved = 2, ///< Reserved for future use.
};
/**
* This enumeration specifies the Metric values in Type ID Flag.
*
*/
enum MetricEnum : uint8_t
{
kMetricPdusReceived = 0, ///< Number of PDUs received.
kMetricLqi = 1, ///< Link Quality Indicator.
kMetricLinkMargin = 2, ///< Link Margin.
kMetricRssi = 3, ///< RSSI in dbm.
};
/**
* This constant defines the raw value for Type ID Flag for PDU.
*
*/
static constexpr uint8_t kPdu = (kExtendedLength << kLengthOffset) | (kTypeCountSummation << kTypeEnumOffset) |
(kMetricPdusReceived << kMetricEnumOffset);
/**
* This constant defines the raw value for Type ID Flag for LQI.
*
*/
static constexpr uint8_t kLqi = (kShortLength << kLengthOffset) | (kTypeExpMovingAverage << kTypeEnumOffset) |
(kMetricLqi << kMetricEnumOffset);
/**
* This constant defines the raw value for Type ID Flag for Link Margin.
*
*/
static constexpr uint8_t kLinkMargin = (kShortLength << kLengthOffset) |
(kTypeExpMovingAverage << kTypeEnumOffset) |
(kMetricLinkMargin << kMetricEnumOffset);
/**
* This constant defines the raw value for Type ID Flag for RSSI
*
*/
static constexpr uint8_t kRssi = (kShortLength << kLengthOffset) | (kTypeExpMovingAverage << kTypeEnumOffset) |
(kMetricRssi << kMetricEnumOffset);
/**
* Default constructor.
*
*/
LinkMetricsTypeIdFlags(void) = default;
TypeIdFlags(void) = default;
/**
* Constructor for implicit cast from `uint8_t` to `LinkMetricsTypeIdFlags`.
* Constructor to initialize from raw value.
*
* @param[in] aFlags The raw flags value.
*
*/
explicit LinkMetricsTypeIdFlags(uint8_t aTypeIdFlags)
: mTypeIdFlags(aTypeIdFlags)
explicit TypeIdFlags(uint8_t aFlags)
: mFlags(aFlags)
{
}
@@ -119,20 +185,20 @@ public:
* This method initializes the Type ID value
*
*/
void Init(void) { mTypeIdFlags = 0; }
void Init(void) { mFlags = 0; }
/**
* This method clears the Extended flag.
*
*/
void ClearExtendedFlag(void) { mTypeIdFlags &= ~kExtendedFlag; }
void ClearExtendedFlag(void) { mFlags &= ~kExtendedFlag; }
/**
* This method sets the Extended flag, indicating an additional second flags byte after the current 1-byte flags.
* MUST NOT set in Thread 1.2.1.
*
*/
void SetExtendedFlag(void) { mTypeIdFlags |= kExtendedFlag; }
void SetExtendedFlag(void) { mFlags |= kExtendedFlag; }
/**
* This method indicates whether or not the Extended flag is set.
@@ -141,19 +207,19 @@ public:
* @retval false The Extended flag is not set.
*
*/
bool IsExtendedFlagSet(void) const { return (mTypeIdFlags & kExtendedFlag) != 0; }
bool IsExtendedFlagSet(void) const { return (mFlags & kExtendedFlag) != 0; }
/**
* This method clears value length flag.
*
*/
void ClearLengthFlag(void) { mTypeIdFlags &= ~kLengthFlag; }
void ClearLengthFlag(void) { mFlags &= ~kLengthFlag; }
/**
* This method sets the value length flag.
*
*/
void SetLengthFlag(void) { mTypeIdFlags |= kLengthFlag; }
void SetLengthFlag(void) { mFlags |= kLengthFlag; }
/**
* This method indicates whether or not the value length flag is set.
@@ -162,7 +228,7 @@ public:
* @retval false The value length flag is not set, short value length (1 byte)
*
*/
bool IsLengthFlagSet(void) const { return (mTypeIdFlags & kLengthFlag) != 0; }
bool IsLengthFlagSet(void) const { return (mFlags & kLengthFlag) != 0; }
/**
* This method sets the Type/Average Enum.
@@ -170,9 +236,9 @@ public:
* @param[in] aTypeEnum Type/Average Enum.
*
*/
void SetTypeEnum(uint8_t aTypeEnum)
void SetTypeEnum(TypeEnum aTypeEnum)
{
mTypeIdFlags = (mTypeIdFlags & ~kTypeEnumMask) | ((aTypeEnum << kTypeEnumOffset) & kTypeEnumMask);
mFlags = (mFlags & ~kTypeEnumMask) | ((aTypeEnum << kTypeEnumOffset) & kTypeEnumMask);
}
/**
@@ -181,7 +247,7 @@ public:
* @returns The Type/Average Enum.
*
*/
uint8_t GetTypeEnum(void) const { return (mTypeIdFlags & kTypeEnumMask) >> kTypeEnumOffset; }
TypeEnum GetTypeEnum(void) const { return static_cast<TypeEnum>((mFlags & kTypeEnumMask) >> kTypeEnumOffset); }
/**
* This method sets the Metric Enum.
@@ -189,9 +255,9 @@ public:
* @param[in] aMetricEnum Metric Enum.
*
*/
void SetMetricEnum(uint8_t aMetricEnum)
void SetMetricEnum(MetricEnum aMetricEnum)
{
mTypeIdFlags = (mTypeIdFlags & ~kMetricEnumMask) | ((aMetricEnum << kMetricEnumOffset) & kMetricEnumMask);
mFlags = (mFlags & ~kMetricEnumMask) | ((aMetricEnum << kMetricEnumOffset) & kMetricEnumMask);
}
/**
@@ -200,7 +266,10 @@ public:
* @returns The Metric Enum.
*
*/
uint8_t GetMetricEnum(void) const { return (mTypeIdFlags & kMetricEnumMask) >> kMetricEnumOffset; }
MetricEnum GetMetricEnum(void) const
{
return static_cast<MetricEnum>((mFlags & kMetricEnumMask) >> kMetricEnumOffset);
}
/**
* This method returns the raw value of the entire TypeIdFlags.
@@ -208,28 +277,18 @@ public:
* @returns The raw value of TypeIdFlags.
*
*/
uint8_t GetRawValue(void) const { return mTypeIdFlags; }
uint8_t GetRawValue(void) const { return mFlags; }
/**
* This method sets the raw value of the entire TypeIdFlags.
*
* @param[in] aTypeIdFlags The value of entire TypeIdFlags.
* @param[in] aFlags The raw flags value.
*
*/
void SetRawValue(uint8_t aTypeIdFlags) { mTypeIdFlags = aTypeIdFlags; }
void SetRawValue(uint8_t aFlags) { mFlags = aFlags; }
private:
enum
{
kLengthFlag = 1 << 6,
kExtendedFlag = 1 << 7,
kTypeEnumOffset = 3,
kTypeEnumMask = 7 << kTypeEnumOffset,
kMetricEnumOffset = 0,
kMetricEnumMask = 7 << kMetricEnumOffset,
};
uint8_t mTypeIdFlags;
uint8_t mFlags;
} OT_TOOL_PACKED_END;
/**
@@ -237,7 +296,7 @@ private:
*
*/
OT_TOOL_PACKED_BEGIN
class LinkMetricsReportSubTlv : public Tlv, public TlvInfo<kLinkMetricsReportSub>
class ReportSubTlv : public Tlv, public TlvInfo<SubTlv::kReport>
{
public:
/**
@@ -246,7 +305,7 @@ public:
*/
void Init(void)
{
SetType(kLinkMetricsReportSub);
SetType(SubTlv::kReport);
SetLength(sizeof(*this) - sizeof(Tlv));
}
@@ -257,7 +316,7 @@ public:
* @retval false The TLV does not appear to be well-formed.
*
*/
bool IsValid(void) const { return GetLength() >= sizeof(LinkMetricsTypeIdFlags) + sizeof(uint8_t); }
bool IsValid(void) const { return GetLength() >= sizeof(TypeIdFlags) + sizeof(uint8_t); }
/**
* This method returns the Link Metrics Type ID.
@@ -265,7 +324,7 @@ public:
* @returns The Link Metrics Type ID.
*
*/
LinkMetricsTypeIdFlags GetMetricsTypeId(void) const { return mMetricsTypeId; }
TypeIdFlags GetMetricsTypeId(void) const { return mMetricsTypeId; }
/**
* This method sets the Link Metrics Type ID.
@@ -273,9 +332,10 @@ public:
* @param[in] aMetricsTypeID The Link Metrics Type ID to set.
*
*/
void SetMetricsTypeId(LinkMetricsTypeIdFlags aMetricsTypeId)
void SetMetricsTypeId(TypeIdFlags aMetricsTypeId)
{
mMetricsTypeId = aMetricsTypeId;
if (!aMetricsTypeId.IsLengthFlagSet())
{
SetLength(sizeof(*this) - sizeof(Tlv) - sizeof(uint32_t) + sizeof(uint8_t)); // The value is 1 byte long
@@ -315,7 +375,7 @@ public:
void SetMetricsValue32(uint32_t aMetricsValue) { mMetricsValue.m32 = aMetricsValue; }
private:
LinkMetricsTypeIdFlags mMetricsTypeId;
TypeIdFlags mMetricsTypeId;
union
{
uint8_t m8;
@@ -328,7 +388,7 @@ private:
*
*/
OT_TOOL_PACKED_BEGIN
class LinkMetricsQueryOptionsTlv : public Tlv, public TlvInfo<kLinkMetricsQueryOptions>
class QueryOptionsSubTlv : public Tlv, public TlvInfo<SubTlv::kQueryOptions>
{
public:
/**
@@ -337,7 +397,7 @@ public:
*/
void Init(void)
{
SetType(kLinkMetricsQueryOptions);
SetType(SubTlv::kQueryOptions);
SetLength(0);
}
@@ -348,7 +408,7 @@ public:
* @retval FALSE If the TLV does not appear to be well-formed.
*
*/
bool IsValid(void) const { return GetLength() >= sizeof(LinkMetricsTypeIdFlags); }
bool IsValid(void) const { return GetLength() >= sizeof(TypeIdFlags); }
} OT_TOOL_PACKED_END;
@@ -361,38 +421,47 @@ class SeriesFlags
{
public:
/**
* Default constructor
* This type represents which frames to be accounted in a Forward Tracking Series.
*
* @sa otLinkMetricsSeriesFlags
*
*/
SeriesFlags(void) { mSeriesFlags = 0; }
typedef otLinkMetricsSeriesFlags Info;
/**
* Copy constructor
* Default constructor.
*
*/
SeriesFlags(const SeriesFlags &aSeriesFlags) { mSeriesFlags = aSeriesFlags.mSeriesFlags; }
SeriesFlags(void)
: mFlags(0)
{
}
/**
* This method sets the values of this object from a `otLinkMetricsSeriesFlags` object.
* This method sets the values from an `Info` object.
*
* @param[in] aSeriesFlags The `otLinkMetricsSeriesFlags` object.
* @param[in] aSeriesFlags The `Info` object.
*
*/
void SetFromOtSeriesFlags(const otLinkMetricsSeriesFlags aSeriesFlags)
void SetFrom(const Info &aSeriesFlags)
{
Clear();
if (aSeriesFlags.mLinkProbe)
{
SetLinkProbeFlag();
}
if (aSeriesFlags.mMacData)
{
SetMacDataFlag();
}
if (aSeriesFlags.mMacDataRequest)
{
SetMacDataRequestFlag();
}
if (aSeriesFlags.mMacAck)
{
SetMacAckFlag();
@@ -403,13 +472,13 @@ public:
* This method clears the Link Probe flag.
*
*/
void ClearLinkProbeFlag(void) { mSeriesFlags &= ~kLinkProbeFlag; }
void ClearLinkProbeFlag(void) { mFlags &= ~kLinkProbeFlag; }
/**
* This method sets the Link Probe flag.
*
*/
void SetLinkProbeFlag(void) { mSeriesFlags |= kLinkProbeFlag; }
void SetLinkProbeFlag(void) { mFlags |= kLinkProbeFlag; }
/**
* This method indicates whether or not the Link Probe flag is set.
@@ -418,19 +487,19 @@ public:
* @retval false The Link Probe flag is not set.
*
*/
bool IsLinkProbeFlagSet(void) const { return (mSeriesFlags & kLinkProbeFlag) != 0; }
bool IsLinkProbeFlagSet(void) const { return (mFlags & kLinkProbeFlag) != 0; }
/**
* This method clears the MAC Data flag.
*
*/
void ClearMacDataFlag(void) { mSeriesFlags &= ~kMacDataFlag; }
void ClearMacDataFlag(void) { mFlags &= ~kMacDataFlag; }
/**
* This method sets the MAC Data flag.
*
*/
void SetMacDataFlag(void) { mSeriesFlags |= kMacDataFlag; }
void SetMacDataFlag(void) { mFlags |= kMacDataFlag; }
/**
* This method indicates whether or not the MAC Data flag is set.
@@ -439,19 +508,19 @@ public:
* @retval false The MAC Data flag is not set.
*
*/
bool IsMacDataFlagSet(void) const { return (mSeriesFlags & kMacDataFlag) != 0; }
bool IsMacDataFlagSet(void) const { return (mFlags & kMacDataFlag) != 0; }
/**
* This method clears the MAC Data Request flag.
*
*/
void ClearMacDataRequestFlag(void) { mSeriesFlags &= ~kMacDataRequestFlag; }
void ClearMacDataRequestFlag(void) { mFlags &= ~kMacDataRequestFlag; }
/**
* This method sets the MAC Data Request flag.
*
*/
void SetMacDataRequestFlag(void) { mSeriesFlags |= kMacDataRequestFlag; }
void SetMacDataRequestFlag(void) { mFlags |= kMacDataRequestFlag; }
/**
* This method indicates whether or not the MAC Data Request flag is set.
@@ -460,19 +529,19 @@ public:
* @retval false The MAC Data Request flag is not set.
*
*/
bool IsMacDataRequestFlagSet(void) const { return (mSeriesFlags & kMacDataRequestFlag) != 0; }
bool IsMacDataRequestFlagSet(void) const { return (mFlags & kMacDataRequestFlag) != 0; }
/**
* This method clears the Mac Ack flag.
*
*/
void ClearMacAckFlag(void) { mSeriesFlags &= ~kMacAckFlag; }
void ClearMacAckFlag(void) { mFlags &= ~kMacAckFlag; }
/**
* This method sets the Mac Ack flag.
*
*/
void SetMacAckFlag(void) { mSeriesFlags |= kMacAckFlag; }
void SetMacAckFlag(void) { mFlags |= kMacAckFlag; }
/**
* This method indicates whether or not the Mac Ack flag is set.
@@ -481,75 +550,69 @@ public:
* @retval false The Mac Ack flag is not set.
*
*/
bool IsMacAckFlagSet(void) const { return (mSeriesFlags & kMacAckFlag) != 0; }
bool IsMacAckFlagSet(void) const { return (mFlags & kMacAckFlag) != 0; }
/**
* This method returns the raw value of mSeriesFlags.
* This method returns the raw value of flags.
*
*/
uint8_t GetRawValue(void) const { return mSeriesFlags; }
uint8_t GetRawValue(void) const { return mFlags; }
/**
* This method clears the all the flags.
*
*/
void Clear(void) { mSeriesFlags = 0; }
/**
* This method overloads the assignment operator.
*
*/
void operator=(const SeriesFlags &aSeriesFlags) { mSeriesFlags = aSeriesFlags.mSeriesFlags; }
void Clear(void) { mFlags = 0; }
private:
enum
{
kLinkProbeFlag = 1 << 0,
kMacDataFlag = 1 << 1,
kMacDataRequestFlag = 1 << 2,
kMacAckFlag = 1 << 3,
};
static constexpr uint8_t kLinkProbeFlag = 1 << 0;
static constexpr uint8_t kMacDataFlag = 1 << 1;
static constexpr uint8_t kMacDataRequestFlag = 1 << 2;
static constexpr uint8_t kMacAckFlag = 1 << 3;
uint8_t mSeriesFlags;
uint8_t mFlags;
} OT_TOOL_PACKED_END;
enum LinkMetricsEnhAckFlags : uint8_t
/**
* This enumeration type represent Enhanced-ACK Flags.
*
*/
enum EnhAckFlags : uint8_t
{
kEnhAckClear = OT_LINK_METRICS_ENH_ACK_CLEAR, ///< Clear.
kEnhAckRegister = OT_LINK_METRICS_ENH_ACK_REGISTER, ///< Register.
};
static uint8_t TypeIdFlagsFromLinkMetricsFlags(LinkMetricsTypeIdFlags *aTypeIdFlags,
const otLinkMetrics & aLinkMetricsFlags)
static uint8_t TypeIdFlagsFromMetrics(TypeIdFlags aTypeIdFlags[], const Metrics &aMetrics)
{
uint8_t count = 0;
if (aLinkMetricsFlags.mPduCount)
if (aMetrics.mPduCount)
{
aTypeIdFlags[count++].SetRawValue(kTypeIdFlagPdu);
aTypeIdFlags[count++].SetRawValue(TypeIdFlags::kPdu);
}
if (aLinkMetricsFlags.mLqi)
if (aMetrics.mLqi)
{
aTypeIdFlags[count++].SetRawValue(kTypeIdFlagLqi);
aTypeIdFlags[count++].SetRawValue(TypeIdFlags::kLqi);
}
if (aLinkMetricsFlags.mLinkMargin)
if (aMetrics.mLinkMargin)
{
aTypeIdFlags[count++].SetRawValue(kTypeIdFlagLinkMargin);
aTypeIdFlags[count++].SetRawValue(TypeIdFlags::kLinkMargin);
}
if (aLinkMetricsFlags.mRssi)
if (aMetrics.mRssi)
{
aTypeIdFlags[count++].SetRawValue(kTypeIdFlagRssi);
aTypeIdFlags[count++].SetRawValue(TypeIdFlags::kRssi);
}
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
if (aLinkMetricsFlags.mReserved)
if (aMetrics.mReserved)
{
for (uint8_t i = 0; i < count; i++)
{
aTypeIdFlags[i].SetTypeEnum(LinkMetricsTypeIdFlags::kTypeEnumReserved);
aTypeIdFlags[i].SetTypeEnum(TypeIdFlags::kTypeReserved);
}
}
#endif
@@ -558,14 +621,14 @@ static uint8_t TypeIdFlagsFromLinkMetricsFlags(LinkMetricsTypeIdFlags *aTypeIdFl
}
OT_TOOL_PACKED_BEGIN
class EnhAckLinkMetricsConfigurationSubTlv : public Tlv
class EnhAckConfigSubTlv : public Tlv, public TlvInfo<SubTlv::kEnhAckConfig>
{
public:
/**
* Default constructor
*
*/
EnhAckLinkMetricsConfigurationSubTlv(void) { Init(); }
EnhAckConfigSubTlv(void) { Init(); }
/**
* This method initializes the TLV.
@@ -573,8 +636,8 @@ public:
*/
void Init(void)
{
SetType(kEnhancedACKConfiguration);
SetLength(sizeof(LinkMetricsEnhAckFlags));
SetType(SubTlv::kEnhAckConfig);
SetLength(sizeof(EnhAckFlags));
}
/**
@@ -583,27 +646,26 @@ public:
* @param[in] aEnhAckFlags The value of Enhanced ACK Flags.
*
*/
void SetEnhAckFlags(otLinkMetricsEnhAckFlags aEnhAckFlags)
void SetEnhAckFlags(EnhAckFlags aEnhAckFlags)
{
memcpy(mSubTlvs + kEnhAckFlagsOffset, &aEnhAckFlags, sizeof(aEnhAckFlags));
}
/**
* This method sets Type Id Flags.
* This method sets Type ID Flags.
*
* @param[in] aLinkMetricsFlags A pointer to a `otLinkMetrics` representing the Type Id Flags.
* @param[in] aMetrics A metrics flags to indicate the Type ID Flags.
*
*/
void SetTypeIdFlags(const otLinkMetrics *aLinkMetricsFlags)
void SetTypeIdFlags(const Metrics &aMetrics)
{
uint8_t typeIdFlagsCount;
uint8_t count;
OT_ASSERT(aLinkMetricsFlags != nullptr);
typeIdFlagsCount = TypeIdFlagsFromLinkMetricsFlags(
reinterpret_cast<LinkMetricsTypeIdFlags *>(mSubTlvs + kTypeIdFlagsOffset), *aLinkMetricsFlags);
OT_ASSERT(typeIdFlagsCount <= kMaxTypeIdFlagsEnhAck);
count = TypeIdFlagsFromMetrics(reinterpret_cast<TypeIdFlags *>(mSubTlvs + kTypeIdFlagsOffset), aMetrics);
SetLength(sizeof(LinkMetricsEnhAckFlags) + sizeof(LinkMetricsTypeIdFlags) * typeIdFlagsCount);
OT_ASSERT(count <= kMaxTypeIdFlagsEnhAck);
SetLength(sizeof(EnhAckFlags) + sizeof(TypeIdFlags) * count);
}
private:
@@ -612,12 +674,13 @@ private:
kMaxTypeIdFlagsEnhAck = 3,
kEnhAckFlagsOffset = 0,
kTypeIdFlagsOffset = sizeof(LinkMetricsTypeIdFlags),
kTypeIdFlagsOffset = sizeof(TypeIdFlags),
};
uint8_t mSubTlvs[sizeof(LinkMetricsEnhAckFlags) + sizeof(LinkMetricsTypeIdFlags) * kMaxTypeIdFlagsEnhAck];
uint8_t mSubTlvs[sizeof(EnhAckFlags) + sizeof(TypeIdFlags) * kMaxTypeIdFlagsEnhAck];
} OT_TOOL_PACKED_END;
} // namespace LinkMetrics
} // namespace ot
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+10 -10
View File
@@ -2512,7 +2512,7 @@ exit:
}
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
Error Mle::SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::LinkMetricsStatus aStatus)
Error Mle::SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus)
{
Error error = kErrorNone;
Message *message;
@@ -2523,7 +2523,7 @@ Error Mle::SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, L
SuccessOrExit(error = AppendHeader(*message, kCommandLinkMetricsManagementResponse));
tlv.SetType(Tlv::kLinkMetricsManagement);
statusSubTlv.SetType(kLinkMetricsStatus);
statusSubTlv.SetType(LinkMetrics::SubTlv::kStatus);
statusSubTlv.SetLength(sizeof(aStatus));
tlv.SetLength(statusSubTlv.GetSize());
@@ -3031,8 +3031,8 @@ void Mle::HandleDataResponse(const Message &aMessage, const Ip6::MessageInfo &aM
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
if (Tlv::FindTlvValueOffset(aMessage, Tlv::kLinkMetricsReport, metricsReportValueOffset, length) == kErrorNone)
{
Get<LinkMetrics>().HandleLinkMetricsReport(aMessage, metricsReportValueOffset, length,
aMessageInfo.GetPeerAddr());
Get<LinkMetrics::LinkMetrics>().HandleReport(aMessage, metricsReportValueOffset, length,
aMessageInfo.GetPeerAddr());
}
#endif
@@ -3942,14 +3942,14 @@ void Mle::HandleLinkMetricsManagementRequest(const Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
Neighbor * aNeighbor)
{
Error error = kErrorNone;
LinkMetrics::LinkMetricsStatus status;
Error error = kErrorNone;
LinkMetrics::Status status;
Log(kMessageReceive, kTypeLinkMetricsManagementRequest, aMessageInfo.GetPeerAddr());
VerifyOrExit(aNeighbor != nullptr, error = kErrorInvalidState);
SuccessOrExit(error = Get<LinkMetrics>().HandleLinkMetricsManagementRequest(aMessage, *aNeighbor, status));
SuccessOrExit(error = Get<LinkMetrics::LinkMetrics>().HandleManagementRequest(aMessage, *aNeighbor, status));
error = SendLinkMetricsManagementResponse(aMessageInfo.GetPeerAddr(), status);
exit:
@@ -3969,7 +3969,7 @@ void Mle::HandleLinkMetricsManagementResponse(const Message & aMessage,
VerifyOrExit(aNeighbor != nullptr, error = kErrorInvalidState);
error = Get<LinkMetrics>().HandleLinkMetricsManagementResponse(aMessage, aMessageInfo.GetPeerAddr());
error = Get<LinkMetrics::LinkMetrics>().HandleManagementResponse(aMessage, aMessageInfo.GetPeerAddr());
exit:
LogProcessError(kTypeLinkMetricsManagementResponse, error);
@@ -3984,8 +3984,8 @@ void Mle::HandleLinkProbe(const Message &aMessage, const Ip6::MessageInfo &aMess
Log(kMessageReceive, kTypeLinkProbe, aMessageInfo.GetPeerAddr());
SuccessOrExit(error = Get<LinkMetrics>().HandleLinkProbe(aMessage, seriesId));
aNeighbor->AggregateLinkMetrics(seriesId, LinkMetricsSeriesInfo::kSeriesTypeLinkProbe, aMessage.GetAverageLqi(),
SuccessOrExit(error = Get<LinkMetrics::LinkMetrics>().HandleLinkProbe(aMessage, seriesId));
aNeighbor->AggregateLinkMetrics(seriesId, LinkMetrics::SeriesInfo::kSeriesTypeLinkProbe, aMessage.GetAverageLqi(),
aMessage.GetAverageRss());
exit:
+2 -2
View File
@@ -97,7 +97,7 @@ class Mle : public InstanceLocator, private NonCopyable
friend class DiscoverScanner;
friend class ot::Notifier;
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
friend class ot::LinkMetrics;
friend class ot::LinkMetrics::LinkMetrics;
#endif
public:
@@ -1809,7 +1809,7 @@ private:
bool PrepareAnnounceState(void);
void SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce, const Ip6::Address &aDestination);
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::LinkMetricsStatus aStatus);
Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::Status aStatus);
#endif
uint32_t Reattach(void);
+1 -1
View File
@@ -3290,7 +3290,7 @@ void MleRouter::SendDataResponse(const Ip6::Address &aDestination,
OT_ASSERT(aRequestMessage != nullptr);
neighbor = mNeighborTable.FindNeighbor(aDestination);
VerifyOrExit(neighbor != nullptr, error = kErrorInvalidState);
SuccessOrExit(error = Get<LinkMetrics>().AppendLinkMetricsReport(*message, *aRequestMessage, *neighbor));
SuccessOrExit(error = Get<LinkMetrics::LinkMetrics>().AppendReport(*message, *aRequestMessage, *neighbor));
break;
#endif
}
+1 -1
View File
@@ -302,7 +302,7 @@ private:
TimeSync mTimeSync;
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
LinkMetrics mLinkMetrics;
LinkMetrics::LinkMetrics mLinkMetrics;
#endif
};
+8 -8
View File
@@ -163,8 +163,8 @@ void Neighbor::GenerateChallenge(void)
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
void Neighbor::AggregateLinkMetrics(uint8_t aSeriesId, uint8_t aFrameType, uint8_t aLqi, int8_t aRss)
{
for (LinkMetricsSeriesInfo *entry = mLinkMetricsSeriesInfoList.GetHead(); entry != nullptr;
entry = entry->GetNext())
for (LinkMetrics::SeriesInfo *entry = mLinkMetricsSeriesInfoList.GetHead(); entry != nullptr;
entry = entry->GetNext())
{
if (aSeriesId == 0 || aSeriesId == entry->GetSeriesId())
{
@@ -173,17 +173,17 @@ void Neighbor::AggregateLinkMetrics(uint8_t aSeriesId, uint8_t aFrameType, uint8
}
}
LinkMetricsSeriesInfo *Neighbor::GetForwardTrackingSeriesInfo(const uint8_t &aSeriesId)
LinkMetrics::SeriesInfo *Neighbor::GetForwardTrackingSeriesInfo(const uint8_t &aSeriesId)
{
return mLinkMetricsSeriesInfoList.FindMatching(aSeriesId);
}
void Neighbor::AddForwardTrackingSeriesInfo(LinkMetricsSeriesInfo &aLinkMetricsSeriesInfo)
void Neighbor::AddForwardTrackingSeriesInfo(LinkMetrics::SeriesInfo &aSeriesInfo)
{
mLinkMetricsSeriesInfoList.Push(aLinkMetricsSeriesInfo);
mLinkMetricsSeriesInfoList.Push(aSeriesInfo);
}
LinkMetricsSeriesInfo *Neighbor::RemoveForwardTrackingSeriesInfo(const uint8_t &aSeriesId)
LinkMetrics::SeriesInfo *Neighbor::RemoveForwardTrackingSeriesInfo(const uint8_t &aSeriesId)
{
return mLinkMetricsSeriesInfoList.RemoveMatching(aSeriesId);
}
@@ -192,8 +192,8 @@ void Neighbor::RemoveAllForwardTrackingSeriesInfo(void)
{
while (!mLinkMetricsSeriesInfoList.IsEmpty())
{
LinkMetricsSeriesInfo *seriesInfo = mLinkMetricsSeriesInfoList.Pop();
Get<LinkMetrics>().mLinkMetricsSeriesInfoPool.Free(*seriesInfo);
LinkMetrics::SeriesInfo *seriesInfo = mLinkMetricsSeriesInfoList.Pop();
Get<LinkMetrics::LinkMetrics>().mSeriesInfoPool.Free(*seriesInfo);
}
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+20 -18
View File
@@ -681,32 +681,32 @@ public:
void AggregateLinkMetrics(uint8_t aSeriesId, uint8_t aFrameType, uint8_t aLqi, int8_t aRss);
/**
* This method adds a new LinkMetricsSeriesInfo to the neighbor's list.
* This method adds a new LinkMetrics::SeriesInfo to the neighbor's list.
*
* @param[in] A reference to the new LinkMetricsSeriesInfo.
* @param[in] A reference to the new SeriesInfo.
*
*/
void AddForwardTrackingSeriesInfo(LinkMetricsSeriesInfo &aLinkMetricsSeriesInfo);
void AddForwardTrackingSeriesInfo(LinkMetrics::SeriesInfo &aSeriesInfo);
/**
* This method finds a specific LinkMetricsSeriesInfo by Series ID.
* This method finds a specific LinkMetrics::SeriesInfo by Series ID.
*
* @param[in] aSeriesId A reference to the Series ID.
*
* @returns The pointer to the LinkMetricsSeriesInfo. `nullptr` if not found.
* @returns The pointer to the LinkMetrics::SeriesInfo. `nullptr` if not found.
*
*/
LinkMetricsSeriesInfo *GetForwardTrackingSeriesInfo(const uint8_t &aSeriesId);
LinkMetrics::SeriesInfo *GetForwardTrackingSeriesInfo(const uint8_t &aSeriesId);
/**
* This method removes a specific LinkMetricsSeriesInfo by Series ID.
* This method removes a specific LinkMetrics::SeriesInfo by Series ID.
*
* @param[in] aSeriesId A reference to the Series ID to remove.
*
* @returns The pointer to the LinkMetricsSeriesInfo. `nullptr` if not found.
* @returns The pointer to the LinkMetrics::SeriesInfo. `nullptr` if not found.
*
*/
LinkMetricsSeriesInfo *RemoveForwardTrackingSeriesInfo(const uint8_t &aSeriesId);
LinkMetrics::SeriesInfo *RemoveForwardTrackingSeriesInfo(const uint8_t &aSeriesId);
/**
* This method removes all the Series and return the data structures to the Pool.
@@ -720,7 +720,7 @@ public:
* @returns Enh-ACK Probing metrics configured.
*
*/
const otLinkMetrics &GetEnhAckProbingMetrics(void) const { return mEnhAckProbingMetrics; }
const LinkMetrics::Metrics &GetEnhAckProbingMetrics(void) const { return mEnhAckProbingMetrics; }
/**
* This method sets the Enh-ACK Probing metrics (this `Neighbor` object is the Probing Subject).
@@ -728,7 +728,7 @@ public:
* @param[in] aEnhAckProbingMetrics The metrics value to set.
*
*/
void SetEnhAckProbingMetrics(const otLinkMetrics &aEnhAckProbingMetrics)
void SetEnhAckProbingMetrics(const LinkMetrics::Metrics &aEnhAckProbingMetrics)
{
mEnhAckProbingMetrics = aEnhAckProbingMetrics;
}
@@ -802,13 +802,15 @@ private:
uint8_t mVersion; ///< The MLE version
LinkQualityInfo mLinkInfo; ///< Link quality info (contains average RSS, link margin and link quality)
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
LinkedList<LinkMetricsSeriesInfo> mLinkMetricsSeriesInfoList; ///< A list of Link Metrics Forward Tracking Series
///< that is being tracked for this neighbor. Note
///< that this device is the Subject and this
///< this neighbor is the Initiator.
otLinkMetrics mEnhAckProbingMetrics; ///< Metrics configured for Enh-ACK Based Probing at the Probing Subject
///< (this neighbor). Note that this device is the Initiator and this neighbor
///< is the Subject.
// A list of Link Metrics Forward Tracking Series that is being
// tracked for this neighbor. Note that this device is the
// Subject and this neighbor is the Initiator.
LinkedList<LinkMetrics::SeriesInfo> mLinkMetricsSeriesInfoList;
// Metrics configured for Enh-ACK Based Probing at the Probing
// Subject (this neighbor). Note that this device is the Initiator
// and this neighbor is the Subject.
LinkMetrics::Metrics mEnhAckProbingMetrics;
#endif
};