mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
[dataset] change updater to use DatasetManager (#6227)
This commit changes the dataset updater implementation to leverage MeshCoP::DatasetManager, which already provides a mechanism to communicate Pending Dataset updates with the Leader. The DatasetManager implementation ensures that only one CoAP transaction is outstanding at a time. This commit also ensures that any unspecified values are copied from the Active Dataset.
This commit is contained in:
+1
-1
@@ -287,6 +287,7 @@ cc_library_static {
|
||||
"src/core/meshcop/dataset_local.cpp",
|
||||
"src/core/meshcop/dataset_manager.cpp",
|
||||
"src/core/meshcop/dataset_manager_ftd.cpp",
|
||||
"src/core/meshcop/dataset_updater.cpp",
|
||||
"src/core/meshcop/dtls.cpp",
|
||||
"src/core/meshcop/energy_scan_client.cpp",
|
||||
"src/core/meshcop/joiner.cpp",
|
||||
@@ -360,7 +361,6 @@ cc_library_static {
|
||||
"src/core/utils/channel_manager.cpp",
|
||||
"src/core/utils/channel_monitor.cpp",
|
||||
"src/core/utils/child_supervision.cpp",
|
||||
"src/core/utils/dataset_updater.cpp",
|
||||
"src/core/utils/flash.cpp",
|
||||
"src/core/utils/heap.cpp",
|
||||
"src/core/utils/jam_detector.cpp",
|
||||
|
||||
+1
-1
@@ -250,6 +250,7 @@ LOCAL_SRC_FILES := \
|
||||
src/core/meshcop/dataset_local.cpp \
|
||||
src/core/meshcop/dataset_manager.cpp \
|
||||
src/core/meshcop/dataset_manager_ftd.cpp \
|
||||
src/core/meshcop/dataset_updater.cpp \
|
||||
src/core/meshcop/dtls.cpp \
|
||||
src/core/meshcop/energy_scan_client.cpp \
|
||||
src/core/meshcop/joiner.cpp \
|
||||
@@ -323,7 +324,6 @@ LOCAL_SRC_FILES := \
|
||||
src/core/utils/channel_manager.cpp \
|
||||
src/core/utils/channel_monitor.cpp \
|
||||
src/core/utils/child_supervision.cpp \
|
||||
src/core/utils/dataset_updater.cpp \
|
||||
src/core/utils/flash.cpp \
|
||||
src/core/utils/heap.cpp \
|
||||
src/core/utils/jam_detector.cpp \
|
||||
|
||||
@@ -80,7 +80,6 @@ typedef void (*otDatasetUpdaterCallback)(otError aError, void *aContext);
|
||||
* @param[in] aDataset A pointer to the Dataset containing the fields to change.
|
||||
* @param[in] aCallback A callback to indicate when Dataset update request finishes.
|
||||
* @param[in] aContext An arbitrary context passed to callback.
|
||||
* @param[in] aRetryWaitInterval The wait time after sending Pending dataset before retrying (interval in ms).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Dataset update started successfully (@p aCallback will be invoked on completion).
|
||||
* @retval OT_ERROR_INVALID_STATE Device is disabled (MLE is disabled).
|
||||
@@ -92,8 +91,7 @@ typedef void (*otDatasetUpdaterCallback)(otError aError, void *aContext);
|
||||
otError otDatasetUpdaterRequestUpdate(otInstance * aInstance,
|
||||
const otOperationalDataset *aDataset,
|
||||
otDatasetUpdaterCallback aCallback,
|
||||
void * aContext,
|
||||
uint32_t aReryWaitInterval);
|
||||
void * aContext);
|
||||
|
||||
/**
|
||||
* This function cancels an ongoing (if any) Operational Dataset update request.
|
||||
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (81)
|
||||
#define OPENTHREAD_API_VERSION (82)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
+2
-2
@@ -445,6 +445,8 @@ openthread_core_files = [
|
||||
"meshcop/dataset_manager.cpp",
|
||||
"meshcop/dataset_manager.hpp",
|
||||
"meshcop/dataset_manager_ftd.cpp",
|
||||
"meshcop/dataset_updater.cpp",
|
||||
"meshcop/dataset_updater.hpp",
|
||||
"meshcop/dtls.cpp",
|
||||
"meshcop/dtls.hpp",
|
||||
"meshcop/energy_scan_client.cpp",
|
||||
@@ -598,8 +600,6 @@ openthread_core_files = [
|
||||
"utils/channel_monitor.hpp",
|
||||
"utils/child_supervision.cpp",
|
||||
"utils/child_supervision.hpp",
|
||||
"utils/dataset_updater.cpp",
|
||||
"utils/dataset_updater.hpp",
|
||||
"utils/flash.cpp",
|
||||
"utils/flash.hpp",
|
||||
"utils/heap.cpp",
|
||||
|
||||
@@ -125,6 +125,7 @@ set(COMMON_SOURCES
|
||||
meshcop/dataset_local.cpp
|
||||
meshcop/dataset_manager.cpp
|
||||
meshcop/dataset_manager_ftd.cpp
|
||||
meshcop/dataset_updater.cpp
|
||||
meshcop/dtls.cpp
|
||||
meshcop/energy_scan_client.cpp
|
||||
meshcop/joiner.cpp
|
||||
@@ -198,7 +199,6 @@ set(COMMON_SOURCES
|
||||
utils/channel_manager.cpp
|
||||
utils/channel_monitor.cpp
|
||||
utils/child_supervision.cpp
|
||||
utils/dataset_updater.cpp
|
||||
utils/flash.cpp
|
||||
utils/heap.cpp
|
||||
utils/jam_detector.cpp
|
||||
|
||||
@@ -202,6 +202,7 @@ SOURCES_COMMON = \
|
||||
meshcop/dataset_local.cpp \
|
||||
meshcop/dataset_manager.cpp \
|
||||
meshcop/dataset_manager_ftd.cpp \
|
||||
meshcop/dataset_updater.cpp \
|
||||
meshcop/dtls.cpp \
|
||||
meshcop/energy_scan_client.cpp \
|
||||
meshcop/joiner.cpp \
|
||||
@@ -275,7 +276,6 @@ SOURCES_COMMON = \
|
||||
utils/channel_manager.cpp \
|
||||
utils/channel_monitor.cpp \
|
||||
utils/child_supervision.cpp \
|
||||
utils/dataset_updater.cpp \
|
||||
utils/flash.cpp \
|
||||
utils/heap.cpp \
|
||||
utils/jam_detector.cpp \
|
||||
@@ -450,6 +450,7 @@ HEADERS_COMMON = \
|
||||
meshcop/dataset.hpp \
|
||||
meshcop/dataset_local.hpp \
|
||||
meshcop/dataset_manager.hpp \
|
||||
meshcop/dataset_updater.hpp \
|
||||
meshcop/dtls.hpp \
|
||||
meshcop/energy_scan_client.hpp \
|
||||
meshcop/joiner.hpp \
|
||||
@@ -531,7 +532,6 @@ HEADERS_COMMON = \
|
||||
utils/channel_manager.hpp \
|
||||
utils/channel_monitor.hpp \
|
||||
utils/child_supervision.hpp \
|
||||
utils/dataset_updater.hpp \
|
||||
utils/flash.hpp \
|
||||
utils/heap.hpp \
|
||||
utils/jam_detector.hpp \
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
#include "common/instance.hpp"
|
||||
#include "common/locator-getters.hpp"
|
||||
#include "utils/dataset_updater.hpp"
|
||||
#include "meshcop/dataset_updater.hpp"
|
||||
|
||||
using namespace ot;
|
||||
|
||||
@@ -46,27 +46,26 @@ using namespace ot;
|
||||
otError otDatasetUpdaterRequestUpdate(otInstance * aInstance,
|
||||
const otOperationalDataset *aDataset,
|
||||
otDatasetUpdaterCallback aCallback,
|
||||
void * aContext,
|
||||
uint32_t aReryWaitInterval)
|
||||
void * aContext)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<Utils::DatasetUpdater>().RequestUpdate(*static_cast<const MeshCoP::Dataset::Info *>(aDataset),
|
||||
aCallback, aContext, aReryWaitInterval);
|
||||
return instance.Get<MeshCoP::DatasetUpdater>().RequestUpdate(*static_cast<const MeshCoP::Dataset::Info *>(aDataset),
|
||||
aCallback, aContext);
|
||||
}
|
||||
|
||||
void otDatasetUpdaterCancelUpdate(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
instance.Get<Utils::DatasetUpdater>().CancelUpdate();
|
||||
instance.Get<MeshCoP::DatasetUpdater>().CancelUpdate();
|
||||
}
|
||||
|
||||
bool otDatasetUpdaterIsUpdateOngoing(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<Utils::DatasetUpdater>().IsUpdateOngoing();
|
||||
return instance.Get<MeshCoP::DatasetUpdater>().IsUpdateOngoing();
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
|
||||
|
||||
@@ -64,6 +64,9 @@
|
||||
#include "common/settings.hpp"
|
||||
#include "crypto/mbedtls.hpp"
|
||||
#include "meshcop/border_agent.hpp"
|
||||
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
|
||||
#include "meshcop/dataset_updater.hpp"
|
||||
#endif
|
||||
#include "net/ip6.hpp"
|
||||
#include "thread/announce_sender.hpp"
|
||||
#include "thread/link_quality.hpp"
|
||||
@@ -76,9 +79,6 @@
|
||||
#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
|
||||
#include "utils/channel_monitor.hpp"
|
||||
#endif
|
||||
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
|
||||
#include "utils/dataset_updater.hpp"
|
||||
#endif
|
||||
|
||||
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
||||
#include "backbone_router/bbr_leader.hpp"
|
||||
@@ -359,7 +359,7 @@ private:
|
||||
#endif
|
||||
|
||||
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
|
||||
Utils::DatasetUpdater mDatasetUpdater;
|
||||
MeshCoP::DatasetUpdater mDatasetUpdater;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
|
||||
@@ -757,7 +757,7 @@ template <> inline Utils::ChannelManager &Instance::Get(void)
|
||||
#endif
|
||||
|
||||
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
|
||||
template <> inline Utils::DatasetUpdater &Instance::Get(void)
|
||||
template <> inline MeshCoP::DatasetUpdater &Instance::Get(void)
|
||||
{
|
||||
return mDatasetUpdater;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ void Notifier::EmitEvents(void)
|
||||
Get<Utils::ChildSupervisor>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
|
||||
Get<Utils::DatasetUpdater>().HandleNotifierEvents(events);
|
||||
Get<MeshCoP::DatasetUpdater>().HandleNotifierEvents(events);
|
||||
#endif
|
||||
#endif // OPENTHREAD_FTD
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY
|
||||
#define OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY 1000
|
||||
#define OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY 30000
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -199,6 +199,17 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError DatasetManager::SaveLocal(const Dataset &aDataset)
|
||||
{
|
||||
otError error;
|
||||
|
||||
SuccessOrExit(error = mLocal.Save(aDataset));
|
||||
HandleDatasetUpdated();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void DatasetManager::HandleDatasetUpdated(void)
|
||||
{
|
||||
switch (Get<Mle::MleRouter>().GetRole())
|
||||
@@ -745,6 +756,17 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError PendingDataset::Save(const Dataset &aDataset)
|
||||
{
|
||||
otError error;
|
||||
|
||||
SuccessOrExit(error = DatasetManager::SaveLocal(aDataset));
|
||||
StartDelayTimer();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError PendingDataset::Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
@@ -285,6 +285,17 @@ protected:
|
||||
*/
|
||||
otError Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
|
||||
|
||||
/**
|
||||
* This method saves the Operational Dataset in non-volatile memory.
|
||||
*
|
||||
* @param[in] aDataset The Operational Dataset.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully applied configuration.
|
||||
* @retval OT_ERROR_PARSE The dataset has at least one TLV with invalid format.
|
||||
*
|
||||
*/
|
||||
otError SaveLocal(const Dataset &aDataset);
|
||||
|
||||
/**
|
||||
* This method handles a MGMT_GET request message.
|
||||
*
|
||||
@@ -566,6 +577,17 @@ public:
|
||||
*/
|
||||
otError Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
|
||||
|
||||
/**
|
||||
* This method saves the Operational Dataset in non-volatile memory.
|
||||
*
|
||||
* @param[in] aDataset The Operational Dataset.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully applied configuration.
|
||||
* @retval OT_ERROR_PARSE The dataset has at least one TLV with invalid format.
|
||||
*
|
||||
*/
|
||||
otError Save(const Dataset &aDataset);
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
/**
|
||||
* This method starts the Leader functions for maintaining the Active Operational Dataset.
|
||||
|
||||
@@ -43,12 +43,10 @@
|
||||
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
|
||||
|
||||
namespace ot {
|
||||
namespace Utils {
|
||||
namespace MeshCoP {
|
||||
|
||||
DatasetUpdater::DatasetUpdater(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mState(kStateIdle)
|
||||
, mWaitInterval(kWaitInterval)
|
||||
, mCallback(nullptr)
|
||||
, mCallbackContext(nullptr)
|
||||
, mTimer(aInstance, DatasetUpdater::HandleTimer)
|
||||
@@ -56,16 +54,13 @@ DatasetUpdater::DatasetUpdater(Instance &aInstance)
|
||||
{
|
||||
}
|
||||
|
||||
otError DatasetUpdater::RequestUpdate(const MeshCoP::Dataset::Info &aDataset,
|
||||
Callback aCallback,
|
||||
void * aContext,
|
||||
uint32_t aReryWaitInterval)
|
||||
otError DatasetUpdater::RequestUpdate(const MeshCoP::Dataset::Info &aDataset, Callback aCallback, void *aContext)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message *message = nullptr;
|
||||
|
||||
VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
|
||||
VerifyOrExit(mState == kStateIdle, error = OT_ERROR_BUSY);
|
||||
VerifyOrExit(mDataset == nullptr, error = OT_ERROR_BUSY);
|
||||
|
||||
VerifyOrExit(!aDataset.IsActiveTimestampPresent() && !aDataset.IsPendingTimestampPresent(),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
@@ -77,11 +72,9 @@ otError DatasetUpdater::RequestUpdate(const MeshCoP::Dataset::Info &aDataset,
|
||||
|
||||
mCallback = aCallback;
|
||||
mCallbackContext = aContext;
|
||||
mWaitInterval = aReryWaitInterval;
|
||||
mDataset = message;
|
||||
mState = kStateUpdateRequested;
|
||||
|
||||
PreparePendingDataset();
|
||||
mTimer.Start(1);
|
||||
|
||||
exit:
|
||||
FreeMessageOnError(message, error);
|
||||
@@ -90,12 +83,13 @@ exit:
|
||||
|
||||
void DatasetUpdater::CancelUpdate(void)
|
||||
{
|
||||
if (mState != kStateIdle)
|
||||
{
|
||||
FreeMessage(mDataset);
|
||||
mState = kStateIdle;
|
||||
mTimer.Stop();
|
||||
}
|
||||
VerifyOrExit(mDataset != nullptr);
|
||||
|
||||
FreeMessage(mDataset);
|
||||
mTimer.Stop();
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void DatasetUpdater::HandleTimer(Timer &aTimer)
|
||||
@@ -105,28 +99,20 @@ void DatasetUpdater::HandleTimer(Timer &aTimer)
|
||||
|
||||
void DatasetUpdater::HandleTimer(void)
|
||||
{
|
||||
switch (mState)
|
||||
{
|
||||
case kStateIdle:
|
||||
break;
|
||||
case kStateUpdateRequested:
|
||||
case kStateSentMgmtPendingDataset:
|
||||
PreparePendingDataset();
|
||||
break;
|
||||
}
|
||||
PreparePendingDataset();
|
||||
}
|
||||
|
||||
void DatasetUpdater::PreparePendingDataset(void)
|
||||
{
|
||||
Dataset dataset(Dataset::kPending);
|
||||
MeshCoP::Dataset::Info requestedDataset;
|
||||
otError error;
|
||||
MeshCoP::Dataset::Info newDataset;
|
||||
MeshCoP::Dataset::Info curDataset;
|
||||
|
||||
VerifyOrExit(mState != kStateIdle);
|
||||
VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), Finish(OT_ERROR_INVALID_STATE));
|
||||
IgnoreError(mDataset->Read(0, requestedDataset));
|
||||
|
||||
error = Get<MeshCoP::ActiveDataset>().Read(curDataset);
|
||||
error = Get<ActiveDataset>().Read(dataset);
|
||||
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
@@ -136,80 +122,51 @@ void DatasetUpdater::PreparePendingDataset(void)
|
||||
// right after the network is formed but before the active
|
||||
// dataset is created.
|
||||
|
||||
mState = kStateUpdateRequested;
|
||||
mTimer.Start(kRetryInterval);
|
||||
ExitNow();
|
||||
ExitNow(error = OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
IgnoreError(mDataset->Read(0, newDataset));
|
||||
IgnoreError(dataset.SetFrom(requestedDataset));
|
||||
|
||||
if (newDataset.IsSubsetOf(curDataset))
|
||||
if (!requestedDataset.IsDelayPresent())
|
||||
{
|
||||
// If new requested Dataset is already contained in the current
|
||||
// Active Dataset, no change is required, and we can report the
|
||||
// update to be successful.
|
||||
uint32_t delay = kDefaultDelay;
|
||||
|
||||
Finish(OT_ERROR_NONE);
|
||||
ExitNow();
|
||||
SuccessOrExit(error = dataset.SetTlv(Tlv::kDelayTimer, delay));
|
||||
}
|
||||
|
||||
if (newDataset.IsActiveTimestampPresent())
|
||||
{
|
||||
// Presence of the active timestamp in the new Dataset
|
||||
// indicates that it is a retry. In this case, we ensure
|
||||
// that the timestamp is ahead of current active dataset.
|
||||
// This covers the case where another device in network
|
||||
// requested a Dataset update after this device.
|
||||
Timestamp timestamp;
|
||||
|
||||
VerifyOrExit(newDataset.GetActiveTimestamp() > curDataset.GetActiveTimestamp(), Finish(OT_ERROR_ALREADY));
|
||||
}
|
||||
else
|
||||
{
|
||||
newDataset.SetActiveTimestamp(curDataset.GetActiveTimestamp() +
|
||||
Random::NonCrypto::GetUint32InRange(1, kMaxTimestampIncrease));
|
||||
}
|
||||
|
||||
if (!newDataset.IsDelayPresent())
|
||||
{
|
||||
newDataset.SetDelay(kDefaultDelay);
|
||||
}
|
||||
|
||||
if (!newDataset.IsPendingTimestampPresent())
|
||||
{
|
||||
uint32_t timestampIncrease = Random::NonCrypto::GetUint32InRange(1, kMaxTimestampIncrease);
|
||||
|
||||
if (Get<MeshCoP::PendingDataset>().Read(curDataset) == OT_ERROR_NONE)
|
||||
if (Get<PendingDataset>().GetTimestamp() != nullptr)
|
||||
{
|
||||
newDataset.SetPendingTimestamp(curDataset.GetPendingTimestamp() + timestampIncrease);
|
||||
}
|
||||
else
|
||||
{
|
||||
newDataset.SetPendingTimestamp(timestampIncrease);
|
||||
timestamp = *Get<PendingDataset>().GetTimestamp();
|
||||
}
|
||||
|
||||
mDataset->Write(0, newDataset);
|
||||
timestamp.AdvanceRandomTicks();
|
||||
dataset.SetTimestamp(timestamp);
|
||||
}
|
||||
|
||||
error = Get<MeshCoP::PendingDataset>().SendSetRequest(newDataset, nullptr, 0);
|
||||
{
|
||||
ActiveTimestampTlv *tlv = dataset.GetTlv<ActiveTimestampTlv>();
|
||||
tlv->AdvanceRandomTicks();
|
||||
}
|
||||
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
mState = kStateSentMgmtPendingDataset;
|
||||
mTimer.Start(newDataset.GetDelay() + mWaitInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
mTimer.Start(kRetryInterval);
|
||||
}
|
||||
SuccessOrExit(error = Get<PendingDataset>().Save(dataset));
|
||||
|
||||
exit:
|
||||
return;
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
Finish(error);
|
||||
}
|
||||
}
|
||||
|
||||
void DatasetUpdater::Finish(otError aError)
|
||||
{
|
||||
OT_ASSERT(mDataset != nullptr);
|
||||
|
||||
FreeMessage(mDataset);
|
||||
mState = kStateIdle;
|
||||
mDataset = nullptr;
|
||||
|
||||
if (mCallback != nullptr)
|
||||
{
|
||||
@@ -219,21 +176,30 @@ void DatasetUpdater::Finish(otError aError)
|
||||
|
||||
void DatasetUpdater::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
VerifyOrExit(mState == kStateSentMgmtPendingDataset);
|
||||
MeshCoP::Dataset::Info requestedDataset;
|
||||
MeshCoP::Dataset::Info dataset;
|
||||
|
||||
if (aEvents.Contains(kEventActiveDatasetChanged))
|
||||
VerifyOrExit(mDataset != nullptr);
|
||||
|
||||
VerifyOrExit(aEvents.ContainsAny(kEventActiveDatasetChanged | kEventPendingDatasetChanged));
|
||||
|
||||
IgnoreError(mDataset->Read(0, requestedDataset));
|
||||
|
||||
if (aEvents.Contains(kEventActiveDatasetChanged) && Get<MeshCoP::ActiveDataset>().Read(dataset) == OT_ERROR_NONE)
|
||||
{
|
||||
MeshCoP::Dataset::Info requestedDataset;
|
||||
MeshCoP::Dataset::Info activeDataset;
|
||||
|
||||
SuccessOrExit(Get<MeshCoP::ActiveDataset>().Read(activeDataset));
|
||||
IgnoreError(mDataset->Read(0, requestedDataset));
|
||||
|
||||
if (requestedDataset.IsSubsetOf(activeDataset))
|
||||
if (requestedDataset.IsSubsetOf(dataset))
|
||||
{
|
||||
Finish(OT_ERROR_NONE);
|
||||
}
|
||||
else if (requestedDataset.GetActiveTimestamp() <= activeDataset.GetActiveTimestamp())
|
||||
else if (requestedDataset.GetActiveTimestamp() <= dataset.GetActiveTimestamp())
|
||||
{
|
||||
Finish(OT_ERROR_ALREADY);
|
||||
}
|
||||
}
|
||||
|
||||
if (aEvents.Contains(kEventPendingDatasetChanged) && Get<MeshCoP::PendingDataset>().Read(dataset) == OT_ERROR_NONE)
|
||||
{
|
||||
if (!requestedDataset.IsSubsetOf(dataset))
|
||||
{
|
||||
Finish(OT_ERROR_ALREADY);
|
||||
}
|
||||
@@ -243,7 +209,7 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
#endif // #if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
|
||||
@@ -47,7 +47,7 @@
|
||||
#include "meshcop/meshcop_tlvs.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Utils {
|
||||
namespace MeshCoP {
|
||||
|
||||
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
|
||||
|
||||
@@ -93,7 +93,6 @@ public:
|
||||
* @param[in] aDataset Dataset info containing fields to change.
|
||||
* @param[in] aCallback A callback to indicate when Dataset update request finishes.
|
||||
* @param[in] aContext An arbitrary context passed to callback.
|
||||
* @param[in] aRetryWaitInterval The wait time after sending Pending dataset before retrying (interval in ms).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Dataset update started successfully (@p aCallback will be invoked on completion).
|
||||
* @retval OT_ERROR_INVALID_STATE Device is disabled (MLE is disabled).
|
||||
@@ -102,10 +101,7 @@ public:
|
||||
* @retval OT_ERROR_NO_BUFS Could not allocated buffer to save Dataset.
|
||||
*
|
||||
*/
|
||||
otError RequestUpdate(const MeshCoP::Dataset::Info &aDataset,
|
||||
Callback aCallback,
|
||||
void * aContext,
|
||||
uint32_t aReryWaitInterval = kWaitInterval);
|
||||
otError RequestUpdate(const MeshCoP::Dataset::Info &aDataset, Callback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* This method cancels an ongoing (if any) Operational Dataset update request.
|
||||
@@ -120,26 +116,14 @@ public:
|
||||
* @retval FALSE There is no ongoing update.
|
||||
*
|
||||
*/
|
||||
bool IsUpdateOngoing(void) const { return (mState != kStateIdle); }
|
||||
bool IsUpdateOngoing(void) const { return mDataset != nullptr; }
|
||||
|
||||
private:
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateIdle,
|
||||
kStateUpdateRequested,
|
||||
kStateSentMgmtPendingDataset,
|
||||
};
|
||||
|
||||
enum : uint32_t
|
||||
{
|
||||
// Default delay (in ms) in Pending Dataset.
|
||||
kDefaultDelay = OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY,
|
||||
kDefaultDelay = OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY, // Default delay (in ms) in Pending Dataset.
|
||||
|
||||
// Default wait interval (in ms) after sending Pending Dataset to retry (in addition Dataset Delay)
|
||||
kWaitInterval = OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_RETRY_WAIT_INTERVAL,
|
||||
|
||||
kRetryInterval = 1000, // In ms. Retry interval when preparing and/or sending Pending Dataset fails.
|
||||
kMaxTimestampIncrease = 128, // Maximum increase of Pending/Active Timestamp during Dataset Update.
|
||||
kRetryInterval = 1000, // In ms. Retry interval when preparing and/or sending Pending Dataset fails.
|
||||
};
|
||||
|
||||
static void HandleTimer(Timer &aTimer);
|
||||
@@ -148,8 +132,6 @@ private:
|
||||
void Finish(otError aError);
|
||||
void HandleNotifierEvents(Events aEvents);
|
||||
|
||||
State mState;
|
||||
uint32_t mWaitInterval;
|
||||
Callback mCallback;
|
||||
void * mCallbackContext;
|
||||
TimerMilli mTimer;
|
||||
@@ -158,7 +140,7 @@ private:
|
||||
|
||||
#endif // (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
#endif // DATASET_UPDATER_HPP_
|
||||
@@ -68,5 +68,19 @@ int Timestamp::Compare(const Timestamp &aCompare) const
|
||||
return rval;
|
||||
}
|
||||
|
||||
void Timestamp::AdvanceRandomTicks(void)
|
||||
{
|
||||
uint16_t ticks = GetTicks();
|
||||
|
||||
ticks += Random::NonCrypto::GetUint32InRange(1, kMaxRandomTicks);
|
||||
|
||||
if (ticks & (kTicksMask >> kTicksOffset))
|
||||
{
|
||||
SetSeconds(GetSeconds() + 1);
|
||||
}
|
||||
|
||||
SetTicks(ticks);
|
||||
}
|
||||
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <openthread/platform/toolchain.h>
|
||||
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/random.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
@@ -137,11 +138,18 @@ public:
|
||||
((aAuthoritative << kAuthoritativeOffset) & kAuthoritativeMask));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method increments the timestamp by a random number of ticks [0, 32767].
|
||||
*
|
||||
*/
|
||||
void AdvanceRandomTicks(void);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kTicksOffset = 1,
|
||||
kTicksMask = 0x7fff << kTicksOffset,
|
||||
kMaxRandomTicks = 0x7fff,
|
||||
kAuthoritativeOffset = 0,
|
||||
kAuthoritativeMask = 1 << kAuthoritativeOffset,
|
||||
};
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
#include "common/locator-getters.hpp"
|
||||
#include "common/logging.hpp"
|
||||
#include "common/random.hpp"
|
||||
#include "meshcop/dataset_updater.hpp"
|
||||
#include "radio/radio.hpp"
|
||||
#include "utils/dataset_updater.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
|
||||
|
||||
@@ -73,7 +73,6 @@ void ChannelManager::RequestChannelChange(uint8_t aChannel)
|
||||
if (mState == kStateChangeInProgress)
|
||||
{
|
||||
VerifyOrExit(mChannel != aChannel);
|
||||
Get<DatasetUpdater>().CancelUpdate();
|
||||
}
|
||||
|
||||
mState = kStateChangeRequested;
|
||||
@@ -106,7 +105,7 @@ void ChannelManager::StartDatasetUpdate(void)
|
||||
dataset.SetChannel(mChannel);
|
||||
dataset.SetDelay(Time::SecToMsec(mDelay));
|
||||
|
||||
switch (Get<DatasetUpdater>().RequestUpdate(dataset, HandleDatasetUpdateDone, this, kChangeCheckWaitInterval))
|
||||
switch (Get<MeshCoP::DatasetUpdater>().RequestUpdate(dataset, HandleDatasetUpdateDone, this))
|
||||
{
|
||||
case OT_ERROR_NONE:
|
||||
mState = kStateChangeInProgress;
|
||||
|
||||
@@ -233,9 +233,6 @@ private:
|
||||
// Retry interval to resend Pending Dataset in case of tx failure (in ms).
|
||||
kPendingDatasetTxRetryInterval = 20000,
|
||||
|
||||
// Wait time after sending Pending Dataset to check whether the channel was changed (in ms).
|
||||
kChangeCheckWaitInterval = 30000,
|
||||
|
||||
// Maximum jitter/wait time to start a requested channel change (in ms).
|
||||
kRequestStartJitterInterval = 10000,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user