From 39fca696500e8dabbd30001cdbb868201360229c Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Thu, 23 Sep 2021 22:42:09 -0700 Subject: [PATCH] [meshcop] update handling of Active/Pending Timestamp TLVs (#7027) This commit updates and simplifies processing of Active/Pending Timestamp TLVs (in MeshCoP and MLE) by using TLV helper methods that read/write the TLV's timestamp value from/in a message. --- src/core/meshcop/dataset.cpp | 41 ++++--- src/core/meshcop/dataset.hpp | 12 +- src/core/meshcop/dataset_local.cpp | 35 ++---- src/core/meshcop/dataset_manager.cpp | 43 +++---- src/core/meshcop/dataset_manager_ftd.cpp | 68 ++++------ src/core/meshcop/dataset_updater.cpp | 3 +- src/core/meshcop/meshcop_tlvs.hpp | 62 +++++++++- src/core/meshcop/timestamp.hpp | 9 +- src/core/thread/mle.cpp | 150 ++++++++++++----------- src/core/thread/mle_router.cpp | 122 ++++++++++-------- src/core/thread/mle_tlvs.hpp | 74 ++--------- 11 files changed, 299 insertions(+), 320 deletions(-) diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index 19a61d8a3..ea78a490c 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -191,7 +191,7 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const switch (cur->GetType()) { case Tlv::kActiveTimestamp: - aDatasetInfo.SetActiveTimestamp(static_cast(cur)->GetSeconds()); + aDatasetInfo.SetActiveTimestamp(static_cast(cur)->GetTimestamp().GetSeconds()); break; case Tlv::kChannel: @@ -235,7 +235,8 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const break; case Tlv::kPendingTimestamp: - aDatasetInfo.SetPendingTimestamp(static_cast(cur)->GetSeconds()); + aDatasetInfo.SetPendingTimestamp( + static_cast(cur)->GetTimestamp().GetSeconds()); break; case Tlv::kPskc: @@ -288,20 +289,20 @@ Error Dataset::SetFrom(const Info &aDatasetInfo) if (aDatasetInfo.IsActiveTimestampPresent()) { - ActiveTimestampTlv tlv; - tlv.Init(); - tlv.SetSeconds(aDatasetInfo.GetActiveTimestamp()); - tlv.SetTicks(0); - IgnoreError(SetTlv(tlv)); + Timestamp timestamp; + + timestamp.Clear(); + timestamp.SetSeconds(aDatasetInfo.GetActiveTimestamp()); + IgnoreError(SetTlv(Tlv::kActiveTimestamp, timestamp)); } if (aDatasetInfo.IsPendingTimestampPresent()) { - PendingTimestampTlv tlv; - tlv.Init(); - tlv.SetSeconds(aDatasetInfo.GetPendingTimestamp()); - tlv.SetTicks(0); - IgnoreError(SetTlv(tlv)); + Timestamp timestamp; + + timestamp.Clear(); + timestamp.SetSeconds(aDatasetInfo.GetPendingTimestamp()); + IgnoreError(SetTlv(Tlv::kPendingTimestamp, timestamp)); } if (aDatasetInfo.IsDelayPresent()) @@ -371,25 +372,27 @@ Error Dataset::SetFrom(const Info &aDatasetInfo) return error; } -const Timestamp *Dataset::GetTimestamp(Type aType) const +Error Dataset::GetTimestamp(Type aType, Timestamp &aTimestamp) const { - const Timestamp *timestamp = nullptr; + Error error = kErrorNone; if (aType == kActive) { const ActiveTimestampTlv *tlv = GetTlv(); - VerifyOrExit(tlv != nullptr); - timestamp = static_cast(tlv); + + VerifyOrExit(tlv != nullptr, error = kErrorNotFound); + aTimestamp = tlv->GetTimestamp(); } else { const PendingTimestampTlv *tlv = GetTlv(); - VerifyOrExit(tlv != nullptr); - timestamp = static_cast(tlv); + + VerifyOrExit(tlv != nullptr, error = kErrorNotFound); + aTimestamp = tlv->GetTimestamp(); } exit: - return timestamp; + return error; } void Dataset::SetTimestamp(Type aType, const Timestamp &aTimestamp) diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp index b68388eb4..8b5113465 100644 --- a/src/core/meshcop/dataset.hpp +++ b/src/core/meshcop/dataset.hpp @@ -729,19 +729,21 @@ public: TimeMilli GetUpdateTime(void) const { return mUpdateTime; } /** - * This method returns a reference to the Timestamp. + * This method gets the Timestamp (Active or Pending). * - * @param[in] aType The type of the dataset, active or pending. + * @param[in] aType The type: active or pending. + * @param[out] aTimestamp A reference to a `Timestamp` to output the value. * - * @returns A pointer to the Timestamp. + * @retval kErrorNone Timestamp was read successfully. @p aTimestamp is updated. + * @retval kErrorNotFound Could not find the requested Timestamp TLV. * */ - const Timestamp *GetTimestamp(Type aType) const; + Error GetTimestamp(Type aType, Timestamp &aTimestamp) const; /** * This method sets the Timestamp value. * - * @param[in] aType The type of the dataset, active or pending. + * @param[in] aType The type: active or pending. * @param[in] aTimestamp A Timestamp. * */ diff --git a/src/core/meshcop/dataset_local.cpp b/src/core/meshcop/dataset_local.cpp index f304986eb..20138e540 100644 --- a/src/core/meshcop/dataset_local.cpp +++ b/src/core/meshcop/dataset_local.cpp @@ -55,35 +55,28 @@ DatasetLocal::DatasetLocal(Instance &aInstance, Dataset::Type aType) , mTimestampPresent(false) , mSaved(false) { - mTimestamp.Init(); + mTimestamp.Clear(); } void DatasetLocal::Clear(void) { IgnoreError(Get().DeleteOperationalDataset(IsActive())); - mTimestamp.Init(); + mTimestamp.Clear(); mTimestampPresent = false; mSaved = false; } Error DatasetLocal::Restore(Dataset &aDataset) { - const Timestamp *timestamp; - Error error; + Error error; mTimestampPresent = false; error = Read(aDataset); SuccessOrExit(error); - mSaved = true; - timestamp = aDataset.GetTimestamp(mType); - - if (timestamp != nullptr) - { - mTimestamp = *timestamp; - mTimestampPresent = true; - } + mSaved = true; + mTimestampPresent = (aDataset.GetTimestamp(mType, mTimestamp) == kErrorNone); exit: return error; @@ -177,8 +170,7 @@ Error DatasetLocal::Save(const otOperationalDatasetTlvs &aDataset) Error DatasetLocal::Save(const Dataset &aDataset) { - const Timestamp *timestamp; - Error error = kErrorNone; + Error error = kErrorNone; if (aDataset.GetSize() == 0) { @@ -194,19 +186,8 @@ Error DatasetLocal::Save(const Dataset &aDataset) otLogInfoMeshCoP("%s dataset set", Dataset::TypeToString(mType)); } - timestamp = aDataset.GetTimestamp(mType); - - if (timestamp != nullptr) - { - mTimestamp = *timestamp; - mTimestampPresent = true; - } - else - { - mTimestampPresent = false; - } - - mUpdateTime = TimerMilli::GetNow(); + mTimestampPresent = (aDataset.GetTimestamp(mType, mTimestamp) == kErrorNone); + mUpdateTime = TimerMilli::GetNow(); exit: return error; diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index 68843068c..5eed7190e 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -59,7 +59,7 @@ DatasetManager::DatasetManager(Instance &aInstance, Dataset::Type aType, Timer:: , mMgmtSetCallback(nullptr) , mMgmtSetCallbackContext(nullptr) { - mTimestamp.Init(); + mTimestamp.Clear(); } const Timestamp *DatasetManager::GetTimestamp(void) const @@ -82,9 +82,8 @@ int DatasetManager::Compare(const Timestamp &aTimestamp) const Error DatasetManager::Restore(void) { - Error error; - Dataset dataset; - const Timestamp *timestamp; + Error error; + Dataset dataset; mTimer.Stop(); @@ -92,13 +91,7 @@ Error DatasetManager::Restore(void) SuccessOrExit(error = mLocal.Restore(dataset)); - timestamp = dataset.GetTimestamp(GetType()); - - if (timestamp != nullptr) - { - mTimestamp = *timestamp; - mTimestampValid = true; - } + mTimestampValid = (dataset.GetTimestamp(GetType(), mTimestamp) == kErrorNone); if (IsActiveDataset()) { @@ -125,7 +118,7 @@ exit: void DatasetManager::Clear(void) { - mTimestamp.Init(); + mTimestamp.Clear(); mTimestampValid = false; mLocal.Clear(); mTimer.Stop(); @@ -139,16 +132,12 @@ void DatasetManager::HandleDetach(void) Error DatasetManager::Save(const Dataset &aDataset) { - Error error = kErrorNone; - const Timestamp *timestamp; - int compare; - bool isNetworkkeyUpdated = false; + Error error = kErrorNone; + int compare; + bool isNetworkkeyUpdated = false; - timestamp = aDataset.GetTimestamp(GetType()); - - if (timestamp != nullptr) + if (aDataset.GetTimestamp(GetType(), mTimestamp) == kErrorNone) { - mTimestamp = *timestamp; mTimestampValid = true; if (IsActiveDataset()) @@ -157,7 +146,7 @@ Error DatasetManager::Save(const Dataset &aDataset) } } - compare = mLocal.Compare(timestamp); + compare = mLocal.Compare(mTimestampValid ? &mTimestamp : nullptr); if (isNetworkkeyUpdated || compare > 0) { @@ -285,13 +274,13 @@ void DatasetManager::SendSet(void) if (IsActiveDataset()) { - Dataset pendingDataset; + Dataset pendingDataset; + Timestamp timestamp; + IgnoreError(Get().Read(pendingDataset)); - const ActiveTimestampTlv *tlv = pendingDataset.GetTlv(); - const Timestamp * pendingActiveTimestamp = static_cast(tlv); - - if (pendingActiveTimestamp != nullptr && mLocal.Compare(pendingActiveTimestamp) == 0) + if ((pendingDataset.GetTimestamp(Dataset::kActive, timestamp) == kErrorNone) && + (mLocal.Compare(×tamp) == 0)) { // stop registration attempts during dataset transition ExitNow(error = kErrorInvalidState); @@ -762,7 +751,7 @@ void PendingDataset::ClearNetwork(void) { Dataset dataset; - mTimestamp.Init(); + mTimestamp.Clear(); mTimestampValid = false; IgnoreError(DatasetManager::Save(dataset)); } diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index 1d1a2d586..9f836c1fc 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -70,30 +70,21 @@ Error DatasetManager::AppendMleDatasetTlv(Message &aMessage) const Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { - Tlv tlv; - Timestamp * timestamp; - uint16_t offset = aMessage.GetOffset(); - Tlv::Type type; - bool isUpdateFromCommissioner = false; - bool doesAffectConnectivity = false; - bool doesAffectNetworkKey = false; - bool hasNetworkKey = false; - StateTlv::State state = StateTlv::kReject; - Dataset dataset; - - ActiveTimestampTlv activeTimestamp; - PendingTimestampTlv pendingTimestamp; + Tlv tlv; + uint16_t offset = aMessage.GetOffset(); + bool isUpdateFromCommissioner = false; + bool doesAffectConnectivity = false; + bool doesAffectNetworkKey = false; + bool hasNetworkKey = false; + StateTlv::State state = StateTlv::kReject; + Dataset dataset; + Timestamp activeTimestamp; ChannelTlv channel; uint16_t sessionId; Mle::MeshLocalPrefix meshLocalPrefix; NetworkKey networkKey; uint16_t panId; - activeTimestamp.SetLength(0); - pendingTimestamp.SetLength(0); - channel.SetLength(0); - pendingTimestamp.SetLength(0); - VerifyOrExit(Get().IsLeader()); // verify that TLV data size is less than maximum TLV value size @@ -107,33 +98,21 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo // verify that does not overflow dataset buffer VerifyOrExit((offset - aMessage.GetOffset()) <= Dataset::kMaxSize); - type = (GetType() == Dataset::kActive) ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp; + // verify the request includes a timestamp that is ahead of the locally stored value + SuccessOrExit(Tlv::Find(aMessage, activeTimestamp)); - if (Tlv::FindTlv(aMessage, activeTimestamp) != kErrorNone) + if (GetType() == Dataset::kPending) { - ExitNow(); - } + Timestamp pendingTimestamp; - VerifyOrExit(activeTimestamp.IsValid()); - - if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone) - { - VerifyOrExit(pendingTimestamp.IsValid()); - } - - if (type == Tlv::kActiveTimestamp) - { - timestamp = static_cast(&activeTimestamp); + SuccessOrExit(Tlv::Find(aMessage, pendingTimestamp)); + VerifyOrExit(mLocal.Compare(&pendingTimestamp) > 0); } else { - VerifyOrExit(pendingTimestamp.GetLength() > 0); - timestamp = static_cast(&pendingTimestamp); + VerifyOrExit(mLocal.Compare(&activeTimestamp) > 0); } - // verify the request includes a timestamp that is ahead of the locally stored value - VerifyOrExit(mLocal.Compare(timestamp) > 0); - // check channel if (Tlv::FindTlv(aMessage, channel) == kErrorNone) { @@ -174,7 +153,7 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo } // check active timestamp rollback - if (type == Tlv::kPendingTimestamp && (!hasNetworkKey || !doesAffectNetworkKey)) + if (GetType() == Dataset::kPending && (!hasNetworkKey || !doesAffectNetworkKey)) { // no change to network key, active timestamp must be ahead const Timestamp *localActiveTimestamp = Get().GetTimestamp(); @@ -196,7 +175,7 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo } // verify an MGMT_ACTIVE_SET.req from a Commissioner does not affect connectivity - VerifyOrExit(!isUpdateFromCommissioner || type == Tlv::kPendingTimestamp || !doesAffectConnectivity); + VerifyOrExit(!isUpdateFromCommissioner || GetType() == Dataset::kPending || !doesAffectConnectivity); if (isUpdateFromCommissioner) { @@ -205,7 +184,7 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo IgnoreError(Get().Read(dataset)); } - if (type == Tlv::kPendingTimestamp || !doesAffectConnectivity) + if (GetType() == Dataset::kPending || !doesAffectConnectivity) { offset = aMessage.GetOffset(); @@ -328,11 +307,10 @@ Error ActiveDataset::GenerateLocal(void) if (dataset.GetTlv() == nullptr) { - ActiveTimestampTlv activeTimestampTlv; - activeTimestampTlv.Init(); - activeTimestampTlv.SetSeconds(0); - activeTimestampTlv.SetTicks(0); - IgnoreError(dataset.SetTlv(activeTimestampTlv)); + Timestamp timestamp; + + timestamp.Clear(); + IgnoreError(dataset.SetTlv(Tlv::kActiveTimestamp, timestamp)); } if (dataset.GetTlv() == nullptr) diff --git a/src/core/meshcop/dataset_updater.cpp b/src/core/meshcop/dataset_updater.cpp index bce95055c..81854577f 100644 --- a/src/core/meshcop/dataset_updater.cpp +++ b/src/core/meshcop/dataset_updater.cpp @@ -150,7 +150,8 @@ void DatasetUpdater::PreparePendingDataset(void) { ActiveTimestampTlv *tlv = dataset.GetTlv(); - tlv->AdvanceRandomTicks(); + + tlv->GetTimestamp().AdvanceRandomTicks(); } SuccessOrExit(error = Get().Save(dataset)); diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp index c1e638d7e..e3048eaf5 100644 --- a/src/core/meshcop/meshcop_tlvs.hpp +++ b/src/core/meshcop/meshcop_tlvs.hpp @@ -1003,7 +1003,7 @@ private: * */ OT_TOOL_PACKED_BEGIN -class ActiveTimestampTlv : public Tlv, public Timestamp, public SimpleTlvInfo +class ActiveTimestampTlv : public Tlv, public SimpleTlvInfo { public: /** @@ -1014,7 +1014,7 @@ public: { SetType(kActiveTimestamp); SetLength(sizeof(*this) - sizeof(Tlv)); - Timestamp::Init(); + mTimestamp.Clear(); } /** @@ -1025,6 +1025,33 @@ public: * */ bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); } + + /** + * This method gets the timestamp. + * + * @returns The timestamp. + * + */ + const Timestamp &GetTimestamp(void) const { return mTimestamp; } + + /** + * This method returns a reference to the timestamp. + * + * @returns A reference to the timestamp. + * + */ + Timestamp &GetTimestamp(void) { return mTimestamp; } + + /** + * This method sets the timestamp. + * + * @param[in] aTimestamp The new timestamp. + * + */ + void SetTimestamp(const Timestamp &aTimestamp) { mTimestamp = aTimestamp; } + +private: + Timestamp mTimestamp; } OT_TOOL_PACKED_END; /** @@ -1137,7 +1164,7 @@ private: * */ OT_TOOL_PACKED_BEGIN -class PendingTimestampTlv : public Tlv, public Timestamp, public SimpleTlvInfo +class PendingTimestampTlv : public Tlv, public SimpleTlvInfo { public: /** @@ -1148,7 +1175,7 @@ public: { SetType(kPendingTimestamp); SetLength(sizeof(*this) - sizeof(Tlv)); - Timestamp::Init(); + mTimestamp.Clear(); } /** @@ -1159,6 +1186,33 @@ public: * */ bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); } + + /** + * This method gets the timestamp. + * + * @returns The timestamp. + * + */ + const Timestamp &GetTimestamp(void) const { return mTimestamp; } + + /** + * This method returns a reference to the timestamp. + * + * @returns A reference to the timestamp. + * + */ + Timestamp &GetTimestamp(void) { return mTimestamp; } + + /** + * This method sets the timestamp. + * + * @param[in] aTimestamp The new timestamp. + * + */ + void SetTimestamp(const Timestamp &aTimestamp) { mTimestamp = aTimestamp; } + +private: + Timestamp mTimestamp; } OT_TOOL_PACKED_END; /** diff --git a/src/core/meshcop/timestamp.hpp b/src/core/meshcop/timestamp.hpp index 3c3972c5b..061aafcc1 100644 --- a/src/core/meshcop/timestamp.hpp +++ b/src/core/meshcop/timestamp.hpp @@ -41,6 +41,7 @@ #include +#include "common/clearable.hpp" #include "common/encoding.hpp" #include "common/random.hpp" @@ -55,15 +56,9 @@ using ot::Encoding::BigEndian::HostSwap32; * */ OT_TOOL_PACKED_BEGIN -class Timestamp +class Timestamp : public Clearable { public: - /** - * This method initializes the Timestamp - * - */ - void Init(void) { memset(this, 0, sizeof(*this)); } - /** * This method compares this timestamp to another. * diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 8e9cc28d8..e2d9f66a8 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1426,16 +1426,11 @@ Error Mle::AppendXtalAccuracy(Message &aMessage) Error Mle::AppendActiveTimestamp(Message &aMessage) { - Error error; - ActiveTimestampTlv timestampTlv; - const MeshCoP::Timestamp *timestamp; + Error error = kErrorNone; + const MeshCoP::Timestamp *timestamp = Get().GetTimestamp(); - timestamp = Get().GetTimestamp(); - VerifyOrExit(timestamp, error = kErrorNone); - - timestampTlv.Init(); - *static_cast(×tampTlv) = *timestamp; - error = timestampTlv.AppendTo(aMessage); + VerifyOrExit(timestamp != nullptr); + error = Tlv::Append(aMessage, *timestamp); exit: return error; @@ -1443,16 +1438,11 @@ exit: Error Mle::AppendPendingTimestamp(Message &aMessage) { - Error error; - PendingTimestampTlv timestampTlv; - const MeshCoP::Timestamp *timestamp; + Error error = kErrorNone; + const MeshCoP::Timestamp *timestamp = Get().GetTimestamp(); - timestamp = Get().GetTimestamp(); - VerifyOrExit(timestamp && timestamp->GetSeconds() != 0, error = kErrorNone); - - timestampTlv.Init(); - *static_cast(×tampTlv) = *timestamp; - error = timestampTlv.AppendTo(aMessage); + VerifyOrExit(timestamp != nullptr && timestamp->GetSeconds() != 0); + error = Tlv::Append(aMessage, *timestamp); exit: return error; @@ -2508,7 +2498,7 @@ void Mle::SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, Annou { Error error = kErrorNone; ChannelTlv channel; - ActiveTimestampTlv activeTimestamp; + MeshCoP::Timestamp activeTimestamp; Message * message = nullptr; VerifyOrExit(Get().GetSupportedChannelMask().ContainsChannel(aChannel), error = kErrorInvalidArgs); @@ -2525,11 +2515,9 @@ void Mle::SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, Annou switch (aMode) { case kOrphanAnnounce: - activeTimestamp.Init(); - activeTimestamp.SetSeconds(0); - activeTimestamp.SetTicks(0); + activeTimestamp.Clear(); activeTimestamp.SetAuthoritative(true); - SuccessOrExit(error = activeTimestamp.AppendTo(*message)); + SuccessOrExit(error = Tlv::Append(*message, activeTimestamp)); break; case kNormalAnnounce: @@ -3133,15 +3121,18 @@ bool Mle::IsNetworkDataNewer(const LeaderData &aLeaderData) Error Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { - Error error = kErrorNone; - LeaderData leaderData; - ActiveTimestampTlv activeTimestamp; - PendingTimestampTlv pendingTimestamp; - uint16_t networkDataOffset = 0; - uint16_t activeDatasetOffset = 0; - uint16_t pendingDatasetOffset = 0; - bool dataRequest = false; - Tlv tlv; + Error error = kErrorNone; + LeaderData leaderData; + MeshCoP::Timestamp activeTimestamp; + MeshCoP::Timestamp pendingTimestamp; + const MeshCoP::Timestamp *timestamp; + bool hasActiveTimestamp = false; + bool hasPendingTimestamp = false; + uint16_t networkDataOffset = 0; + uint16_t activeDatasetOffset = 0; + uint16_t pendingDatasetOffset = 0; + bool dataRequest = false; + Tlv tlv; // Leader Data SuccessOrExit(error = ReadLeaderData(aMessage, leaderData)); @@ -3165,11 +3156,11 @@ Error Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMe } // Active Timestamp - if (Tlv::FindTlv(aMessage, activeTimestamp) == kErrorNone) + switch (Tlv::Find(aMessage, activeTimestamp)) { - const MeshCoP::Timestamp *timestamp; + case kErrorNone: + hasActiveTimestamp = true; - VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse); timestamp = Get().GetTimestamp(); // if received timestamp does not match the local value and message does not contain the dataset, @@ -3179,18 +3170,22 @@ Error Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMe { ExitNow(dataRequest = true); } - } - else - { - activeTimestamp.SetLength(0); + + break; + + case kErrorNotFound: + break; + + default: + ExitNow(error = kErrorParse); } // Pending Timestamp - if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone) + switch (Tlv::Find(aMessage, pendingTimestamp)) { - const MeshCoP::Timestamp *timestamp; + case kErrorNone: + hasPendingTimestamp = true; - VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse); timestamp = Get().GetTimestamp(); // if received timestamp does not match the local value and message does not contain the dataset, @@ -3200,10 +3195,14 @@ Error Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMe { ExitNow(dataRequest = true); } - } - else - { - pendingTimestamp.SetLength(0); + + break; + + case kErrorNotFound: + break; + + default: + ExitNow(error = kErrorParse); } if (Tlv::FindTlvOffset(aMessage, Tlv::kNetworkData, networkDataOffset) == kErrorNone) @@ -3227,7 +3226,7 @@ Error Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMe #endif { // Active Dataset - if (activeTimestamp.GetLength() > 0) + if (hasActiveTimestamp) { if (activeDatasetOffset > 0) { @@ -3238,7 +3237,7 @@ Error Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMe } // Pending Dataset - if (pendingTimestamp.GetLength() > 0) + if (hasPendingTimestamp) { if (pendingDatasetOffset > 0) { @@ -3596,15 +3595,14 @@ void Mle::HandleChildIdResponse(const Message & aMessage, { OT_UNUSED_VARIABLE(aMessageInfo); - Error error = kErrorNone; - LeaderData leaderData; - uint16_t sourceAddress; - uint16_t shortAddress; - ActiveTimestampTlv activeTimestamp; - PendingTimestampTlv pendingTimestamp; - Tlv tlv; - uint16_t networkDataOffset; - uint16_t offset; + Error error = kErrorNone; + LeaderData leaderData; + uint16_t sourceAddress; + uint16_t shortAddress; + MeshCoP::Timestamp timestamp; + Tlv tlv; + uint16_t networkDataOffset; + uint16_t offset; // Source Address SuccessOrExit(error = Tlv::Find(aMessage, sourceAddress)); @@ -3626,17 +3624,22 @@ void Mle::HandleChildIdResponse(const Message & aMessage, SuccessOrExit(error); // Active Timestamp - if (Tlv::FindTlv(aMessage, activeTimestamp) == kErrorNone) + switch (Tlv::Find(aMessage, timestamp)) { - VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse); - + case kErrorNone: // Active Dataset if (Tlv::FindTlvOffset(aMessage, Tlv::kActiveDataset, offset) == kErrorNone) { IgnoreError(aMessage.Read(offset, tlv)); - IgnoreError( - Get().Save(activeTimestamp, aMessage, offset + sizeof(tlv), tlv.GetLength())); + IgnoreError(Get().Save(timestamp, aMessage, offset + sizeof(tlv), tlv.GetLength())); } + break; + + case kErrorNotFound: + break; + + default: + ExitNow(error = kErrorParse); } // clear Pending Dataset if device succeed to reattach using stored Pending Dataset @@ -3646,21 +3649,24 @@ void Mle::HandleChildIdResponse(const Message & aMessage, } // Pending Timestamp - if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone) + switch (Tlv::Find(aMessage, timestamp)) { - VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse); - + case kErrorNone: // Pending Dataset if (Tlv::FindTlvOffset(aMessage, Tlv::kPendingDataset, offset) == kErrorNone) { IgnoreError(aMessage.Read(offset, tlv)); IgnoreError( - Get().Save(pendingTimestamp, aMessage, offset + sizeof(tlv), tlv.GetLength())); + Get().Save(timestamp, aMessage, offset + sizeof(tlv), tlv.GetLength())); } - } - else - { + break; + + case kErrorNotFound: Get().ClearNetwork(); + break; + + default: + ExitNow(error = kErrorParse); } #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE @@ -3935,7 +3941,7 @@ void Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessa Error error = kErrorNone; ChannelTlv channelTlv; - ActiveTimestampTlv timestamp; + MeshCoP::Timestamp timestamp; const MeshCoP::Timestamp *localTimestamp; uint8_t channel; uint16_t panId; @@ -3947,9 +3953,7 @@ void Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessa channel = static_cast(channelTlv.GetChannel()); - SuccessOrExit(error = Tlv::FindTlv(aMessage, timestamp)); - VerifyOrExit(timestamp.IsValid(), error = kErrorParse); - + SuccessOrExit(error = Tlv::Find(aMessage, timestamp)); SuccessOrExit(error = Tlv::Find(aMessage, panId)); localTimestamp = Get().GetTimestamp(); diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 37d9bcd22..22fa09523 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -2191,22 +2191,23 @@ void MleRouter::HandleChildIdRequest(const Message & aMessage, const Ip6::MessageInfo &aMessageInfo, uint32_t aKeySequence) { - Error error = kErrorNone; - Mac::ExtAddress extAddr; - uint16_t version; - Challenge response; - uint32_t linkFrameCounter; - uint32_t mleFrameCounter; - uint8_t modeBitmask; - DeviceMode mode; - uint32_t timeout; - RequestedTlvs requestedTlvs; - ActiveTimestampTlv activeTimestamp; - PendingTimestampTlv pendingTimestamp; - Child * child; - Router * router; - uint8_t numTlvs; - uint16_t addressRegistrationOffset = 0; + Error error = kErrorNone; + Mac::ExtAddress extAddr; + uint16_t version; + Challenge response; + uint32_t linkFrameCounter; + uint32_t mleFrameCounter; + uint8_t modeBitmask; + DeviceMode mode; + uint32_t timeout; + RequestedTlvs requestedTlvs; + MeshCoP::Timestamp timestamp; + bool needsActiveDatasetTlv; + bool needsPendingDatasetTlv; + Child * child; + Router * router; + uint8_t numTlvs; + uint16_t addressRegistrationOffset = 0; Log(kMessageReceive, kTypeChildIdRequest, aMessageInfo.GetPeerAddr()); @@ -2250,19 +2251,29 @@ void MleRouter::HandleChildIdRequest(const Message & aMessage, VerifyOrExit(requestedTlvs.mNumTlvs <= Child::kMaxRequestTlvs, error = kErrorParse); // Active Timestamp - activeTimestamp.SetLength(0); - - if (Tlv::FindTlv(aMessage, activeTimestamp) == kErrorNone) + needsActiveDatasetTlv = true; + switch (Tlv::Find(aMessage, timestamp)) { - VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse); + case kErrorNone: + needsActiveDatasetTlv = (Get().Compare(timestamp) != 0); + break; + case kErrorNotFound: + break; + default: + ExitNow(error = kErrorParse); } // Pending Timestamp - pendingTimestamp.SetLength(0); - - if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone) + needsPendingDatasetTlv = true; + switch (Tlv::Find(aMessage, timestamp)) { - VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse); + case kErrorNone: + needsPendingDatasetTlv = (Get().Compare(timestamp) != 0); + break; + case kErrorNotFound: + break; + default: + ExitNow(error = kErrorParse); } if (!mode.IsFullThreadDevice()) @@ -2317,12 +2328,12 @@ void MleRouter::HandleChildIdRequest(const Message & aMessage, child->SetRequestTlv(numTlvs, requestedTlvs.mTlvs[numTlvs]); } - if (activeTimestamp.GetLength() == 0 || Get().Compare(activeTimestamp) != 0) + if (needsActiveDatasetTlv) { child->SetRequestTlv(numTlvs++, Tlv::kActiveDataset); } - if (pendingTimestamp.GetLength() == 0 || Get().Compare(pendingTimestamp) != 0) + if (needsPendingDatasetTlv) { child->SetRequestTlv(numTlvs++, Tlv::kPendingDataset); } @@ -2700,12 +2711,11 @@ void MleRouter::HandleDataRequest(const Message & aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor * aNeighbor) { - Error error = kErrorNone; - RequestedTlvs requestedTlvs; - ActiveTimestampTlv activeTimestamp; - PendingTimestampTlv pendingTimestamp; - uint8_t tlvs[4]; - uint8_t numTlvs; + Error error = kErrorNone; + RequestedTlvs requestedTlvs; + MeshCoP::Timestamp timestamp; + uint8_t tlvs[4]; + uint8_t numTlvs; Log(kMessageReceive, kTypeDataRequest, aMessageInfo.GetPeerAddr()); @@ -2715,34 +2725,46 @@ void MleRouter::HandleDataRequest(const Message & aMessage, SuccessOrExit(error = FindTlvRequest(aMessage, requestedTlvs)); VerifyOrExit(requestedTlvs.mNumTlvs <= sizeof(tlvs), error = kErrorParse); - // Active Timestamp - activeTimestamp.SetLength(0); - - if (Tlv::FindTlv(aMessage, activeTimestamp) == kErrorNone) - { - VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse); - } - - // Pending Timestamp - pendingTimestamp.SetLength(0); - - if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone) - { - VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse); - } - memset(tlvs, Tlv::kInvalid, sizeof(tlvs)); memcpy(tlvs, requestedTlvs.mTlvs, requestedTlvs.mNumTlvs); numTlvs = requestedTlvs.mNumTlvs; - if (activeTimestamp.GetLength() == 0 || Get().Compare(activeTimestamp)) + // Active Timestamp + switch (Tlv::Find(aMessage, timestamp)) { + case kErrorNone: + if (Get().Compare(timestamp) == 0) + { + break; + } + + OT_FALL_THROUGH; + + case kErrorNotFound: tlvs[numTlvs++] = Tlv::kActiveDataset; + break; + + default: + ExitNow(error = kErrorParse); } - if (pendingTimestamp.GetLength() == 0 || Get().Compare(pendingTimestamp)) + // Pending Timestamp + switch (Tlv::Find(aMessage, timestamp)) { + case kErrorNone: + if (Get().Compare(timestamp) == 0) + { + break; + } + + OT_FALL_THROUGH; + + case kErrorNotFound: tlvs[numTlvs++] = Tlv::kPendingDataset; + break; + + default: + ExitNow(error = kErrorParse); } SendDataResponse(aMessageInfo.GetPeerAddr(), tlvs, numTlvs, 0, &aMessage); diff --git a/src/core/thread/mle_tlvs.hpp b/src/core/thread/mle_tlvs.hpp index 5b2c4cf95..1ca11f3a2 100644 --- a/src/core/thread/mle_tlvs.hpp +++ b/src/core/thread/mle_tlvs.hpp @@ -218,6 +218,18 @@ typedef UintTlvInfo VersionTlv; */ typedef UintTlvInfo PanIdTlv; +/** + * This class defines Active Timestamp TLV constants and types. + * + */ +typedef SimpleTlvInfo ActiveTimestampTlv; + +/** + * This class defines Pending Timestamp TLV constants and types. + * + */ +typedef SimpleTlvInfo PendingTimestampTlv; + /** * This class defines CSL Timeout TLV constants and types. * @@ -1191,68 +1203,6 @@ private: #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE -/** - * This class implements Active Timestamp TLV generation and parsing. - * - */ -OT_TOOL_PACKED_BEGIN -class ActiveTimestampTlv : public Tlv, - public MeshCoP::Timestamp, - public SimpleTlvInfo -{ -public: - /** - * This method initializes the TLV. - * - */ - void Init(void) - { - SetType(Tlv::kActiveTimestamp); - SetLength(sizeof(*this) - sizeof(Tlv)); - Timestamp::Init(); - } - - /** - * This method indicates whether or not the TLV appears to be well-formed. - * - * @retval TRUE If the TLV appears to be well-formed. - * @retval FALSE If the TLV does not appear to be well-formed. - * - */ - bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); } -} OT_TOOL_PACKED_END; - -/** - * This class implements Pending Timestamp TLV generation and parsing. - * - */ -OT_TOOL_PACKED_BEGIN -class PendingTimestampTlv : public Tlv, - public MeshCoP::Timestamp, - public SimpleTlvInfo -{ -public: - /** - * This method initializes the TLV. - * - */ - void Init(void) - { - SetType(Tlv::kPendingTimestamp); - SetLength(sizeof(*this) - sizeof(Tlv)); - Timestamp::Init(); - } - - /** - * This method indicates whether or not the TLV appears to be well-formed. - * - * @retval TRUE If the TLV appears to be well-formed. - * @retval FALSE If the TLV does not appear to be well-formed. - * - */ - bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); } -} OT_TOOL_PACKED_END; - #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE) /** * This class implements CSL Channel TLV generation and parsing.