diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp index 3904cf88a..165999d93 100644 --- a/src/core/meshcop/dataset.hpp +++ b/src/core/meshcop/dataset.hpp @@ -839,12 +839,12 @@ template <> inline const uint32_t &Dataset::Info::Get(voi template <> inline void Dataset::Info::Get(Timestamp &aTimestamp) const { - aTimestamp.SetFromTimestamp(mActiveTimestamp); + aTimestamp.SetFrom(mActiveTimestamp); } template <> inline void Dataset::Info::Get(Timestamp &aTimestamp) const { - aTimestamp.SetFromTimestamp(mPendingTimestamp); + aTimestamp.SetFrom(mPendingTimestamp); } template <> inline void Dataset::Info::Set(const Timestamp &aTimestamp) diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index 40ead331d..ec6e89077 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -60,19 +60,12 @@ DatasetManager::DatasetManager(Instance &aInstance, Type aType, Timer::Handler a : InstanceLocator(aInstance) , mType(aType) , mLocalSaved(false) - , mLocalTimestampValid(false) - , mNetworkTimestampValid(false) , mMgmtPending(false) , mLocalUpdateTime(0) , mTimer(aInstance, aTimerHandler) { - mLocalTimestamp.Clear(); - mNetworkTimestamp.Clear(); -} - -const Timestamp *DatasetManager::GetTimestamp(void) const -{ - return mNetworkTimestampValid ? &mNetworkTimestamp : nullptr; + mLocalTimestamp.SetToInvalid(); + mNetworkTimestamp.SetToInvalid(); } Error DatasetManager::Restore(void) @@ -94,8 +87,8 @@ void DatasetManager::Restore(const Dataset &aDataset) { mTimer.Stop(); - mNetworkTimestampValid = false; - mLocalTimestampValid = false; + mNetworkTimestamp.SetToInvalid(); + mLocalTimestamp.SetToInvalid(); VerifyOrExit(aDataset.GetLength() != 0); @@ -103,9 +96,7 @@ void DatasetManager::Restore(const Dataset &aDataset) if (aDataset.ReadTimestamp(mType, mLocalTimestamp) == kErrorNone) { - mLocalTimestampValid = true; - mNetworkTimestampValid = true; - mNetworkTimestamp = mLocalTimestamp; + mNetworkTimestamp = mLocalTimestamp; } if (IsActiveDataset()) @@ -256,12 +247,10 @@ exit: void DatasetManager::Clear(void) { - mNetworkTimestamp.Clear(); - mLocalTimestamp.Clear(); + mNetworkTimestamp.SetToInvalid(); + mLocalTimestamp.SetToInvalid(); - mNetworkTimestampValid = false; - mLocalTimestampValid = false; - mLocalSaved = false; + mLocalSaved = false; #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE DestroySecurelyStoredKeys(); @@ -299,17 +288,12 @@ Error DatasetManager::Save(const Dataset &aDataset, bool aAllowOlderTimestamp) Error error = kErrorNone; int compare; - if (aDataset.ReadTimestamp(mType, mNetworkTimestamp) == kErrorNone) + if ((aDataset.ReadTimestamp(mType, mNetworkTimestamp) == kErrorNone) && IsActiveDataset()) { - mNetworkTimestampValid = true; - - if (IsActiveDataset()) - { - SuccessOrExit(error = ApplyConfiguration(aDataset)); - } + SuccessOrExit(error = ApplyConfiguration(aDataset)); } - compare = Timestamp::Compare(GetTimestamp(), GetLocalTimestamp()); + compare = Timestamp::Compare(mNetworkTimestamp, mLocalTimestamp); if ((compare > 0) || aAllowOlderTimestamp) { @@ -412,8 +396,12 @@ void DatasetManager::LocalSave(const Dataset &aDataset) LogInfo("%s dataset set", Dataset::TypeToString(mType)); } - mLocalTimestampValid = (aDataset.ReadTimestamp(mType, mLocalTimestamp) == kErrorNone); - mLocalUpdateTime = TimerMilli::GetNow(); + if (aDataset.ReadTimestamp(mType, mLocalTimestamp) != kErrorNone) + { + mLocalTimestamp.SetToInvalid(); + } + + mLocalUpdateTime = TimerMilli::GetNow(); if (IsPendingDataset()) { @@ -469,7 +457,7 @@ void DatasetManager::SyncLocalWithLeader(const Dataset &aDataset) VerifyOrExit(!mMgmtPending, error = kErrorBusy); VerifyOrExit(Get().IsChild() || Get().IsRouter(), error = kErrorInvalidState); - VerifyOrExit(Timestamp::Compare(GetTimestamp(), GetLocalTimestamp()) < 0, error = kErrorAlready); + VerifyOrExit(mNetworkTimestamp < mLocalTimestamp, error = kErrorAlready); if (IsActiveDataset()) { @@ -478,8 +466,7 @@ void DatasetManager::SyncLocalWithLeader(const Dataset &aDataset) IgnoreError(Get().Read(pendingDataset)); - if ((pendingDataset.Read(timestamp) == kErrorNone) && - (Timestamp::Compare(×tamp, GetLocalTimestamp()) == 0)) + if ((pendingDataset.Read(timestamp) == kErrorNone) && (timestamp == mLocalTimestamp)) { // Stop registration attempts during dataset transition ExitNow(error = kErrorInvalidState); @@ -830,9 +817,9 @@ ActiveDatasetManager::ActiveDatasetManager(Instance &aInstance) { } -bool ActiveDatasetManager::IsPartiallyComplete(void) const { return mLocalSaved && !mNetworkTimestampValid; } +bool ActiveDatasetManager::IsPartiallyComplete(void) const { return mLocalSaved && !mNetworkTimestamp.IsValid(); } -bool ActiveDatasetManager::IsComplete(void) const { return mLocalSaved && mNetworkTimestampValid; } +bool ActiveDatasetManager::IsComplete(void) const { return mLocalSaved && mNetworkTimestamp.IsValid(); } bool ActiveDatasetManager::IsCommissioned(void) const { @@ -914,7 +901,7 @@ void PendingDatasetManager::HandleDelayTimer(void) SuccessOrExit(dataset.Read(activeTimestamp)); - if (Timestamp::Compare(&activeTimestamp, Get().GetTimestamp()) > 0) + if (activeTimestamp > Get().GetTimestamp()) { shouldReplaceActive = true; } diff --git a/src/core/meshcop/dataset_manager.hpp b/src/core/meshcop/dataset_manager.hpp index d641ef0c9..d351f56f2 100644 --- a/src/core/meshcop/dataset_manager.hpp +++ b/src/core/meshcop/dataset_manager.hpp @@ -66,12 +66,12 @@ public: typedef otDatasetMgmtSetCallback MgmtSetCallback; /** - * Returns a pointer to the Timestamp. + * Returns the network Timestamp. * - * @returns A pointer to the Timestamp. + * @returns The network Timestamp. * */ - const Timestamp *GetTimestamp(void) const; + const Timestamp &GetTimestamp(void) const { return mNetworkTimestamp; } /** * Clears the Operational Dataset. @@ -316,8 +316,6 @@ private: const otMessageInfo *aMessageInfo, Error aError); - const Timestamp *GetLocalTimestamp(void) const { return mLocalTimestampValid ? &mLocalTimestamp : nullptr; } - #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE void MoveKeysToSecureStorage(Dataset &aDataset) const; void DestroySecurelyStoredKeys(void) const; @@ -334,8 +332,6 @@ private: Type mType; bool mLocalSaved : 1; - bool mLocalTimestampValid : 1; - bool mNetworkTimestampValid : 1; bool mMgmtPending : 1; TimeMilli mLocalUpdateTime; Timestamp mLocalTimestamp; diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index 1eb6a9b26..18b57c794 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -110,11 +110,11 @@ Error DatasetManager::ProcessSetOrReplaceRequest(MgmtCommand aCommand, Timestamp pendingTimestamp; SuccessOrExit(dataset.Read(pendingTimestamp)); - VerifyOrExit(Timestamp::Compare(&pendingTimestamp, GetLocalTimestamp()) > 0); + VerifyOrExit(pendingTimestamp > mLocalTimestamp); } else { - VerifyOrExit(Timestamp::Compare(&activeTimestamp, GetLocalTimestamp()) > 0); + VerifyOrExit(activeTimestamp > mLocalTimestamp); } // Determine whether the new Dataset affects connectivity @@ -155,9 +155,7 @@ Error DatasetManager::ProcessSetOrReplaceRequest(MgmtCommand aCommand, if (IsPendingDataset() && !aInfo.mAffectsNetworkKey) { - const Timestamp *localActiveTimestamp = Get().GetTimestamp(); - - VerifyOrExit(Timestamp::Compare(&activeTimestamp, localActiveTimestamp) > 0); + VerifyOrExit(activeTimestamp > Get().GetTimestamp()); } // Determine whether the request is from commissioner. @@ -299,7 +297,7 @@ Error ActiveDatasetManager::GenerateLocal(void) Dataset dataset; VerifyOrExit(Get().IsAttached(), error = kErrorInvalidState); - VerifyOrExit(!mLocalTimestampValid, error = kErrorAlready); + VerifyOrExit(!mLocalTimestamp.IsValid(), error = kErrorAlready); IgnoreError(Read(dataset)); diff --git a/src/core/meshcop/dataset_updater.cpp b/src/core/meshcop/dataset_updater.cpp index c59ffacbd..ed5d7f1d3 100644 --- a/src/core/meshcop/dataset_updater.cpp +++ b/src/core/meshcop/dataset_updater.cpp @@ -88,11 +88,9 @@ Error DatasetUpdater::RequestUpdate(Dataset &aDataset, UpdaterCallback aCallback activeTimestamp.AdvanceRandomTicks(); SuccessOrExit(error = aDataset.Write(activeTimestamp)); - if (Get().GetTimestamp() != nullptr) - { - pendingTimestamp = *Get().GetTimestamp(); - } - else + pendingTimestamp = Get().GetTimestamp(); + + if (!pendingTimestamp.IsValid()) { pendingTimestamp.Clear(); pendingTimestamp.SetSeconds(1); @@ -204,7 +202,7 @@ void DatasetUpdater::HandleDatasetChanged(Dataset::Type aType) SuccessOrExit(newDataset.ReadTimestamp(aType, newTimestamp)); SuccessOrExit(requestedDataset.ReadTimestamp(aType, requestedTimestamp)); - if (Timestamp::Compare(newTimestamp, requestedTimestamp) >= 0) + if (newTimestamp >= requestedTimestamp) { Finish(kErrorAlready); } diff --git a/src/core/meshcop/timestamp.cpp b/src/core/meshcop/timestamp.cpp index 5ed659413..59732fe9b 100644 --- a/src/core/meshcop/timestamp.cpp +++ b/src/core/meshcop/timestamp.cpp @@ -35,54 +35,78 @@ #include "common/code_utils.hpp" #include "common/num_utils.hpp" +#include "common/numeric_limits.hpp" namespace ot { namespace MeshCoP { -void Timestamp::ConvertTo(otTimestamp &aTimestamp) const +void Timestamp::ConvertTo(Info &aInfo) const { - aTimestamp.mSeconds = GetSeconds(); - aTimestamp.mTicks = GetTicks(); - aTimestamp.mAuthoritative = GetAuthoritative(); + aInfo.mSeconds = GetSeconds(); + aInfo.mTicks = GetTicks(); + aInfo.mAuthoritative = GetAuthoritative(); } -void Timestamp::SetFromTimestamp(const otTimestamp &aTimestamp) +void Timestamp::SetFrom(const Info &aInfo) { - SetSeconds(aTimestamp.mSeconds); - SetTicks(aTimestamp.mTicks); - SetAuthoritative(aTimestamp.mAuthoritative); + SetSeconds(aInfo.mSeconds); + SetTicks(aInfo.mTicks); + SetAuthoritative(aInfo.mAuthoritative); } -int Timestamp::Compare(const Timestamp *aFirst, const Timestamp *aSecond) +void Timestamp::SetToInvalid(void) { - int rval; + mSeconds16 = NumericLimits::kMax; + mSeconds32 = NumericLimits::kMax; + mTicksAndAuthFlag = NumericLimits::kMax; +} - if (aFirst == nullptr) - { - // When `aFirst` is null but `aSecond is not, we return -1, - // (indicate `aFirst (null) < aSecond (non-null)`). - ExitNow(rval = (aSecond == nullptr) ? 0 : -1); - } +bool Timestamp::IsValid(void) const +{ + return (mSeconds16 != NumericLimits::kMax) || (mSeconds32 != NumericLimits::kMax) || + (mTicksAndAuthFlag != NumericLimits::kMax); +} - if (aSecond == nullptr) - { - // When `aFirst` is not null, but `aSecond` is, we return +1, - // (indicate `aFirst (non-null) > aSecond (null)`). - ExitNow(rval = 1); - } +void Timestamp::SetToOrphanAnnounce(void) +{ + mSeconds16 = 0; + mSeconds32 = 0; + SetTicksAndAuthFlag(kAuthoritativeFlag); +} - // Both are non-null. +bool Timestamp::IsOrphanAnnounce(void) const +{ + return (mSeconds16 == 0) && (mSeconds32 == 0) && (GetTicksAndAuthFlag() == kAuthoritativeFlag); +} - rval = Compare(*aFirst, *aSecond); +uint64_t Timestamp::GetSeconds(void) const +{ + return (static_cast(BigEndian::HostSwap16(mSeconds16)) << 32) + BigEndian::HostSwap32(mSeconds32); +} -exit: - return rval; +void Timestamp::SetSeconds(uint64_t aSeconds) +{ + mSeconds16 = BigEndian::HostSwap16(static_cast(aSeconds >> 32)); + mSeconds32 = BigEndian::HostSwap32(static_cast(aSeconds & 0xffffffff)); +} + +void Timestamp::SetTicks(uint16_t aTicks) +{ + SetTicksAndAuthFlag((GetTicksAndAuthFlag() & ~kTicksMask) | ((aTicks << kTicksOffset) & kTicksMask)); +} + +void Timestamp::SetAuthoritative(bool aAuthoritative) +{ + SetTicksAndAuthFlag((GetTicksAndAuthFlag() & kTicksMask) | (aAuthoritative ? kAuthoritativeFlag : 0)); } int Timestamp::Compare(const Timestamp &aFirst, const Timestamp &aSecond) { int rval; + rval = ThreeWayCompare(aFirst.IsValid(), aSecond.IsValid()); + VerifyOrExit(rval == 0); + rval = ThreeWayCompare(aFirst.GetSeconds(), aSecond.GetSeconds()); VerifyOrExit(rval == 0); diff --git a/src/core/meshcop/timestamp.hpp b/src/core/meshcop/timestamp.hpp index 6dabe1960..a39ed1f92 100644 --- a/src/core/meshcop/timestamp.hpp +++ b/src/core/meshcop/timestamp.hpp @@ -58,16 +58,58 @@ class Timestamp : public Clearable { public: /** - * Converts the timestamp to `otTimestamp`. + * Represents timestamp components. * */ - void ConvertTo(otTimestamp &aTimestamp) const; + typedef otTimestamp Info; /** - * Sets the timestamp from `otTimestamp`. + * Copies the `Timestamp` information to `Timestamp::Info` data structure. + * + * @param[out] aInfo A reference to a `Timestamp::Info` to populate. * */ - void SetFromTimestamp(const otTimestamp &aTimestamp); + void ConvertTo(Info &aInfo) const; + + /** + * Sets the `Timestamp` from a given component-wise `Info` structure. + * + * @param[in] aInfo A `Timestamp::Info` structure. + * + */ + void SetFrom(const Info &aInfo); + + /** + * Sets the `Timestamp` to invalid value. + * + */ + void SetToInvalid(void); + + /** + * Indicates whether or not the `Timestamp` is valid. + * + * @retval TRUE The timestamp is valid. + * @retval FALSE The timestamp is not valid. + * + */ + bool IsValid(void) const; + + /** + * Sets the `Timestamp` to value used in MLE Orphan Announce messages. + * + * Second and ticks fields are set to zero with Authoritative flag set. + * + */ + void SetToOrphanAnnounce(void); + + /** + * Indicates whether the timestamp indicates an MLE Orphan Announce message. + * + * @retval TRUE The timestamp indicates an Orphan Announce message. + * @retval FALSE The timestamp does not indicate an Orphan Announce message. + * + */ + bool IsOrphanAnnounce(void) const; /** * Returns the Seconds value. @@ -75,10 +117,7 @@ public: * @returns The Seconds value. * */ - uint64_t GetSeconds(void) const - { - return (static_cast(BigEndian::HostSwap16(mSeconds16)) << 32) + BigEndian::HostSwap32(mSeconds32); - } + uint64_t GetSeconds(void) const; /** * Sets the Seconds value. @@ -86,11 +125,7 @@ public: * @param[in] aSeconds The Seconds value. * */ - void SetSeconds(uint64_t aSeconds) - { - mSeconds16 = BigEndian::HostSwap16(static_cast(aSeconds >> 32)); - mSeconds32 = BigEndian::HostSwap32(static_cast(aSeconds & 0xffffffff)); - } + void SetSeconds(uint64_t aSeconds); /** * Returns the Ticks value. @@ -98,7 +133,7 @@ public: * @returns The Ticks value. * */ - uint16_t GetTicks(void) const { return BigEndian::HostSwap16(mTicks) >> kTicksOffset; } + uint16_t GetTicks(void) const { return GetTicksAndAuthFlag() >> kTicksOffset; } /** * Sets the Ticks value. @@ -106,11 +141,7 @@ public: * @param[in] aTicks The Ticks value. * */ - void SetTicks(uint16_t aTicks) - { - mTicks = BigEndian::HostSwap16((BigEndian::HostSwap16(mTicks) & ~kTicksMask) | - ((aTicks << kTicksOffset) & kTicksMask)); - } + void SetTicks(uint16_t aTicks); /** * Returns the Authoritative value. @@ -118,7 +149,7 @@ public: * @returns The Authoritative value. * */ - bool GetAuthoritative(void) const { return (BigEndian::HostSwap16(mTicks) & kAuthoritativeMask) != 0; } + bool GetAuthoritative(void) const { return (GetTicksAndAuthFlag() & kAuthoritativeFlag) != 0; } /** * Sets the Authoritative value. @@ -126,11 +157,7 @@ public: * @param[in] aAuthoritative The Authoritative value. * */ - void SetAuthoritative(bool aAuthoritative) - { - mTicks = BigEndian::HostSwap16((BigEndian::HostSwap16(mTicks) & kTicksMask) | - ((aAuthoritative << kAuthoritativeOffset) & kAuthoritativeMask)); - } + void SetAuthoritative(bool aAuthoritative); /** * Increments the timestamp by a random number of ticks [0, 32767]. @@ -138,33 +165,11 @@ public: */ void AdvanceRandomTicks(void); - /** - * Indicates whether the timestamp indicates an MLE Orphan Announce message. - * - * @retval TRUE The timestamp indicates an Orphan Announce message. - * @retval FALSE If the timestamp does not indicate an Orphan Announce message. - * - */ - bool IsOrphanTimestamp(void) const { return GetSeconds() == 0 && GetTicks() == 0 && GetAuthoritative(); } - /** * Compares two timestamps. * - * Either one or both @p aFirst or @p aSecond can be `nullptr`. A non-null timestamp is considered greater than - * a null one. If both are null, they are considered as equal. - * - * @param[in] aFirst A pointer to the first timestamp to compare (can be nullptr). - * @param[in] aSecond A pointer to the second timestamp to compare (can be nullptr). - * - * @retval -1 if @p aFirst is less than @p aSecond (`aFirst < aSecond`). - * @retval 0 if @p aFirst is equal to @p aSecond (`aFirst == aSecond`). - * @retval 1 if @p aFirst is greater than @p aSecond (`aFirst > aSecond`). - * - */ - static int Compare(const Timestamp *aFirst, const Timestamp *aSecond); - - /** - * Compares two timestamps. + * Either one or both @p aFirst or @p aSecond can be invalid. A valid timestamp is considered greater than an + * invalid one. If both are invalid, they are considered as equal. * * @param[in] aFirst A reference to the first timestamp to compare. * @param[in] aSecond A reference to the second timestamp to compare. @@ -176,16 +181,27 @@ public: */ static int Compare(const Timestamp &aFirst, const Timestamp &aSecond); + // Comparison operator overloads for two `Timestamp` instances. + bool operator==(const Timestamp &aOther) const { return Compare(*this, aOther) == 0; } + bool operator!=(const Timestamp &aOther) const { return Compare(*this, aOther) != 0; } + bool operator>(const Timestamp &aOther) const { return Compare(*this, aOther) > 0; } + bool operator<(const Timestamp &aOther) const { return Compare(*this, aOther) < 0; } + bool operator>=(const Timestamp &aOther) const { return Compare(*this, aOther) >= 0; } + bool operator<=(const Timestamp &aOther) const { return Compare(*this, aOther) <= 0; } + private: + uint16_t GetTicksAndAuthFlag(void) const { return BigEndian::HostSwap16(mTicksAndAuthFlag); } + void SetTicksAndAuthFlag(uint16_t aValue) { mTicksAndAuthFlag = BigEndian::HostSwap16(aValue); } + static constexpr uint8_t kTicksOffset = 1; static constexpr uint16_t kTicksMask = 0x7fff << kTicksOffset; static constexpr uint8_t kAuthoritativeOffset = 0; - static constexpr uint16_t kAuthoritativeMask = 1 << kAuthoritativeOffset; + static constexpr uint16_t kAuthoritativeFlag = 1 << kAuthoritativeOffset; static constexpr uint16_t kMaxTicks = 0x7fff; uint16_t mSeconds16; // bits 32-47 uint32_t mSeconds32; // bits 0-31 - uint16_t mTicks; + uint16_t mTicksAndAuthFlag; } OT_TOOL_PACKED_END; } // namespace MeshCoP diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 2d9e88656..50ae43db2 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -2227,8 +2227,7 @@ void Mle::SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, Annou switch (aMode) { case kOrphanAnnounce: - activeTimestamp.Clear(); - activeTimestamp.SetAuthoritative(true); + activeTimestamp.SetToOrphanAnnounce(); SuccessOrExit(error = Tlv::Append(*message, activeTimestamp)); break; @@ -2938,7 +2937,7 @@ Error Mle::HandleLeaderData(RxInfo &aRxInfo) break; } #endif - if (MeshCoP::Timestamp::Compare(&activeTimestamp, Get().GetTimestamp()) != 0) + if (activeTimestamp != Get().GetTimestamp()) { // Send an MLE Data Request if the received timestamp // mismatches the local value and the message does not @@ -2966,7 +2965,7 @@ Error Mle::HandleLeaderData(RxInfo &aRxInfo) break; } #endif - if (MeshCoP::Timestamp::Compare(&pendingTimestamp, Get().GetTimestamp()) != 0) + if (pendingTimestamp != Get().GetTimestamp()) { VerifyOrExit(aRxInfo.mMessage.ContainsTlv(Tlv::kPendingDataset), dataRequest = true); savePendingDataset = true; @@ -3672,15 +3671,14 @@ exit: void Mle::HandleAnnounce(RxInfo &aRxInfo) { - Error error = kErrorNone; - ChannelTlvValue channelTlvValue; - MeshCoP::Timestamp timestamp; - const MeshCoP::Timestamp *localTimestamp; - uint8_t channel; - uint16_t panId; - bool isFromOrphan; - bool channelAndPanIdMatch; - int timestampCompare; + Error error = kErrorNone; + ChannelTlvValue channelTlvValue; + MeshCoP::Timestamp timestamp; + uint8_t channel; + uint16_t panId; + bool isFromOrphan; + bool channelAndPanIdMatch; + int timestampCompare; Log(kMessageReceive, kTypeAnnounce, aRxInfo.mMessageInfo.GetPeerAddr()); @@ -3692,10 +3690,8 @@ void Mle::HandleAnnounce(RxInfo &aRxInfo) aRxInfo.mClass = RxInfo::kPeerMessage; - localTimestamp = Get().GetTimestamp(); - - isFromOrphan = timestamp.IsOrphanTimestamp(); - timestampCompare = MeshCoP::Timestamp::Compare(×tamp, localTimestamp); + isFromOrphan = timestamp.IsOrphanAnnounce(); + timestampCompare = MeshCoP::Timestamp::Compare(timestamp, Get().GetTimestamp()); channelAndPanIdMatch = (channel == Get().GetPanChannel()) && (panId == Get().GetPanId()); if (isFromOrphan || (timestampCompare < 0)) @@ -4732,10 +4728,10 @@ Error Mle::TxMessage::AppendXtalAccuracyTlv(void) Error Mle::TxMessage::AppendActiveTimestampTlv(void) { Error error = kErrorNone; - const MeshCoP::Timestamp *timestamp = Get().GetTimestamp(); + const MeshCoP::Timestamp ×tamp = Get().GetTimestamp(); - VerifyOrExit(timestamp != nullptr); - error = Tlv::Append(*this, *timestamp); + VerifyOrExit(timestamp.IsValid()); + error = Tlv::Append(*this, timestamp); exit: return error; @@ -4744,10 +4740,10 @@ exit: Error Mle::TxMessage::AppendPendingTimestampTlv(void) { Error error = kErrorNone; - const MeshCoP::Timestamp *timestamp = Get().GetTimestamp(); + const MeshCoP::Timestamp ×tamp = Get().GetTimestamp(); - VerifyOrExit(timestamp != nullptr && timestamp->GetSeconds() != 0); - error = Tlv::Append(*this, *timestamp); + VerifyOrExit(timestamp.IsValid() && timestamp.GetSeconds() != 0); + error = Tlv::Append(*this, timestamp); exit: return error; diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 363a40d96..67dd68dde 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -2020,7 +2020,7 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo) switch (Tlv::Find(aRxInfo.mMessage, timestamp)) { case kErrorNone: - if (MeshCoP::Timestamp::Compare(×tamp, Get().GetTimestamp()) == 0) + if (timestamp == Get().GetTimestamp()) { break; } @@ -2038,7 +2038,7 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo) switch (Tlv::Find(aRxInfo.mMessage, timestamp)) { case kErrorNone: - if (MeshCoP::Timestamp::Compare(×tamp, Get().GetTimestamp()) == 0) + if (timestamp == Get().GetTimestamp()) { break; } @@ -2503,7 +2503,7 @@ void MleRouter::HandleDataRequest(RxInfo &aRxInfo) switch (Tlv::Find(aRxInfo.mMessage, timestamp)) { case kErrorNone: - if (MeshCoP::Timestamp::Compare(×tamp, Get().GetTimestamp()) == 0) + if (timestamp == Get().GetTimestamp()) { break; } @@ -2521,7 +2521,7 @@ void MleRouter::HandleDataRequest(RxInfo &aRxInfo) switch (Tlv::Find(aRxInfo.mMessage, timestamp)) { case kErrorNone: - if (MeshCoP::Timestamp::Compare(×tamp, Get().GetTimestamp()) == 0) + if (timestamp == Get().GetTimestamp()) { break; } diff --git a/tests/unit/test_meshcop.cpp b/tests/unit/test_meshcop.cpp index 6dae027de..04480fec2 100644 --- a/tests/unit/test_meshcop.cpp +++ b/tests/unit/test_meshcop.cpp @@ -115,40 +115,86 @@ void TestSteeringData(void) void TestTimestamp(void) { - MeshCoP::Timestamp t1; - MeshCoP::Timestamp t2; + MeshCoP::Timestamp t1; + MeshCoP::Timestamp t2; + MeshCoP::Timestamp::Info info; t1.Clear(); - t2.Clear(); - VerifyOrQuit(t1.GetSeconds() == 0); VerifyOrQuit(t1.GetTicks() == 0); VerifyOrQuit(!t1.GetAuthoritative()); + VerifyOrQuit(t1.IsValid()); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t1, t1) == 0); - VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) == 0); - VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, nullptr) > 0); - VerifyOrQuit(MeshCoP::Timestamp::Compare(nullptr, &t2) < 0); - VerifyOrQuit(MeshCoP::Timestamp::Compare(nullptr, nullptr) == 0); + t1.ConvertTo(info); + VerifyOrQuit(info.mSeconds == 0); + VerifyOrQuit(info.mTicks == 0); + VerifyOrQuit(!info.mAuthoritative); - t1.SetTicks(10); - VerifyOrQuit(t1.GetTicks() == 10); - VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) > 0); - VerifyOrQuit(MeshCoP::Timestamp::Compare(&t2, &t1) < 0); + t2.SetToInvalid(); + VerifyOrQuit(!t2.IsValid()); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t2, t2) == 0); - t2.SetTicks(10); - VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) == 0); + t2.ConvertTo(info); + VerifyOrQuit(info.mSeconds == 0xffffffffffff); + VerifyOrQuit(info.mTicks == 0x7fff); + VerifyOrQuit(info.mAuthoritative); + + VerifyOrQuit(MeshCoP::Timestamp::Compare(t1, t2) > 0); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t2, t1) < 0); + + t2 = t1; + VerifyOrQuit(MeshCoP::Timestamp::Compare(t1, t2) == 0); + VerifyOrQuit(t2.IsValid()); + VerifyOrQuit(t1.IsValid()); + + t1.SetSeconds(0x12345678abcd); + VerifyOrQuit(t1.GetSeconds() == 0x12345678abcd); + VerifyOrQuit(t1.IsValid()); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t1, t2) > 0); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t2, t1) < 0); + + t2.SetSeconds(0x12345678abcd); + VerifyOrQuit(t1.GetSeconds() == 0x12345678abcd); + VerifyOrQuit(t2.IsValid()); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t1, t2) == 0); t1.SetAuthoritative(true); - VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) > 0); + VerifyOrQuit(t1.GetAuthoritative()); + VerifyOrQuit(t1.IsValid()); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t1, t2) > 0); - t1.SetSeconds(1); - VerifyOrQuit(t1.GetSeconds() == 1); - VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) > 0); - VerifyOrQuit(MeshCoP::Timestamp::Compare(&t2, &t1) < 0); + t1.SetAuthoritative(false); + VerifyOrQuit(!t1.GetAuthoritative()); + VerifyOrQuit(t1.IsValid()); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t1, t2) == 0); - t2.SetSeconds(1); - t2.SetAuthoritative(true); - VerifyOrQuit(MeshCoP::Timestamp::Compare(&t1, &t2) == 0); + t1.SetTicks(0x7fff); + VerifyOrQuit(t1.GetTicks() == 0x7fff); + VerifyOrQuit(!t1.GetAuthoritative()); + VerifyOrQuit(t1.IsValid()); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t1, t2) > 0); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t2, t1) < 0); + + t2.SetTicks(0x7fff); + VerifyOrQuit(t2.GetTicks() == 0x7fff); + VerifyOrQuit(!t2.GetAuthoritative()); + VerifyOrQuit(t2.IsValid()); + VerifyOrQuit(MeshCoP::Timestamp::Compare(t1, t2) == 0); + + t2.ConvertTo(info); + VerifyOrQuit(info.mSeconds == 0x12345678abcd); + VerifyOrQuit(info.mTicks == 0x7fff); + VerifyOrQuit(!info.mAuthoritative); + + t1.SetToOrphanAnnounce(); + VerifyOrQuit(t1.IsValid()); + VerifyOrQuit(t1.IsOrphanAnnounce()); + + t1.ConvertTo(info); + VerifyOrQuit(info.mSeconds == 0); + VerifyOrQuit(info.mTicks == 0); + VerifyOrQuit(info.mAuthoritative); printf("TestTimestamp() passed\n"); }