mirror of
https://github.com/espressif/openthread.git
synced 2026-07-27 06:17:47 +00:00
Delay the Tlv that affects connectivity by using Pending Operational Dataset. (#869)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user