Append default Active Dataset sub-tlvs when Leader forms a partition. (#1039)

* if any Active Dataset sub-tlvs missed, append it with default value.

* if any tlv that would affect the network connectivity included in
  MGMT_ACTIVE_SET.req, but the value is identical with current one,
  take this change as a immediate update.

* update auto-test 9.2.7.
This commit is contained in:
Xiao Ma
2016-12-07 05:29:37 +08:00
committed by Jonathan Hui
parent 28fa90b1ce
commit b3f91ee85f
5 changed files with 134 additions and 39 deletions
+32 -3
View File
@@ -330,14 +330,20 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const
Tlv::Type type;
bool isUpdateFromCommissioner = false;
bool isUpdateAffectConnectivity = false;
bool isUpdateIdenticalValue = true;
StateTlv::State state = StateTlv::kAccept;
ActiveTimestampTlv activeTimestamp;
NetworkMasterKeyTlv masterKey;
ChannelTlv channel;
MeshLocalPrefixTlv meshLocalPrefix;
PanIdTlv panId;
activeTimestamp.SetLength(0);
masterKey.SetLength(0);
channel.SetLength(0);
meshLocalPrefix.SetLength(0);
panId.SetLength(0);
VerifyOrExit(mMle.GetDeviceState() == Mle::kDeviceStateLeader, state = StateTlv::kReject);
@@ -352,7 +358,7 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const
if (tlvType == type)
{
aMessage.Read(offset + sizeof(Tlv), sizeof(timestamp), &timestamp);
aMessage.Read(offset + sizeof(tlv), sizeof(timestamp), &timestamp);
}
switch (tlvType)
@@ -369,6 +375,15 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const
aMessage.Read(offset, sizeof(channel), &channel);
VerifyOrExit(channel.GetChannel() >= kPhyMinChannel && channel.GetChannel() <= kPhyMaxChannel,
state = StateTlv::kReject);
break;
case Tlv::kMeshLocalPrefix:
aMessage.Read(offset, sizeof(meshLocalPrefix), &meshLocalPrefix);
break;
case Tlv::kPanId:
aMessage.Read(offset, sizeof(panId), &panId);
break;
default:
break;
@@ -418,8 +433,22 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const
offset += sizeof(tlv) + tlv.GetLength();
}
// verify whether or not tlv value is identical with current one
if (isUpdateAffectConnectivity &&
(channel.GetChannel() != mNetif.GetMac().GetChannel() ||
panId.GetPanId() != mNetif.GetMac().GetPanId() ||
memcmp(meshLocalPrefix.GetMeshLocalPrefix(), mNetif.GetMle().GetMeshLocalPrefix(),
meshLocalPrefix.GetLength()) != 0 ||
memcmp(masterKey.GetNetworkMasterKey(), mNetif.GetKeyManager().GetMasterKey(NULL),
masterKey.GetLength()) != 0))
{
isUpdateIdenticalValue = false;
otLogInfoMeshCoP("Request includes tlv that affects connectivity.");
}
// verify the update from commissioner should not contain tlv would affect connectivity
VerifyOrExit(!isUpdateFromCommissioner || !isUpdateAffectConnectivity, state = StateTlv::kReject);
VerifyOrExit(!isUpdateFromCommissioner || !(isUpdateAffectConnectivity && !isUpdateIdenticalValue),
state = StateTlv::kReject);
// verify the request includes a timestamp that is ahead of the locally stored value
VerifyOrExit(offset == aMessage.GetLength() && (mLocal.GetTimestamp() == NULL ||
@@ -446,7 +475,7 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const
mLocal.Set(mNetif.GetActiveDataset().GetNetwork());
}
if (!isUpdateAffectConnectivity)
if (!isUpdateAffectConnectivity || isUpdateIdenticalValue)
{
offset = aMessage.GetOffset();
+96 -33
View File
@@ -65,62 +65,128 @@ ActiveDataset::ActiveDataset(ThreadNetif &aThreadNetif):
mCoapServer.AddResource(mResourceGet);
}
bool ActiveDataset::IsTlvInitialized(Tlv::Type aType)
{
bool rval = false;
const Tlv *cur = reinterpret_cast<const Tlv *>(mLocal.GetBytes());
const Tlv *end = reinterpret_cast<const Tlv *>(mLocal.GetBytes() + mLocal.GetSize());
while (cur < end)
{
if (aType == cur->GetType())
{
ExitNow(rval = true);
}
cur = cur->GetNext();
}
exit:
return rval;
}
ThreadError ActiveDataset::GenerateLocal(void)
{
ThreadError error = kThreadError_None;
otOperationalDataset dataset;
VerifyOrExit(mNetif.GetMle().IsAttached() && mLocal.GetTimestamp() == NULL, error = kThreadError_InvalidState);
VerifyOrExit(mNetif.GetMle().IsAttached(), error = kThreadError_InvalidState);
memset(&dataset, 0, sizeof(dataset));
// Active Timestamp
dataset.mActiveTimestamp = 0;
dataset.mIsActiveTimestampSet = true;
if (!IsTlvInitialized(Tlv::kActiveTimestamp))
{
ActiveTimestampTlv activeTimestampTlv;
activeTimestampTlv.Init();
activeTimestampTlv.SetSeconds(0);
activeTimestampTlv.SetTicks(0);
mLocal.Set(activeTimestampTlv);
}
// Channel
dataset.mChannel = mNetif.GetMac().GetChannel();
dataset.mIsChannelSet = true;
if (!IsTlvInitialized(Tlv::kChannel))
{
ChannelTlv tlv;
tlv.Init();
tlv.SetChannelPage(0);
tlv.SetChannel(mNetif.GetMac().GetChannel());
mLocal.Set(tlv);
}
// channelMask
dataset.mChannelMaskPage0 = kPhySupportedChannelMask;
dataset.mIsChannelMaskPage0Set = true;
if (!IsTlvInitialized(Tlv::kChannelMask))
{
ChannelMask0Tlv tlv;
tlv.Init();
tlv.SetMask(kPhySupportedChannelMask);
mLocal.Set(tlv);
}
// Extended PAN ID
memcpy(dataset.mExtendedPanId.m8, mNetif.GetMac().GetExtendedPanId(), sizeof(dataset.mExtendedPanId));
dataset.mIsExtendedPanIdSet = true;
if (!IsTlvInitialized(Tlv::kExtendedPanId))
{
ExtendedPanIdTlv tlv;
tlv.Init();
tlv.SetExtendedPanId(mNetif.GetMac().GetExtendedPanId());
mLocal.Set(tlv);
}
// Mesh-Local Prefix
memcpy(dataset.mMeshLocalPrefix.m8, mNetif.GetMle().GetMeshLocalPrefix(), sizeof(dataset.mMeshLocalPrefix));
dataset.mIsMeshLocalPrefixSet = true;
if (!IsTlvInitialized(Tlv::kMeshLocalPrefix))
{
MeshLocalPrefixTlv tlv;
tlv.Init();
tlv.SetMeshLocalPrefix(mNetif.GetMle().GetMeshLocalPrefix());
mLocal.Set(tlv);
}
// Master Key
const uint8_t *key;
uint8_t keyLength;
key = mNetif.GetKeyManager().GetMasterKey(&keyLength);
memcpy(dataset.mMasterKey.m8, key, keyLength);
dataset.mIsMasterKeySet = true;
if (!IsTlvInitialized(Tlv::kNetworkMasterKey))
{
NetworkMasterKeyTlv tlv;
tlv.Init();
tlv.SetNetworkMasterKey(mNetif.GetKeyManager().GetMasterKey(NULL));
mLocal.Set(tlv);
}
// Network Name
const char *name;
name = mNetif.GetMac().GetNetworkName();
memcpy(dataset.mNetworkName.m8, name, strlen(name));
dataset.mIsNetworkNameSet = true;
if (!IsTlvInitialized(Tlv::kNetworkMasterKey))
{
NetworkNameTlv tlv;
tlv.Init();
tlv.SetNetworkName(mNetif.GetMac().GetNetworkName());
mLocal.Set(tlv);
}
// Pan ID
dataset.mPanId = mNetif.GetMac().GetPanId();
dataset.mIsPanIdSet = true;
if (!IsTlvInitialized(Tlv::kPanId))
{
PanIdTlv tlv;
tlv.Init();
tlv.SetPanId(mNetif.GetMac().GetPanId());
mLocal.Set(tlv);
}
// PSKc
memset(dataset.mPSKc.m8, 0, OT_PSKC_MAX_SIZE);
dataset.mIsPSKcSet = true;
if (!IsTlvInitialized(Tlv::kPSKc))
{
const uint8_t PSKc[16] = {0};
PSKcTlv tlv;
tlv.Init();
tlv.SetPSKc(PSKc);
mLocal.Set(tlv);
}
// Security Policy
dataset.mSecurityPolicy.mRotationTime = static_cast<uint16_t>(mNetif.GetKeyManager().GetKeyRotation());
dataset.mSecurityPolicy.mFlags = mNetif.GetKeyManager().GetSecurityPolicyFlags();
dataset.mIsSecurityPolicySet = true;
mLocal.Set(dataset);
if (!IsTlvInitialized(Tlv::kSecurityPolicy))
{
SecurityPolicyTlv tlv;
tlv.Init();
tlv.SetRotationTime(static_cast<uint16_t>(mNetif.GetKeyManager().GetKeyRotation()));
tlv.SetFlags(mNetif.GetKeyManager().GetSecurityPolicyFlags());
mLocal.Set(tlv);
}
exit:
return error;
@@ -128,10 +194,7 @@ exit:
void ActiveDataset::StartLeader(void)
{
if (mLocal.GetTimestamp() == NULL)
{
GenerateLocal();
}
GenerateLocal();
mLocal.Store();
mNetwork = mLocal;
+2
View File
@@ -65,6 +65,8 @@ private:
const otMessageInfo *aMessageInfo);
void HandleSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
bool IsTlvInitialized(Tlv::Type aType);
Coap::Resource mResourceGet;
Coap::Resource mResourceSet;
};
+1 -1
View File
@@ -2522,7 +2522,7 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa
}
else
{
mNetif.GetPendingDataset().Clear(false);
mNetif.GetPendingDataset().Clear(true);
}
// Parent Attach Success
@@ -41,7 +41,7 @@ ROUTER = 3
LEADER_ACTIVE_TIMESTAMP = 10
ROUTER_ACTIVE_TIMESTAMP = 20
ROUTER_PENDING_TIMESTAMP = 30
ROUTER_PENDING_ACTIVE_TIMESTAMP = 21
ROUTER_PENDING_ACTIVE_TIMESTAMP = 25
COMMISSIONER_PENDING_CHANNEL = 20
COMMISSIONER_PENDING_PANID = 0xafce
@@ -59,7 +59,6 @@ class Cert_9_2_7_DelayTimer(unittest.TestCase):
self.nodes[COMMISSIONER].enable_whitelist()
self.nodes[COMMISSIONER].set_router_selection_jitter(1)
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)
@@ -88,6 +87,8 @@ class Cert_9_2_7_DelayTimer(unittest.TestCase):
self.nodes[COMMISSIONER].start()
time.sleep(5)
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
self.nodes[COMMISSIONER].commissioner_start()
time.sleep(20)
self.nodes[ROUTER].start()
time.sleep(10)