mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
[mle] introduce Connectivity and ConnectivityTlvValue types (#12300)
This change separates the Connectivity TLV value format from its logical structure by introducing `ConnectivityTlvValue` (raw format) and `Connectivity` (parsed info). This replaces the `ConnectivityTlv` class and enables value format sharing between MLE and Network Diagnostics (without improper TLV inheritance). It also updates `ParentCandidate` to use the new `Connectivity` class for better field encapsulation. It also updates `ConnectivityTlvValue` parsing to handle optional fields and enforce spec-defined minimums for these fields.
This commit is contained in:
committed by
GitHub
parent
e3b565cc40
commit
0e72f56941
+40
-34
@@ -3862,12 +3862,11 @@ exit:
|
||||
|
||||
Error Mle::TxMessage::AppendConnectivityTlv(void)
|
||||
{
|
||||
ConnectivityTlv tlv;
|
||||
ConnectivityTlvValue tlvValue;
|
||||
|
||||
tlv.Init();
|
||||
Get<Mle>().FillConnectivityTlv(tlv);
|
||||
Get<Mle>().FillConnectivityTlvValue(tlvValue);
|
||||
|
||||
return tlv.AppendTo(*this);
|
||||
return Tlv::Append<ConnectivityTlv>(*this, &tlvValue, sizeof(tlvValue));
|
||||
}
|
||||
|
||||
Error Mle::TxMessage::AppendAddressRegistrationTlv(Child &aChild)
|
||||
@@ -4071,6 +4070,20 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Mle::RxMessage::ReadConnectivityTlv(Connectivity &aConnectivity) const
|
||||
{
|
||||
Error error;
|
||||
ConnectivityTlvValue tlvValue;
|
||||
OffsetRange offsetRange;
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(*this, ConnectivityTlv::kType, offsetRange));
|
||||
SuccessOrExit(error = tlvValue.ParseFrom(*this, offsetRange));
|
||||
tlvValue.GetConnectivity(aConnectivity);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Mle::RxMessage::ReadAndSetNetworkDataTlv(const LeaderData &aLeaderData) const
|
||||
{
|
||||
Error error;
|
||||
@@ -5032,7 +5045,7 @@ bool Mle::Attacher::HasMoreChannelsToAnnounce(void) const
|
||||
|
||||
bool Mle::Attacher::IsBetterParent(uint16_t aRloc16,
|
||||
uint8_t aTwoWayLinkMargin,
|
||||
const ConnectivityTlv &aConnectivityTlv,
|
||||
const Connectivity &aConnectivity,
|
||||
uint16_t aVersion,
|
||||
const Mac::CslAccuracy &aCslAccuracy)
|
||||
{
|
||||
@@ -5045,11 +5058,11 @@ bool Mle::Attacher::IsBetterParent(uint16_t aRloc16,
|
||||
rval = ThreeWayCompare(IsRouterRloc16(aRloc16), IsRouterRloc16(mParentCandidate.GetRloc16()));
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
rval = ThreeWayCompare(aConnectivityTlv.GetParentPriority(), mParentCandidate.mPriority);
|
||||
rval = ThreeWayCompare(aConnectivity.GetParentPriority(), mParentCandidate.mConnectivity.GetParentPriority());
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
// Prefer the parent with highest quality links (Link Quality 3 field in Connectivity TLV) to neighbors
|
||||
rval = ThreeWayCompare(aConnectivityTlv.GetLinkQuality3(), mParentCandidate.mLinkQuality3);
|
||||
rval = ThreeWayCompare(aConnectivity.GetNumLinkQuality3(), mParentCandidate.mConnectivity.GetNumLinkQuality3());
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
// Thread 1.2 Specification 4.5.2.1.2 Child Impacting Criteria
|
||||
@@ -5057,17 +5070,17 @@ bool Mle::Attacher::IsBetterParent(uint16_t aRloc16,
|
||||
rval = ThreeWayCompare(aVersion, mParentCandidate.GetVersion());
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
rval = ThreeWayCompare(aConnectivityTlv.GetSedBufferSize(), mParentCandidate.mSedBufferSize);
|
||||
rval = ThreeWayCompare(aConnectivity.GetSedBufferSize(), mParentCandidate.mConnectivity.GetSedBufferSize());
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
rval = ThreeWayCompare(aConnectivityTlv.GetSedDatagramCount(), mParentCandidate.mSedDatagramCount);
|
||||
rval = ThreeWayCompare(aConnectivity.GetSedDatagramCount(), mParentCandidate.mConnectivity.GetSedDatagramCount());
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
// Extra rules
|
||||
rval = ThreeWayCompare(aConnectivityTlv.GetLinkQuality2(), mParentCandidate.mLinkQuality2);
|
||||
rval = ThreeWayCompare(aConnectivity.GetNumLinkQuality2(), mParentCandidate.mConnectivity.GetNumLinkQuality2());
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
rval = ThreeWayCompare(aConnectivityTlv.GetLinkQuality1(), mParentCandidate.mLinkQuality1);
|
||||
rval = ThreeWayCompare(aConnectivity.GetNumLinkQuality1(), mParentCandidate.mConnectivity.GetNumLinkQuality1());
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
@@ -5100,7 +5113,7 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo)
|
||||
LeaderData leaderData;
|
||||
uint8_t linkMarginOut;
|
||||
uint8_t twoWayLinkMargin;
|
||||
ConnectivityTlv connectivityTlv;
|
||||
Connectivity connectivity;
|
||||
uint32_t linkFrameCounter;
|
||||
uint32_t mleFrameCounter;
|
||||
Mac::ExtAddress extAddress;
|
||||
@@ -5131,8 +5144,7 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo)
|
||||
SuccessOrExit(error = Tlv::Find<LinkMarginTlv>(aRxInfo.mMessage, linkMarginOut));
|
||||
twoWayLinkMargin = Min(Get<Mac::Mac>().ComputeLinkMargin(rss), linkMarginOut);
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlv(aRxInfo.mMessage, connectivityTlv));
|
||||
VerifyOrExit(connectivityTlv.IsValid(), error = kErrorParse);
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadConnectivityTlv(connectivity));
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
switch (aRxInfo.mMessage.ReadCslClockAccuracyTlv(cslAccuracy))
|
||||
@@ -5157,10 +5169,10 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo)
|
||||
parentinfo.mExtAddr = extAddress;
|
||||
parentinfo.mRloc16 = sourceAddress;
|
||||
parentinfo.mRssi = rss;
|
||||
parentinfo.mPriority = connectivityTlv.GetParentPriority();
|
||||
parentinfo.mLinkQuality3 = connectivityTlv.GetLinkQuality3();
|
||||
parentinfo.mLinkQuality2 = connectivityTlv.GetLinkQuality2();
|
||||
parentinfo.mLinkQuality1 = connectivityTlv.GetLinkQuality1();
|
||||
parentinfo.mPriority = connectivity.GetParentPriority();
|
||||
parentinfo.mLinkQuality3 = connectivity.GetNumLinkQuality3();
|
||||
parentinfo.mLinkQuality2 = connectivity.GetNumLinkQuality2();
|
||||
parentinfo.mLinkQuality1 = connectivity.GetNumLinkQuality1();
|
||||
parentinfo.mIsAttached = Get<Mle>().IsAttached();
|
||||
|
||||
mParentResponseCallback.Invoke(&parentinfo);
|
||||
@@ -5173,9 +5185,9 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo)
|
||||
if (Get<Mle>().IsFullThreadDevice() && !Get<Mle>().IsDetached())
|
||||
{
|
||||
bool isPartitionIdSame = (leaderData.GetPartitionId() == Get<Mle>().mLeaderData.GetPartitionId());
|
||||
bool isIdSequenceSame = (connectivityTlv.GetIdSequence() == Get<RouterTable>().GetRouterIdSequence());
|
||||
bool isIdSequenceSame = (connectivity.GetIdSequence() == Get<RouterTable>().GetRouterIdSequence());
|
||||
bool isIdSequenceGreater =
|
||||
SerialNumber::IsGreater(connectivityTlv.GetIdSequence(), Get<RouterTable>().GetRouterIdSequence());
|
||||
SerialNumber::IsGreater(connectivity.GetIdSequence(), Get<RouterTable>().GetRouterIdSequence());
|
||||
|
||||
switch (mMode)
|
||||
{
|
||||
@@ -5194,7 +5206,7 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo)
|
||||
case kBetterPartition:
|
||||
VerifyOrExit(!isPartitionIdSame);
|
||||
|
||||
VerifyOrExit(ComparePartitions(connectivityTlv.IsSingleton(), leaderData, Get<Mle>().IsSingleton(),
|
||||
VerifyOrExit(ComparePartitions(connectivity.IsSingleton(), leaderData, Get<Mle>().IsSingleton(),
|
||||
Get<Mle>().mLeaderData) > 0);
|
||||
break;
|
||||
|
||||
@@ -5217,8 +5229,8 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo)
|
||||
#if OPENTHREAD_FTD
|
||||
if (Get<Mle>().IsFullThreadDevice())
|
||||
{
|
||||
compare = ComparePartitions(connectivityTlv.IsSingleton(), leaderData, mParentCandidate.mIsSingleton,
|
||||
mParentCandidate.mLeaderData);
|
||||
compare = ComparePartitions(connectivity.IsSingleton(), leaderData,
|
||||
mParentCandidate.mConnectivity.IsSingleton(), mParentCandidate.mLeaderData);
|
||||
}
|
||||
|
||||
// Only consider partitions that are the same or better
|
||||
@@ -5228,7 +5240,7 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo)
|
||||
// Only consider better parents if the partitions are the same
|
||||
if (compare == 0)
|
||||
{
|
||||
VerifyOrExit(IsBetterParent(sourceAddress, twoWayLinkMargin, connectivityTlv, version, cslAccuracy));
|
||||
VerifyOrExit(IsBetterParent(sourceAddress, twoWayLinkMargin, connectivity, version, cslAccuracy));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5267,20 +5279,14 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo)
|
||||
mParentCandidate.SetLinkQualityOut(LinkQualityForLinkMargin(linkMarginOut));
|
||||
mParentCandidate.SetState(Neighbor::kStateParentResponse);
|
||||
mParentCandidate.SetKeySequence(aRxInfo.mKeySequence);
|
||||
mParentCandidate.SetLeaderCost(connectivityTlv.GetLeaderCost());
|
||||
mParentCandidate.SetLeaderCost(connectivity.GetLeaderCost());
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
mParentCandidate.SetCslAccuracy(cslAccuracy);
|
||||
#endif
|
||||
|
||||
mParentCandidate.mPriority = connectivityTlv.GetParentPriority();
|
||||
mParentCandidate.mLinkQuality3 = connectivityTlv.GetLinkQuality3();
|
||||
mParentCandidate.mLinkQuality2 = connectivityTlv.GetLinkQuality2();
|
||||
mParentCandidate.mLinkQuality1 = connectivityTlv.GetLinkQuality1();
|
||||
mParentCandidate.mSedBufferSize = connectivityTlv.GetSedBufferSize();
|
||||
mParentCandidate.mSedDatagramCount = connectivityTlv.GetSedDatagramCount();
|
||||
mParentCandidate.mLeaderData = leaderData;
|
||||
mParentCandidate.mIsSingleton = connectivityTlv.IsSingleton();
|
||||
mParentCandidate.mLinkMargin = twoWayLinkMargin;
|
||||
mParentCandidate.mConnectivity = connectivity;
|
||||
mParentCandidate.mLeaderData = leaderData;
|
||||
mParentCandidate.mLinkMargin = twoWayLinkMargin;
|
||||
|
||||
exit:
|
||||
LogProcessError(kTypeParentResponse, error);
|
||||
|
||||
+10
-14
@@ -1033,11 +1033,11 @@ public:
|
||||
const LeaderData &aLeaderDataB);
|
||||
|
||||
/**
|
||||
* Fills an ConnectivityTlv.
|
||||
* Fills a `ConnectivityTlvValue`.
|
||||
*
|
||||
* @param[out] aTlv A reference to the tlv to be filled.
|
||||
* @param[out] aTlvValue A reference to a `ConnectivityTlvValue` be filled.
|
||||
*/
|
||||
void FillConnectivityTlv(ConnectivityTlv &aTlv);
|
||||
void FillConnectivityTlvValue(ConnectivityTlvValue &aTlvValue) const;
|
||||
|
||||
/**
|
||||
* Schedule tx of MLE Advertisement message (unicast) to the given neighboring router after a random delay.
|
||||
@@ -1598,6 +1598,7 @@ private:
|
||||
Error ReadFrameCounterTlvs(uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const;
|
||||
Error ReadTlvRequestTlv(TlvList &aTlvList) const;
|
||||
Error ReadLeaderDataTlv(LeaderData &aLeaderData) const;
|
||||
Error ReadConnectivityTlv(Connectivity &aConnectivity) const;
|
||||
Error ReadAndSetNetworkDataTlv(const LeaderData &aLeaderData) const;
|
||||
Error ReadAndSaveActiveDataset(const MeshCoP::Timestamp &aActiveTimestamp) const;
|
||||
Error ReadAndSavePendingDataset(const MeshCoP::Timestamp &aPendingTimestamp) const;
|
||||
@@ -1795,16 +1796,10 @@ private:
|
||||
void Clear(void);
|
||||
void CopyTo(Parent &aParent) const;
|
||||
|
||||
RxChallenge mRxChallenge;
|
||||
int8_t mPriority;
|
||||
uint8_t mLinkQuality3;
|
||||
uint8_t mLinkQuality2;
|
||||
uint8_t mLinkQuality1;
|
||||
uint16_t mSedBufferSize;
|
||||
uint8_t mSedDatagramCount;
|
||||
uint8_t mLinkMargin;
|
||||
LeaderData mLeaderData;
|
||||
bool mIsSingleton;
|
||||
RxChallenge mRxChallenge;
|
||||
Connectivity mConnectivity;
|
||||
uint8_t mLinkMargin;
|
||||
LeaderData mLeaderData;
|
||||
};
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -1925,7 +1920,7 @@ private:
|
||||
bool PrepareAnnounceState(void);
|
||||
bool IsBetterParent(uint16_t aRloc16,
|
||||
uint8_t aTwoWayLinkMargin,
|
||||
const ConnectivityTlv &aConnectivityTlv,
|
||||
const Connectivity &aConnectivity,
|
||||
uint16_t aVersion,
|
||||
const Mac::CslAccuracy &aCslAccuracy);
|
||||
|
||||
@@ -2364,6 +2359,7 @@ private:
|
||||
void ClearAlternateRloc16(void);
|
||||
uint8_t SelectLeaderId(void) const;
|
||||
uint32_t SelectPartitionId(void) const;
|
||||
void DetermineConnectivity(Connectivity &aConnectivity) const;
|
||||
void HandleDetachStart(void);
|
||||
void HandleChildStart(void);
|
||||
void HandleSecurityPolicyChanged(void);
|
||||
|
||||
+22
-22
@@ -3660,38 +3660,30 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Mle::FillConnectivityTlv(ConnectivityTlv &aTlv)
|
||||
void Mle::DetermineConnectivity(Connectivity &aConnectivity) const
|
||||
{
|
||||
int8_t parentPriority = kParentPriorityMedium;
|
||||
aConnectivity.Clear();
|
||||
|
||||
if (mParentPriority != kParentPriorityUnspecified)
|
||||
{
|
||||
parentPriority = mParentPriority;
|
||||
}
|
||||
else
|
||||
aConnectivity.mParentPriority = GetAssignParentPriority();
|
||||
|
||||
if (aConnectivity.mParentPriority == kParentPriorityUnspecified)
|
||||
{
|
||||
uint16_t numChildren = mChildTable.GetNumChildren(Child::kInStateValid);
|
||||
uint16_t maxAllowed = mChildTable.GetMaxChildrenAllowed();
|
||||
|
||||
if ((maxAllowed - numChildren) < (maxAllowed / 3))
|
||||
{
|
||||
parentPriority = kParentPriorityLow;
|
||||
aConnectivity.mParentPriority = kParentPriorityLow;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentPriority = kParentPriorityMedium;
|
||||
aConnectivity.mParentPriority = kParentPriorityMedium;
|
||||
}
|
||||
}
|
||||
|
||||
aTlv.SetParentPriority(parentPriority);
|
||||
|
||||
aTlv.SetLinkQuality1(0);
|
||||
aTlv.SetLinkQuality2(0);
|
||||
aTlv.SetLinkQuality3(0);
|
||||
|
||||
if (IsChild())
|
||||
{
|
||||
aTlv.IncrementLinkQuality(mParent.GetLinkQualityIn());
|
||||
aConnectivity.IncrementNumForLinkQuality(mParent.GetLinkQualityIn());
|
||||
}
|
||||
|
||||
for (const Router &router : Get<RouterTable>())
|
||||
@@ -3706,14 +3698,22 @@ void Mle::FillConnectivityTlv(ConnectivityTlv &aTlv)
|
||||
continue;
|
||||
}
|
||||
|
||||
aTlv.IncrementLinkQuality(router.GetTwoWayLinkQuality());
|
||||
aConnectivity.IncrementNumForLinkQuality(router.GetTwoWayLinkQuality());
|
||||
}
|
||||
|
||||
aTlv.SetActiveRouters(mRouterTable.GetActiveRouterCount());
|
||||
aTlv.SetLeaderCost(Min(mRouterTable.GetPathCostToLeader(), kMaxRouteCost));
|
||||
aTlv.SetIdSequence(mRouterTable.GetRouterIdSequence());
|
||||
aTlv.SetSedBufferSize(OPENTHREAD_CONFIG_DEFAULT_SED_BUFFER_SIZE);
|
||||
aTlv.SetSedDatagramCount(OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT);
|
||||
aConnectivity.mLeaderCost = Min(mRouterTable.GetPathCostToLeader(), kMaxRouteCost);
|
||||
aConnectivity.mIdSequence = mRouterTable.GetRouterIdSequence();
|
||||
aConnectivity.mActiveRouters = mRouterTable.GetActiveRouterCount();
|
||||
aConnectivity.mSedBufferSize = Connectivity::kDefaultSedBufferSize;
|
||||
aConnectivity.mSedDatagramCount = Connectivity::kDefaultSedDatagramCount;
|
||||
}
|
||||
|
||||
void Mle::FillConnectivityTlvValue(ConnectivityTlvValue &aTlvValue) const
|
||||
{
|
||||
Connectivity connectivity;
|
||||
|
||||
DetermineConnectivity(connectivity);
|
||||
aTlvValue.InitFrom(connectivity);
|
||||
}
|
||||
|
||||
bool Mle::ShouldDowngrade(uint8_t aNeighborId, const RouteTlv &aRouteTlv) const
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
namespace ot {
|
||||
namespace Mle {
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// RouteTlv
|
||||
|
||||
#if !OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
|
||||
|
||||
void RouteTlv::Init(void)
|
||||
@@ -69,33 +72,68 @@ exit:
|
||||
|
||||
#endif // #if !OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
|
||||
|
||||
void ConnectivityTlv::IncrementLinkQuality(LinkQuality aLinkQuality)
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// ConnectivityTlvValue
|
||||
|
||||
void ConnectivityTlvValue::InitFrom(const Connectivity &aConnectivity)
|
||||
{
|
||||
switch (aLinkQuality)
|
||||
mFlags = 0;
|
||||
|
||||
WriteBits<uint8_t, kFlagsParentPriorityMask>(mFlags, Preference::To2BitUint(aConnectivity.GetParentPriority()));
|
||||
mLinkQuality3 = aConnectivity.GetNumLinkQuality3();
|
||||
mLinkQuality2 = aConnectivity.GetNumLinkQuality2();
|
||||
mLinkQuality1 = aConnectivity.GetNumLinkQuality1();
|
||||
mLeaderCost = aConnectivity.GetLeaderCost();
|
||||
mIdSequence = aConnectivity.GetIdSequence();
|
||||
mActiveRouters = aConnectivity.GetActiveRouterCount();
|
||||
mSedBufferSize = BigEndian::HostSwap16(aConnectivity.GetSedBufferSize());
|
||||
mSedDatagramCount = aConnectivity.GetSedDatagramCount();
|
||||
}
|
||||
|
||||
void ConnectivityTlvValue::GetConnectivity(Connectivity &aConnectivity) const
|
||||
{
|
||||
aConnectivity.Clear();
|
||||
|
||||
aConnectivity.mParentPriority = Preference::From2BitUint(ReadBits<uint8_t, kFlagsParentPriorityMask>(mFlags));
|
||||
aConnectivity.mLinkQuality3 = mLinkQuality3;
|
||||
aConnectivity.mLinkQuality2 = mLinkQuality2;
|
||||
aConnectivity.mLinkQuality1 = mLinkQuality1;
|
||||
aConnectivity.mLeaderCost = mLeaderCost;
|
||||
aConnectivity.mIdSequence = mIdSequence;
|
||||
aConnectivity.mActiveRouters = mActiveRouters;
|
||||
aConnectivity.mSedBufferSize = BigEndian::HostSwap16(mSedBufferSize);
|
||||
aConnectivity.mSedDatagramCount = mSedDatagramCount;
|
||||
}
|
||||
|
||||
Error ConnectivityTlvValue::ParseFrom(const Message &aMessage, const OffsetRange &aOffsetRange)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t size = aOffsetRange.GetLength();
|
||||
|
||||
// The `mSedBufferSize` and `mSedDatagramCount` fields are
|
||||
// optional and are included as a pair. If the received TLV size
|
||||
// indicates they are not present, we read the partial TLV value
|
||||
// and then set the fields to their default minimum values.
|
||||
// Otherwise, we read the full structure.
|
||||
|
||||
if (size == kMinSize)
|
||||
{
|
||||
case kLinkQuality0:
|
||||
break;
|
||||
case kLinkQuality1:
|
||||
mLinkQuality1++;
|
||||
break;
|
||||
case kLinkQuality2:
|
||||
mLinkQuality2++;
|
||||
break;
|
||||
case kLinkQuality3:
|
||||
mLinkQuality3++;
|
||||
break;
|
||||
SuccessOrExit(error = aMessage.Read(aOffsetRange, this, size));
|
||||
|
||||
mSedBufferSize = BigEndian::HostSwap16(kMinSedBufferSize);
|
||||
mSedDatagramCount = kMinSedDatagramCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(error = aMessage.Read(aOffsetRange, *this));
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
int8_t ConnectivityTlv::GetParentPriority(void) const
|
||||
{
|
||||
return Preference::From2BitUint(mFlags >> kFlagsParentPriorityOffset);
|
||||
}
|
||||
|
||||
void ConnectivityTlv::SetParentPriority(int8_t aParentPriority)
|
||||
{
|
||||
mFlags = static_cast<uint8_t>(Preference::To2BitUint(aParentPriority) << kFlagsParentPriorityOffset);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// ChannelTlvValue
|
||||
|
||||
void ChannelTlvValue::SetChannelAndPage(uint16_t aChannel)
|
||||
{
|
||||
@@ -137,6 +175,9 @@ exit:
|
||||
return isValid;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// LeaderDataTlvValue
|
||||
|
||||
LeaderDataTlvValue::LeaderDataTlvValue(const LeaderData &aLeaderData)
|
||||
: mPartitionId(BigEndian::HostSwap32(aLeaderData.GetPartitionId()))
|
||||
, mWeighting(aLeaderData.GetWeighting())
|
||||
|
||||
+35
-182
@@ -653,207 +653,55 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements Connectivity TLV generation and parsing.
|
||||
* Represents a Connectivity TLV value.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ConnectivityTlv : public Tlv, public TlvInfo<Tlv::kConnectivity>
|
||||
class ConnectivityTlvValue
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes the TLV.
|
||||
* Initializes the Connectivity TLV value from a given `Connectivity` object.
|
||||
*
|
||||
* @param[in] aConnectivity The `Connectivity` to use for initialization.
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
SetType(kConnectivity);
|
||||
SetLength(sizeof(*this) - sizeof(Tlv));
|
||||
}
|
||||
void InitFrom(const Connectivity &aConnectivity);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TLV appears to be well-formed.
|
||||
* Gets the connectivity information from the TLV value.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
* @param[out] aConnectivity A reference to a `Connectivity` object to output the information.
|
||||
*/
|
||||
bool IsValid(void) const
|
||||
{
|
||||
return IsSedBufferingIncluded() ||
|
||||
(GetLength() == sizeof(*this) - sizeof(Tlv) - sizeof(mSedBufferSize) - sizeof(mSedDatagramCount));
|
||||
}
|
||||
void GetConnectivity(Connectivity &aConnectivity) const;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the sed buffer size and datagram count are included.
|
||||
* Parses a Connectivity TLV value from a given message.
|
||||
*
|
||||
* @retval TRUE If the sed buffer size and datagram count are included.
|
||||
* @retval FALSE If the sed buffer size and datagram count are not included.
|
||||
* The SED Buffer Size and Datagram Count fields are optional in the Connectivity TLV. If not present in the
|
||||
* message, this method populates them with their default minimum values defined by Thread specification.
|
||||
*
|
||||
* @param[in] aMessage The message to parse from.
|
||||
* @param[in] aOffsetRange The offset range within the message containing the TLV value.
|
||||
*
|
||||
* @retval kErrorNone Successfully parsed the TLV value.
|
||||
* @retval kErrorParse Failed to parse the TLV value from the message.
|
||||
*/
|
||||
bool IsSedBufferingIncluded(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
|
||||
|
||||
/**
|
||||
* Returns the Parent Priority value.
|
||||
*
|
||||
* @returns The Parent Priority value.
|
||||
*/
|
||||
int8_t GetParentPriority(void) const;
|
||||
|
||||
/**
|
||||
* Sets the Parent Priority value.
|
||||
*
|
||||
* @param[in] aParentPriority The Parent Priority value.
|
||||
*/
|
||||
void SetParentPriority(int8_t aParentPriority);
|
||||
|
||||
/**
|
||||
* Returns the Link Quality 3 value.
|
||||
*
|
||||
* @returns The Link Quality 3 value.
|
||||
*/
|
||||
uint8_t GetLinkQuality3(void) const { return mLinkQuality3; }
|
||||
|
||||
/**
|
||||
* Sets the Link Quality 3 value.
|
||||
*
|
||||
* @param[in] aLinkQuality The Link Quality 3 value.
|
||||
*/
|
||||
void SetLinkQuality3(uint8_t aLinkQuality) { mLinkQuality3 = aLinkQuality; }
|
||||
|
||||
/**
|
||||
* Returns the Link Quality 2 value.
|
||||
*
|
||||
* @returns The Link Quality 2 value.
|
||||
*/
|
||||
uint8_t GetLinkQuality2(void) const { return mLinkQuality2; }
|
||||
|
||||
/**
|
||||
* Sets the Link Quality 2 value.
|
||||
*
|
||||
* @param[in] aLinkQuality The Link Quality 2 value.
|
||||
*/
|
||||
void SetLinkQuality2(uint8_t aLinkQuality) { mLinkQuality2 = aLinkQuality; }
|
||||
|
||||
/**
|
||||
* Sets the Link Quality 1 value.
|
||||
*
|
||||
* @returns The Link Quality 1 value.
|
||||
*/
|
||||
uint8_t GetLinkQuality1(void) const { return mLinkQuality1; }
|
||||
|
||||
/**
|
||||
* Sets the Link Quality 1 value.
|
||||
*
|
||||
* @param[in] aLinkQuality The Link Quality 1 value.
|
||||
*/
|
||||
void SetLinkQuality1(uint8_t aLinkQuality) { mLinkQuality1 = aLinkQuality; }
|
||||
|
||||
/**
|
||||
* Increments the Link Quality N field in TLV for a given Link Quality N (1,2,3).
|
||||
*
|
||||
* The Link Quality N field specifies the number of neighboring router devices with which the sender shares a link
|
||||
* of quality N.
|
||||
*
|
||||
* @param[in] aLinkQuality The Link Quality N (1,2,3) field to update.
|
||||
*/
|
||||
void IncrementLinkQuality(LinkQuality aLinkQuality);
|
||||
|
||||
/**
|
||||
* Sets the Active Routers value.
|
||||
*
|
||||
* @returns The Active Routers value.
|
||||
*/
|
||||
uint8_t GetActiveRouters(void) const { return mActiveRouters; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the partition is a singleton based on Active Routers value.
|
||||
*
|
||||
* @retval TRUE The partition is a singleton.
|
||||
* @retval FALSE The partition is not a singleton.
|
||||
*/
|
||||
bool IsSingleton(void) const { return (mActiveRouters <= 1); }
|
||||
|
||||
/**
|
||||
* Sets the Active Routers value.
|
||||
*
|
||||
* @param[in] aActiveRouters The Active Routers value.
|
||||
*/
|
||||
void SetActiveRouters(uint8_t aActiveRouters) { mActiveRouters = aActiveRouters; }
|
||||
|
||||
/**
|
||||
* Returns the Leader Cost value.
|
||||
*
|
||||
* @returns The Leader Cost value.
|
||||
*/
|
||||
uint8_t GetLeaderCost(void) const { return mLeaderCost; }
|
||||
|
||||
/**
|
||||
* Sets the Leader Cost value.
|
||||
*
|
||||
* @param[in] aCost The Leader Cost value.
|
||||
*/
|
||||
void SetLeaderCost(uint8_t aCost) { mLeaderCost = aCost; }
|
||||
|
||||
/**
|
||||
* Returns the ID Sequence value.
|
||||
*
|
||||
* @returns The ID Sequence value.
|
||||
*/
|
||||
uint8_t GetIdSequence(void) const { return mIdSequence; }
|
||||
|
||||
/**
|
||||
* Sets the ID Sequence value.
|
||||
*
|
||||
* @param[in] aSequence The ID Sequence value.
|
||||
*/
|
||||
void SetIdSequence(uint8_t aSequence) { mIdSequence = aSequence; }
|
||||
|
||||
/**
|
||||
* Returns the SED Buffer Size value.
|
||||
*
|
||||
* @returns The SED Buffer Size value.
|
||||
*/
|
||||
uint16_t GetSedBufferSize(void) const
|
||||
{
|
||||
uint16_t buffersize = OPENTHREAD_CONFIG_DEFAULT_SED_BUFFER_SIZE;
|
||||
|
||||
if (IsSedBufferingIncluded())
|
||||
{
|
||||
buffersize = BigEndian::HostSwap16(mSedBufferSize);
|
||||
}
|
||||
return buffersize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SED Buffer Size value.
|
||||
*
|
||||
* @param[in] aSedBufferSize The SED Buffer Size value.
|
||||
*/
|
||||
void SetSedBufferSize(uint16_t aSedBufferSize) { mSedBufferSize = BigEndian::HostSwap16(aSedBufferSize); }
|
||||
|
||||
/**
|
||||
* Returns the SED Datagram Count value.
|
||||
*
|
||||
* @returns The SED Datagram Count value.
|
||||
*/
|
||||
uint8_t GetSedDatagramCount(void) const
|
||||
{
|
||||
uint8_t count = OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT;
|
||||
|
||||
if (IsSedBufferingIncluded())
|
||||
{
|
||||
count = mSedDatagramCount;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SED Datagram Count value.
|
||||
*
|
||||
* @param[in] aSedDatagramCount The SED Datagram Count value.
|
||||
*/
|
||||
void SetSedDatagramCount(uint8_t aSedDatagramCount) { mSedDatagramCount = aSedDatagramCount; }
|
||||
Error ParseFrom(const Message &aMessage, const OffsetRange &aOffsetRange);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kFlagsParentPriorityOffset = 6;
|
||||
static constexpr uint8_t kFlagsParentPriorityMask = (3 << kFlagsParentPriorityOffset);
|
||||
|
||||
static constexpr uint8_t kMinSize = 7; // Exclude the optional `mSedBufferSize` and `mSedDatagramCount`.
|
||||
|
||||
// The default minimum values to use when the optional fields
|
||||
// `mSedBufferSize`, `mSedDatagramCount` are not included. These
|
||||
// numbers are from Thread Conformance Specification 1.4.1-dr3:
|
||||
// "A Thread Router MUST be able to buffer at least one 1280-octet
|
||||
// IPv6 datagram destined for an attached SED".
|
||||
|
||||
static constexpr uint16_t kMinSedBufferSize = 1280;
|
||||
static constexpr uint8_t kMinSedDatagramCount = 1;
|
||||
|
||||
uint8_t mFlags;
|
||||
uint8_t mLinkQuality3;
|
||||
uint8_t mLinkQuality2;
|
||||
@@ -865,6 +713,11 @@ private:
|
||||
uint8_t mSedDatagramCount;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* Defines Connectivity TLV constants.
|
||||
*/
|
||||
typedef TlvInfo<Tlv::kConnectivity> ConnectivityTlv;
|
||||
|
||||
/**
|
||||
* Provides constants and methods for generation and parsing of Address Registration TLV.
|
||||
*/
|
||||
|
||||
@@ -190,6 +190,27 @@ bool RxChallenge::operator==(const TxChallenge &aTxChallenge) const
|
||||
return (mArray.GetLength() == kMaxSize) && (memcmp(mArray.GetArrayBuffer(), aTxChallenge.m8, kMaxSize) == 0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Connectivity
|
||||
|
||||
void Connectivity::IncrementNumForLinkQuality(uint8_t aLinkQuality)
|
||||
{
|
||||
switch (aLinkQuality)
|
||||
{
|
||||
case kLinkQuality1:
|
||||
mLinkQuality1++;
|
||||
break;
|
||||
case kLinkQuality2:
|
||||
mLinkQuality2++;
|
||||
break;
|
||||
case kLinkQuality3:
|
||||
mLinkQuality3++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
const char *RoleToString(DeviceRole aRole)
|
||||
|
||||
@@ -42,10 +42,9 @@
|
||||
#if OPENTHREAD_CONFIG_P2P_ENABLE
|
||||
#include <openthread/provisional/p2p.h>
|
||||
#endif
|
||||
#include <openthread/netdiag.h>
|
||||
#include <openthread/thread.h>
|
||||
#if OPENTHREAD_FTD
|
||||
#include <openthread/thread_ftd.h>
|
||||
#endif
|
||||
|
||||
#include "common/array.hpp"
|
||||
#include "common/as_core_type.hpp"
|
||||
@@ -68,6 +67,8 @@ class Message;
|
||||
|
||||
namespace Mle {
|
||||
|
||||
class Mle;
|
||||
|
||||
/**
|
||||
* @addtogroup core-mle-core
|
||||
*
|
||||
@@ -746,6 +747,92 @@ private:
|
||||
uint8_t m8[RxChallenge::kMaxSize];
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents device connectivity info from Connectivity TLV.
|
||||
*/
|
||||
class Connectivity : public otNetworkDiagConnectivity, public Clearable<Connectivity>
|
||||
{
|
||||
friend class Mle;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the Parent Priority value.
|
||||
*
|
||||
* @returns The Parent Priority value.
|
||||
*/
|
||||
int8_t GetParentPriority(void) const { return mParentPriority; }
|
||||
|
||||
/**
|
||||
* Returns the number of neighbors with link quality 3.
|
||||
*
|
||||
* @returns The number of neighbors with link quality 3.
|
||||
*/
|
||||
uint8_t GetNumLinkQuality3(void) const { return mLinkQuality3; }
|
||||
|
||||
/**
|
||||
* Returns the number of neighbors with link quality 2.
|
||||
*
|
||||
* @returns The number of neighbors with link quality 2.
|
||||
*/
|
||||
uint8_t GetNumLinkQuality2(void) const { return mLinkQuality2; }
|
||||
|
||||
/**
|
||||
* Returns the number of neighbors with link quality 1.
|
||||
*
|
||||
* @returns The number of neighbors with link quality 1.
|
||||
*/
|
||||
uint8_t GetNumLinkQuality1(void) const { return mLinkQuality1; }
|
||||
|
||||
/**
|
||||
* Returns the Leader Cost value.
|
||||
*
|
||||
* @returns The Leader Cost value.
|
||||
*/
|
||||
uint8_t GetLeaderCost(void) const { return mLeaderCost; }
|
||||
|
||||
/**
|
||||
* Returns the Router ID Sequence value.
|
||||
*
|
||||
* @returns The Router ID Sequence value.
|
||||
*/
|
||||
uint8_t GetIdSequence(void) const { return mIdSequence; }
|
||||
|
||||
/**
|
||||
* Returns the Active Routers value.
|
||||
*
|
||||
* @returns The Active Routers value.
|
||||
*/
|
||||
uint8_t GetActiveRouterCount(void) const { return mActiveRouters; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the partition is a singleton based on Active Router Count.
|
||||
*
|
||||
* @retval TRUE The partition is a singleton.
|
||||
* @retval FALSE The partition is not a singleton.
|
||||
*/
|
||||
bool IsSingleton(void) const { return (mActiveRouters <= 1); }
|
||||
|
||||
/**
|
||||
* Returns the SED Buffer Size value.
|
||||
*
|
||||
* @returns The SED Buffer Size value.
|
||||
*/
|
||||
uint16_t GetSedBufferSize(void) const { return mSedBufferSize; }
|
||||
|
||||
/**
|
||||
* Returns the SED Datagram Count value.
|
||||
*
|
||||
* @returns The SED Datagram Count value.
|
||||
*/
|
||||
uint8_t GetSedDatagramCount(void) const { return mSedDatagramCount; }
|
||||
|
||||
private:
|
||||
static constexpr uint16_t kDefaultSedBufferSize = OPENTHREAD_CONFIG_DEFAULT_SED_BUFFER_SIZE;
|
||||
static constexpr uint8_t kDefaultSedDatagramCount = OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT;
|
||||
|
||||
void IncrementNumForLinkQuality(uint8_t aLinkQuality);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a MLE Key Material
|
||||
*/
|
||||
|
||||
@@ -549,11 +549,10 @@ Error Server::AppendDiagTlv(uint8_t aTlvType, Message &aMessage)
|
||||
|
||||
case Tlv::kConnectivity:
|
||||
{
|
||||
ConnectivityTlv tlv;
|
||||
ConnectivityTlvValue tlvValue;
|
||||
|
||||
tlv.Init();
|
||||
Get<Mle::Mle>().FillConnectivityTlv(tlv);
|
||||
error = tlv.AppendTo(aMessage);
|
||||
Get<Mle::Mle>().FillConnectivityTlvValue(tlvValue);
|
||||
error = Tlv::Append<ConnectivityTlv>(aMessage, &tlvValue, sizeof(tlvValue));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1298,12 +1297,10 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
|
||||
|
||||
case Tlv::kConnectivity:
|
||||
{
|
||||
ConnectivityTlv connectivityTlv;
|
||||
ConnectivityTlvValue tlvValue;
|
||||
|
||||
VerifyOrExit(!tlvInfo.mIsExtended, error = kErrorParse);
|
||||
SuccessOrExit(error = aMessage.Read(offset, connectivityTlv));
|
||||
VerifyOrExit(connectivityTlv.IsValid(), error = kErrorParse);
|
||||
connectivityTlv.GetConnectivity(aDiagTlv.mData.mConnectivity);
|
||||
SuccessOrExit(error = tlvValue.ParseFrom(aMessage, tlvInfo.mValueOffsetRange));
|
||||
tlvValue.GetConnectivity(AsCoreType(&aDiagTlv.mData.mConnectivity));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <openthread/netdiag.h>
|
||||
#include <openthread/thread.h>
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/clearable.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/message.hpp"
|
||||
@@ -276,45 +277,20 @@ typedef SimpleTlvInfo<Tlv::kBrLocalOnlinkPrefix, Ip6::NetworkPrefix> BrLocalOnli
|
||||
*/
|
||||
typedef SimpleTlvInfo<Tlv::kBrFavoredOnLinkPrefix, Ip6::NetworkPrefix> BrFavoredOnLinkPrefixTlv;
|
||||
|
||||
typedef otNetworkDiagConnectivity Connectivity; ///< Network Diagnostic Connectivity value.
|
||||
/**
|
||||
* Represents information parsed from Connectivity TLV.
|
||||
*/
|
||||
typedef Mle::Connectivity Connectivity;
|
||||
|
||||
/**
|
||||
* Implements Connectivity TLV generation and parsing.
|
||||
* Represents a Connectivity TLV value.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ConnectivityTlv : public Mle::ConnectivityTlv
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kType = ot::NetworkDiagnostic::Tlv::kConnectivity; ///< The TLV Type value.
|
||||
typedef Mle::ConnectivityTlvValue ConnectivityTlvValue;
|
||||
|
||||
/**
|
||||
* Initializes the TLV.
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
Mle::ConnectivityTlv::Init();
|
||||
ot::Tlv::SetType(kType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the `Connectivity` value.
|
||||
*
|
||||
* @param[out] aConnectivity A reference to `Connectivity` to populate.
|
||||
*/
|
||||
void GetConnectivity(Connectivity &aConnectivity) const
|
||||
{
|
||||
aConnectivity.mParentPriority = GetParentPriority();
|
||||
aConnectivity.mLinkQuality3 = GetLinkQuality3();
|
||||
aConnectivity.mLinkQuality2 = GetLinkQuality2();
|
||||
aConnectivity.mLinkQuality1 = GetLinkQuality1();
|
||||
aConnectivity.mLeaderCost = GetLeaderCost();
|
||||
aConnectivity.mIdSequence = GetIdSequence();
|
||||
aConnectivity.mActiveRouters = GetActiveRouters();
|
||||
aConnectivity.mSedBufferSize = GetSedBufferSize();
|
||||
aConnectivity.mSedDatagramCount = GetSedDatagramCount();
|
||||
}
|
||||
|
||||
} OT_TOOL_PACKED_END;
|
||||
/**
|
||||
* Defines Connectivity TLV constants.
|
||||
*/
|
||||
typedef TlvInfo<Tlv::kConnectivity> ConnectivityTlv;
|
||||
|
||||
/**
|
||||
* Implements Route TLV generation and parsing.
|
||||
@@ -1126,6 +1102,9 @@ private:
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
} // namespace NetworkDiagnostic
|
||||
|
||||
DefineCoreType(otNetworkDiagConnectivity, NetworkDiagnostic::Connectivity);
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OT_CORE_THREAD_NETWORK_DIAGNOSTIC_TLVS_HPP_
|
||||
|
||||
Reference in New Issue
Block a user