mirror of
https://github.com/espressif/openthread.git
synced 2026-08-26 12:11:17 +00:00
Remove RAM buffers for local operational datasets. (#1929)
The local Active and Pending Operational Datsets are stored in non-volatile memory. This commit dynamically retrieves those datasets from non-volatile memory when they are needed. This commit also simplifies the use of the Operational Datasets by having the RAM buffer store the local Operational Dataset when in the detached state.
This commit is contained in:
@@ -96,6 +96,7 @@
|
||||
<ClCompile Include="..\..\src\core\meshcop\announce_begin_client.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\commissioner.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_local.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_manager.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_manager_ftd.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dtls.cpp" />
|
||||
@@ -177,6 +178,7 @@
|
||||
<ClInclude Include="..\..\src\core\meshcop\announce_begin_client.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\commissioner.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset_local.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset_manager.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dtls.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\energy_scan_client.hpp" />
|
||||
|
||||
@@ -249,6 +249,9 @@
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset.cpp">
|
||||
<Filter>Source Files\thread</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_local.cpp">
|
||||
<Filter>Source Files\thread</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_manager.cpp">
|
||||
<Filter>Source Files\thread</Filter>
|
||||
</ClCompile>
|
||||
@@ -509,6 +512,9 @@
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset.hpp">
|
||||
<Filter>Header Files\thread</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset_local.hpp">
|
||||
<Filter>Header Files\thread</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset_manager.hpp">
|
||||
<Filter>Header Files\thread</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
<ClCompile Include="..\..\src\core\mac\mac_whitelist.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\commissioner.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_local.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_manager.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_manager_ftd.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dtls.cpp" />
|
||||
@@ -209,6 +210,7 @@
|
||||
<ClInclude Include="..\..\src\core\meshcop\announce_begin_client.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\commissioner.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset_local.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset_manager.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dtls.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\energy_scan_client.hpp" />
|
||||
|
||||
@@ -252,6 +252,9 @@
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset.cpp">
|
||||
<Filter>Source Files\thread</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_local.cpp">
|
||||
<Filter>Source Files\thread</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\meshcop\dataset_manager.cpp">
|
||||
<Filter>Source Files\thread</Filter>
|
||||
</ClCompile>
|
||||
@@ -509,6 +512,9 @@
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset.hpp">
|
||||
<Filter>Header Files\thread</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset_local.hpp">
|
||||
<Filter>Header Files\thread</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\core\meshcop\dataset_manager.hpp">
|
||||
<Filter>Header Files\thread</Filter>
|
||||
</ClInclude>
|
||||
|
||||
+12
-4
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -38,8 +38,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openthread/platform/settings.h>
|
||||
|
||||
#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<Tlv *>(mTlvs);
|
||||
Tlv *end = reinterpret_cast<Tlv *>(mTlvs + mLength);
|
||||
const Tlv *cur = reinterpret_cast<const Tlv *>(mTlvs);
|
||||
const Tlv *end = reinterpret_cast<const Tlv *>(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()));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <openthread/config.h>
|
||||
|
||||
#include "dataset_local.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openthread/platform/settings.h>
|
||||
|
||||
#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<DelayTimerTlv *>(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<const Tlv *>(dataset.mTlvs);
|
||||
end = reinterpret_cast<const Tlv *>(dataset.mTlvs + dataset.mLength);
|
||||
|
||||
memset(&aDataset, 0, sizeof(aDataset));
|
||||
|
||||
while (cur < end)
|
||||
{
|
||||
switch (cur->GetType())
|
||||
{
|
||||
|
||||
case Tlv::kActiveTimestamp:
|
||||
{
|
||||
const ActiveTimestampTlv *tlv = static_cast<const ActiveTimestampTlv *>(cur);
|
||||
aDataset.mActiveTimestamp = tlv->GetSeconds();
|
||||
aDataset.mIsActiveTimestampSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kChannel:
|
||||
{
|
||||
const ChannelTlv *tlv = static_cast<const ChannelTlv *>(cur);
|
||||
aDataset.mChannel = tlv->GetChannel();
|
||||
aDataset.mIsChannelSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kChannelMask:
|
||||
{
|
||||
uint8_t tlvLength = cur->GetLength();
|
||||
const uint8_t *entry = reinterpret_cast<const uint8_t *>(cur) + sizeof(Tlv);
|
||||
const uint8_t *entryEnd = entry + tlvLength;
|
||||
|
||||
while (entry < entryEnd)
|
||||
{
|
||||
if (reinterpret_cast<const ChannelMaskEntry *>(entry)->GetChannelPage() == 0)
|
||||
{
|
||||
uint8_t i = sizeof(ChannelMaskEntry);
|
||||
aDataset.mChannelMaskPage0 = static_cast<uint32_t>(entry[i] | (entry[i + 1] << 8) |
|
||||
(entry[i + 2] << 16) | (entry[i + 3] << 24));
|
||||
aDataset.mIsChannelMaskPage0Set = true;
|
||||
break;
|
||||
}
|
||||
|
||||
entry += (reinterpret_cast<const ChannelMaskEntry *>(entry)->GetMaskLength() +
|
||||
sizeof(ChannelMaskEntry));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kDelayTimer:
|
||||
{
|
||||
const DelayTimerTlv *tlv = static_cast<const DelayTimerTlv *>(cur);
|
||||
aDataset.mDelay = tlv->GetDelayTimer();
|
||||
aDataset.mIsDelaySet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kExtendedPanId:
|
||||
{
|
||||
const ExtendedPanIdTlv *tlv = static_cast<const ExtendedPanIdTlv *>(cur);
|
||||
memcpy(aDataset.mExtendedPanId.m8, tlv->GetExtendedPanId(), sizeof(aDataset.mExtendedPanId));
|
||||
aDataset.mIsExtendedPanIdSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kMeshLocalPrefix:
|
||||
{
|
||||
const MeshLocalPrefixTlv *tlv = static_cast<const MeshLocalPrefixTlv *>(cur);
|
||||
memcpy(aDataset.mMeshLocalPrefix.m8, tlv->GetMeshLocalPrefix(), sizeof(aDataset.mMeshLocalPrefix));
|
||||
aDataset.mIsMeshLocalPrefixSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kNetworkMasterKey:
|
||||
{
|
||||
const NetworkMasterKeyTlv *tlv = static_cast<const NetworkMasterKeyTlv *>(cur);
|
||||
aDataset.mMasterKey = tlv->GetNetworkMasterKey();
|
||||
aDataset.mIsMasterKeySet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kNetworkName:
|
||||
{
|
||||
const NetworkNameTlv *tlv = static_cast<const NetworkNameTlv *>(cur);
|
||||
memcpy(aDataset.mNetworkName.m8, tlv->GetNetworkName(), tlv->GetLength());
|
||||
aDataset.mIsNetworkNameSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kPanId:
|
||||
{
|
||||
const PanIdTlv *panid = static_cast<const PanIdTlv *>(cur);
|
||||
aDataset.mPanId = panid->GetPanId();
|
||||
aDataset.mIsPanIdSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kPendingTimestamp:
|
||||
{
|
||||
const PendingTimestampTlv *tlv = static_cast<const PendingTimestampTlv *>(cur);
|
||||
aDataset.mPendingTimestamp = tlv->GetSeconds();
|
||||
aDataset.mIsPendingTimestampSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kPSKc:
|
||||
{
|
||||
const PSKcTlv *tlv = static_cast<const PSKcTlv *>(cur);
|
||||
memcpy(aDataset.mPSKc.m8, tlv->GetPSKc(), tlv->GetLength());
|
||||
aDataset.mIsPSKcSet = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kSecurityPolicy:
|
||||
{
|
||||
const SecurityPolicyTlv *tlv = static_cast<const SecurityPolicyTlv *>(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<uint16_t>(Settings::kKeyActiveDataset);
|
||||
}
|
||||
else
|
||||
{
|
||||
rval = static_cast<uint16_t>(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
|
||||
@@ -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_
|
||||
@@ -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<const Tlv *>(dataset->GetBytes());
|
||||
end = reinterpret_cast<const Tlv *>(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<const ActiveTimestampTlv *>(netif.GetPendingDataset().GetTlv(
|
||||
Tlv::kActiveTimestamp));
|
||||
const Timestamp *pendingActiveTimestamp = static_cast<const Timestamp *>(tlv);
|
||||
|
||||
if (pendingActiveTimestamp != NULL &&
|
||||
netif.GetActiveDataset().GetLocal().Compare(pendingActiveTimestamp) >= 0)
|
||||
{
|
||||
// stop registration attempts during dataset transition
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
Register();
|
||||
|
||||
tlv = static_cast<const ActiveTimestampTlv *>(netif.GetPendingDataset().GetNetwork().Get(Tlv::kActiveTimestamp));
|
||||
pendingActiveTimestamp = static_cast<const Timestamp *>(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<PendingDatasetBase *>(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<Timestamp *>(&activeTimestamp) :
|
||||
static_cast<Timestamp *>(&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<Tlv::Type>(aTlvs[index]))) != NULL)
|
||||
if ((tlv = mNetwork.Get(static_cast<const Tlv::Type>(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<DelayTimerTlv *>(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<DelayTimerTlv *>(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<DelayTimerTlv *>(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<DelayTimerTlv *>(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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
#define WPP_NAME "dataset_manager.tmh"
|
||||
#define WPP_NAME "dataset_manager_ftd.tmh"
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
@@ -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<uint16_t>(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;
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
+19
-42
@@ -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<MeshCoP::ChannelMask0Tlv *>(GetNetif().GetActiveDataset().GetNetwork().Get(
|
||||
MeshCoP::Tlv::kChannelMask));
|
||||
channelMask = static_cast<const MeshCoP::ChannelMask0Tlv *>(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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user