mirror of
https://github.com/espressif/openthread.git
synced 2026-08-01 00:27:47 +00:00
[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.
This commit is contained in:
@@ -191,7 +191,7 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const
|
||||
switch (cur->GetType())
|
||||
{
|
||||
case Tlv::kActiveTimestamp:
|
||||
aDatasetInfo.SetActiveTimestamp(static_cast<const ActiveTimestampTlv *>(cur)->GetSeconds());
|
||||
aDatasetInfo.SetActiveTimestamp(static_cast<const ActiveTimestampTlv *>(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<const PendingTimestampTlv *>(cur)->GetSeconds());
|
||||
aDatasetInfo.SetPendingTimestamp(
|
||||
static_cast<const PendingTimestampTlv *>(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<ActiveTimestampTlv>();
|
||||
VerifyOrExit(tlv != nullptr);
|
||||
timestamp = static_cast<const Timestamp *>(tlv);
|
||||
|
||||
VerifyOrExit(tlv != nullptr, error = kErrorNotFound);
|
||||
aTimestamp = tlv->GetTimestamp();
|
||||
}
|
||||
else
|
||||
{
|
||||
const PendingTimestampTlv *tlv = GetTlv<PendingTimestampTlv>();
|
||||
VerifyOrExit(tlv != nullptr);
|
||||
timestamp = static_cast<const Timestamp *>(tlv);
|
||||
|
||||
VerifyOrExit(tlv != nullptr, error = kErrorNotFound);
|
||||
aTimestamp = tlv->GetTimestamp();
|
||||
}
|
||||
|
||||
exit:
|
||||
return timestamp;
|
||||
return error;
|
||||
}
|
||||
|
||||
void Dataset::SetTimestamp(Type aType, const Timestamp &aTimestamp)
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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<Settings>().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;
|
||||
|
||||
@@ -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<PendingDataset>().Read(pendingDataset));
|
||||
|
||||
const ActiveTimestampTlv *tlv = pendingDataset.GetTlv<ActiveTimestampTlv>();
|
||||
const Timestamp * pendingActiveTimestamp = static_cast<const Timestamp *>(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));
|
||||
}
|
||||
|
||||
@@ -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<Mle::MleRouter>().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<ActiveTimestampTlv>(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<Timestamp *>(&activeTimestamp);
|
||||
SuccessOrExit(Tlv::Find<PendingTimestampTlv>(aMessage, pendingTimestamp));
|
||||
VerifyOrExit(mLocal.Compare(&pendingTimestamp) > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(pendingTimestamp.GetLength() > 0);
|
||||
timestamp = static_cast<Timestamp *>(&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<ActiveDataset>().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<ActiveDataset>().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<ActiveTimestampTlv>() == 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<ChannelTlv>() == nullptr)
|
||||
|
||||
@@ -150,7 +150,8 @@ void DatasetUpdater::PreparePendingDataset(void)
|
||||
|
||||
{
|
||||
ActiveTimestampTlv *tlv = dataset.GetTlv<ActiveTimestampTlv>();
|
||||
tlv->AdvanceRandomTicks();
|
||||
|
||||
tlv->GetTimestamp().AdvanceRandomTicks();
|
||||
}
|
||||
|
||||
SuccessOrExit(error = Get<PendingDataset>().Save(dataset));
|
||||
|
||||
@@ -1003,7 +1003,7 @@ private:
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ActiveTimestampTlv : public Tlv, public Timestamp, public SimpleTlvInfo<Tlv::kActiveTimestamp, Timestamp>
|
||||
class ActiveTimestampTlv : public Tlv, public SimpleTlvInfo<Tlv::kActiveTimestamp, Timestamp>
|
||||
{
|
||||
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<Tlv::kPendingTimestamp, Timestamp>
|
||||
class PendingTimestampTlv : public Tlv, public SimpleTlvInfo<Tlv::kPendingTimestamp, Timestamp>
|
||||
{
|
||||
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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include <openthread/platform/toolchain.h>
|
||||
|
||||
#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<Timestamp>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the Timestamp
|
||||
*
|
||||
*/
|
||||
void Init(void) { memset(this, 0, sizeof(*this)); }
|
||||
|
||||
/**
|
||||
* This method compares this timestamp to another.
|
||||
*
|
||||
|
||||
+77
-73
@@ -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<MeshCoP::ActiveDataset>().GetTimestamp();
|
||||
|
||||
timestamp = Get<MeshCoP::ActiveDataset>().GetTimestamp();
|
||||
VerifyOrExit(timestamp, error = kErrorNone);
|
||||
|
||||
timestampTlv.Init();
|
||||
*static_cast<MeshCoP::Timestamp *>(×tampTlv) = *timestamp;
|
||||
error = timestampTlv.AppendTo(aMessage);
|
||||
VerifyOrExit(timestamp != nullptr);
|
||||
error = Tlv::Append<ActiveTimestampTlv>(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<MeshCoP::PendingDataset>().GetTimestamp();
|
||||
|
||||
timestamp = Get<MeshCoP::PendingDataset>().GetTimestamp();
|
||||
VerifyOrExit(timestamp && timestamp->GetSeconds() != 0, error = kErrorNone);
|
||||
|
||||
timestampTlv.Init();
|
||||
*static_cast<MeshCoP::Timestamp *>(×tampTlv) = *timestamp;
|
||||
error = timestampTlv.AppendTo(aMessage);
|
||||
VerifyOrExit(timestamp != nullptr && timestamp->GetSeconds() != 0);
|
||||
error = Tlv::Append<PendingTimestampTlv>(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<Mac::Mac>().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<ActiveTimestampTlv>(*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<ActiveTimestampTlv>(aMessage, activeTimestamp))
|
||||
{
|
||||
const MeshCoP::Timestamp *timestamp;
|
||||
case kErrorNone:
|
||||
hasActiveTimestamp = true;
|
||||
|
||||
VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse);
|
||||
timestamp = Get<MeshCoP::ActiveDataset>().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<PendingTimestampTlv>(aMessage, pendingTimestamp))
|
||||
{
|
||||
const MeshCoP::Timestamp *timestamp;
|
||||
case kErrorNone:
|
||||
hasPendingTimestamp = true;
|
||||
|
||||
VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse);
|
||||
timestamp = Get<MeshCoP::PendingDataset>().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<SourceAddressTlv>(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<ActiveTimestampTlv>(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<MeshCoP::ActiveDataset>().Save(activeTimestamp, aMessage, offset + sizeof(tlv), tlv.GetLength()));
|
||||
IgnoreError(Get<MeshCoP::ActiveDataset>().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<PendingTimestampTlv>(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<MeshCoP::PendingDataset>().Save(pendingTimestamp, aMessage, offset + sizeof(tlv), tlv.GetLength()));
|
||||
Get<MeshCoP::PendingDataset>().Save(timestamp, aMessage, offset + sizeof(tlv), tlv.GetLength()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
case kErrorNotFound:
|
||||
Get<MeshCoP::PendingDataset>().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<uint8_t>(channelTlv.GetChannel());
|
||||
|
||||
SuccessOrExit(error = Tlv::FindTlv(aMessage, timestamp));
|
||||
VerifyOrExit(timestamp.IsValid(), error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = Tlv::Find<ActiveTimestampTlv>(aMessage, timestamp));
|
||||
SuccessOrExit(error = Tlv::Find<PanIdTlv>(aMessage, panId));
|
||||
|
||||
localTimestamp = Get<MeshCoP::ActiveDataset>().GetTimestamp();
|
||||
|
||||
@@ -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<ActiveTimestampTlv>(aMessage, timestamp))
|
||||
{
|
||||
VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse);
|
||||
case kErrorNone:
|
||||
needsActiveDatasetTlv = (Get<MeshCoP::ActiveDataset>().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<PendingTimestampTlv>(aMessage, timestamp))
|
||||
{
|
||||
VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse);
|
||||
case kErrorNone:
|
||||
needsPendingDatasetTlv = (Get<MeshCoP::PendingDataset>().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<MeshCoP::ActiveDataset>().Compare(activeTimestamp) != 0)
|
||||
if (needsActiveDatasetTlv)
|
||||
{
|
||||
child->SetRequestTlv(numTlvs++, Tlv::kActiveDataset);
|
||||
}
|
||||
|
||||
if (pendingTimestamp.GetLength() == 0 || Get<MeshCoP::PendingDataset>().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<MeshCoP::ActiveDataset>().Compare(activeTimestamp))
|
||||
// Active Timestamp
|
||||
switch (Tlv::Find<ActiveTimestampTlv>(aMessage, timestamp))
|
||||
{
|
||||
case kErrorNone:
|
||||
if (Get<MeshCoP::ActiveDataset>().Compare(timestamp) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
OT_FALL_THROUGH;
|
||||
|
||||
case kErrorNotFound:
|
||||
tlvs[numTlvs++] = Tlv::kActiveDataset;
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
if (pendingTimestamp.GetLength() == 0 || Get<MeshCoP::PendingDataset>().Compare(pendingTimestamp))
|
||||
// Pending Timestamp
|
||||
switch (Tlv::Find<PendingTimestampTlv>(aMessage, timestamp))
|
||||
{
|
||||
case kErrorNone:
|
||||
if (Get<MeshCoP::PendingDataset>().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);
|
||||
|
||||
@@ -218,6 +218,18 @@ typedef UintTlvInfo<Tlv::kVersion, uint16_t> VersionTlv;
|
||||
*/
|
||||
typedef UintTlvInfo<Tlv::kPanId, uint16_t> PanIdTlv;
|
||||
|
||||
/**
|
||||
* This class defines Active Timestamp TLV constants and types.
|
||||
*
|
||||
*/
|
||||
typedef SimpleTlvInfo<Tlv::kActiveTimestamp, MeshCoP::Timestamp> ActiveTimestampTlv;
|
||||
|
||||
/**
|
||||
* This class defines Pending Timestamp TLV constants and types.
|
||||
*
|
||||
*/
|
||||
typedef SimpleTlvInfo<Tlv::kPendingTimestamp, MeshCoP::Timestamp> 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<Tlv::kActiveTimestamp, MeshCoP::Timestamp>
|
||||
{
|
||||
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<Tlv::kPendingTimestamp, MeshCoP::Timestamp>
|
||||
{
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user