From 85521db9af49ce8129fe3b087a2cabff961f6ec6 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Fri, 4 Nov 2016 23:53:33 +0800 Subject: [PATCH] Delay the Tlv that affects connectivity by using Pending Operational Dataset. (#869) --- src/core/thread/meshcop_dataset_manager.cpp | 104 ++++++++++++++---- src/core/thread/meshcop_dataset_manager.hpp | 8 +- src/core/thread/meshcop_tlvs.hpp | 6 + .../thread-cert/Cert_9_2_07_DelayTimer.py | 10 +- 4 files changed, 102 insertions(+), 26 deletions(-) diff --git a/src/core/thread/meshcop_dataset_manager.cpp b/src/core/thread/meshcop_dataset_manager.cpp index cd8b5fec9..88f47a3b6 100644 --- a/src/core/thread/meshcop_dataset_manager.cpp +++ b/src/core/thread/meshcop_dataset_manager.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -319,6 +320,7 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const uint16_t offset = aMessage.GetOffset(); Tlv::Type type; bool isUpdateFromCommissioner = false; + bool isUpdateAffectConnectivity = false; StateTlv::State state = StateTlv::kAccept; ActiveTimestampTlv activeTimestamp; @@ -362,7 +364,7 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const (tlvType == Tlv::kChannel || tlvType == Tlv::kMeshLocalPrefix || tlvType == Tlv::kPanId || tlvType == Tlv::kNetworkMasterKey)) { - ExitNow(state = StateTlv::kReject); + isUpdateAffectConnectivity = true; } // verify session id is the same @@ -401,6 +403,9 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const offset += sizeof(tlv) + tlv.GetLength(); } + // verify the update from commissioner should not contain tlv would affect connectivity + VerifyOrExit(!isUpdateFromCommissioner || !isUpdateAffectConnectivity, state = StateTlv::kReject); + // verify the request includes a timestamp that is ahead of the locally stored value VerifyOrExit(offset == aMessage.GetLength() && (mLocal.GetTimestamp() == NULL || mLocal.GetTimestamp()->Compare(timestamp) > 0), state = StateTlv::kReject); @@ -426,32 +431,39 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const mLocal.Set(mNetif.GetActiveDataset().GetNetwork()); } - offset = aMessage.GetOffset(); - - while (offset < aMessage.GetLength()) + if (!isUpdateAffectConnectivity) { - OT_TOOL_PACKED_BEGIN - struct - { - Tlv tlv; - uint8_t value[Dataset::kMaxValueSize]; - } OT_TOOL_PACKED_END data; + offset = aMessage.GetOffset(); - aMessage.Read(offset, sizeof(Tlv), &data.tlv); - aMessage.Read(offset + sizeof(Tlv), data.tlv.GetLength(), data.value); - - if (data.tlv.GetType() != Tlv::kCommissionerSessionId) + while (offset < aMessage.GetLength()) { - mLocal.Set(data.tlv); + OT_TOOL_PACKED_BEGIN + struct + { + Tlv tlv; + uint8_t value[Dataset::kMaxValueSize]; + } OT_TOOL_PACKED_END data; + + aMessage.Read(offset, sizeof(Tlv), &data.tlv); + aMessage.Read(offset + sizeof(Tlv), data.tlv.GetLength(), data.value); + + if (data.tlv.GetType() != Tlv::kCommissionerSessionId) + { + mLocal.Set(data.tlv); + } + + offset += sizeof(Tlv) + data.tlv.GetLength(); } - offset += sizeof(Tlv) + data.tlv.GetLength(); + mLocal.Store(); + mNetwork = mLocal; + mNetworkDataLeader.IncrementVersion(); + mNetworkDataLeader.IncrementStableVersion(); + } + else + { + mNetif.GetPendingDataset().ApplyActiveDataset(activeTimestamp, aMessage); } - - mLocal.Store(); - mNetwork = mLocal; - mNetworkDataLeader.IncrementVersion(); - mNetworkDataLeader.IncrementStableVersion(); // notify commissioner if update is from thread device if (!isUpdateFromCommissioner) @@ -862,6 +874,12 @@ ThreadError ActiveDataset::Set(const Dataset &aDataset) SuccessOrExit(error = DatasetManager::Set(aDataset)); DatasetManager::ApplyConfiguration(); + if (mMle.GetDeviceState() == Mle::kDeviceStateLeader) + { + mNetworkDataLeader.IncrementVersion(); + mNetworkDataLeader.IncrementStableVersion(); + } + exit: return error; } @@ -1100,5 +1118,49 @@ void PendingDataset::HandleTimer(void) Clear(false); } +void PendingDataset::ApplyActiveDataset(const Timestamp &aTimestamp, Message &aMessage) +{ + uint16_t offset = aMessage.GetOffset(); + DelayTimerTlv delayTimer; + uint8_t flags; + + VerifyOrExit(mMle.IsAttached(), ;); + + while (offset < aMessage.GetLength()) + { + OT_TOOL_PACKED_BEGIN + struct + { + Tlv tlv; + uint8_t value[Dataset::kMaxValueSize]; + } OT_TOOL_PACKED_END data; + + aMessage.Read(offset, sizeof(Tlv), &data.tlv); + aMessage.Read(offset + sizeof(Tlv), data.tlv.GetLength(), data.value); + mNetwork.Set(data.tlv); + offset += sizeof(Tlv) + data.tlv.GetLength(); + } + + // add delay timer tlv + delayTimer.Init(); + delayTimer.SetDelayTimer(Timer::SecToMsec(DelayTimerTlv::kMinDelayTimer)); + mNetwork.Set(delayTimer); + + // add pending timestamp tlv + mNetwork.SetTimestamp(aTimestamp); + HandleNetworkUpdate(flags); + + // reset delay timer + ResetDelayTimer(kFlagNetworkUpdated); + +exit: + {} +} + +void PendingDataset::HandleNetworkUpdate(uint8_t &aFlags) +{ + DatasetManager::HandleNetworkUpdate(aFlags); +} + } // namespace MeshCoP } // namespace Thread diff --git a/src/core/thread/meshcop_dataset_manager.hpp b/src/core/thread/meshcop_dataset_manager.hpp index ae1ccc735..8fdaf28e0 100644 --- a/src/core/thread/meshcop_dataset_manager.hpp +++ b/src/core/thread/meshcop_dataset_manager.hpp @@ -81,6 +81,8 @@ protected: void Get(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void HandleNetworkUpdate(uint8_t &aFlags); + ThreadError Set(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); Dataset mLocal; @@ -98,8 +100,6 @@ private: static void HandleTimer(void *aContext); void HandleTimer(void); - void HandleNetworkUpdate(uint8_t &aFlags); - ThreadError Register(void); void SendSetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo, StateTlv::State aState); void SendGetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo, @@ -165,6 +165,8 @@ public: void UpdateDelayTimer(void); + void ApplyActiveDataset(const Timestamp &aTimestamp, Message &aMessage); + private: static void HandleGet(void *aContext, Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); @@ -180,6 +182,8 @@ private: void ResetDelayTimer(uint8_t aFlags); void UpdateDelayTimer(Dataset &aDataset, uint32_t &aStartTime); + void HandleNetworkUpdate(uint8_t &aFlags); + Coap::Resource mResourceGet; Coap::Resource mResourceSet; diff --git a/src/core/thread/meshcop_tlvs.hpp b/src/core/thread/meshcop_tlvs.hpp index f7cb208c2..0b58119d1 100644 --- a/src/core/thread/meshcop_tlvs.hpp +++ b/src/core/thread/meshcop_tlvs.hpp @@ -1243,6 +1243,12 @@ public: */ void SetDelayTimer(uint32_t aDelayTimer) { mDelayTimer = HostSwap32(aDelayTimer); } + enum + { + kMaxDelayTimer = 259200, ///< maximum delay timer value for a Pending Dataset in seconds + kMinDelayTimer = 28800, ///< minimum delay timer value for a Pending Dataset in seconds + }; + private: uint32_t mDelayTimer; } OT_TOOL_PACKED_END; diff --git a/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py b/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py index 3120e2bf9..95b354e4e 100755 --- a/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py +++ b/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py @@ -52,22 +52,26 @@ class Cert_9_2_7_DelayTimer(unittest.TestCase): for i in range(1,4): self.nodes[i] = node.Node(i) - self.nodes[COMMISSIONER].set_active_dataset(LEADER_ACTIVE_TIMESTAMP, panid=PANID_INIT) + self.nodes[COMMISSIONER].set_active_dataset(LEADER_ACTIVE_TIMESTAMP) self.nodes[COMMISSIONER].set_mode('rsdn') + self.nodes[COMMISSIONER].set_panid(PANID_INIT) self.nodes[COMMISSIONER].add_whitelist(self.nodes[LEADER].get_addr64()) self.nodes[COMMISSIONER].enable_whitelist() self.nodes[COMMISSIONER].set_router_selection_jitter(1) - self.nodes[LEADER].set_active_dataset(LEADER_ACTIVE_TIMESTAMP, panid=PANID_INIT) + self.nodes[LEADER].set_active_dataset(LEADER_ACTIVE_TIMESTAMP) self.nodes[LEADER].set_mode('rsdn') + self.nodes[LEADER].set_panid(PANID_INIT) self.nodes[LEADER].set_partition_id(0xffffffff) self.nodes[LEADER].add_whitelist(self.nodes[COMMISSIONER].get_addr64()) self.nodes[LEADER].enable_whitelist() self.nodes[LEADER].set_router_selection_jitter(1) - self.nodes[ROUTER].set_active_dataset(ROUTER_ACTIVE_TIMESTAMP, panid=PANID_INIT) + self.nodes[ROUTER].set_active_dataset(ROUTER_ACTIVE_TIMESTAMP) self.nodes[ROUTER].set_pending_dataset(ROUTER_PENDING_TIMESTAMP, ROUTER_PENDING_ACTIVE_TIMESTAMP) self.nodes[ROUTER].set_mode('rsdn') + self.nodes[ROUTER].set_panid(PANID_INIT) + self.nodes[ROUTER].set_partition_id(0x1) self.nodes[ROUTER].enable_whitelist() self.nodes[ROUTER].set_router_selection_jitter(1)