diff --git a/etc/visual-studio/libopenthread.vcxproj b/etc/visual-studio/libopenthread.vcxproj
index 945af97c4..e1e702a6d 100644
--- a/etc/visual-studio/libopenthread.vcxproj
+++ b/etc/visual-studio/libopenthread.vcxproj
@@ -96,6 +96,7 @@
+
@@ -177,6 +178,7 @@
+
diff --git a/etc/visual-studio/libopenthread.vcxproj.filters b/etc/visual-studio/libopenthread.vcxproj.filters
index dc88bc545..7a7335c39 100644
--- a/etc/visual-studio/libopenthread.vcxproj.filters
+++ b/etc/visual-studio/libopenthread.vcxproj.filters
@@ -249,6 +249,9 @@
Source Files\thread
+
+ Source Files\thread
+
Source Files\thread
@@ -509,6 +512,9 @@
Header Files\thread
+
+ Header Files\thread
+
Header Files\thread
diff --git a/etc/visual-studio/libopenthread_k.vcxproj b/etc/visual-studio/libopenthread_k.vcxproj
index 648b03fca..78cb04e86 100644
--- a/etc/visual-studio/libopenthread_k.vcxproj
+++ b/etc/visual-studio/libopenthread_k.vcxproj
@@ -103,6 +103,7 @@
+
@@ -209,6 +210,7 @@
+
diff --git a/etc/visual-studio/libopenthread_k.vcxproj.filters b/etc/visual-studio/libopenthread_k.vcxproj.filters
index 6f72961a6..d3a6d1cfc 100644
--- a/etc/visual-studio/libopenthread_k.vcxproj.filters
+++ b/etc/visual-studio/libopenthread_k.vcxproj.filters
@@ -252,6 +252,9 @@
Source Files\thread
+
+ Source Files\thread
+
Source Files\thread
@@ -509,6 +512,9 @@
Header Files\thread
+
+ Header Files\thread
+
Header Files\thread
diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp
index 54445ed52..b2fb16138 100644
--- a/src/cli/cli_dataset.cpp
+++ b/src/cli/cli_dataset.cpp
@@ -232,21 +232,29 @@ otError Dataset::ProcessHelp(otInstance *aInstance, int argc, char *argv[])
otError Dataset::ProcessActive(otInstance *aInstance, int argc, char *argv[])
{
otOperationalDataset dataset;
- otDatasetGetActive(aInstance, &dataset);
+ otError error;
+ SuccessOrExit(error = otDatasetGetActive(aInstance, &dataset));
+ error = Print(dataset);
+
+exit:
OT_UNUSED_VARIABLE(argc);
OT_UNUSED_VARIABLE(argv);
- return Print(dataset);
+ return error;
}
otError Dataset::ProcessPending(otInstance *aInstance, int argc, char *argv[])
{
otOperationalDataset dataset;
- otDatasetGetPending(aInstance, &dataset);
+ otError error;
+ SuccessOrExit(error = otDatasetGetPending(aInstance, &dataset));
+ error = Print(dataset);
+
+exit:
OT_UNUSED_VARIABLE(argc);
OT_UNUSED_VARIABLE(argv);
- return Print(dataset);
+ return error;
}
#if OPENTHREAD_FTD
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index f3ec6e6b9..6833de15a 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -138,6 +138,7 @@ SOURCES_COMMON = \
meshcop/announce_begin_client.cpp \
meshcop/commissioner.cpp \
meshcop/dataset.cpp \
+ meshcop/dataset_local.cpp \
meshcop/dataset_manager.cpp \
meshcop/dataset_manager_ftd.cpp \
meshcop/dtls.cpp \
@@ -236,6 +237,7 @@ HEADERS_COMMON = \
meshcop/announce_begin_client.hpp \
meshcop/commissioner.hpp \
meshcop/dataset.hpp \
+ meshcop/dataset_local.hpp \
meshcop/dataset_manager.hpp \
meshcop/dataset_manager_ftd.hpp \
meshcop/dataset_manager_mtd.hpp \
diff --git a/src/core/api/dataset_api.cpp b/src/core/api/dataset_api.cpp
index 33aaaff5e..bf0a1c719 100644
--- a/src/core/api/dataset_api.cpp
+++ b/src/core/api/dataset_api.cpp
@@ -60,7 +60,7 @@ otError otDatasetGetActive(otInstance *aInstance, otOperationalDataset *aDataset
VerifyOrExit(aDataset != NULL, error = OT_ERROR_INVALID_ARGS);
- aInstance->mThreadNetif.GetActiveDataset().GetLocal().Get(*aDataset);
+ error = aInstance->mThreadNetif.GetActiveDataset().GetLocal().Get(*aDataset);
exit:
return error;
@@ -72,7 +72,7 @@ otError otDatasetGetPending(otInstance *aInstance, otOperationalDataset *aDatase
VerifyOrExit(aDataset != NULL, error = OT_ERROR_INVALID_ARGS);
- aInstance->mThreadNetif.GetPendingDataset().GetLocal().Get(*aDataset);
+ error = aInstance->mThreadNetif.GetPendingDataset().GetLocal().Get(*aDataset);
exit:
return error;
diff --git a/src/core/api/link_api.cpp b/src/core/api/link_api.cpp
index 84ff8df8c..36e16fbd4 100644
--- a/src/core/api/link_api.cpp
+++ b/src/core/api/link_api.cpp
@@ -55,8 +55,8 @@ otError otLinkSetChannel(otInstance *aInstance, uint8_t aChannel)
error = OT_ERROR_INVALID_STATE);
error = aInstance->mThreadNetif.GetMac().SetChannel(aChannel);
- aInstance->mThreadNetif.GetActiveDataset().Clear(false);
- aInstance->mThreadNetif.GetPendingDataset().Clear(false);
+ aInstance->mThreadNetif.GetActiveDataset().Clear();
+ aInstance->mThreadNetif.GetPendingDataset().Clear();
exit:
return error;
@@ -117,8 +117,8 @@ otError otLinkSetPanId(otInstance *aInstance, otPanId aPanId)
error = OT_ERROR_INVALID_STATE);
error = aInstance->mThreadNetif.GetMac().SetPanId(aPanId);
- aInstance->mThreadNetif.GetActiveDataset().Clear(false);
- aInstance->mThreadNetif.GetPendingDataset().Clear(false);
+ aInstance->mThreadNetif.GetActiveDataset().Clear();
+ aInstance->mThreadNetif.GetPendingDataset().Clear();
exit:
return error;
diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp
index fcb8033f2..f68ce7d5d 100644
--- a/src/core/api/thread_api.cpp
+++ b/src/core/api/thread_api.cpp
@@ -75,8 +75,8 @@ otError otThreadSetExtendedPanId(otInstance *aInstance, const uint8_t *aExtended
mlPrefix[7] = 0x00;
aInstance->mThreadNetif.GetMle().SetMeshLocalPrefix(mlPrefix);
- aInstance->mThreadNetif.GetActiveDataset().Clear(false);
- aInstance->mThreadNetif.GetPendingDataset().Clear(false);
+ aInstance->mThreadNetif.GetActiveDataset().Clear();
+ aInstance->mThreadNetif.GetPendingDataset().Clear();
exit:
return error;
@@ -165,8 +165,8 @@ otError otThreadSetMasterKey(otInstance *aInstance, const otMasterKey *aKey)
error = OT_ERROR_INVALID_STATE);
error = aInstance->mThreadNetif.GetKeyManager().SetMasterKey(*aKey);
- aInstance->mThreadNetif.GetActiveDataset().Clear(false);
- aInstance->mThreadNetif.GetPendingDataset().Clear(false);
+ aInstance->mThreadNetif.GetActiveDataset().Clear();
+ aInstance->mThreadNetif.GetPendingDataset().Clear();
exit:
return error;
@@ -190,8 +190,8 @@ otError otThreadSetMeshLocalPrefix(otInstance *aInstance, const uint8_t *aMeshLo
error = OT_ERROR_INVALID_STATE);
error = aInstance->mThreadNetif.GetMle().SetMeshLocalPrefix(aMeshLocalPrefix);
- aInstance->mThreadNetif.GetActiveDataset().Clear(false);
- aInstance->mThreadNetif.GetPendingDataset().Clear(false);
+ aInstance->mThreadNetif.GetActiveDataset().Clear();
+ aInstance->mThreadNetif.GetPendingDataset().Clear();
exit:
return error;
@@ -215,8 +215,8 @@ otError otThreadSetNetworkName(otInstance *aInstance, const char *aNetworkName)
error = OT_ERROR_INVALID_STATE);
error = aInstance->mThreadNetif.GetMac().SetNetworkName(aNetworkName);
- aInstance->mThreadNetif.GetActiveDataset().Clear(false);
- aInstance->mThreadNetif.GetPendingDataset().Clear(false);
+ aInstance->mThreadNetif.GetActiveDataset().Clear();
+ aInstance->mThreadNetif.GetPendingDataset().Clear();
exit:
return error;
diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp
index 7cfa92028..967304f3e 100644
--- a/src/core/api/thread_ftd_api.cpp
+++ b/src/core/api/thread_ftd_api.cpp
@@ -266,8 +266,8 @@ otError otThreadSetPSKc(otInstance *aInstance, const uint8_t *aPSKc)
error = OT_ERROR_INVALID_STATE);
aInstance->mThreadNetif.GetKeyManager().SetPSKc(aPSKc);
- aInstance->mThreadNetif.GetActiveDataset().Clear(false);
- aInstance->mThreadNetif.GetPendingDataset().Clear(false);
+ aInstance->mThreadNetif.GetActiveDataset().Clear();
+ aInstance->mThreadNetif.GetPendingDataset().Clear();
exit:
return error;
diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp
index ca788c18b..9140b74ea 100644
--- a/src/core/meshcop/dataset.cpp
+++ b/src/core/meshcop/dataset.cpp
@@ -38,8 +38,6 @@
#include
-#include
-
#include "openthread-instance.h"
#include "common/code_utils.hpp"
#include "common/settings.hpp"
@@ -49,21 +47,16 @@
namespace ot {
namespace MeshCoP {
-Dataset::Dataset(otInstance *aInstance, const Tlv::Type aType) :
- InstanceLocator(aInstance),
- mType(aType),
- mLength(0)
+Dataset::Dataset(const Tlv::Type aType) :
+ mUpdateTime(0),
+ mLength(0),
+ mType(aType)
{
}
-void Dataset::Clear(bool isLocal)
+void Dataset::Clear(void)
{
mLength = 0;
-
- if (isLocal)
- {
- otPlatSettingsDelete(GetInstance(), GetSettingsKey(), -1);
- }
}
Tlv *Dataset::Get(Tlv::Type aType)
@@ -252,6 +245,8 @@ otError Dataset::Set(const Dataset &aDataset)
Remove(Tlv::kDelayTimer);
}
+ mUpdateTime = aDataset.GetUpdateTime();
+
return OT_ERROR_NONE;
}
@@ -362,6 +357,8 @@ otError Dataset::Set(const otOperationalDataset &aDataset)
Set(tlv);
}
+ mUpdateTime = Timer::GetNow();
+
exit:
return error;
}
@@ -406,60 +403,6 @@ void Dataset::SetTimestamp(const Timestamp &aTimestamp)
}
}
-int Dataset::Compare(const Dataset &aCompare) const
-{
- const Timestamp *thisTimestamp = GetTimestamp();
- const Timestamp *compareTimestamp = aCompare.GetTimestamp();
- int rval;
-
- if (compareTimestamp == NULL && thisTimestamp == NULL)
- {
- rval = 0;
- }
- else if (compareTimestamp == NULL && thisTimestamp != NULL)
- {
- rval = -1;
- }
- else if (compareTimestamp != NULL && thisTimestamp == NULL)
- {
- rval = 1;
- }
- else
- {
- rval = thisTimestamp->Compare(*compareTimestamp);
- }
-
- return rval;
-}
-
-otError Dataset::Restore(void)
-{
- otError error;
- uint16_t length = sizeof(mTlvs);
-
- error = otPlatSettingsGet(GetInstance(), GetSettingsKey(), 0, mTlvs, &length);
- mLength = (error == OT_ERROR_NONE) ? length : 0;
-
- return error;
-}
-
-otError Dataset::Store(void)
-{
- otError error;
- uint16_t key = GetSettingsKey();
-
- if (mLength == 0)
- {
- error = otPlatSettingsDelete(GetInstance(), key, 0);
- }
- else
- {
- error = otPlatSettingsSet(GetInstance(), key, mTlvs, mLength);
- }
-
- return error;
-}
-
otError Dataset::Set(const Tlv &aTlv)
{
otError error = OT_ERROR_NONE;
@@ -483,15 +426,23 @@ otError Dataset::Set(const Tlv &aTlv)
memcpy(mTlvs + mLength, &aTlv, sizeof(Tlv) + aTlv.GetLength());
mLength += sizeof(Tlv) + aTlv.GetLength();
+ mUpdateTime = Timer::GetNow();
+
exit:
return error;
}
otError Dataset::Set(const Message &aMessage, uint16_t aOffset, uint8_t aLength)
{
- aMessage.Read(aOffset, aLength, mTlvs);
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aLength == aMessage.Read(aOffset, aLength, mTlvs), error = OT_ERROR_INVALID_ARGS);
mLength = aLength;
- return OT_ERROR_NONE;
+
+ mUpdateTime = Timer::GetNow();
+
+exit:
+ return error;
}
void Dataset::Remove(Tlv::Type aType)
@@ -505,13 +456,15 @@ exit:
return;
}
-otError Dataset::AppendMleDatasetTlv(Message &aMessage)
+otError Dataset::AppendMleDatasetTlv(Message &aMessage) const
{
otError error = OT_ERROR_NONE;
Mle::Tlv tlv;
Mle::Tlv::Type type;
- Tlv *cur = reinterpret_cast(mTlvs);
- Tlv *end = reinterpret_cast(mTlvs + mLength);
+ const Tlv *cur = reinterpret_cast(mTlvs);
+ const Tlv *end = reinterpret_cast(mTlvs + mLength);
+
+ VerifyOrExit(mLength > 0);
type = (mType == Tlv::kActiveTimestamp ? Mle::Tlv::kActiveDataset : Mle::Tlv::kPendingDataset);
@@ -521,7 +474,29 @@ otError Dataset::AppendMleDatasetTlv(Message &aMessage)
while (cur < end)
{
- if (cur->GetType() != mType)
+ if (cur->GetType() == mType)
+ {
+ ; // skip Active or Pending Timestamp TLV
+ }
+ else if (cur->GetType() == Tlv::kDelayTimer)
+ {
+ uint32_t elapsed = Timer::GetNow() - mUpdateTime;
+ DelayTimerTlv delayTimer;
+
+ memcpy(&delayTimer, cur, sizeof(delayTimer));
+
+ if (delayTimer.GetDelayTimer() > elapsed)
+ {
+ delayTimer.SetDelayTimer(delayTimer.GetDelayTimer() - elapsed);
+ }
+ else
+ {
+ delayTimer.SetDelayTimer(0);
+ }
+
+ SuccessOrExit(error = aMessage.Append(&delayTimer, sizeof(delayTimer)));
+ }
+ else
{
SuccessOrExit(error = aMessage.Append(cur, sizeof(Tlv) + cur->GetLength()));
}
diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp
index de2d81d56..c850371d0 100644
--- a/src/core/meshcop/dataset.hpp
+++ b/src/core/meshcop/dataset.hpp
@@ -42,8 +42,10 @@
namespace ot {
namespace MeshCoP {
-class Dataset: public InstanceLocator
+class Dataset
{
+ friend class DatasetLocal;
+
public:
enum
{
@@ -54,19 +56,16 @@ public:
/**
* This constructor initializes the object.
*
- * @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aType The type of the dataset, active or pending.
*
*/
- Dataset(otInstance *aInstance, const Tlv::Type aType);
+ Dataset(const Tlv::Type aType);
/**
* This method clears the Dataset.
*
- * @param[in] isLocal TRUE to delete the local dataset from non-volatile memory, FALSE not.
- *
*/
- void Clear(bool isLocal);
+ void Clear(void);
/**
* This method returns a pointer to the TLV.
@@ -106,6 +105,14 @@ public:
*/
uint16_t GetSize(void) const { return mLength; }
+ /**
+ * This method returns the local time the dataset was last updated.
+ *
+ * @returns The local time the dataset was last updated.
+ *
+ */
+ uint32_t GetUpdateTime(void) const { return mUpdateTime; }
+
/**
* This method returns a reference to the Timestamp.
*
@@ -120,36 +127,6 @@ public:
*/
void SetTimestamp(const Timestamp &aTimestamp);
- /**
- * This method compares this dataset to another based on the timestamp.
- *
- * @param[in] aCompare A reference to the timestamp to compare.
- *
- * @retval -1 if @p aCompare is older than this dataset.
- * @retval 0 if @p aCompare is equal to this dataset.
- * @retval 1 if @p aCompare is newer than this dataset.
- *
- */
- int Compare(const Dataset &aCompare) const;
-
- /**
- * This method restores dataset from non-volatile memory.
- *
- * @retval OT_ERROR_NONE Successfully restore the dataset.
- * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
- *
- */
- otError Restore(void);
-
- /**
- * This method stores dataset into non-volatile memory.
- *
- * @retval OT_ERROR_NONE Successfully store the dataset.
- * @retval OT_ERROR_NO_BUFS Could not store the dataset due to insufficient memory space.
- *
- */
- otError Store(void);
-
/**
* This method sets a TLV in the Dataset.
*
@@ -161,11 +138,41 @@ public:
*/
otError Set(const Tlv &aTlv);
+ /**
+ * This method sets the Dataset using TLVs stored in a message buffer.
+ *
+ * @param[in] aMessage The message buffer.
+ * @param[in] aOffset The message buffer offset where the dataset starts.
+ * @param[in] aLength The TLVs length in the message buffer in bytes.
+ *
+ * @retval OT_ERROR_NONE Successfully set the Dataset.
+ * @retval OT_ERROR_INVALID_ARGS The values of @p aOffset and @p aLength are not valid for @p aMessage.
+ *
+ */
otError Set(const Message &aMessage, uint16_t aOffset, uint8_t aLength);
+ /**
+ * This method sets the Dataset using an existing Dataset.
+ *
+ * If this Dataset is an Active Dataset, any Pending Timestamp and Delay Timer TLVs will be omitted in the copy
+ * from @p aDataset.
+ *
+ * @param[in] aDataset The input Dataset.
+ *
+ * @retval OT_ERROR_NONE Successfully set the Dataset.
+ *
+ */
otError Set(const Dataset &aDataset);
#if OPENTHREAD_FTD
+ /**
+ * This method sets the Dataset.
+ *
+ * @param[in] aDataset The input Dataset.
+ *
+ * @retval OT_ERROR_NONE Successfully set the Dataset.
+ *
+ */
otError Set(const otOperationalDataset &aDataset);
#endif
@@ -184,16 +191,17 @@ public:
* @retval OT_ERROR_NO_BUFS Insufficient available buffers to append the message with MLE Dataset TLV.
*
*/
- otError AppendMleDatasetTlv(Message &aMessage);
+ otError AppendMleDatasetTlv(Message &aMessage) const;
private:
uint16_t GetSettingsKey(void);
void Remove(uint8_t *aStart, uint8_t aLength);
- Tlv::Type mType; ///< Active or Pending
uint8_t mTlvs[kMaxSize]; ///< The Dataset buffer
+ uint32_t mUpdateTime; ///< Local time last updated
uint16_t mLength; ///< The number of valid bytes in @var mTlvs
+ Tlv::Type mType; ///< Active or Pending
};
} // namespace MeshCoP
diff --git a/src/core/meshcop/dataset_local.cpp b/src/core/meshcop/dataset_local.cpp
new file mode 100644
index 000000000..9dedb1362
--- /dev/null
+++ b/src/core/meshcop/dataset_local.cpp
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2016-2017, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements common methods for manipulating MeshCoP Datasets.
+ *
+ */
+
+#define WPP_NAME "dataset_local.tmh"
+
+#include
+
+#include "dataset_local.hpp"
+
+#include
+
+#include
+
+#include "common/code_utils.hpp"
+#include "common/logging.hpp"
+#include "common/settings.hpp"
+#include "meshcop/dataset.hpp"
+#include "meshcop/meshcop_tlvs.hpp"
+#include "thread/mle_tlvs.hpp"
+
+namespace ot {
+namespace MeshCoP {
+
+DatasetLocal::DatasetLocal(otInstance *aInstance, const Tlv::Type aType) :
+ InstanceLocator(aInstance),
+ mUpdateTime(0),
+ mType(aType)
+{
+}
+
+void DatasetLocal::Clear(void)
+{
+ otPlatSettingsDelete(GetInstance(), GetSettingsKey(), -1);
+}
+
+bool DatasetLocal::IsPresent(void) const
+{
+ return otPlatSettingsGet(GetInstance(), GetSettingsKey(), 0, NULL, NULL) == OT_ERROR_NONE;
+}
+
+otError DatasetLocal::Get(Dataset &aDataset)
+{
+ DelayTimerTlv *delayTimer;
+ uint32_t elapsed;
+ otError error;
+
+ aDataset.mLength = sizeof(aDataset.mTlvs);
+
+ error = otPlatSettingsGet(GetInstance(), GetSettingsKey(), 0, aDataset.mTlvs, &aDataset.mLength);
+ SuccessOrExit(error);
+
+ delayTimer = static_cast(aDataset.Get(Tlv::kDelayTimer));
+ VerifyOrExit(delayTimer);
+
+ elapsed = Timer::GetNow() - mUpdateTime;
+
+ if (delayTimer->GetDelayTimer() > elapsed)
+ {
+ delayTimer->SetDelayTimer(delayTimer->GetDelayTimer() - elapsed);
+ }
+ else
+ {
+ delayTimer->SetDelayTimer(0);
+ }
+
+ aDataset.mUpdateTime = Timer::GetNow();
+
+exit:
+ return error;
+}
+
+otError DatasetLocal::Get(otOperationalDataset &aDataset) const
+{
+ Dataset dataset(mType);
+ otError error;
+ const Tlv *cur;
+ const Tlv *end;
+
+ dataset.mLength = sizeof(dataset.mTlvs);
+
+ error = otPlatSettingsGet(GetInstance(), GetSettingsKey(), 0, dataset.mTlvs, &dataset.mLength);
+ SuccessOrExit(error);
+
+ cur = reinterpret_cast(dataset.mTlvs);
+ end = reinterpret_cast(dataset.mTlvs + dataset.mLength);
+
+ memset(&aDataset, 0, sizeof(aDataset));
+
+ while (cur < end)
+ {
+ switch (cur->GetType())
+ {
+
+ case Tlv::kActiveTimestamp:
+ {
+ const ActiveTimestampTlv *tlv = static_cast(cur);
+ aDataset.mActiveTimestamp = tlv->GetSeconds();
+ aDataset.mIsActiveTimestampSet = true;
+ break;
+ }
+
+ case Tlv::kChannel:
+ {
+ const ChannelTlv *tlv = static_cast(cur);
+ aDataset.mChannel = tlv->GetChannel();
+ aDataset.mIsChannelSet = true;
+ break;
+ }
+
+ case Tlv::kChannelMask:
+ {
+ uint8_t tlvLength = cur->GetLength();
+ const uint8_t *entry = reinterpret_cast(cur) + sizeof(Tlv);
+ const uint8_t *entryEnd = entry + tlvLength;
+
+ while (entry < entryEnd)
+ {
+ if (reinterpret_cast(entry)->GetChannelPage() == 0)
+ {
+ uint8_t i = sizeof(ChannelMaskEntry);
+ aDataset.mChannelMaskPage0 = static_cast(entry[i] | (entry[i + 1] << 8) |
+ (entry[i + 2] << 16) | (entry[i + 3] << 24));
+ aDataset.mIsChannelMaskPage0Set = true;
+ break;
+ }
+
+ entry += (reinterpret_cast(entry)->GetMaskLength() +
+ sizeof(ChannelMaskEntry));
+ }
+
+ break;
+ }
+
+ case Tlv::kDelayTimer:
+ {
+ const DelayTimerTlv *tlv = static_cast(cur);
+ aDataset.mDelay = tlv->GetDelayTimer();
+ aDataset.mIsDelaySet = true;
+ break;
+ }
+
+ case Tlv::kExtendedPanId:
+ {
+ const ExtendedPanIdTlv *tlv = static_cast(cur);
+ memcpy(aDataset.mExtendedPanId.m8, tlv->GetExtendedPanId(), sizeof(aDataset.mExtendedPanId));
+ aDataset.mIsExtendedPanIdSet = true;
+ break;
+ }
+
+ case Tlv::kMeshLocalPrefix:
+ {
+ const MeshLocalPrefixTlv *tlv = static_cast(cur);
+ memcpy(aDataset.mMeshLocalPrefix.m8, tlv->GetMeshLocalPrefix(), sizeof(aDataset.mMeshLocalPrefix));
+ aDataset.mIsMeshLocalPrefixSet = true;
+ break;
+ }
+
+ case Tlv::kNetworkMasterKey:
+ {
+ const NetworkMasterKeyTlv *tlv = static_cast(cur);
+ aDataset.mMasterKey = tlv->GetNetworkMasterKey();
+ aDataset.mIsMasterKeySet = true;
+ break;
+ }
+
+ case Tlv::kNetworkName:
+ {
+ const NetworkNameTlv *tlv = static_cast(cur);
+ memcpy(aDataset.mNetworkName.m8, tlv->GetNetworkName(), tlv->GetLength());
+ aDataset.mIsNetworkNameSet = true;
+ break;
+ }
+
+ case Tlv::kPanId:
+ {
+ const PanIdTlv *panid = static_cast(cur);
+ aDataset.mPanId = panid->GetPanId();
+ aDataset.mIsPanIdSet = true;
+ break;
+ }
+
+ case Tlv::kPendingTimestamp:
+ {
+ const PendingTimestampTlv *tlv = static_cast(cur);
+ aDataset.mPendingTimestamp = tlv->GetSeconds();
+ aDataset.mIsPendingTimestampSet = true;
+ break;
+ }
+
+ case Tlv::kPSKc:
+ {
+ const PSKcTlv *tlv = static_cast(cur);
+ memcpy(aDataset.mPSKc.m8, tlv->GetPSKc(), tlv->GetLength());
+ aDataset.mIsPSKcSet = true;
+ break;
+ }
+
+ case Tlv::kSecurityPolicy:
+ {
+ const SecurityPolicyTlv *tlv = static_cast(cur);
+ aDataset.mSecurityPolicy.mRotationTime = tlv->GetRotationTime();
+ aDataset.mSecurityPolicy.mFlags = tlv->GetFlags();
+ aDataset.mIsSecurityPolicySet = true;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ cur = cur->GetNext();
+ }
+
+exit:
+ return error;
+}
+
+#if OPENTHREAD_FTD
+
+otError DatasetLocal::Set(const otOperationalDataset &aDataset)
+{
+ otError error = OT_ERROR_NONE;
+ Dataset dataset(mType);
+ MeshCoP::ActiveTimestampTlv activeTimestampTlv;
+
+ VerifyOrExit(aDataset.mIsActiveTimestampSet, error = OT_ERROR_INVALID_ARGS);
+
+ activeTimestampTlv.Init();
+ activeTimestampTlv.SetSeconds(aDataset.mActiveTimestamp);
+ activeTimestampTlv.SetTicks(0);
+ dataset.Set(activeTimestampTlv);
+
+ if (mType == Tlv::kPendingTimestamp)
+ {
+ MeshCoP::PendingTimestampTlv pendingTimestampTlv;
+
+ VerifyOrExit(aDataset.mIsPendingTimestampSet, error = OT_ERROR_INVALID_ARGS);
+
+ pendingTimestampTlv.Init();
+ pendingTimestampTlv.SetSeconds(aDataset.mPendingTimestamp);
+ pendingTimestampTlv.SetTicks(0);
+ dataset.Set(pendingTimestampTlv);
+
+ if (aDataset.mIsDelaySet)
+ {
+ MeshCoP::DelayTimerTlv tlv;
+ tlv.Init();
+ tlv.SetDelayTimer(aDataset.mDelay);
+ dataset.Set(tlv);
+ }
+ }
+
+ if (aDataset.mIsChannelSet)
+ {
+ MeshCoP::ChannelTlv tlv;
+ tlv.Init();
+ tlv.SetChannelPage(0);
+ tlv.SetChannel(aDataset.mChannel);
+ dataset.Set(tlv);
+ }
+
+ if (aDataset.mIsChannelMaskPage0Set)
+ {
+ MeshCoP::ChannelMask0Tlv tlv;
+ tlv.Init();
+ tlv.SetMask(aDataset.mChannelMaskPage0);
+ dataset.Set(tlv);
+ }
+
+ if (aDataset.mIsExtendedPanIdSet)
+ {
+ MeshCoP::ExtendedPanIdTlv tlv;
+ tlv.Init();
+ tlv.SetExtendedPanId(aDataset.mExtendedPanId.m8);
+ dataset.Set(tlv);
+ }
+
+ if (aDataset.mIsMeshLocalPrefixSet)
+ {
+ MeshCoP::MeshLocalPrefixTlv tlv;
+ tlv.Init();
+ tlv.SetMeshLocalPrefix(aDataset.mMeshLocalPrefix.m8);
+ dataset.Set(tlv);
+ }
+
+ if (aDataset.mIsMasterKeySet)
+ {
+ MeshCoP::NetworkMasterKeyTlv tlv;
+ tlv.Init();
+ tlv.SetNetworkMasterKey(aDataset.mMasterKey);
+ dataset.Set(tlv);
+ }
+
+ if (aDataset.mIsNetworkNameSet)
+ {
+ MeshCoP::NetworkNameTlv tlv;
+ tlv.Init();
+ tlv.SetNetworkName(aDataset.mNetworkName.m8);
+ dataset.Set(tlv);
+ }
+
+ if (aDataset.mIsPanIdSet)
+ {
+ MeshCoP::PanIdTlv tlv;
+ tlv.Init();
+ tlv.SetPanId(aDataset.mPanId);
+ dataset.Set(tlv);
+ }
+
+ if (aDataset.mIsPSKcSet)
+ {
+ MeshCoP::PSKcTlv tlv;
+ tlv.Init();
+ tlv.SetPSKc(aDataset.mPSKc.m8);
+ dataset.Set(tlv);
+ }
+
+ if (aDataset.mIsSecurityPolicySet)
+ {
+ MeshCoP::SecurityPolicyTlv tlv;
+ tlv.Init();
+ tlv.SetRotationTime(aDataset.mSecurityPolicy.mRotationTime);
+ tlv.SetFlags(aDataset.mSecurityPolicy.mFlags);
+ dataset.Set(tlv);
+ }
+
+ if (dataset.GetSize() == 0)
+ {
+ error = otPlatSettingsDelete(GetInstance(), GetSettingsKey(), 0);
+ otLogInfoMeshCoP(GetInstance(), "%s dataset deleted", mType == Tlv::kActiveTimestamp ? "Active" : "Pending");
+ }
+ else
+ {
+ error = otPlatSettingsSet(GetInstance(), GetSettingsKey(), dataset.GetBytes(), dataset.GetSize());
+ otLogInfoMeshCoP(GetInstance(), "%s dataset set", mType == Tlv::kActiveTimestamp ? "Active" : "Pending");
+ }
+
+exit:
+ return error;
+}
+
+#endif // OPENTHREAD_FTD
+
+otError DatasetLocal::Set(const Dataset &aDataset)
+{
+ Dataset dataset(aDataset);
+ otError error;
+
+ if (mType == Tlv::kActiveTimestamp)
+ {
+ dataset.Remove(Tlv::kPendingTimestamp);
+ dataset.Remove(Tlv::kDelayTimer);
+ }
+
+ if (dataset.GetSize() == 0)
+ {
+ error = otPlatSettingsDelete(GetInstance(), GetSettingsKey(), 0);
+ otLogInfoMeshCoP(GetInstance(), "%s dataset deleted", mType == Tlv::kActiveTimestamp ? "Active" : "Pending");
+ }
+ else
+ {
+ error = otPlatSettingsSet(GetInstance(), GetSettingsKey(), dataset.GetBytes(), dataset.GetSize());
+ otLogInfoMeshCoP(GetInstance(), "%s dataset set", mType == Tlv::kActiveTimestamp ? "Active" : "Pending");
+ }
+
+ SuccessOrExit(error);
+
+ mUpdateTime = Timer::GetNow();
+
+exit:
+ return error;
+}
+
+otError DatasetLocal::Restore(void)
+{
+ Dataset dataset(mType);
+ otError error;
+
+ dataset.mLength = sizeof(dataset.mTlvs);
+ error = otPlatSettingsGet(GetInstance(), GetSettingsKey(), 0, dataset.mTlvs, &dataset.mLength);
+ SuccessOrExit(error);
+
+ mUpdateTime = Timer::GetNow();
+
+exit:
+ return error;
+}
+
+uint16_t DatasetLocal::GetSettingsKey(void) const
+{
+ uint16_t rval;
+
+ if (mType == Tlv::kActiveTimestamp)
+ {
+ rval = static_cast(Settings::kKeyActiveDataset);
+ }
+ else
+ {
+ rval = static_cast(Settings::kKeyPendingDataset);
+ }
+
+ return rval;
+}
+
+int DatasetLocal::Compare(const Timestamp *aCompareTimestamp)
+{
+ const Timestamp *thisTimestamp;
+ Dataset dataset(mType);
+ int rval = 1;
+
+ SuccessOrExit(Get(dataset));
+
+ thisTimestamp = dataset.GetTimestamp();
+
+ if (aCompareTimestamp == NULL && thisTimestamp == NULL)
+ {
+ rval = 0;
+ }
+ else if (aCompareTimestamp == NULL && thisTimestamp != NULL)
+ {
+ rval = -1;
+ }
+ else if (aCompareTimestamp != NULL && thisTimestamp == NULL)
+ {
+ rval = 1;
+ }
+ else
+ {
+ rval = thisTimestamp->Compare(*aCompareTimestamp);
+ }
+
+exit:
+ return rval;
+}
+
+} // namespace MeshCoP
+} // namespace ot
diff --git a/src/core/meshcop/dataset_local.hpp b/src/core/meshcop/dataset_local.hpp
new file mode 100644
index 000000000..16de33106
--- /dev/null
+++ b/src/core/meshcop/dataset_local.hpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2016-2017, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes definitions for managing MeshCoP Datasets.
+ *
+ */
+
+#ifndef MESHCOP_DATASET_LOCAL_HPP_
+#define MESHCOP_DATASET_LOCAL_HPP_
+
+#include "common/locator.hpp"
+#include "meshcop/dataset.hpp"
+#include "meshcop/meshcop_tlvs.hpp"
+
+namespace ot {
+namespace MeshCoP {
+
+class DatasetLocal: public InstanceLocator
+{
+public:
+ /**
+ * This constructor initializes the object.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aType The type of the dataset, active or pending.
+ *
+ */
+ DatasetLocal(otInstance *aInstance, const Tlv::Type aType);
+
+ /**
+ * This method indicates whether this is an Active or Pending Dataset.
+ *
+ * @retval Tlv::kActiveTimestamp when this is an Active Dataset.
+ * @retval Tlv::kPendingTimetamp when this is a Pending Dataset.
+ *
+ */
+ Tlv::Type GetType(void) const { return mType; }
+
+ /**
+ * This method clears the Dataset.
+ *
+ */
+ void Clear(void);
+
+ /**
+ * This method indicates whether or not the dataset is present in non-volatile memory.
+ *
+ * @retval TRUE if the dataset is present in non-volatile memory.
+ * @retval FALSE if the dataset is not present in non-volatile memory.
+ *
+ */
+ bool IsPresent(void) const;
+
+ /**
+ * This method returns a pointer to the Active or Pending Timestamp value.
+ *
+ * @returns A pointer to the Active or Pending Timestamp value or NULL if the dataset is invalid.
+ *
+ */
+ const Timestamp *GetTimestamp(void) const;
+
+ /**
+ * This method retrieves the dataset from non-volatile memory.
+ *
+ * @param[out] aDataset Where to place the dataset.
+ *
+ * @retval OT_ERROR_NONE Successfully retrieved the dataset.
+ * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ *
+ */
+ otError Get(Dataset &aDataset);
+
+ /**
+ * This method retrieves the dataset from non-volatile memory.
+ *
+ * @param[out] aDataset Where to place the dataset.
+ *
+ * @retval OT_ERROR_NONE Successfully retrieved the dataset.
+ * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ *
+ */
+ otError Get(otOperationalDataset &aDataset) const;
+
+ /**
+ * This method returns the local time this dataset was last updated or restored.
+ *
+ * @returns The local time this dataset was last updated or restored.
+ *
+ */
+ uint32_t GetUpdateTime(void) const { return mUpdateTime; }
+
+#if OPENTHREAD_FTD
+ /**
+ * This method stores the dataset into non-volatile memory.
+ *
+ * @retval OT_ERROR_NONE Successfully stored the dataset.
+ *
+ */
+ otError Set(const otOperationalDataset &aDataset);
+#endif
+
+ /**
+ * This method stores the dataset into non-volatile memory.
+ *
+ * @retval OT_ERROR_NONE Successfully stored the dataset.
+ *
+ */
+ otError Set(const Dataset &aDataset);
+
+ /**
+ * This method restores dataset from non-volatile memory.
+ *
+ * @retval OT_ERROR_NONE Successfully restore the dataset.
+ * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ *
+ */
+ otError Restore(void);
+
+ /**
+ * This method compares this dataset to another based on the timestamp.
+ *
+ * @param[in] aCompare A reference to the timestamp to compare.
+ *
+ * @retval -1 if @p aCompare is older than this dataset.
+ * @retval 0 if @p aCompare is equal to this dataset.
+ * @retval 1 if @p aCompare is newer than this dataset.
+ *
+ */
+ int Compare(const Timestamp *aCompare);
+
+private:
+ uint16_t GetSettingsKey(void) const;
+ void SetTimestamp(const Dataset &aDataset);
+
+ uint32_t mUpdateTime; ///< Local time last updated
+ Tlv::Type mType; ///< Active or Pending
+};
+
+} // namespace MeshCoP
+} // namespace ot
+
+#endif // MESHCOP_DATASET_LOCAL_HPP_
diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp
index b56082624..86f97c3e3 100644
--- a/src/core/meshcop/dataset_manager.cpp
+++ b/src/core/meshcop/dataset_manager.cpp
@@ -65,22 +65,59 @@ DatasetManager::DatasetManager(ThreadNetif &aThreadNetif, const Tlv::Type aType,
const char *aUriGet, Timer::Handler aTimerHander):
ThreadNetifLocator(aThreadNetif),
mLocal(aThreadNetif.GetInstance(), aType),
- mNetwork(aThreadNetif.GetInstance(), aType),
+ mNetwork(aType),
mTimer(aThreadNetif.GetIp6().mTimerScheduler, aTimerHander, this),
mUriSet(aUriSet),
mUriGet(aUriGet)
{
}
+const Timestamp *DatasetManager::GetTimestamp(void) const
+{
+ return mNetwork.GetTimestamp();
+}
+
+int DatasetManager::Compare(const Timestamp &aTimestamp) const
+{
+ const Timestamp *timestamp = mNetwork.GetTimestamp();
+ int rval = 1;
+
+ if (timestamp)
+ {
+ rval = timestamp->Compare(aTimestamp);
+ }
+
+ return rval;
+}
+
+otError DatasetManager::AppendMleDatasetTlv(Message &aMessage) const
+{
+ return mNetwork.AppendMleDatasetTlv(aMessage);
+}
+
+const Tlv *DatasetManager::GetTlv(Tlv::Type aType) const
+{
+ return mNetwork.Get(aType);
+}
+
otError DatasetManager::ApplyConfiguration(void)
{
ThreadNetif &netif = GetNetif();
otError error = OT_ERROR_NONE;
+ Dataset datasetLocal(mLocal.GetType());
Dataset *dataset;
const Tlv *cur;
const Tlv *end;
- dataset = netif.GetMle().IsAttached() ? &mNetwork : &mLocal;
+ if (netif.GetMle().IsAttached())
+ {
+ dataset = &mNetwork;
+ }
+ else
+ {
+ mLocal.Get(datasetLocal);
+ dataset = &datasetLocal;
+ }
cur = reinterpret_cast(dataset->GetBytes());
end = reinterpret_cast(dataset->GetBytes() + dataset->GetSize());
@@ -165,15 +202,56 @@ otError DatasetManager::ApplyConfiguration(void)
return error;
}
+otError DatasetManager::Restore(void)
+{
+ otError error;
+
+ SuccessOrExit(error = mLocal.Restore());
+ mLocal.Get(mNetwork);
+
+exit:
+ return error;
+}
+
+void DatasetManager::Clear(void)
+{
+ mNetwork.Clear();
+ mLocal.Clear();
+ mTimer.Stop();
+}
+
+void DatasetManager::HandleDetach(void)
+{
+ mLocal.Get(mNetwork);
+ mTimer.Stop();
+}
+
+void DatasetManager::Set(const Dataset &aDataset)
+{
+ mNetwork.Set(aDataset);
+ mLocal.Set(aDataset);
+}
+
+otError DatasetManager::Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength)
+{
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = mNetwork.Set(aMessage, aOffset, aLength));
+ mNetwork.SetTimestamp(aTimestamp);
+ HandleNetworkUpdate();
+
+exit:
+ return error;
+}
+
#if OPENTHREAD_FTD
-otError DatasetManager::Set(const otOperationalDataset &aDataset, uint8_t &aFlags)
+
+otError DatasetManager::Set(const otOperationalDataset &aDataset)
{
ThreadNetif &netif = GetNetif();
otError error = OT_ERROR_NONE;
SuccessOrExit(error = mLocal.Set(aDataset));
- mLocal.Store();
- aFlags = kFlagLocalUpdated;
switch (netif.GetMle().GetRole())
{
@@ -183,8 +261,7 @@ otError DatasetManager::Set(const otOperationalDataset &aDataset, uint8_t &aFlag
break;
case OT_DEVICE_ROLE_LEADER:
- mNetwork = mLocal;
- aFlags |= kFlagNetworkUpdated;
+ mLocal.Get(mNetwork);
netif.GetNetworkDataLeader().IncrementVersion();
netif.GetNetworkDataLeader().IncrementStableVersion();
break;
@@ -196,57 +273,16 @@ otError DatasetManager::Set(const otOperationalDataset &aDataset, uint8_t &aFlag
exit:
return error;
}
+
#endif // OPENTHREAD_FTD
-otError DatasetManager::Clear(uint8_t &aFlags, bool aOnlyClearNetwork)
+void DatasetManager::HandleNetworkUpdate(void)
{
- if (!aOnlyClearNetwork)
- {
- mLocal.Clear(true);
- }
-
- mNetwork.Clear(false);
- HandleNetworkUpdate(aFlags);
- return OT_ERROR_NONE;
-}
-
-otError DatasetManager::Set(const Dataset &aDataset)
-{
- mNetwork.Set(aDataset);
-
- if (mLocal.Compare(aDataset) != 0)
- {
- mLocal.Set(aDataset);
- mLocal.Store();
- }
-
- return OT_ERROR_NONE;
-}
-
-otError DatasetManager::Set(const Timestamp &aTimestamp, const Message &aMessage,
- uint16_t aOffset, uint8_t aLength, uint8_t &aFlags)
-{
- otError error = OT_ERROR_NONE;
-
- SuccessOrExit(error = mNetwork.Set(aMessage, aOffset, aLength));
- mNetwork.SetTimestamp(aTimestamp);
- HandleNetworkUpdate(aFlags);
-
-exit:
- return error;
-}
-
-void DatasetManager::HandleNetworkUpdate(uint8_t &aFlags)
-{
- int compare = mLocal.Compare(mNetwork);
-
- aFlags = kFlagNetworkUpdated;
+ int compare = mLocal.Compare(mNetwork.GetTimestamp());
if (compare > 0)
{
- mLocal = mNetwork;
- mLocal.Store();
- aFlags |= kFlagLocalUpdated;
+ mLocal.Set(mNetwork);
}
else if (compare < 0)
{
@@ -257,32 +293,29 @@ void DatasetManager::HandleNetworkUpdate(uint8_t &aFlags)
void DatasetManager::HandleTimer(void)
{
ThreadNetif &netif = GetNetif();
- const Timestamp *localActiveTimestamp;
- const Timestamp *pendingActiveTimestamp;
- const ActiveTimestampTlv *tlv;
- localActiveTimestamp = netif.GetActiveDataset().GetLocal().GetTimestamp();
- VerifyOrExit(localActiveTimestamp != NULL);
+ VerifyOrExit(netif.GetActiveDataset().GetLocal().IsPresent());
VerifyOrExit(netif.GetMle().IsAttached());
- VerifyOrExit(mLocal.Compare(mNetwork) < 0);
+ VerifyOrExit(mLocal.Compare(mNetwork.GetTimestamp()) < 0);
+
+ if (mLocal.GetType() == Tlv::kActiveTimestamp)
+ {
+ const ActiveTimestampTlv *tlv = static_cast(netif.GetPendingDataset().GetTlv(
+ Tlv::kActiveTimestamp));
+ const Timestamp *pendingActiveTimestamp = static_cast(tlv);
+
+ if (pendingActiveTimestamp != NULL &&
+ netif.GetActiveDataset().GetLocal().Compare(pendingActiveTimestamp) >= 0)
+ {
+ // stop registration attempts during dataset transition
+ ExitNow();
+ }
+ }
Register();
-
- tlv = static_cast(netif.GetPendingDataset().GetNetwork().Get(Tlv::kActiveTimestamp));
- pendingActiveTimestamp = static_cast(tlv);
-
- if (pendingActiveTimestamp != NULL &&
- localActiveTimestamp->Compare(*pendingActiveTimestamp) >= 0)
- {
- // stop registration attempts during dataset transition
- ExitNow();
- }
- else
- {
- mTimer.Start(1000);
- }
+ mTimer.Start(1000);
exit:
return;
@@ -295,21 +328,17 @@ otError DatasetManager::Register(void)
Coap::Header header;
Message *message;
Ip6::MessageInfo messageInfo;
+ Dataset dataset(mLocal.GetType());
header.Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST);
header.SetToken(Coap::Header::kDefaultTokenLength);
header.AppendUriPathOptions(mUriSet);
header.SetPayloadMarker();
- if (strcmp(mUriSet, OT_URI_PATH_PENDING_SET) == 0)
- {
- PendingDatasetBase *pending = static_cast(this);
- pending->UpdateDelayTimer();
- }
-
VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS);
- SuccessOrExit(error = message->Append(mLocal.GetBytes(), mLocal.GetSize()));
+ mLocal.Get(dataset);
+ SuccessOrExit(error = message->Append(dataset.GetBytes(), dataset.GetSize()));
messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16());
netif.GetMle().GetLeaderAloc(messageInfo.GetPeerAddr());
@@ -328,7 +357,8 @@ exit:
return error;
}
-void DatasetManager::Get(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+void DatasetManager::Get(const Coap::Header &aHeader, const Message &aMessage,
+ const Ip6::MessageInfo &aMessageInfo) const
{
Tlv tlv;
uint16_t offset = aMessage.GetOffset();
@@ -414,8 +444,7 @@ otError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const Ip6:
static_cast(&activeTimestamp) :
static_cast(&pendingTimestamp);
- VerifyOrExit(mLocal.GetTimestamp() == NULL || mLocal.GetTimestamp()->Compare(*timestamp) > 0,
- state = StateTlv::kReject);
+ VerifyOrExit(mLocal.Compare(timestamp) > 0, state = StateTlv::kReject);
// check channel
if (Tlv::GetTlv(aMessage, Tlv::kChannel, sizeof(channel), channel) == OT_ERROR_NONE)
@@ -461,7 +490,7 @@ otError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const Ip6:
memcmp(&masterKey.GetNetworkMasterKey(), &netif.GetKeyManager().GetMasterKey(), OT_MASTER_KEY_SIZE) == 0))
{
// no change to master key, active timestamp must be ahead
- const Timestamp *localActiveTimestamp = netif.GetActiveDataset().GetNetwork().GetTimestamp();
+ const Timestamp *localActiveTimestamp = netif.GetActiveDataset().GetTimestamp();
VerifyOrExit(localActiveTimestamp == NULL || localActiveTimestamp->Compare(activeTimestamp) > 0,
state = StateTlv::kReject);
@@ -488,10 +517,13 @@ otError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const Ip6:
state = StateTlv::kReject);
// update dataset
- if (type == Tlv::kPendingTimestamp && isUpdateFromCommissioner)
+ if (isUpdateFromCommissioner)
{
- mLocal.Clear(true);
- mLocal.Set(netif.GetActiveDataset().GetNetwork());
+ mNetwork.Set(netif.GetActiveDataset().GetNetwork());
+ }
+ else
+ {
+ mNetwork.Clear();
}
if (type == Tlv::kPendingTimestamp || !doesAffectConnectivity)
@@ -533,15 +565,14 @@ otError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const Ip6:
// fall through
default:
- mLocal.Set(data.tlv);
+ mNetwork.Set(data.tlv);
break;
}
offset += sizeof(Tlv) + data.tlv.GetLength();
}
- mLocal.Store();
- mNetwork = mLocal;
+ mLocal.Set(mNetwork);
netif.GetNetworkDataLeader().IncrementVersion();
netif.GetNetworkDataLeader().IncrementStableVersion();
}
@@ -820,15 +851,12 @@ exit:
#endif // OPENTHREAD_FTD
void DatasetManager::SendGetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
- uint8_t *aTlvs, uint8_t aLength)
+ uint8_t *aTlvs, uint8_t aLength) const
{
ThreadNetif &netif = GetNetif();
- Tlv *tlv;
otError error = OT_ERROR_NONE;
Coap::Header responseHeader;
Message *message;
- uint8_t index;
-
responseHeader.SetDefaultResponseHeader(aRequestHeader);
responseHeader.SetPayloadMarker();
@@ -853,15 +881,17 @@ void DatasetManager::SendGetResponse(const Coap::Header &aRequestHeader, const I
}
else
{
- for (index = 0; index < aLength; index++)
+ for (uint8_t index = 0; index < aLength; index++)
{
+ const Tlv *tlv;
+
if (aTlvs[index] == Tlv::kNetworkMasterKey &&
!(netif.GetKeyManager().GetSecurityPolicyFlags() & OT_SECURITY_POLICY_OBTAIN_MASTER_KEY))
{
continue;
}
- if ((tlv = mNetwork.Get(static_cast(aTlvs[index]))) != NULL)
+ if ((tlv = mNetwork.Get(static_cast(aTlvs[index]))) != NULL)
{
SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength()));
}
@@ -909,31 +939,30 @@ otError ActiveDatasetBase::Restore(void)
{
otError error = OT_ERROR_NONE;
- SuccessOrExit(error = mLocal.Restore());
+ SuccessOrExit(error = DatasetManager::Restore());
SuccessOrExit(error = DatasetManager::ApplyConfiguration());
exit:
return error;
}
-otError ActiveDatasetBase::Clear(bool aOnlyClearNetwork)
+void ActiveDatasetBase::Clear(void)
{
- otError error = OT_ERROR_NONE;
- uint8_t flags;
+ DatasetManager::Clear();
+}
- SuccessOrExit(error = DatasetManager::Clear(flags, aOnlyClearNetwork));
-
-exit:
- return error;
+void ActiveDatasetBase::HandleDetach(void)
+{
+ DatasetManager::HandleDetach();
+ DatasetManager::ApplyConfiguration();
}
#if OPENTHREAD_FTD
otError ActiveDatasetBase::Set(const otOperationalDataset &aDataset)
{
otError error = OT_ERROR_NONE;
- uint8_t flags;
- SuccessOrExit(error = DatasetManager::Set(aDataset, flags));
+ SuccessOrExit(error = DatasetManager::Set(aDataset));
DatasetManager::ApplyConfiguration();
exit:
@@ -941,12 +970,11 @@ exit:
}
#endif // OPENTHREAD_FTD
-otError ActiveDatasetBase::Set(const Dataset &aDataset)
+void ActiveDatasetBase::Set(const Dataset &aDataset)
{
ThreadNetif &netif = GetNetif();
- otError error = OT_ERROR_NONE;
- SuccessOrExit(error = DatasetManager::Set(aDataset));
+ DatasetManager::Set(aDataset);
DatasetManager::ApplyConfiguration();
if (netif.GetMle().GetRole() == OT_DEVICE_ROLE_LEADER)
@@ -954,18 +982,14 @@ otError ActiveDatasetBase::Set(const Dataset &aDataset)
netif.GetNetworkDataLeader().IncrementVersion();
netif.GetNetworkDataLeader().IncrementStableVersion();
}
-
-exit:
- return error;
}
otError ActiveDatasetBase::Set(const Timestamp &aTimestamp, const Message &aMessage,
uint16_t aOffset, uint8_t aLength)
{
otError error = OT_ERROR_NONE;
- uint8_t flags;
- SuccessOrExit(error = DatasetManager::Set(aTimestamp, aMessage, aOffset, aLength, flags));
+ SuccessOrExit(error = DatasetManager::Set(aTimestamp, aMessage, aOffset, aLength));
DatasetManager::ApplyConfiguration();
exit:
@@ -1005,8 +1029,6 @@ PendingDatasetBase::PendingDatasetBase(ThreadNetif &aThreadNetif):
DatasetManager(aThreadNetif, Tlv::kPendingTimestamp, OT_URI_PATH_PENDING_SET, OT_URI_PATH_PENDING_GET,
&PendingDatasetBase::HandleTimer),
mDelayTimer(aThreadNetif.GetIp6().mTimerScheduler, &PendingDatasetBase::HandleDelayTimer, this),
- mLocalTime(0),
- mNetworkTime(0),
mResourceGet(OT_URI_PATH_PENDING_GET, &PendingDatasetBase::HandleGet, this)
{
aThreadNetif.GetCoap().AddResource(mResourceGet);
@@ -1014,129 +1036,69 @@ PendingDatasetBase::PendingDatasetBase(ThreadNetif &aThreadNetif):
otError PendingDatasetBase::Restore(void)
{
- otError error = OT_ERROR_NONE;
-
- SuccessOrExit(error = mLocal.Restore());
-
- ResetDelayTimer(kFlagLocalUpdated);
-
-exit:
- return error;
+ return DatasetManager::Restore();
}
-otError PendingDatasetBase::Clear(bool aOnlyClearNetwork)
+void PendingDatasetBase::Clear(void)
{
- otError error = OT_ERROR_NONE;
- uint8_t flags;
+ DatasetManager::Clear();
+ mDelayTimer.Stop();
+}
- SuccessOrExit(error = DatasetManager::Clear(flags, aOnlyClearNetwork));
- ResetDelayTimer(flags);
+void PendingDatasetBase::ClearNetwork(void)
+{
+ mNetwork.Clear();
+ mDelayTimer.Stop();
+}
-exit:
- return error;
+void PendingDatasetBase::HandleDetach(void)
+{
+ DatasetManager::HandleDetach();
+ StartDelayTimer();
}
#if OPENTHREAD_FTD
otError PendingDatasetBase::Set(const otOperationalDataset &aDataset)
{
otError error = OT_ERROR_NONE;
- uint8_t flags;
- SuccessOrExit(error = DatasetManager::Set(aDataset, flags));
- ResetDelayTimer(flags);
+ SuccessOrExit(error = DatasetManager::Set(aDataset));
+ StartDelayTimer();
exit:
return error;
}
#endif // OPENTHREAD_FTD
-otError PendingDatasetBase::Set(const Dataset &aDataset)
+void PendingDatasetBase::Set(const Dataset &aDataset)
{
- otError error = OT_ERROR_NONE;
-
- SuccessOrExit(error = DatasetManager::Set(aDataset));
- ResetDelayTimer(kFlagLocalUpdated | kFlagNetworkUpdated);
-
-exit:
- return error;
+ DatasetManager::Set(aDataset);
+ StartDelayTimer();
}
otError PendingDatasetBase::Set(const Timestamp &aTimestamp, const Message &aMessage,
uint16_t aOffset, uint8_t aLength)
{
otError error = OT_ERROR_NONE;
- uint8_t flags;
- SuccessOrExit(error = DatasetManager::Set(aTimestamp, aMessage, aOffset, aLength, flags));
- ResetDelayTimer(flags);
+ SuccessOrExit(error = DatasetManager::Set(aTimestamp, aMessage, aOffset, aLength));
+ StartDelayTimer();
exit:
return error;
}
-void PendingDatasetBase::ResetDelayTimer(uint8_t aFlags)
+void PendingDatasetBase::StartDelayTimer(void)
{
DelayTimerTlv *delayTimer;
- if (aFlags & kFlagLocalUpdated)
+ mDelayTimer.Stop();
+
+ if ((delayTimer = static_cast(mNetwork.Get(Tlv::kDelayTimer))) != NULL)
{
- mLocalTime = Timer::GetNow();
+ mDelayTimer.StartAt(mNetwork.GetUpdateTime(), delayTimer->GetDelayTimer());
+ otLogInfoMeshCoP(GetInstance(), "delay timer started");
}
-
- if (aFlags & kFlagNetworkUpdated)
- {
- mNetworkTime = Timer::GetNow();
- mDelayTimer.Stop();
-
- if ((delayTimer = static_cast(mNetwork.Get(Tlv::kDelayTimer))) != NULL)
- {
- if (delayTimer->GetDelayTimer() == 0)
- {
- HandleDelayTimer();
- }
- else
- {
- mDelayTimer.Start(delayTimer->GetDelayTimer());
- otLogInfoMeshCoP(GetInstance(), "delay timer started");
- }
- }
- }
-}
-
-void PendingDatasetBase::UpdateDelayTimer(void)
-{
- UpdateDelayTimer(mLocal, mLocalTime);
- UpdateDelayTimer(mNetwork, mNetworkTime);
-}
-
-void PendingDatasetBase::UpdateDelayTimer(Dataset &aDataset, uint32_t &aStartTime)
-{
- DelayTimerTlv *delayTimer;
- uint32_t now = Timer::GetNow();
- uint32_t elapsed;
- uint32_t delay;
-
- VerifyOrExit((delayTimer = static_cast(aDataset.Get(Tlv::kDelayTimer))) != NULL);
-
- elapsed = now - aStartTime;
-
- delay = delayTimer->GetDelayTimer();
-
- if (delay > elapsed)
- {
- delay -= elapsed;
- }
- else
- {
- delay = 0;
- }
-
- delayTimer->SetDelayTimer(delay);
-
- aStartTime = now;
-
-exit:
- return;
}
void PendingDatasetBase::HandleDelayTimer(Timer &aTimer)
@@ -1146,22 +1108,11 @@ void PendingDatasetBase::HandleDelayTimer(Timer &aTimer)
void PendingDatasetBase::HandleDelayTimer(void)
{
- DelayTimerTlv *delayTimer;
-
otLogInfoMeshCoP(GetInstance(), "pending delay timer expired");
- UpdateDelayTimer();
- delayTimer = static_cast(mNetwork.Get(Tlv::kDelayTimer));
- assert(delayTimer != NULL && delayTimer->GetDelayTimer() == 0);
-
GetNetif().GetActiveDataset().Set(mNetwork);
- Clear(false);
-}
-
-void PendingDatasetBase::HandleNetworkUpdate(uint8_t &aFlags)
-{
- DatasetManager::HandleNetworkUpdate(aFlags);
+ Clear();
}
void PendingDatasetBase::HandleGet(void *aContext, otCoapHeader *aHeader, otMessage *aMessage,
diff --git a/src/core/meshcop/dataset_manager.hpp b/src/core/meshcop/dataset_manager.hpp
index 9585f8b02..366a14f5c 100644
--- a/src/core/meshcop/dataset_manager.hpp
+++ b/src/core/meshcop/dataset_manager.hpp
@@ -41,6 +41,7 @@
#include "common/locator.hpp"
#include "common/timer.hpp"
#include "meshcop/dataset.hpp"
+#include "meshcop/dataset_local.hpp"
#include "net/udp6.hpp"
#include "thread/mle.hpp"
#include "thread/network_data_leader.hpp"
@@ -54,34 +55,154 @@ namespace MeshCoP {
class DatasetManager: public ThreadNetifLocator
{
public:
- Dataset &GetLocal(void) { return mLocal; }
+ /**
+ * This method returns a reference to the Timestamp.
+ *
+ * @returns A pointer to the Timestamp.
+ *
+ */
+ const Timestamp *GetTimestamp(void) const;
+
+ /**
+ * This method compares @p aTimestamp to the dataset's timestamp value.
+ *
+ * @param[in] aCompare A reference to the timestamp to compare.
+ *
+ * @retval -1 if @p aCompare is older than this dataset.
+ * @retval 0 if @p aCompare is equal to this dataset.
+ * @retval 1 if @p aCompare is newer than this dataset.
+ *
+ */
+ int Compare(const Timestamp &aTimestamp) const;
+
+ /**
+ * This method appends the MLE Dataset TLV but excluding MeshCoP Sub Timestamp TLV.
+ *
+ * @retval OT_ERROR_NONE Successfully append MLE Dataset TLV without MeshCoP Sub Timestamp TLV.
+ * @retval OT_ERROR_NO_BUFS Insufficient available buffers to append the message with MLE Dataset TLV.
+ *
+ */
+ otError AppendMleDatasetTlv(Message &aMessage) const;
+
+ /**
+ * This method returns a pointer to the TLV.
+ *
+ * @returns A pointer to the TLV or NULL if none is found.
+ *
+ */
+ const Tlv *GetTlv(Tlv::Type aType) const;
+
+ /**
+ * This method returns the Operational Dataset stored in non-volatile memory.
+ *
+ * @retval A reference to the Operational Dataset stored in non-volatile memory.
+ *
+ */
+ DatasetLocal &GetLocal(void) { return mLocal; }
+
+ /**
+ * This method returns the Operational Dataset for the attached partition.
+ *
+ * When not attached to a partition, the returned dataset is the one stored in non-volatile memory.
+ *
+ * @retval A reference to the Operational Dataset for the attached partition.
+ *
+ */
Dataset &GetNetwork(void) { return mNetwork; }
+ /**
+ * This method applies the Active or Pending Dataset to the Thread interface.
+ *
+ * @retval OT_ERROR_NONE Successfully applied configuration.
+ *
+ */
otError ApplyConfiguration(void);
protected:
- enum
- {
- kFlagLocalUpdated = 1 << 0,
- kFlagNetworkUpdated = 1 << 1,
- };
+ /**
+ * This constructor initializes the object.
+ *
+ * @param[in] aThreadNetif A reference to the Thread network interface.
+ * @param[in] aType Identifies Active or Pending Operational Dataset.
+ * @param[in] aUriSet The URI-PATH for setting the Operational Dataset.
+ * @param[in] aUriGet The URI-PATH for getting the Operational Dataset.
+ * @param[in] aTimerHandler The registration timer handler.
+ *
+ */
DatasetManager(ThreadNetif &aThreadNetif, const Tlv::Type aType, const char *aUriSet, const char *aUriGet,
Timer::Handler aTimerHander);
- otError Clear(uint8_t &aFlags, bool aOnlyClearNetwork);
+ /**
+ * This method restores the Operational Dataset from non-volatile memory.
+ *
+ * @retval OT_ERROR_NONE Successfully restore the dataset.
+ * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ *
+ */
+ otError Restore(void);
- otError Set(const Dataset &aDataset);
+ /**
+ * This method clears the Operational Dataset.
+ *
+ */
+ void Clear(void);
- otError Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength,
- uint8_t &aFlags);
+ /**
+ * This method updates the Operational Dataset when detaching from the network.
+ *
+ * On detach, the Operational Dataset is restored from non-volatile memory.
+ *
+ */
+ void HandleDetach(void);
- void Get(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ /**
+ * This method sets the Operational Dataset in non-volatile memory.
+ *
+ * @param[in] aDataset The Operational Dataset.
+ *
+ */
+ void Set(const Dataset &aDataset);
- void HandleNetworkUpdate(uint8_t &aFlags);
+ /**
+ * This method sets the Operational Dataset for the partition.
+ *
+ * This method also updates the non-volatile version if the partition's Operational Dataset is newer.
+ *
+ * @param[in] aTimestamp The timestamp for the Operational Dataset.
+ * @param[in] aMessage The message buffer.
+ * @param[in] aOffset The offset where the Operational Dataset begins.
+ * @param[in] aLength The length of the Operational Dataset.
+ *
+ */
+ otError Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
+
+ /**
+ * This method handles a MGMT_GET request message.
+ *
+ * @param[in] aHeader The CoAP header.
+ * @param[in] aMessage The CoAP message buffer.
+ * @parma[in] aMessageInfo The message info.
+ *
+ */
+ void Get(const Coap::Header &aHeader, const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const;
+
+ /**
+ * This method compares the partition's Operational Dataset with that stored in non-volatile memory.
+ *
+ * If the partition's Operational Dataset is newer, the non-volatile storage is updated.
+ * If the partition's Operational Dataset is older, the registration process is started.
+ *
+ */
+ void HandleNetworkUpdate(void);
+
+ /**
+ * This method initiates a network data registration message with the Leader.
+ *
+ */
void HandleTimer(void);
- Dataset mLocal;
+ DatasetLocal mLocal;
Dataset mNetwork;
private:
@@ -90,7 +211,8 @@ private:
otError Register(void);
void SendGetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
- uint8_t *aTlvs, uint8_t aLength);
+ uint8_t *aTlvs, uint8_t aLength) const;
+
Timer mTimer;
const char *mUriSet;
@@ -98,11 +220,50 @@ private:
#if OPENTHREAD_FTD
public:
+ /**
+ * This method sends a MGMT_SET request to the Leader.
+ *
+ * @parma[in] aDataset The Operational Datset.
+ * @param[in] aTlvs Any additional raw TLVs to include.
+ * @param[in] aLength Number of bytes in @p aTlvs.
+ *
+ * @retval OT_ERROR_NONE on success.
+ *
+ */
otError SendSetRequest(const otOperationalDataset &aDataset, const uint8_t *aTlvs, uint8_t aLength);
+
+ /**
+ * This method sends a MGMT_GET request.
+ *
+ * @param[in] aTlvTypes The list of TLV types to request.
+ * @param[in] aLength Number of bytes in @p aTlvTypes.
+ * @parma[in] aAddress The IPv6 destination address for the MGMT_GET request.
+ *
+ * @retval OT_ERROR_NONE on success.
+ *
+ */
otError SendGetRequest(const uint8_t *aTlvTypes, uint8_t aLength, const otIp6Address *aAddress);
protected:
- otError Set(const otOperationalDataset &aDataset, uint8_t &aFlags);
+ /**
+ * This method sets the Operational Dataset in non-volatile memory.
+ *
+ * @parma[in] aDataset The Operational Dataset.
+ *
+ */
+ otError Set(const otOperationalDataset &aDataset);
+
+ /**
+ * This method handles the MGMT_SET request message.
+ *
+ * @param[in] aHeader The CoAP header.
+ * @param[in] aMessage The CoAP message buffer.
+ * @parma[in] aMessageInfo The message info.
+ *
+ * @retval OT_ERROR_NONE The MGMT_SET request message was handled successfully.
+ * @retval OT_ERROR_DROP The MGMT_SET request message was dropped.
+ *
+ */
otError Set(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
private:
@@ -113,18 +274,72 @@ private:
class ActiveDatasetBase: public DatasetManager
{
public:
+ /**
+ * Constructor.
+ *
+ * @param[in] aThreadNetif The Thread network interface.
+ *
+ */
ActiveDatasetBase(ThreadNetif &aThreadNetif);
+ /**
+ * This method restores the Active Operational Dataset from non-volatile memory.
+ *
+ * This method will also configure the Thread interface using the Active Operational Dataset.
+ *
+ * @retval OT_ERROR_NONE Successfully restore the dataset.
+ * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ *
+ */
otError Restore(void);
- otError Clear(bool aOnlyClearNetwork);
+ /**
+ * This method clears the Active Operational Dataset.
+ *
+ */
+ void Clear(void);
+
+ /**
+ * This method updates the Operational Dataset when detaching from the network.
+ *
+ * On detach, the Operational Dataset is restored from non-volatile memory and reconfigures the Thread
+ * interface.
+ *
+ */
+ void HandleDetach(void);
#if OPENTHREAD_FTD
+ /**
+ * This method sets the Operational Dataset in non-volatile memory.
+ *
+ * @parma[in] aDataset The Operational Dataset.
+ *
+ */
otError Set(const otOperationalDataset &aDataset);
#endif
- otError Set(const Dataset &aDataset);
+ /**
+ * This method sets the Operational Dataset in non-volatile memory.
+ *
+ * This method also reconfigures the Thread interface.
+ *
+ * @param[in] aDataset The Operational Dataset.
+ *
+ */
+ void Set(const Dataset &aDataset);
+ /**
+ * This method sets the Operational Dataset for the partition.
+ *
+ * This method also reconfigures the Thread interface.
+ * This method also updates the non-volatile version if the partition's Operational Dataset is newer.
+ *
+ * @param[in] aTimestamp The timestamp for the Operational Dataset.
+ * @param[in] aMessage The message buffer.
+ * @param[in] aOffset The offset where the Operational Dataset begins.
+ * @param[in] aLength The length of the Operational Dataset.
+ *
+ */
otError Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
private:
@@ -141,34 +356,93 @@ private:
class PendingDatasetBase: public DatasetManager
{
public:
+ /**
+ * Constructor.
+ *
+ * @param[in] The Thread network interface.
+ *
+ */
PendingDatasetBase(ThreadNetif &aThreadNetif);
+ /**
+ * This method restores the Operational Dataset from non-volatile memory.
+ *
+ * @retval OT_ERROR_NONE Successfully restore the dataset.
+ * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ *
+ */
otError Restore(void);
- otError Clear(bool aOnlyClearNetwork);
+ /**
+ * This method clears the Pending Operational Dataset.
+ *
+ * This method also stops the Delay Timer if it was active.
+ *
+ */
+ void Clear(void);
+
+ /**
+ * This method clears the network Pending Operational Dataset.
+ *
+ * This method also stops the Delay Timer if it was active.
+ *
+ */
+ void ClearNetwork(void);
+
+ /**
+ * This method updates the Operational Dataset when detaching from the network.
+ *
+ * On detach, the Operational Dataset is restored from non-volatile memory.
+ *
+ * This method also stops the Delay Timer if it was active.
+ *
+ */
+ void HandleDetach(void);
#if OPENTHREAD_FTD
+ /**
+ * This method sets the Operational Dataset in non-volatile memory.
+ *
+ * This method also starts the Delay Timer.
+ *
+ * @parma[in] aDataset The Operational Dataset.
+ *
+ */
otError Set(const otOperationalDataset &aDataset);
#endif
- otError Set(const Dataset &aDataset);
+ /**
+ * This method sets the Operational Dataset in non-volatile memory.
+ *
+ * This method also starts the Delay Timer.
+ *
+ * @param[in] aDataset The Operational Dataset.
+ *
+ */
+ void Set(const Dataset &aDataset);
+ /**
+ * This method sets the Operational Dataset for the partition.
+ *
+ * This method also updates the non-volatile version if the partition's Operational Dataset is newer.
+ *
+ * This method also starts the Delay Timer.
+ *
+ * @param[in] aTimestamp The timestamp for the Operational Dataset.
+ * @param[in] aMessage The message buffer.
+ * @param[in] aOffset The offset where the Operational Dataset begins.
+ * @param[in] aLength The length of the Operational Dataset.
+ *
+ */
otError Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
- void UpdateDelayTimer(void);
-
protected:
static void HandleDelayTimer(Timer &aTimer);
void HandleDelayTimer(void);
-
- void ResetDelayTimer(uint8_t aFlags);
- void UpdateDelayTimer(Dataset &aDataset, uint32_t &aStartTime);
-
- void HandleNetworkUpdate(uint8_t &aFlags);
+ void StartDelayTimer(void);
+ void HandleNetworkUpdate(void);
Timer mDelayTimer;
- uint32_t mLocalTime;
- uint32_t mNetworkTime;
private:
static void HandleGet(void *aContext, otCoapHeader *aHeader, otMessage *aMessage,
diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp
index 12a27b816..a54ca0bcb 100644
--- a/src/core/meshcop/dataset_manager_ftd.cpp
+++ b/src/core/meshcop/dataset_manager_ftd.cpp
@@ -34,7 +34,7 @@
#if OPENTHREAD_FTD
-#define WPP_NAME "dataset_manager.tmh"
+#define WPP_NAME "dataset_manager_ftd.tmh"
#include
@@ -67,114 +67,113 @@ ActiveDataset::ActiveDataset(ThreadNetif &aThreadNetif):
{
}
-bool ActiveDataset::IsTlvInitialized(Tlv::Type aType)
-{
- return mLocal.Get(aType) != NULL;
-}
-
otError ActiveDataset::GenerateLocal(void)
{
ThreadNetif &netif = GetNetif();
otError error = OT_ERROR_NONE;
- otOperationalDataset dataset;
+ Dataset dataset(mLocal.GetType());
VerifyOrExit(netif.GetMle().IsAttached(), error = OT_ERROR_INVALID_STATE);
- memset(&dataset, 0, sizeof(dataset));
+ mLocal.Get(dataset);
// Active Timestamp
- if (!IsTlvInitialized(Tlv::kActiveTimestamp))
+ if (dataset.Get(Tlv::kActiveTimestamp) == NULL)
{
ActiveTimestampTlv activeTimestampTlv;
activeTimestampTlv.Init();
activeTimestampTlv.SetSeconds(0);
activeTimestampTlv.SetTicks(0);
- mLocal.Set(activeTimestampTlv);
+ dataset.Set(activeTimestampTlv);
}
// Channel
- if (!IsTlvInitialized(Tlv::kChannel))
+ if (dataset.Get(Tlv::kChannel) == NULL)
{
ChannelTlv tlv;
tlv.Init();
tlv.SetChannelPage(0);
tlv.SetChannel(netif.GetMac().GetChannel());
- mLocal.Set(tlv);
+ dataset.Set(tlv);
}
// channelMask
- if (!IsTlvInitialized(Tlv::kChannelMask))
+ if (dataset.Get(Tlv::kChannelMask) == NULL)
{
ChannelMask0Tlv tlv;
tlv.Init();
tlv.SetMask(OT_RADIO_SUPPORTED_CHANNELS);
- mLocal.Set(tlv);
+ dataset.Set(tlv);
}
// Extended PAN ID
- if (!IsTlvInitialized(Tlv::kExtendedPanId))
+ if (dataset.Get(Tlv::kExtendedPanId) == NULL)
{
ExtendedPanIdTlv tlv;
tlv.Init();
tlv.SetExtendedPanId(netif.GetMac().GetExtendedPanId());
- mLocal.Set(tlv);
+ dataset.Set(tlv);
}
// Mesh-Local Prefix
- if (!IsTlvInitialized(Tlv::kMeshLocalPrefix))
+ if (dataset.Get(Tlv::kMeshLocalPrefix) == NULL)
{
MeshLocalPrefixTlv tlv;
tlv.Init();
tlv.SetMeshLocalPrefix(netif.GetMle().GetMeshLocalPrefix());
- mLocal.Set(tlv);
+ dataset.Set(tlv);
}
// Master Key
- if (!IsTlvInitialized(Tlv::kNetworkMasterKey))
+ if (dataset.Get(Tlv::kNetworkMasterKey) == NULL)
{
NetworkMasterKeyTlv tlv;
tlv.Init();
tlv.SetNetworkMasterKey(netif.GetKeyManager().GetMasterKey());
- mLocal.Set(tlv);
+ dataset.Set(tlv);
}
// Network Name
- if (!IsTlvInitialized(Tlv::kNetworkName))
+ if (dataset.Get(Tlv::kNetworkName) == NULL)
{
NetworkNameTlv tlv;
tlv.Init();
tlv.SetNetworkName(netif.GetMac().GetNetworkName());
- mLocal.Set(tlv);
+ dataset.Set(tlv);
}
// Pan ID
- if (!IsTlvInitialized(Tlv::kPanId))
+ if (dataset.Get(Tlv::kPanId) == NULL)
{
PanIdTlv tlv;
tlv.Init();
tlv.SetPanId(netif.GetMac().GetPanId());
- mLocal.Set(tlv);
+ dataset.Set(tlv);
}
// PSKc
- if (!IsTlvInitialized(Tlv::kPSKc))
+ if (dataset.Get(Tlv::kPSKc) == NULL)
{
PSKcTlv tlv;
tlv.Init();
tlv.SetPSKc(netif.GetKeyManager().GetPSKc());
- mLocal.Set(tlv);
+ dataset.Set(tlv);
}
// Security Policy
- if (!IsTlvInitialized(Tlv::kSecurityPolicy))
+ if (dataset.Get(Tlv::kSecurityPolicy) == NULL)
{
SecurityPolicyTlv tlv;
tlv.Init();
tlv.SetRotationTime(static_cast(netif.GetKeyManager().GetKeyRotation()));
tlv.SetFlags(netif.GetKeyManager().GetSecurityPolicyFlags());
- mLocal.Set(tlv);
+ dataset.Set(tlv);
}
+ SuccessOrExit(error = mLocal.Set(dataset));
+
+ otLogInfoMeshCoP(GetInstance(), "Generated local dataset");
+
exit:
return error;
}
@@ -183,8 +182,7 @@ void ActiveDataset::StartLeader(void)
{
GenerateLocal();
- mLocal.Store();
- mNetwork = mLocal;
+ mLocal.Get(mNetwork);
GetNetif().GetCoap().AddResource(mResourceSet);
}
@@ -218,10 +216,8 @@ PendingDataset::PendingDataset(ThreadNetif &aThreadNetif):
void PendingDataset::StartLeader(void)
{
- UpdateDelayTimer(mLocal, mLocalTime);
- mLocal.Store();
- mNetwork = mLocal;
- ResetDelayTimer(kFlagNetworkUpdated);
+ mLocal.Get(mNetwork);
+ StartDelayTimer();
GetNetif().GetCoap().AddResource(mResourceSet);
}
@@ -242,7 +238,7 @@ void PendingDataset::HandleSet(void *aContext, otCoapHeader *aHeader, otMessage
void PendingDataset::HandleSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
SuccessOrExit(DatasetManager::Set(aHeader, aMessage, aMessageInfo));
- ResetDelayTimer(kFlagLocalUpdated | kFlagNetworkUpdated);
+ StartDelayTimer();
exit:
return;
@@ -253,7 +249,6 @@ void PendingDataset::ApplyActiveDataset(const Timestamp &aTimestamp, Message &aM
ThreadNetif &netif = GetNetif();
uint16_t offset = aMessage.GetOffset();
DelayTimerTlv delayTimer;
- uint8_t flags;
VerifyOrExit(netif.GetMle().IsAttached());
@@ -279,10 +274,10 @@ void PendingDataset::ApplyActiveDataset(const Timestamp &aTimestamp, Message &aM
// add pending timestamp tlv
mNetwork.SetTimestamp(aTimestamp);
- HandleNetworkUpdate(flags);
+ DatasetManager::HandleNetworkUpdate();
// reset delay timer
- ResetDelayTimer(kFlagNetworkUpdated);
+ StartDelayTimer();
exit:
return;
diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp
index 2222dee6e..a7790e411 100644
--- a/src/core/meshcop/joiner_router.cpp
+++ b/src/core/meshcop/joiner_router.cpp
@@ -327,7 +327,7 @@ otError JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessage
ExtendedPanIdTlv extendedPanId;
NetworkNameTlv networkName;
NetworkKeySequenceTlv networkKeySequence;
- Tlv *tlv;
+ const Tlv *tlv;
DelayedJoinEntHeader delayedMessage;
@@ -356,7 +356,7 @@ otError JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessage
networkName.SetNetworkName(netif.GetMac().GetNetworkName());
SuccessOrExit(error = message->Append(&networkName, sizeof(Tlv) + networkName.GetLength()));
- if ((tlv = netif.GetActiveDataset().GetNetwork().Get(Tlv::kActiveTimestamp)) != NULL)
+ if ((tlv = netif.GetActiveDataset().GetTlv(Tlv::kActiveTimestamp)) != NULL)
{
SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength()));
}
@@ -367,7 +367,7 @@ otError JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessage
SuccessOrExit(error = message->Append(&activeTimestamp, sizeof(activeTimestamp)));
}
- if ((tlv = netif.GetActiveDataset().GetNetwork().Get(Tlv::kChannelMask)) != NULL)
+ if ((tlv = netif.GetActiveDataset().GetTlv(Tlv::kChannelMask)) != NULL)
{
SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength()));
}
@@ -378,7 +378,7 @@ otError JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessage
SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask)));
}
- if ((tlv = netif.GetActiveDataset().GetNetwork().Get(Tlv::kPSKc)) != NULL)
+ if ((tlv = netif.GetActiveDataset().GetTlv(Tlv::kPSKc)) != NULL)
{
SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength()));
}
@@ -389,7 +389,7 @@ otError JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessage
SuccessOrExit(error = message->Append(&pskc, sizeof(pskc)));
}
- if ((tlv = netif.GetActiveDataset().GetNetwork().Get(Tlv::kSecurityPolicy)) != NULL)
+ if ((tlv = netif.GetActiveDataset().GetTlv(Tlv::kSecurityPolicy)) != NULL)
{
SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength()));
}
diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp
index edf7b5b29..68073cc85 100644
--- a/src/core/thread/mle.cpp
+++ b/src/core/thread/mle.cpp
@@ -260,8 +260,8 @@ otError Mle::Stop(bool aClearNetworkDatasets)
if (aClearNetworkDatasets)
{
- netif.GetActiveDataset().Clear(true);
- netif.GetPendingDataset().Clear(true);
+ netif.GetActiveDataset().HandleDetach();
+ netif.GetPendingDataset().HandleDetach();
}
mRole = OT_DEVICE_ROLE_DISABLED;
@@ -353,10 +353,9 @@ otError Mle::Store(void)
VerifyOrExit(IsAttached(), error = OT_ERROR_INVALID_STATE);
- if (netif.GetActiveDataset().GetLocal().GetTimestamp() == NULL)
+ if (netif.GetActiveDataset().GetTimestamp() == NULL)
{
netif.GetActiveDataset().GenerateLocal();
- netif.GetActiveDataset().GetLocal().Store();
}
memset(&networkInfo, 0, sizeof(networkInfo));
@@ -475,11 +474,7 @@ otError Mle::BecomeDetached(void)
VerifyOrExit(mRole != OT_DEVICE_ROLE_DISABLED, error = OT_ERROR_INVALID_STATE);
- if (mReattachState == kReattachStop)
- {
- netif.GetPendingDataset().UpdateDelayTimer();
- netif.GetPendingDataset().Set(netif.GetPendingDataset().GetLocal());
- }
+ netif.GetPendingDataset().HandleDetach();
SetStateDetached();
SetRloc16(Mac::kShortAddrInvalid);
@@ -1201,18 +1196,14 @@ exit:
return error;
}
-otError Mle::AppendActiveTimestamp(Message &aMessage, bool aCouldUseLocal)
+otError Mle::AppendActiveTimestamp(Message &aMessage)
{
ThreadNetif &netif = GetNetif();
otError error;
ActiveTimestampTlv timestampTlv;
const MeshCoP::Timestamp *timestamp;
- if ((timestamp = netif.GetActiveDataset().GetNetwork().GetTimestamp()) == NULL && aCouldUseLocal)
- {
- timestamp = netif.GetActiveDataset().GetLocal().GetTimestamp();
- }
-
+ timestamp = netif.GetActiveDataset().GetTimestamp();
VerifyOrExit(timestamp, error = OT_ERROR_NONE);
timestampTlv.Init();
@@ -1229,7 +1220,7 @@ otError Mle::AppendPendingTimestamp(Message &aMessage)
PendingTimestampTlv timestampTlv;
const MeshCoP::Timestamp *timestamp;
- timestamp = GetNetif().GetPendingDataset().GetNetwork().GetTimestamp();
+ timestamp = GetNetif().GetPendingDataset().GetTimestamp();
VerifyOrExit(timestamp && timestamp->GetSeconds() != 0, error = OT_ERROR_NONE);
timestampTlv.Init();
@@ -1376,7 +1367,6 @@ void Mle::HandleParentRequestTimer(void)
{
mReattachState = kReattachStop;
netif.GetActiveDataset().Restore();
- netif.GetPendingDataset().Set(netif.GetPendingDataset().GetLocal());
}
if (mReattachState == kReattachStop)
@@ -1602,7 +1592,7 @@ otError Mle::SendChildIdRequest(void)
}
SuccessOrExit(error = AppendTlvRequest(*message, tlvs, sizeof(tlvs)));
- SuccessOrExit(error = AppendActiveTimestamp(*message, true));
+ SuccessOrExit(error = AppendActiveTimestamp(*message));
SuccessOrExit(error = AppendPendingTimestamp(*message));
memset(&destination, 0, sizeof(destination));
@@ -1636,7 +1626,7 @@ otError Mle::SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aT
VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS);
SuccessOrExit(error = AppendHeader(*message, Header::kCommandDataRequest));
SuccessOrExit(error = AppendTlvRequest(*message, aTlvs, aTlvsLength));
- SuccessOrExit(error = AppendActiveTimestamp(*message, false));
+ SuccessOrExit(error = AppendActiveTimestamp(*message));
SuccessOrExit(error = AppendPendingTimestamp(*message));
if (aDelay)
@@ -1853,7 +1843,7 @@ otError Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce)
}
else
{
- SuccessOrExit(error = AppendActiveTimestamp(*message, false));
+ SuccessOrExit(error = AppendActiveTimestamp(*message));
}
panid.Init();
@@ -1879,11 +1869,11 @@ exit:
void Mle::SendOrphanAnnounce(void)
{
- MeshCoP::ChannelMask0Tlv *channelMask;
+ const MeshCoP::ChannelMask0Tlv *channelMask;
uint8_t channel;
- channelMask = static_cast(GetNetif().GetActiveDataset().GetNetwork().Get(
- MeshCoP::Tlv::kChannelMask));
+ channelMask = static_cast(GetNetif().GetActiveDataset().GetTlv(
+ MeshCoP::Tlv::kChannelMask));
VerifyOrExit(channelMask != NULL);
@@ -2432,7 +2422,7 @@ otError Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &a
const MeshCoP::Timestamp *timestamp;
VerifyOrExit(activeTimestamp.IsValid(), error = OT_ERROR_PARSE);
- timestamp = netif.GetActiveDataset().GetNetwork().GetTimestamp();
+ timestamp = netif.GetActiveDataset().GetTimestamp();
// if received timestamp does not match the local value and message does not contain the dataset,
// send MLE Data Request
@@ -2453,7 +2443,7 @@ otError Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &a
const MeshCoP::Timestamp *timestamp;
VerifyOrExit(pendingTimestamp.IsValid(), error = OT_ERROR_PARSE);
- timestamp = netif.GetPendingDataset().GetNetwork().GetTimestamp();
+ timestamp = netif.GetPendingDataset().GetTimestamp();
// if received timestamp does not match the local value and message does not contain the dataset,
// send MLE Data Request
@@ -2491,10 +2481,6 @@ otError Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &a
tlv.GetLength());
}
}
- else
- {
- netif.GetActiveDataset().Clear(false);
- }
// Pending Dataset
if (pendingTimestamp.GetLength() > 0)
@@ -2506,10 +2492,6 @@ otError Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &a
tlv.GetLength());
}
}
- else
- {
- netif.GetPendingDataset().Clear(false);
- }
mRetrieveNewNetworkData = false;
@@ -2768,17 +2750,12 @@ otError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::MessageIn
aMessage.Read(offset, sizeof(tlv), &tlv);
netif.GetActiveDataset().Set(activeTimestamp, aMessage, offset + sizeof(tlv), tlv.GetLength());
}
- else if (netif.GetActiveDataset().GetNetwork().GetTimestamp() == NULL &&
- netif.GetActiveDataset().GetLocal().GetTimestamp() != NULL)
- {
- netif.GetActiveDataset().Set(netif.GetActiveDataset().GetLocal());
- }
}
- // clear local Pending Dataset if device succeed to reattach using stored Pending Dataset
+ // clear Pending Dataset if device succeed to reattach using stored Pending Dataset
if (mReattachState == kReattachPending)
{
- netif.GetPendingDataset().GetLocal().Clear(true);
+ netif.GetPendingDataset().Clear();
}
// Pending Timestamp
@@ -2795,7 +2772,7 @@ otError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::MessageIn
}
else
{
- netif.GetPendingDataset().Clear(true);
+ netif.GetPendingDataset().ClearNetwork();
}
// Parent Attach Success
@@ -3054,7 +3031,7 @@ otError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMe
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kPanId, sizeof(panid), panid));
VerifyOrExit(panid.IsValid(), error = OT_ERROR_PARSE);
- localTimestamp = netif.GetActiveDataset().GetNetwork().GetTimestamp();
+ localTimestamp = netif.GetActiveDataset().GetTimestamp();
if (localTimestamp == NULL || localTimestamp->Compare(timestamp) > 0)
{
diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp
index 650d62cd7..43dec0c8f 100644
--- a/src/core/thread/mle.hpp
+++ b/src/core/thread/mle.hpp
@@ -1120,14 +1120,12 @@ protected:
* This method appends a Active Timestamp TLV to a message.
*
* @param[in] aMessage A reference to the message.
- * @param[in] aCouldUseLocal True to use local Active Timestamp when network Active Timestamp is not available,
- * False not.
*
* @retval OT_ERROR_NONE Successfully appended the Active Timestamp TLV.
* @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Active Timestamp TLV.
*
*/
- otError AppendActiveTimestamp(Message &aMessage, bool aCouldUseLocal);
+ otError AppendActiveTimestamp(Message &aMessage);
/**
* This method appends a Pending Timestamp TLV to a message.
diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp
index 8279ee2e9..46c21f507 100644
--- a/src/core/thread/mle_router.cpp
+++ b/src/core/thread/mle_router.cpp
@@ -2191,15 +2191,13 @@ otError MleRouter::HandleChildIdRequest(const Message &aMessage, const Ip6::Mess
}
if (activeTimestamp.GetLength() == 0 ||
- netif.GetActiveDataset().GetNetwork().GetTimestamp() == NULL ||
- netif.GetActiveDataset().GetNetwork().GetTimestamp()->Compare(activeTimestamp) != 0)
+ netif.GetActiveDataset().Compare(activeTimestamp) != 0)
{
child->SetRequestTlv(numTlvs++, Tlv::kActiveDataset);
}
if (pendingTimestamp.GetLength() == 0 ||
- netif.GetPendingDataset().GetNetwork().GetTimestamp() == NULL ||
- netif.GetPendingDataset().GetNetwork().GetTimestamp()->Compare(pendingTimestamp) != 0)
+ netif.GetPendingDataset().Compare(pendingTimestamp) != 0)
{
child->SetRequestTlv(numTlvs++, Tlv::kPendingDataset);
}
@@ -2465,15 +2463,13 @@ otError MleRouter::HandleDataRequest(const Message &aMessage, const Ip6::Message
numTlvs = tlvRequest.GetLength();
if (activeTimestamp.GetLength() == 0 ||
- netif.GetActiveDataset().GetNetwork().GetTimestamp() == NULL ||
- netif.GetActiveDataset().GetNetwork().GetTimestamp()->Compare(activeTimestamp) != 0)
+ netif.GetActiveDataset().Compare(activeTimestamp))
{
tlvs[numTlvs++] = Tlv::kActiveDataset;
}
if (pendingTimestamp.GetLength() == 0 ||
- netif.GetPendingDataset().GetNetwork().GetTimestamp() == NULL ||
- netif.GetPendingDataset().GetNetwork().GetTimestamp()->Compare(pendingTimestamp) != 0)
+ netif.GetPendingDataset().Compare(pendingTimestamp))
{
tlvs[numTlvs++] = Tlv::kPendingDataset;
}
@@ -2747,7 +2743,7 @@ otError MleRouter::SendChildIdResponse(Child *aChild)
SuccessOrExit(error = AppendHeader(*message, Header::kCommandChildIdResponse));
SuccessOrExit(error = AppendSourceAddress(*message));
SuccessOrExit(error = AppendLeaderData(*message));
- SuccessOrExit(error = AppendActiveTimestamp(*message, false));
+ SuccessOrExit(error = AppendActiveTimestamp(*message));
SuccessOrExit(error = AppendPendingTimestamp(*message));
if (aChild->GetState() != Neighbor::kStateValid)
@@ -2852,7 +2848,7 @@ otError MleRouter::SendChildUpdateRequest(Child *aChild)
SuccessOrExit(error = AppendSourceAddress(*message));
SuccessOrExit(error = AppendLeaderData(*message));
SuccessOrExit(error = AppendNetworkData(*message, !aChild->IsFullNetworkData()));
- SuccessOrExit(error = AppendActiveTimestamp(*message, false));
+ SuccessOrExit(error = AppendActiveTimestamp(*message));
SuccessOrExit(error = AppendPendingTimestamp(*message));
SuccessOrExit(error = AppendTlvRequest(*message, tlvs, sizeof(tlvs)));
@@ -2915,7 +2911,7 @@ otError MleRouter::SendChildUpdateResponse(Child *aChild, const Ip6::MessageInfo
case Tlv::kNetworkData:
SuccessOrExit(error = AppendNetworkData(*message, !aChild->IsFullNetworkData()));
- SuccessOrExit(error = AppendActiveTimestamp(*message, false));
+ SuccessOrExit(error = AppendActiveTimestamp(*message));
SuccessOrExit(error = AppendPendingTimestamp(*message));
break;
@@ -2967,7 +2963,7 @@ otError MleRouter::SendDataResponse(const Ip6::Address &aDestination, const uint
SuccessOrExit(error = AppendHeader(*message, Header::kCommandDataResponse));
SuccessOrExit(error = AppendSourceAddress(*message));
SuccessOrExit(error = AppendLeaderData(*message));
- SuccessOrExit(error = AppendActiveTimestamp(*message, false));
+ SuccessOrExit(error = AppendActiveTimestamp(*message));
SuccessOrExit(error = AppendPendingTimestamp(*message));
for (int i = 0; i < aTlvsLength; i++)
@@ -4497,29 +4493,12 @@ exit:
otError MleRouter::AppendActiveDataset(Message &aMessage)
{
- ThreadNetif &netif = GetNetif();
- otError error = OT_ERROR_NONE;
-
- VerifyOrExit(netif.GetActiveDataset().GetNetwork().GetSize() > 0);
-
- SuccessOrExit(error = netif.GetActiveDataset().GetNetwork().AppendMleDatasetTlv(aMessage));
-
-exit:
- return error;
+ return GetNetif().GetActiveDataset().AppendMleDatasetTlv(aMessage);
}
otError MleRouter::AppendPendingDataset(Message &aMessage)
{
- ThreadNetif &netif = GetNetif();
- otError error = OT_ERROR_NONE;
-
- VerifyOrExit(netif.GetPendingDataset().GetNetwork().GetSize() > 0);
-
- netif.GetPendingDataset().UpdateDelayTimer();
- SuccessOrExit(error = netif.GetPendingDataset().GetNetwork().AppendMleDatasetTlv(aMessage));
-
-exit:
- return error;
+ return GetNetif().GetPendingDataset().AppendMleDatasetTlv(aMessage);
}
bool MleRouter::HasMinDowngradeNeighborRouters(void)
diff --git a/tests/scripts/thread-cert/Cert_9_2_08_PersistentDatasets.py b/tests/scripts/thread-cert/Cert_9_2_08_PersistentDatasets.py
index a1a3d3a1a..91a29770f 100755
--- a/tests/scripts/thread-cert/Cert_9_2_08_PersistentDatasets.py
+++ b/tests/scripts/thread-cert/Cert_9_2_08_PersistentDatasets.py
@@ -45,7 +45,7 @@ LEADER_ACTIVE_TIMESTAMP = 10
COMMISSIONER_PENDING_CHANNEL = 20
COMMISSIONER_PENDING_PANID = 0xafce
-class Cert_9_2_8_DelayTimer(unittest.TestCase):
+class Cert_9_2_8_PersistentDatasets(unittest.TestCase):
def setUp(self):
self.nodes = {}
for i in range(1,6):
@@ -129,11 +129,8 @@ class Cert_9_2_8_DelayTimer(unittest.TestCase):
time.sleep(5)
self.nodes[ROUTER].reset()
- self._setUpRouter()
self.nodes[ED].reset()
- self._setUpEd()
self.nodes[SED].reset()
- self._setUpSed()
time.sleep(60)
@@ -143,8 +140,15 @@ class Cert_9_2_8_DelayTimer(unittest.TestCase):
self.assertEqual(self.nodes[LEADER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
self.assertEqual(self.nodes[COMMISSIONER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
+ # reset the devices here again to simulate the fact that the devices were disabled the entire time
+ self.nodes[ROUTER].reset()
+ self._setUpRouter()
self.nodes[ROUTER].start()
+ self.nodes[ED].reset()
+ self._setUpEd()
self.nodes[ED].start()
+ self.nodes[SED].reset()
+ self._setUpSed()
self.nodes[SED].start()
self.assertEqual(self.nodes[ROUTER].get_panid(), PANID_INIT)