[timestamp] add IsValid() and comparison operator overloads (#10325)

This commit enhances the handling of `Timestamp`.

Methods `SetToInvalid()` and `IsValid()` are added to the `Timestamp`
class. The value where all bytes are set to `0xff` is used to
represent an invalid `Timestamp`. This corresponds to max seconds,
max ticks with the authoritative (`U`) flag set.

This helps simplify `DatasetManager`, where we need to track local and
network Active/Pending timestamps, which may not be present. These
are now represented by setting the `Timestamp` to the invalid value
(replacing the earlier model where a `Timestamp` pointer was used
with `nullptr` representing an invalid timestamp).

This allows us to simplify the `Timestamp::Compare()` method, now
getting two `Timestamp &` instead of `Timestamp *`. With this, we can
also define comparison operator overloads to compare two `Timestamp`
objects, which helps make the code simpler and more readable.
This commit is contained in:
Abtin Keshavarzian
2024-06-04 13:48:31 -07:00
committed by GitHub
parent 5bb3667a49
commit fcd3c5c4b7
10 changed files with 243 additions and 182 deletions
+2 -2
View File
@@ -839,12 +839,12 @@ template <> inline const uint32_t &Dataset::Info::Get<Dataset::kChannelMask>(voi
template <> inline void Dataset::Info::Get<Dataset::kActiveTimestamp>(Timestamp &aTimestamp) const
{
aTimestamp.SetFromTimestamp(mActiveTimestamp);
aTimestamp.SetFrom(mActiveTimestamp);
}
template <> inline void Dataset::Info::Get<Dataset::kPendingTimestamp>(Timestamp &aTimestamp) const
{
aTimestamp.SetFromTimestamp(mPendingTimestamp);
aTimestamp.SetFrom(mPendingTimestamp);
}
template <> inline void Dataset::Info::Set<Dataset::kActiveTimestamp>(const Timestamp &aTimestamp)
+22 -35
View File
@@ -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<Mle::MleRouter>().IsChild() || Get<Mle::MleRouter>().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<PendingDatasetManager>().Read(pendingDataset));
if ((pendingDataset.Read<ActiveTimestampTlv>(timestamp) == kErrorNone) &&
(Timestamp::Compare(&timestamp, GetLocalTimestamp()) == 0))
if ((pendingDataset.Read<ActiveTimestampTlv>(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<ActiveTimestampTlv>(activeTimestamp));
if (Timestamp::Compare(&activeTimestamp, Get<ActiveDatasetManager>().GetTimestamp()) > 0)
if (activeTimestamp > Get<ActiveDatasetManager>().GetTimestamp())
{
shouldReplaceActive = true;
}
+3 -7
View File
@@ -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;
+4 -6
View File
@@ -110,11 +110,11 @@ Error DatasetManager::ProcessSetOrReplaceRequest(MgmtCommand aCommand,
Timestamp pendingTimestamp;
SuccessOrExit(dataset.Read<PendingTimestampTlv>(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<ActiveDatasetManager>().GetTimestamp();
VerifyOrExit(Timestamp::Compare(&activeTimestamp, localActiveTimestamp) > 0);
VerifyOrExit(activeTimestamp > Get<ActiveDatasetManager>().GetTimestamp());
}
// Determine whether the request is from commissioner.
@@ -299,7 +297,7 @@ Error ActiveDatasetManager::GenerateLocal(void)
Dataset dataset;
VerifyOrExit(Get<Mle::MleRouter>().IsAttached(), error = kErrorInvalidState);
VerifyOrExit(!mLocalTimestampValid, error = kErrorAlready);
VerifyOrExit(!mLocalTimestamp.IsValid(), error = kErrorAlready);
IgnoreError(Read(dataset));
+4 -6
View File
@@ -88,11 +88,9 @@ Error DatasetUpdater::RequestUpdate(Dataset &aDataset, UpdaterCallback aCallback
activeTimestamp.AdvanceRandomTicks();
SuccessOrExit(error = aDataset.Write<ActiveTimestampTlv>(activeTimestamp));
if (Get<PendingDatasetManager>().GetTimestamp() != nullptr)
{
pendingTimestamp = *Get<PendingDatasetManager>().GetTimestamp();
}
else
pendingTimestamp = Get<PendingDatasetManager>().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);
}
+50 -26
View File
@@ -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<uint16_t>::kMax;
mSeconds32 = NumericLimits<uint32_t>::kMax;
mTicksAndAuthFlag = NumericLimits<uint16_t>::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<uint16_t>::kMax) || (mSeconds32 != NumericLimits<uint32_t>::kMax) ||
(mTicksAndAuthFlag != NumericLimits<uint16_t>::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<uint64_t>(BigEndian::HostSwap16(mSeconds16)) << 32) + BigEndian::HostSwap32(mSeconds32);
}
exit:
return rval;
void Timestamp::SetSeconds(uint64_t aSeconds)
{
mSeconds16 = BigEndian::HostSwap16(static_cast<uint16_t>(aSeconds >> 32));
mSeconds32 = BigEndian::HostSwap32(static_cast<uint32_t>(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);
+67 -51
View File
@@ -58,16 +58,58 @@ class Timestamp : public Clearable<Timestamp>
{
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<uint64_t>(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<uint16_t>(aSeconds >> 32));
mSeconds32 = BigEndian::HostSwap32(static_cast<uint32_t>(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
+19 -23
View File
@@ -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<ActiveTimestampTlv>(*message, activeTimestamp));
break;
@@ -2938,7 +2937,7 @@ Error Mle::HandleLeaderData(RxInfo &aRxInfo)
break;
}
#endif
if (MeshCoP::Timestamp::Compare(&activeTimestamp, Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()) != 0)
if (activeTimestamp != Get<MeshCoP::ActiveDatasetManager>().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<MeshCoP::PendingDatasetManager>().GetTimestamp()) != 0)
if (pendingTimestamp != Get<MeshCoP::PendingDatasetManager>().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<MeshCoP::ActiveDatasetManager>().GetTimestamp();
isFromOrphan = timestamp.IsOrphanTimestamp();
timestampCompare = MeshCoP::Timestamp::Compare(&timestamp, localTimestamp);
isFromOrphan = timestamp.IsOrphanAnnounce();
timestampCompare = MeshCoP::Timestamp::Compare(timestamp, Get<MeshCoP::ActiveDatasetManager>().GetTimestamp());
channelAndPanIdMatch = (channel == Get<Mac::Mac>().GetPanChannel()) && (panId == Get<Mac::Mac>().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<MeshCoP::ActiveDatasetManager>().GetTimestamp();
const MeshCoP::Timestamp &timestamp = Get<MeshCoP::ActiveDatasetManager>().GetTimestamp();
VerifyOrExit(timestamp != nullptr);
error = Tlv::Append<ActiveTimestampTlv>(*this, *timestamp);
VerifyOrExit(timestamp.IsValid());
error = Tlv::Append<ActiveTimestampTlv>(*this, timestamp);
exit:
return error;
@@ -4744,10 +4740,10 @@ exit:
Error Mle::TxMessage::AppendPendingTimestampTlv(void)
{
Error error = kErrorNone;
const MeshCoP::Timestamp *timestamp = Get<MeshCoP::PendingDatasetManager>().GetTimestamp();
const MeshCoP::Timestamp &timestamp = Get<MeshCoP::PendingDatasetManager>().GetTimestamp();
VerifyOrExit(timestamp != nullptr && timestamp->GetSeconds() != 0);
error = Tlv::Append<PendingTimestampTlv>(*this, *timestamp);
VerifyOrExit(timestamp.IsValid() && timestamp.GetSeconds() != 0);
error = Tlv::Append<PendingTimestampTlv>(*this, timestamp);
exit:
return error;
+4 -4
View File
@@ -2020,7 +2020,7 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo)
switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp))
{
case kErrorNone:
if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()) == 0)
if (timestamp == Get<MeshCoP::ActiveDatasetManager>().GetTimestamp())
{
break;
}
@@ -2038,7 +2038,7 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo)
switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, timestamp))
{
case kErrorNone:
if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::PendingDatasetManager>().GetTimestamp()) == 0)
if (timestamp == Get<MeshCoP::PendingDatasetManager>().GetTimestamp())
{
break;
}
@@ -2503,7 +2503,7 @@ void MleRouter::HandleDataRequest(RxInfo &aRxInfo)
switch (Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp))
{
case kErrorNone:
if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()) == 0)
if (timestamp == Get<MeshCoP::ActiveDatasetManager>().GetTimestamp())
{
break;
}
@@ -2521,7 +2521,7 @@ void MleRouter::HandleDataRequest(RxInfo &aRxInfo)
switch (Tlv::Find<PendingTimestampTlv>(aRxInfo.mMessage, timestamp))
{
case kErrorNone:
if (MeshCoP::Timestamp::Compare(&timestamp, Get<MeshCoP::PendingDatasetManager>().GetTimestamp()) == 0)
if (timestamp == Get<MeshCoP::PendingDatasetManager>().GetTimestamp())
{
break;
}
+68 -22
View File
@@ -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");
}