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:
Jonathan Hui
2017-07-05 09:41:08 -07:00
committed by GitHub
parent bbab3074ed
commit 0d27c3e00b
22 changed files with 1321 additions and 495 deletions
+2
View File
@@ -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
View File
@@ -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
+2
View File
@@ -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 \
+2 -2
View File
@@ -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;
+4 -4
View File
@@ -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;
+8 -8
View File
@@ -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;
+2 -2
View File
@@ -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;
+47 -72
View File
@@ -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()));
}
+46 -38
View File
@@ -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
+470
View File
@@ -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
+169
View File
@@ -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_
+165 -214
View File
@@ -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,
+302 -28
View File
@@ -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,
+33 -38
View File
@@ -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;
+5 -5
View File
@@ -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
View File
@@ -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)
{
+1 -3
View File
@@ -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.
+10 -31
View File
@@ -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)