Delay the Tlv that affects connectivity by using Pending Operational Dataset. (#869)

This commit is contained in:
Xiao Ma
2016-11-04 08:53:33 -07:00
committed by Jonathan Hui
parent d624bcb1c1
commit 85521db9af
4 changed files with 102 additions and 26 deletions
+83 -21
View File
@@ -47,6 +47,7 @@
#include <platform/random.h>
#include <thread/meshcop_dataset.hpp>
#include <thread/meshcop_dataset_manager.hpp>
#include <thread/meshcop_tlvs.hpp>
#include <thread/thread_netif.hpp>
#include <thread/thread_tlvs.hpp>
#include <thread/thread_uris.hpp>
@@ -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
+6 -2
View File
@@ -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;
+6
View File
@@ -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;
@@ -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)