mirror of
https://github.com/espressif/openthread.git
synced 2026-07-25 05:24:08 +00:00
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:
@@ -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), ×tamp);
|
||||
aMessage.Read(offset + sizeof(tlv), sizeof(timestamp), ×tamp);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user