[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:
Abtin Keshavarzian
2021-09-23 22:42:09 -07:00
committed by GitHub
parent 6ef5534a51
commit 39fca69650
11 changed files with 299 additions and 320 deletions
+22 -19
View File
@@ -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)
+7 -5
View File
@@ -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.
*
*/
+8 -27
View File
@@ -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;
+16 -27
View File
@@ -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(&timestamp) == 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));
}
+23 -45
View File
@@ -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)
+2 -1
View File
@@ -150,7 +150,8 @@ void DatasetUpdater::PreparePendingDataset(void)
{
ActiveTimestampTlv *tlv = dataset.GetTlv<ActiveTimestampTlv>();
tlv->AdvanceRandomTicks();
tlv->GetTimestamp().AdvanceRandomTicks();
}
SuccessOrExit(error = Get<PendingDataset>().Save(dataset));
+58 -4
View File
@@ -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;
/**
+2 -7
View File
@@ -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
View File
@@ -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 *>(&timestampTlv) = *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 *>(&timestampTlv) = *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();
+72 -50
View File
@@ -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);
+12 -62
View File
@@ -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.