diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 5c0a9353e..d3d96e925 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -3862,12 +3862,11 @@ exit: Error Mle::TxMessage::AppendConnectivityTlv(void) { - ConnectivityTlv tlv; + ConnectivityTlvValue tlvValue; - tlv.Init(); - Get().FillConnectivityTlv(tlv); + Get().FillConnectivityTlvValue(tlvValue); - return tlv.AppendTo(*this); + return Tlv::Append(*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(aRxInfo.mMessage, linkMarginOut)); twoWayLinkMargin = Min(Get().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().IsAttached(); mParentResponseCallback.Invoke(&parentinfo); @@ -5173,9 +5185,9 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo) if (Get().IsFullThreadDevice() && !Get().IsDetached()) { bool isPartitionIdSame = (leaderData.GetPartitionId() == Get().mLeaderData.GetPartitionId()); - bool isIdSequenceSame = (connectivityTlv.GetIdSequence() == Get().GetRouterIdSequence()); + bool isIdSequenceSame = (connectivity.GetIdSequence() == Get().GetRouterIdSequence()); bool isIdSequenceGreater = - SerialNumber::IsGreater(connectivityTlv.GetIdSequence(), Get().GetRouterIdSequence()); + SerialNumber::IsGreater(connectivity.GetIdSequence(), Get().GetRouterIdSequence()); switch (mMode) { @@ -5194,7 +5206,7 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo) case kBetterPartition: VerifyOrExit(!isPartitionIdSame); - VerifyOrExit(ComparePartitions(connectivityTlv.IsSingleton(), leaderData, Get().IsSingleton(), + VerifyOrExit(ComparePartitions(connectivity.IsSingleton(), leaderData, Get().IsSingleton(), Get().mLeaderData) > 0); break; @@ -5217,8 +5229,8 @@ void Mle::Attacher::HandleParentResponse(RxInfo &aRxInfo) #if OPENTHREAD_FTD if (Get().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); diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 43868a779..810c8dfb6 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -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); diff --git a/src/core/thread/mle_ftd.cpp b/src/core/thread/mle_ftd.cpp index 4cb8ec5de..9610b9e24 100644 --- a/src/core/thread/mle_ftd.cpp +++ b/src/core/thread/mle_ftd.cpp @@ -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()) @@ -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 diff --git a/src/core/thread/mle_tlvs.cpp b/src/core/thread/mle_tlvs.cpp index bd07d0484..61350c3fb 100644 --- a/src/core/thread/mle_tlvs.cpp +++ b/src/core/thread/mle_tlvs.cpp @@ -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(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(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(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()) diff --git a/src/core/thread/mle_tlvs.hpp b/src/core/thread/mle_tlvs.hpp index 353f21ade..a88dd90f8 100644 --- a/src/core/thread/mle_tlvs.hpp +++ b/src/core/thread/mle_tlvs.hpp @@ -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 +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 ConnectivityTlv; + /** * Provides constants and methods for generation and parsing of Address Registration TLV. */ diff --git a/src/core/thread/mle_types.cpp b/src/core/thread/mle_types.cpp index e0c7799e5..b2d5ba36a 100644 --- a/src/core/thread/mle_types.cpp +++ b/src/core/thread/mle_types.cpp @@ -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) diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp index 42ba53cb9..e67d1df58 100644 --- a/src/core/thread/mle_types.hpp +++ b/src/core/thread/mle_types.hpp @@ -42,10 +42,9 @@ #if OPENTHREAD_CONFIG_P2P_ENABLE #include #endif +#include #include -#if OPENTHREAD_FTD #include -#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 +{ + 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 */ diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp index 4838eb998..97ff2ef34 100644 --- a/src/core/thread/network_diagnostic.cpp +++ b/src/core/thread/network_diagnostic.cpp @@ -549,11 +549,10 @@ Error Server::AppendDiagTlv(uint8_t aTlvType, Message &aMessage) case Tlv::kConnectivity: { - ConnectivityTlv tlv; + ConnectivityTlvValue tlvValue; - tlv.Init(); - Get().FillConnectivityTlv(tlv); - error = tlv.AppendTo(aMessage); + Get().FillConnectivityTlvValue(tlvValue); + error = Tlv::Append(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; } diff --git a/src/core/thread/network_diagnostic_tlvs.hpp b/src/core/thread/network_diagnostic_tlvs.hpp index 95b8b494e..23ed04ee7 100644 --- a/src/core/thread/network_diagnostic_tlvs.hpp +++ b/src/core/thread/network_diagnostic_tlvs.hpp @@ -39,6 +39,7 @@ #include #include +#include "common/as_core_type.hpp" #include "common/clearable.hpp" #include "common/encoding.hpp" #include "common/message.hpp" @@ -276,45 +277,20 @@ typedef SimpleTlvInfo BrLocalOnli */ typedef SimpleTlvInfo 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 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_