mirror of
https://github.com/espressif/openthread.git
synced 2026-09-04 00:00:06 +00:00
Network information storage for fast synchronization after reset. (#992)
* Network information storage for fast synchronization after reset. * Following network information will be stored in none-volatile memory and restored after reset: - All devices store its specific network information. - Children store parent information. - Router and Leader store their children information. * THCI: use truly reset in APIs that ask for reset action. * Use Child Update Request to retrieve children information after parent reset
This commit is contained in:
@@ -46,6 +46,9 @@ enum
|
||||
{
|
||||
kKeyActiveDataset = 0x0001,
|
||||
kKeyPendingDataset = 0x0002,
|
||||
kKeyNetworkInfo = 0x0003,
|
||||
kKeyParentInfo = 0x0004,
|
||||
kKeyChildInfo = 0x0005,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -65,61 +65,72 @@ ActiveDataset::ActiveDataset(ThreadNetif &aThreadNetif):
|
||||
mCoapServer.AddResource(mResourceGet);
|
||||
}
|
||||
|
||||
ThreadError ActiveDataset::GenerateLocal(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
otOperationalDataset dataset;
|
||||
|
||||
VerifyOrExit(mNetif.GetMle().IsAttached() && mLocal.GetTimestamp() == NULL, error = kThreadError_InvalidState);
|
||||
|
||||
memset(&dataset, 0, sizeof(dataset));
|
||||
|
||||
// Active Timestamp
|
||||
dataset.mActiveTimestamp = 0;
|
||||
dataset.mIsActiveTimestampSet = true;
|
||||
|
||||
// Channel
|
||||
dataset.mChannel = mNetif.GetMac().GetChannel();
|
||||
dataset.mIsChannelSet = true;
|
||||
|
||||
// channelMask
|
||||
dataset.mChannelMaskPage0 = kPhySupportedChannelMask;
|
||||
dataset.mIsChannelMaskPage0Set = true;
|
||||
|
||||
// Extended PAN ID
|
||||
memcpy(dataset.mExtendedPanId.m8, mNetif.GetMac().GetExtendedPanId(), sizeof(dataset.mExtendedPanId));
|
||||
dataset.mIsExtendedPanIdSet = true;
|
||||
|
||||
// Mesh-Local Prefix
|
||||
memcpy(dataset.mMeshLocalPrefix.m8, mNetif.GetMle().GetMeshLocalPrefix(), sizeof(dataset.mMeshLocalPrefix));
|
||||
dataset.mIsMeshLocalPrefixSet = true;
|
||||
|
||||
// Master Key
|
||||
const uint8_t *key;
|
||||
uint8_t keyLength;
|
||||
key = mNetif.GetKeyManager().GetMasterKey(&keyLength);
|
||||
memcpy(dataset.mMasterKey.m8, key, keyLength);
|
||||
dataset.mIsMasterKeySet = true;
|
||||
|
||||
// Network Name
|
||||
const char *name;
|
||||
name = mNetif.GetMac().GetNetworkName();
|
||||
memcpy(dataset.mNetworkName.m8, name, strlen(name));
|
||||
dataset.mIsNetworkNameSet = true;
|
||||
|
||||
// Pan ID
|
||||
dataset.mPanId = mNetif.GetMac().GetPanId();
|
||||
dataset.mIsPanIdSet = true;
|
||||
|
||||
// PSKc
|
||||
memset(dataset.mPSKc.m8, 0, OT_PSKC_MAX_SIZE);
|
||||
dataset.mIsPSKcSet = true;
|
||||
|
||||
// Security Policy
|
||||
dataset.mSecurityPolicy.mRotationTime = static_cast<uint16_t>(mNetif.GetKeyManager().GetKeyRotation());
|
||||
dataset.mSecurityPolicy.mFlags = mNetif.GetKeyManager().GetSecurityPolicyFlags();
|
||||
dataset.mIsSecurityPolicySet = true;
|
||||
|
||||
mLocal.Set(dataset);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void ActiveDataset::StartLeader(void)
|
||||
{
|
||||
if (mLocal.GetTimestamp() == NULL)
|
||||
{
|
||||
otOperationalDataset dataset;
|
||||
|
||||
memset(&dataset, 0, sizeof(dataset));
|
||||
|
||||
// Active Timestamp
|
||||
dataset.mActiveTimestamp = 0;
|
||||
dataset.mIsActiveTimestampSet = true;
|
||||
|
||||
// Channel
|
||||
dataset.mChannel = mNetif.GetMac().GetChannel();
|
||||
dataset.mIsChannelSet = true;
|
||||
|
||||
// channelMask
|
||||
dataset.mChannelMaskPage0 = kPhySupportedChannelMask;
|
||||
dataset.mIsChannelMaskPage0Set = true;
|
||||
|
||||
// Extended PAN ID
|
||||
memcpy(dataset.mExtendedPanId.m8, mNetif.GetMac().GetExtendedPanId(), sizeof(dataset.mExtendedPanId));
|
||||
dataset.mIsExtendedPanIdSet = true;
|
||||
|
||||
// Mesh-Local Prefix
|
||||
memcpy(dataset.mMeshLocalPrefix.m8, mNetif.GetMle().GetMeshLocalPrefix(), sizeof(dataset.mMeshLocalPrefix));
|
||||
dataset.mIsMeshLocalPrefixSet = true;
|
||||
|
||||
// Master Key
|
||||
const uint8_t *key;
|
||||
uint8_t keyLength;
|
||||
key = mNetif.GetKeyManager().GetMasterKey(&keyLength);
|
||||
memcpy(dataset.mMasterKey.m8, key, keyLength);
|
||||
dataset.mIsMasterKeySet = true;
|
||||
|
||||
// Network Name
|
||||
const char *name;
|
||||
name = mNetif.GetMac().GetNetworkName();
|
||||
memcpy(dataset.mNetworkName.m8, name, strlen(name));
|
||||
dataset.mIsNetworkNameSet = true;
|
||||
|
||||
// Pan ID
|
||||
dataset.mPanId = mNetif.GetMac().GetPanId();
|
||||
dataset.mIsPanIdSet = true;
|
||||
|
||||
// PSKc
|
||||
memset(dataset.mPSKc.m8, 0, OT_PSKC_MAX_SIZE);
|
||||
dataset.mIsPSKcSet = true;
|
||||
|
||||
// Security Policy
|
||||
dataset.mSecurityPolicy.mRotationTime = static_cast<uint16_t>(mNetif.GetKeyManager().GetKeyRotation());
|
||||
dataset.mSecurityPolicy.mFlags = mNetif.GetKeyManager().GetSecurityPolicyFlags();
|
||||
dataset.mIsSecurityPolicySet = true;
|
||||
|
||||
mLocal.Set(dataset);
|
||||
GenerateLocal();
|
||||
}
|
||||
|
||||
mLocal.Store();
|
||||
|
||||
@@ -50,6 +50,8 @@ class ActiveDataset: public ActiveDatasetBase
|
||||
public:
|
||||
ActiveDataset(ThreadNetif &aThreadNetif);
|
||||
|
||||
ThreadError GenerateLocal(void);
|
||||
|
||||
void StartLeader(void);
|
||||
|
||||
void StopLeader(void);
|
||||
|
||||
@@ -48,6 +48,8 @@ class ActiveDataset: public ActiveDatasetBase
|
||||
public:
|
||||
ActiveDataset(ThreadNetif &aThreadNetif) : ActiveDatasetBase(aThreadNetif) { }
|
||||
|
||||
ThreadError GenerateLocal(void) { return kThreadError_NotImplemented; }
|
||||
|
||||
void StartLeader(void) { }
|
||||
|
||||
void StopLeader(void) { }
|
||||
|
||||
@@ -289,6 +289,16 @@
|
||||
#define OPENTHREAD_CONFIG_MAC_WHITELIST_SIZE 32
|
||||
#endif // OPENTHREAD_CONFIG_MAC_WHITELIST_SIZE
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD
|
||||
*
|
||||
* The value ahead of the current frame counter for persistent storage
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD
|
||||
#define OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD 1000
|
||||
#endif // OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_LEVEL
|
||||
*
|
||||
|
||||
+4
-10
@@ -1147,12 +1147,9 @@ otInstance *otInstanceInit(void *aInstanceBuffer, size_t *aInstanceBufferSize)
|
||||
// Construct the context
|
||||
aInstance = new(aInstanceBuffer)otInstance();
|
||||
|
||||
// restore datasets
|
||||
// restore datasets and network information
|
||||
otPlatSettingsInit(aInstance);
|
||||
|
||||
aInstance->mThreadNetif.GetActiveDataset().Restore();
|
||||
|
||||
aInstance->mThreadNetif.GetPendingDataset().Restore();
|
||||
aInstance->mThreadNetif.GetMle().Restore();
|
||||
|
||||
exit:
|
||||
|
||||
@@ -1173,12 +1170,9 @@ otInstance *otInstanceInit()
|
||||
// Construct the context
|
||||
sInstance = new(&sInstanceRaw)otInstance();
|
||||
|
||||
// restore datasets
|
||||
// restore datasets and network information
|
||||
otPlatSettingsInit(sInstance);
|
||||
|
||||
sInstance->mThreadNetif.GetActiveDataset().Restore();
|
||||
|
||||
sInstance->mThreadNetif.GetPendingDataset().Restore();
|
||||
sInstance->mThreadNetif.GetMle().Restore();
|
||||
|
||||
exit:
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ KeyManager::KeyManager(ThreadNetif &aThreadNetif):
|
||||
mKeySequence = 0;
|
||||
mMacFrameCounter = 0;
|
||||
mMleFrameCounter = 0;
|
||||
mStoredMleFrameCounter = 0;
|
||||
mStoredMacFrameCounter = 0;
|
||||
|
||||
mKeyRotationTime = kDefaultKeyRotationTime;
|
||||
mKeySwitchGuardTime = kDefaultKeySwitchGuardTime;
|
||||
@@ -203,9 +205,24 @@ uint32_t KeyManager::GetMacFrameCounter(void) const
|
||||
return mMacFrameCounter;
|
||||
}
|
||||
|
||||
void KeyManager::SetMacFrameCounter(uint32_t aMacFrameCounter)
|
||||
{
|
||||
mMacFrameCounter = aMacFrameCounter;
|
||||
}
|
||||
|
||||
void KeyManager::SetStoredMacFrameCounter(uint32_t aStoredMacFrameCounter)
|
||||
{
|
||||
mStoredMacFrameCounter = aStoredMacFrameCounter;
|
||||
}
|
||||
|
||||
void KeyManager::IncrementMacFrameCounter(void)
|
||||
{
|
||||
mMacFrameCounter++;
|
||||
|
||||
if (mMacFrameCounter >= mStoredMacFrameCounter)
|
||||
{
|
||||
mNetif.GetMle().Store();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t KeyManager::GetMleFrameCounter(void) const
|
||||
@@ -213,9 +230,24 @@ uint32_t KeyManager::GetMleFrameCounter(void) const
|
||||
return mMleFrameCounter;
|
||||
}
|
||||
|
||||
void KeyManager::SetMleFrameCounter(uint32_t aMleFrameCounter)
|
||||
{
|
||||
mMleFrameCounter = aMleFrameCounter;
|
||||
}
|
||||
|
||||
void KeyManager::SetStoredMleFrameCounter(uint32_t aStoredMleFrameCounter)
|
||||
{
|
||||
mStoredMleFrameCounter = aStoredMleFrameCounter;
|
||||
}
|
||||
|
||||
void KeyManager::IncrementMleFrameCounter(void)
|
||||
{
|
||||
mMleFrameCounter++;
|
||||
|
||||
if (mMleFrameCounter >= mStoredMleFrameCounter)
|
||||
{
|
||||
mNetif.GetMle().Store();
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t *KeyManager::GetKek(void) const
|
||||
|
||||
@@ -158,6 +158,22 @@ public:
|
||||
*/
|
||||
uint32_t GetMacFrameCounter(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the current MAC Frame Counter value.
|
||||
*
|
||||
* @param[in] aMacFrameCounter The MAC Frame Counter value.
|
||||
*
|
||||
*/
|
||||
void SetMacFrameCounter(uint32_t aMacFrameCounter);
|
||||
|
||||
/**
|
||||
* This method sets the MAC Frame Counter value which is stored in non-volatile memory.
|
||||
*
|
||||
* @param[in] aStoredMacFrameCounter The stored MAC Frame Counter value.
|
||||
*
|
||||
*/
|
||||
void SetStoredMacFrameCounter(uint32_t aStoredMacFrameCounter);
|
||||
|
||||
/**
|
||||
* This method increments the current MAC Frame Counter value.
|
||||
*
|
||||
@@ -172,6 +188,22 @@ public:
|
||||
*/
|
||||
uint32_t GetMleFrameCounter(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the current MLE Frame Counter value.
|
||||
*
|
||||
* @param[in] aMleFrameCounter The MLE Frame Counter value.
|
||||
*
|
||||
*/
|
||||
void SetMleFrameCounter(uint32_t aMleFrameCounter);
|
||||
|
||||
/**
|
||||
* This method sets the MLE Frame Counter value which is stored in non-volatile memory.
|
||||
*
|
||||
* @param[in] aStoredMleFrameCounter The stored MLE Frame Counter value.
|
||||
*
|
||||
*/
|
||||
void SetStoredMleFrameCounter(uint32_t aStoredMleFrameCounter);
|
||||
|
||||
/**
|
||||
* This method increments the current MLE Frame Counter value.
|
||||
*
|
||||
@@ -300,6 +332,8 @@ private:
|
||||
|
||||
uint32_t mMacFrameCounter;
|
||||
uint32_t mMleFrameCounter;
|
||||
uint32_t mStoredMacFrameCounter;
|
||||
uint32_t mStoredMleFrameCounter;
|
||||
|
||||
uint32_t mKeyRotationTime;
|
||||
uint32_t mKeySwitchGuardTime;
|
||||
|
||||
+244
-4
@@ -38,6 +38,7 @@
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <common/encoding.hpp>
|
||||
#include <common/settings.hpp>
|
||||
#include <crypto/aes_ccm.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <meshcop/tlvs.hpp>
|
||||
@@ -45,6 +46,7 @@
|
||||
#include <net/udp6.hpp>
|
||||
#include <platform/radio.h>
|
||||
#include <platform/random.h>
|
||||
#include <platform/settings.h>
|
||||
#include <thread/address_resolver.hpp>
|
||||
#include <thread/key_manager.hpp>
|
||||
#include <thread/mle_router.hpp>
|
||||
@@ -253,6 +255,85 @@ ThreadError Mle::Stop(bool aClearNetworkDatasets)
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Mle::Restore()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
NetworkInfo networkInfo;
|
||||
uint16_t length;
|
||||
|
||||
mNetif.GetActiveDataset().Restore();
|
||||
mNetif.GetPendingDataset().Restore();
|
||||
|
||||
SuccessOrExit(error = otPlatSettingsGet(mNetif.GetInstance(), kKeyNetworkInfo, 0,
|
||||
reinterpret_cast<uint8_t *>(&networkInfo), &length));
|
||||
|
||||
VerifyOrExit(length == sizeof(networkInfo), error = kThreadError_NotFound);
|
||||
VerifyOrExit(networkInfo.mDeviceState >= kDeviceStateChild, error = kThreadError_NotFound);
|
||||
|
||||
mDeviceMode = networkInfo.mDeviceMode;
|
||||
SetRloc16(networkInfo.mRloc16);
|
||||
mKeyManager.SetCurrentKeySequence(networkInfo.mKeySequence);
|
||||
mKeyManager.SetMleFrameCounter(networkInfo.mMleFrameCounter);
|
||||
mKeyManager.SetMacFrameCounter(networkInfo.mMacFrameCounter);
|
||||
mMac.SetExtAddress(networkInfo.mExtAddress);
|
||||
UpdateLinkLocalAddress();
|
||||
|
||||
if (networkInfo.mDeviceState == kDeviceStateChild)
|
||||
{
|
||||
SuccessOrExit(error = otPlatSettingsGet(mNetif.GetInstance(), kKeyParentInfo, 0,
|
||||
reinterpret_cast<uint8_t *>(&mParent), &length));
|
||||
}
|
||||
else if (networkInfo.mDeviceState == kDeviceStateRouter || networkInfo.mDeviceState == kDeviceStateLeader)
|
||||
{
|
||||
mMleRouter.SetRouterId(GetRouterId(GetRloc16()));
|
||||
mMleRouter.RestoreChildren();
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::Store()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
NetworkInfo networkInfo;
|
||||
|
||||
VerifyOrExit(IsAttached(), error = kThreadError_InvalidState);
|
||||
|
||||
if (mNetif.GetActiveDataset().GetLocal().GetTimestamp() == NULL)
|
||||
{
|
||||
mNetif.GetActiveDataset().GenerateLocal();
|
||||
mNetif.GetActiveDataset().GetLocal().Store();
|
||||
}
|
||||
|
||||
memset(&networkInfo, 0, sizeof(networkInfo));
|
||||
|
||||
networkInfo.mDeviceMode = mDeviceMode;
|
||||
networkInfo.mDeviceState = mDeviceState;
|
||||
networkInfo.mRloc16 = GetRloc16();
|
||||
networkInfo.mKeySequence = mKeyManager.GetCurrentKeySequence();
|
||||
networkInfo.mMleFrameCounter = mKeyManager.GetMleFrameCounter() + OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD;
|
||||
networkInfo.mMacFrameCounter = mKeyManager.GetMacFrameCounter() + OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD;
|
||||
memcpy(networkInfo.mExtAddress.m8, mMac.GetExtAddress(), sizeof(networkInfo.mExtAddress));
|
||||
|
||||
if (mDeviceState == kDeviceStateChild)
|
||||
{
|
||||
SuccessOrExit(error = otPlatSettingsSet(mNetif.GetInstance(), kKeyParentInfo,
|
||||
reinterpret_cast<uint8_t *>(&mParent), sizeof(mParent)));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = otPlatSettingsSet(mNetif.GetInstance(), kKeyNetworkInfo,
|
||||
reinterpret_cast<uint8_t *>(&networkInfo), sizeof(networkInfo)));
|
||||
|
||||
mKeyManager.SetStoredMleFrameCounter(networkInfo.mMleFrameCounter);
|
||||
mKeyManager.SetStoredMacFrameCounter(networkInfo.mMacFrameCounter);
|
||||
|
||||
otLogDebgMle("Store Network Information");
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::Discover(uint32_t aScanChannels, uint16_t aScanDuration, uint16_t aPanId,
|
||||
DiscoverHandler aCallback, void *aContext)
|
||||
{
|
||||
@@ -1068,6 +1149,8 @@ void Mle::HandleNetifStateChanged(uint32_t aFlags, void *aContext)
|
||||
|
||||
void Mle::HandleNetifStateChanged(uint32_t aFlags)
|
||||
{
|
||||
VerifyOrExit(mDeviceState != kDeviceStateDisabled, ;);
|
||||
|
||||
if ((aFlags & (OT_IP6_ADDRESS_ADDED | OT_IP6_ADDRESS_REMOVED)) != 0)
|
||||
{
|
||||
if (!mNetif.IsUnicastAddress(mMeshLocal64.GetAddress()))
|
||||
@@ -1101,6 +1184,14 @@ void Mle::HandleNetifStateChanged(uint32_t aFlags)
|
||||
|
||||
mNetif.GetNetworkDataLocal().SendServerDataNotification();
|
||||
}
|
||||
|
||||
if (aFlags & (OT_NET_ROLE | OT_NET_KEY_SEQUENCE_COUNTER))
|
||||
{
|
||||
Store();
|
||||
}
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
void Mle::HandleParentRequestTimer(void *aContext)
|
||||
@@ -1453,7 +1544,7 @@ ThreadError Mle::SendChildUpdateRequest(void)
|
||||
destination.SetIid(mParent.mMacAddr);
|
||||
SuccessOrExit(error = SendMessage(*message, destination));
|
||||
|
||||
otLogInfoMle("Sent Child Update Request");
|
||||
otLogInfoMle("Sent Child Update Request to parent");
|
||||
|
||||
if ((mDeviceMode & ModeTlv::kModeRxOnWhenIdle) == 0)
|
||||
{
|
||||
@@ -1471,6 +1562,65 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const ChallengeTlv &aChallenge)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Ip6::Address destination;
|
||||
Message *message;
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, ;);
|
||||
message->SetLinkSecurityEnabled(false);
|
||||
SuccessOrExit(error = AppendHeader(*message, Header::kCommandChildUpdateResponse));
|
||||
SuccessOrExit(error = AppendSourceAddress(*message));
|
||||
SuccessOrExit(error = AppendLeaderData(*message));
|
||||
|
||||
for (int i = 0; i < aNumTlvs; i++)
|
||||
{
|
||||
switch (aTlvs[i])
|
||||
{
|
||||
case Tlv::kTimeout:
|
||||
SuccessOrExit(error = AppendTimeout(*message, mTimeout));
|
||||
break;
|
||||
|
||||
case Tlv::kAddressRegistration:
|
||||
if ((mDeviceMode & ModeTlv::kModeFFD) == 0)
|
||||
{
|
||||
SuccessOrExit(error = AppendAddressRegistration(*message));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Tlv::kResponse:
|
||||
SuccessOrExit(error = AppendResponse(*message, aChallenge.GetChallenge(), aChallenge.GetLength()));
|
||||
break;
|
||||
|
||||
case Tlv::kLinkFrameCounter:
|
||||
SuccessOrExit(error = AppendLinkFrameCounter(*message));
|
||||
break;
|
||||
|
||||
case Tlv::kMleFrameCounter:
|
||||
SuccessOrExit(error = AppendMleFrameCounter(*message));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&destination, 0, sizeof(destination));
|
||||
destination.mFields.m16[0] = HostSwap16(0xfe80);
|
||||
destination.SetIid(mParent.mMacAddr);
|
||||
SuccessOrExit(error = SendMessage(*message, destination));
|
||||
|
||||
otLogInfoMle("Sent Child Update Response to parent");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
@@ -1793,6 +1943,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
command == Header::kCommandParentResponse ||
|
||||
command == Header::kCommandChildIdRequest ||
|
||||
command == Header::kCommandChildUpdateRequest ||
|
||||
command == Header::kCommandChildUpdateResponse ||
|
||||
command == Header::kCommandAnnounce))
|
||||
{
|
||||
otLogDebgMle("mle sequence unknown! %d", command);
|
||||
@@ -1843,11 +1994,27 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
break;
|
||||
|
||||
case Header::kCommandChildUpdateRequest:
|
||||
mMleRouter.HandleChildUpdateRequest(aMessage, aMessageInfo);
|
||||
if (mDeviceState == kDeviceStateLeader || mDeviceState == kDeviceStateRouter)
|
||||
{
|
||||
mMleRouter.HandleChildUpdateRequest(aMessage, aMessageInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleChildUpdateRequest(aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Header::kCommandChildUpdateResponse:
|
||||
HandleChildUpdateResponse(aMessage, aMessageInfo);
|
||||
if (mDeviceState == kDeviceStateLeader || mDeviceState == kDeviceStateRouter)
|
||||
{
|
||||
mMleRouter.HandleChildUpdateResponse(aMessage, aMessageInfo, keySequence);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleChildUpdateResponse(aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Header::kCommandAnnounce:
|
||||
@@ -2397,6 +2564,79 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
static const uint8_t kMaxResponseTlvs = 5;
|
||||
|
||||
ThreadError error = kThreadError_None;
|
||||
SourceAddressTlv sourceAddress;
|
||||
LeaderDataTlv leaderData;
|
||||
NetworkDataTlv networkData;
|
||||
ChallengeTlv challenge;
|
||||
TlvRequestTlv tlvRequest;
|
||||
uint8_t dataRequestTlvs[] = {Tlv::kNetworkData};
|
||||
uint8_t tlvs[kMaxResponseTlvs];
|
||||
uint8_t numTlvs = 0;
|
||||
|
||||
otLogInfoMle("Received Child Update Request from parent");
|
||||
|
||||
// Source Address
|
||||
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
|
||||
VerifyOrExit(sourceAddress.IsValid(), error = kThreadError_Parse);
|
||||
VerifyOrExit(mParent.mValid.mRloc16 == sourceAddress.GetRloc16(), error = kThreadError_Drop);
|
||||
|
||||
// Leader Data
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(leaderData.IsValid(), error = kThreadError_Parse);
|
||||
SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());
|
||||
|
||||
if ((mDeviceMode & ModeTlv::kModeFullNetworkData && leaderData.GetDataVersion() != mNetworkData.GetVersion()) ||
|
||||
((mDeviceMode & ModeTlv::kModeFullNetworkData) == 0 &&
|
||||
leaderData.GetStableDataVersion() != mNetworkData.GetStableVersion()))
|
||||
{
|
||||
mRetrieveNewNetworkData = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Network Data
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kNetworkData, sizeof(networkData), networkData) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(networkData.IsValid(), error = kThreadError_Parse);
|
||||
mNetworkData.SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(),
|
||||
(mDeviceMode & ModeTlv::kModeFullNetworkData) == 0,
|
||||
networkData.GetNetworkData(), networkData.GetLength());
|
||||
}
|
||||
|
||||
// TLV Request
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(tlvRequest.IsValid() && tlvRequest.GetLength() <= sizeof(tlvs), error = kThreadError_Parse);
|
||||
memcpy(tlvs, tlvRequest.GetTlvs(), tlvRequest.GetLength());
|
||||
numTlvs += tlvRequest.GetLength();
|
||||
}
|
||||
|
||||
// Challenge
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(challenge.IsValid(), error = kThreadError_Parse);
|
||||
VerifyOrExit(static_cast<size_t>(numTlvs + 3) <= sizeof(tlvs), error = kThreadError_NoBufs);
|
||||
tlvs[numTlvs++] = Tlv::kResponse;
|
||||
tlvs[numTlvs++] = Tlv::kMleFrameCounter;
|
||||
tlvs[numTlvs++] = Tlv::kLinkFrameCounter;
|
||||
}
|
||||
|
||||
if (mRetrieveNewNetworkData)
|
||||
{
|
||||
SendDataRequest(aMessageInfo.GetPeerAddr(), dataRequestTlvs, sizeof(tlvs));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = SendChildUpdateResponse(tlvs, numTlvs, challenge));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::HandleChildUpdateResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
@@ -2409,7 +2649,7 @@ ThreadError Mle::HandleChildUpdateResponse(const Message &aMessage, const Ip6::M
|
||||
NetworkDataTlv networkData;
|
||||
uint8_t tlvs[] = {Tlv::kNetworkData};
|
||||
|
||||
otLogInfoMle("Received Child Update Response");
|
||||
otLogInfoMle("Received Child Update Response from parent");
|
||||
|
||||
// Status
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kStatus, sizeof(status), status) == kThreadError_None)
|
||||
|
||||
@@ -393,6 +393,24 @@ public:
|
||||
*/
|
||||
ThreadError Stop(bool aClearNetworkDatasets);
|
||||
|
||||
/**
|
||||
* This method restores network information from non-volatile memory.
|
||||
*
|
||||
* @retval kThreadError_None Successfully restore the network information.
|
||||
* @retval kThreadError_NotFound There is no valid network information stored in non-volatile memory.
|
||||
*
|
||||
*/
|
||||
ThreadError Restore(void);
|
||||
|
||||
/**
|
||||
* This method stores network information into non-volatile memory.
|
||||
*
|
||||
* @retval kThreadError_None Successfully store the network information.
|
||||
* @retval kThreadError_NoBufs Could not store the network information due to insufficient memory space.
|
||||
*
|
||||
*/
|
||||
ThreadError Store(void);
|
||||
|
||||
/**
|
||||
* This function pointer is called on receiving an MLE Discovery Response message.
|
||||
*
|
||||
@@ -1075,6 +1093,19 @@ protected:
|
||||
*/
|
||||
ThreadError SendChildUpdateRequest(void);
|
||||
|
||||
/**
|
||||
* This method generates an MLE Child Update Response message.
|
||||
*
|
||||
* @param[in] aTlvs A pointer to requested TLV types.
|
||||
* @param[in] aNumTlvs The number of TLV types in @p aTlvs.
|
||||
* @param[in] aChallenge The Challenge TLV for the response.
|
||||
*
|
||||
* @retval kThreadError_None Successfully generated an MLE Child Update Response message.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers to generate the MLE Child Update Response message.
|
||||
*
|
||||
*/
|
||||
ThreadError SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const ChallengeTlv &aChallenge);
|
||||
|
||||
/**
|
||||
* This method submits an MLE message to the UDP socket.
|
||||
*
|
||||
@@ -1205,6 +1236,7 @@ private:
|
||||
|
||||
ThreadError HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleChildIdResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleChildUpdateResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleDataResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleParentResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
|
||||
@@ -1218,6 +1250,22 @@ private:
|
||||
|
||||
bool IsBetterParent(uint16_t aRloc16, uint8_t aLinkQuality, ConnectivityTlv &aConnectivityTlv) const;
|
||||
|
||||
/**
|
||||
* This struct represents the device's own network information for persistent storage.
|
||||
*
|
||||
*/
|
||||
typedef struct NetworkInfo
|
||||
{
|
||||
DeviceState mDeviceState; ///< Current Thread interface state.
|
||||
|
||||
uint8_t mDeviceMode; ///< Device mode setting.
|
||||
uint16_t mRloc16; ///< RLOC16
|
||||
uint32_t mKeySequence; ///< Key Sequence
|
||||
uint32_t mMleFrameCounter; ///< MLE Frame Counter
|
||||
uint32_t mMacFrameCounter; ///< MAC Frame Counter
|
||||
Mac::ExtAddress mExtAddress; ///< Extended Address
|
||||
} NetworkInfo;
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t mChallenge[ChallengeTlv::kMaxSize];
|
||||
|
||||
@@ -63,6 +63,8 @@ enum
|
||||
kParentResponseMaxDelayAll = 1000, ///< Maximum delay for response for Parent Request sent to all devices
|
||||
kMaxResponseDelay = 1000, ///< Maximum delay before responding to a multicast request
|
||||
kMaxChildIdRequestTimeout = 5000, ///< Maximum delay for receiving a Child ID Request
|
||||
kChildUpdateRequestPeriod = 100, ///< The period for sending Child Update Request
|
||||
kMaxChildUpdateResponseTimeout = 2000, ///< Maximum delay for receiving a Child Update Response
|
||||
};
|
||||
|
||||
enum
|
||||
|
||||
@@ -37,9 +37,11 @@
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <common/encoding.hpp>
|
||||
#include <common/settings.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <net/icmp6.hpp>
|
||||
#include <platform/random.h>
|
||||
#include <platform/settings.h>
|
||||
#include <thread/mle_router.hpp>
|
||||
#include <thread/thread_netif.hpp>
|
||||
#include <thread/thread_tlvs.hpp>
|
||||
@@ -55,6 +57,7 @@ MleRouter::MleRouter(ThreadNetif &aThreadNetif):
|
||||
mAdvertiseTimer(aThreadNetif.GetIp6().mTimerScheduler, &MleRouter::HandleAdvertiseTimer, NULL, this),
|
||||
mStateUpdateTimer(aThreadNetif.GetIp6().mTimerScheduler, &MleRouter::HandleStateUpdateTimer, this),
|
||||
mDelayedResponseTimer(aThreadNetif.GetIp6().mTimerScheduler, &MleRouter::HandleDelayedResponseTimer, this),
|
||||
mChildUpdateRequestTimer(aThreadNetif.GetIp6().mTimerScheduler, &MleRouter::HandleChildUpdateRequestTimer, this),
|
||||
mAddressSolicit(OPENTHREAD_URI_ADDRESS_SOLICIT, &MleRouter::HandleAddressSolicit, this),
|
||||
mAddressRelease(OPENTHREAD_URI_ADDRESS_RELEASE, &MleRouter::HandleAddressRelease, this),
|
||||
mCoapServer(aThreadNetif.GetCoapServer()),
|
||||
@@ -371,6 +374,15 @@ ThreadError MleRouter::SetStateRouter(uint16_t aRloc16)
|
||||
mNetif.GetIp6().SetForwardingEnabled(true);
|
||||
mNetif.GetIp6().mMpl.SetTimerExpirations(kMplRouterDataMessageTimerExpirations);
|
||||
|
||||
for (int i = 0; i < mMaxChildrenAllowed; i++)
|
||||
{
|
||||
if (mChildren[i].mState == Neighbor::kStateRestored)
|
||||
{
|
||||
mChildUpdateRequestTimer.Start(kChildUpdateRequestPeriod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
otLogInfoMle("Mode -> Router");
|
||||
return kThreadError_None;
|
||||
}
|
||||
@@ -399,6 +411,15 @@ ThreadError MleRouter::SetStateLeader(uint16_t aRloc16)
|
||||
mNetif.GetIp6().SetForwardingEnabled(true);
|
||||
mNetif.GetIp6().mMpl.SetTimerExpirations(kMplRouterDataMessageTimerExpirations);
|
||||
|
||||
for (int i = 0; i < mMaxChildrenAllowed; i++)
|
||||
{
|
||||
if (mChildren[i].mState == Neighbor::kStateRestored)
|
||||
{
|
||||
mChildUpdateRequestTimer.Start(kChildUpdateRequestPeriod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
otLogInfoMle("Mode -> Leader %d", mLeaderData.GetPartitionId());
|
||||
return kThreadError_None;
|
||||
}
|
||||
@@ -1614,7 +1635,7 @@ ThreadError MleRouter::HandleParentRequest(const Message &aMessage, const Ip6::M
|
||||
child->mDataRequest = false;
|
||||
|
||||
child->mLastHeard = Timer::GetNow();
|
||||
child->mTimeout = Timer::SecToMsec(2 * kParentRequestChildTimeout);
|
||||
child->mTimeout = Timer::MsecToSec(kMaxChildIdRequestTimeout);
|
||||
SuccessOrExit(error = SendParentResponse(child, challenge, !scanMask.IsEndDeviceFlagSet()));
|
||||
|
||||
exit:
|
||||
@@ -1704,10 +1725,9 @@ void MleRouter::HandleStateUpdateTimer(void)
|
||||
continue;
|
||||
|
||||
case Neighbor::kStateParentRequest:
|
||||
timeout = kMaxChildIdRequestTimeout;
|
||||
break;
|
||||
|
||||
case Neighbor::kStateValid:
|
||||
case Neighbor::kStateRestored:
|
||||
case Neighbor::kStateChildUpdateRequest:
|
||||
timeout = Timer::SecToMsec(mChildren[i].mTimeout);
|
||||
break;
|
||||
|
||||
@@ -1817,6 +1837,36 @@ void MleRouter::HandleDelayedResponseTimer(void)
|
||||
}
|
||||
}
|
||||
|
||||
void MleRouter::HandleChildUpdateRequestTimer(void *aContext)
|
||||
{
|
||||
static_cast<MleRouter *>(aContext)->HandleChildUpdateRequestTimer();
|
||||
}
|
||||
|
||||
void MleRouter::HandleChildUpdateRequestTimer(void)
|
||||
{
|
||||
VerifyOrExit(GetDeviceState() == kDeviceStateRouter || GetDeviceState() == kDeviceStateLeader, ;);
|
||||
|
||||
for (int i = 0; i < mMaxChildrenAllowed; i++)
|
||||
{
|
||||
if (mChildren[i].mState == Neighbor::kStateRestored)
|
||||
{
|
||||
SendChildUpdateRequest(&mChildren[i]);
|
||||
mChildren[i].mState = Neighbor::kStateChildUpdateRequest;
|
||||
|
||||
if ((mChildren[i].mMode & ModeTlv::kModeRxOnWhenIdle) != 0)
|
||||
{
|
||||
mChildren[i].mTimeout = Timer::MsecToSec(kMaxChildUpdateResponseTimeout);
|
||||
}
|
||||
|
||||
mChildUpdateRequestTimer.Start(kChildUpdateRequestPeriod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
ThreadError MleRouter::AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
@@ -2116,7 +2166,7 @@ ThreadError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const I
|
||||
uint8_t tlvs[kMaxResponseTlvs];
|
||||
uint8_t tlvslength = 0;
|
||||
|
||||
otLogInfoMle("Received Child Update Request");
|
||||
otLogInfoMle("Received Child Update Request from child");
|
||||
|
||||
// Find Child
|
||||
macAddr.Set(aMessageInfo.GetPeerAddr());
|
||||
@@ -2195,6 +2245,7 @@ ThreadError MleRouter::HandleChildUpdateRequest(const Message &aMessage, const I
|
||||
|
||||
child->mLastHeard = Timer::GetNow();
|
||||
child->mAddSrcMatchEntryShort = true;
|
||||
child->mState = Neighbor::kStateValid;
|
||||
|
||||
SendChildUpdateResponse(child, aMessageInfo, tlvs, tlvslength, &challenge);
|
||||
|
||||
@@ -2202,6 +2253,95 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError MleRouter::HandleChildUpdateResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
|
||||
uint32_t aKeySequence)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
const ThreadMessageInfo *threadMessageInfo = static_cast<const ThreadMessageInfo *>(aMessageInfo.GetLinkInfo());
|
||||
Mac::ExtAddress macAddr;
|
||||
SourceAddressTlv sourceAddress;
|
||||
TimeoutTlv timeout;
|
||||
AddressRegistrationTlv address;
|
||||
ResponseTlv response;
|
||||
LinkFrameCounterTlv linkFrameCounter;
|
||||
MleFrameCounterTlv mleFrameCounter;
|
||||
LeaderDataTlv leaderData;
|
||||
Child *child;
|
||||
|
||||
otLogInfoMle("Received Child Update Response from child");
|
||||
|
||||
// Find Child
|
||||
macAddr.Set(aMessageInfo.GetPeerAddr());
|
||||
|
||||
VerifyOrExit((child = FindChild(macAddr)) != NULL, error = kThreadError_NotFound);
|
||||
|
||||
// Source Address
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(sourceAddress.IsValid(), error = kThreadError_Parse);
|
||||
VerifyOrExit(child->mValid.mRloc16 == sourceAddress.GetRloc16(), error = kThreadError_Parse);
|
||||
}
|
||||
|
||||
// Response
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kResponse, sizeof(response), response) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(response.IsValid() &&
|
||||
memcmp(response.GetResponse(), child->mPending.mChallenge, sizeof(child->mPending.mChallenge)) == 0, ;);
|
||||
}
|
||||
|
||||
// Link-Layer Frame Counter
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kLinkFrameCounter, sizeof(linkFrameCounter), linkFrameCounter) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(linkFrameCounter.IsValid(), error = kThreadError_Parse);
|
||||
child->mValid.mLinkFrameCounter = linkFrameCounter.GetFrameCounter();
|
||||
}
|
||||
|
||||
// MLE Frame Counter
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kMleFrameCounter, sizeof(mleFrameCounter), mleFrameCounter) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(mleFrameCounter.IsValid(), error = kThreadError_Parse);
|
||||
child->mValid.mMleFrameCounter = mleFrameCounter.GetFrameCounter();
|
||||
}
|
||||
|
||||
// Timeout
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kTimeout, sizeof(timeout), timeout) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(timeout.IsValid(), error = kThreadError_Parse);
|
||||
child->mTimeout = timeout.GetTimeout();
|
||||
}
|
||||
|
||||
// Ip6 Address
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kAddressRegistration, sizeof(address), address) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(address.IsValid(), error = kThreadError_Parse);
|
||||
UpdateChildAddresses(address, *child);
|
||||
}
|
||||
|
||||
// Leader Data
|
||||
if (Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData) == kThreadError_None)
|
||||
{
|
||||
VerifyOrExit(leaderData.IsValid(), error = kThreadError_Parse);
|
||||
|
||||
if (child->mMode & ModeTlv::kModeFullNetworkData)
|
||||
{
|
||||
child->mNetworkDataVersion = leaderData.GetDataVersion();
|
||||
}
|
||||
else
|
||||
{
|
||||
child->mNetworkDataVersion = leaderData.GetStableDataVersion();
|
||||
}
|
||||
}
|
||||
|
||||
child->mLastHeard = Timer::GetNow();
|
||||
child->mKeySequence = aKeySequence;
|
||||
child->mLinkInfo.AddRss(mMac.GetNoiseFloor(), threadMessageInfo->mRss);
|
||||
child->mAddSrcMatchEntryShort = true;
|
||||
child->mState = Neighbor::kStateValid;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError MleRouter::HandleDataRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
@@ -2533,6 +2673,7 @@ ThreadError MleRouter::SendChildIdResponse(Child *aChild)
|
||||
|
||||
aChild->mState = Neighbor::kStateValid;
|
||||
mNetif.SetStateChangedFlags(OT_THREAD_CHILD_ADDED);
|
||||
StoreChild(aChild->mValid.mRloc16);
|
||||
|
||||
memset(&destination, 0, sizeof(destination));
|
||||
destination.mFields.m16[0] = HostSwap16(0xfe80);
|
||||
@@ -2551,6 +2692,46 @@ exit:
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError MleRouter::SendChildUpdateRequest(Child *aChild)
|
||||
{
|
||||
static const uint8_t tlvs[] = {Tlv::kTimeout, Tlv::kAddressRegistration};
|
||||
ThreadError error = kThreadError_None;
|
||||
Ip6::Address destination;
|
||||
Message *message;
|
||||
|
||||
VerifyOrExit((message = NewMessage()) != NULL, ;);
|
||||
message->SetLinkSecurityEnabled(false);
|
||||
SuccessOrExit(error = AppendHeader(*message, Header::kCommandChildUpdateRequest));
|
||||
SuccessOrExit(error = AppendSourceAddress(*message));
|
||||
SuccessOrExit(error = AppendLeaderData(*message));
|
||||
SuccessOrExit(error = AppendNetworkData(*message, (aChild->mMode & ModeTlv::kModeFullNetworkData) == 0));
|
||||
SuccessOrExit(error = AppendTlvRequest(*message, tlvs, sizeof(tlvs)));
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(aChild->mPending.mChallenge); i++)
|
||||
{
|
||||
aChild->mPending.mChallenge[i] = static_cast<uint8_t>(otPlatRandomGet());
|
||||
}
|
||||
|
||||
SuccessOrExit(error = AppendChallenge(*message, aChild->mPending.mChallenge,
|
||||
sizeof(aChild->mPending.mChallenge)));
|
||||
|
||||
memset(&destination, 0, sizeof(destination));
|
||||
destination.mFields.m16[0] = HostSwap16(0xfe80);
|
||||
destination.SetIid(aChild->mMacAddr);
|
||||
SuccessOrExit(error = SendMessage(*message, destination));
|
||||
|
||||
otLogInfoMle("Sent Child Update Request to child");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError MleRouter::SendChildUpdateResponse(Child *aChild, const Ip6::MessageInfo &aMessageInfo,
|
||||
const uint8_t *aTlvs, uint8_t aTlvslength,
|
||||
const ChallengeTlv *aChallenge)
|
||||
@@ -2602,7 +2783,7 @@ ThreadError MleRouter::SendChildUpdateResponse(Child *aChild, const Ip6::Message
|
||||
|
||||
SuccessOrExit(error = SendMessage(*message, aMessageInfo.GetPeerAddr()));
|
||||
|
||||
otLogInfoMle("Sent Child Update Response");
|
||||
otLogInfoMle("Sent Child Update Response to child");
|
||||
|
||||
exit:
|
||||
|
||||
@@ -2771,6 +2952,7 @@ ThreadError MleRouter::RemoveNeighbor(Neighbor &aNeighbor)
|
||||
mMesh.UpdateIndirectMessages();
|
||||
mNetif.SetStateChangedFlags(OT_THREAD_CHILD_REMOVED);
|
||||
mNetworkData.SendServerDataNotification(aNeighbor.mValid.mRloc16);
|
||||
RemoveStoredChild(aNeighbor.mValid.mRloc16);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -3045,6 +3227,11 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MleRouter::SetRouterId(uint8_t aRouterId)
|
||||
{
|
||||
mRouterId = aRouterId;
|
||||
}
|
||||
|
||||
Router *MleRouter::GetRouters(uint8_t *aNumRouters)
|
||||
{
|
||||
if (aNumRouters != NULL)
|
||||
@@ -3107,6 +3294,72 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError MleRouter::RestoreChildren(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Child *child;
|
||||
otChildInfo childInfo;
|
||||
uint16_t length;
|
||||
|
||||
for (uint8_t i = 0; i < kMaxChildren; i++)
|
||||
{
|
||||
SuccessOrExit(otPlatSettingsGet(mNetif.GetInstance(), kKeyChildInfo, i,
|
||||
reinterpret_cast<uint8_t *>(&childInfo), &length));
|
||||
VerifyOrExit((child = NewChild()) != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
memset(child, 0, sizeof(*child));
|
||||
|
||||
memcpy(&child->mMacAddr, &childInfo.mExtAddress, sizeof(child->mMacAddr));
|
||||
child->mValid.mRloc16 = childInfo.mRloc16;
|
||||
child->mTimeout = childInfo.mTimeout;
|
||||
child->mMode = (childInfo.mRxOnWhenIdle ? ModeTlv::kModeRxOnWhenIdle : 0) |
|
||||
(childInfo.mSecureDataRequest ? ModeTlv::kModeSecureDataRequest : 0) |
|
||||
(childInfo.mFullFunction ? ModeTlv::kModeFFD : 0) |
|
||||
(childInfo.mFullNetworkData ? ModeTlv::kModeFullNetworkData : 0);
|
||||
child->mState = Neighbor::kStateRestored;
|
||||
child->mLastHeard = Timer::GetNow();
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError MleRouter::RemoveStoredChild(uint16_t aChildRloc16)
|
||||
{
|
||||
ThreadError error = kThreadError_NotFound;
|
||||
otChildInfo childInfo;
|
||||
uint16_t length;
|
||||
|
||||
for (uint8_t i = 0; i < kMaxChildren; i++)
|
||||
{
|
||||
SuccessOrExit(otPlatSettingsGet(mNetif.GetInstance(), kKeyChildInfo, i,
|
||||
reinterpret_cast<uint8_t *>(&childInfo), &length));
|
||||
|
||||
if (childInfo.mRloc16 == aChildRloc16)
|
||||
{
|
||||
error = otPlatSettingsDelete(mNetif.GetInstance(), kKeyChildInfo, i);
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError MleRouter::StoreChild(uint16_t aChildRloc16)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
otChildInfo childInfo;
|
||||
|
||||
SuccessOrExit(error = mMleRouter.GetChildInfoById(GetChildId(aChildRloc16), childInfo));
|
||||
|
||||
error = otPlatSettingsAdd(mNetif.GetInstance(), kKeyChildInfo, reinterpret_cast<uint8_t *>(&childInfo),
|
||||
sizeof(childInfo));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MleRouter::GetChildInfo(Child &aChild, otChildInfo &aChildInfo)
|
||||
{
|
||||
memset(&aChildInfo, 0, sizeof(aChildInfo));
|
||||
@@ -3438,6 +3691,8 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe
|
||||
break;
|
||||
|
||||
case Neighbor::kStateValid:
|
||||
case Neighbor::kStateRestored:
|
||||
case Neighbor::kStateChildUpdateRequest:
|
||||
if (GetRouterId(mChildren[i].mValid.mRloc16) != mRouterId)
|
||||
{
|
||||
RemoveNeighbor(mChildren[i]);
|
||||
|
||||
@@ -298,6 +298,14 @@ public:
|
||||
*/
|
||||
ThreadError SetPreferredRouterId(uint8_t aRouterId);
|
||||
|
||||
/**
|
||||
* This method sets the Router Id from the stored network information.
|
||||
*
|
||||
* @param[in] aRouterId The Router Id.
|
||||
*
|
||||
*/
|
||||
void SetRouterId(uint8_t aRouterId);
|
||||
|
||||
/**
|
||||
* This method returns the next hop towards an RLOC16 destination.
|
||||
*
|
||||
@@ -478,6 +486,37 @@ public:
|
||||
*/
|
||||
ThreadError SetMaxAllowedChildren(uint8_t aMaxChildren);
|
||||
|
||||
/**
|
||||
* This method restores children information from non-volatile memory.
|
||||
*
|
||||
* @retval kThreadErrorNone Successfully restores children information.
|
||||
* @retval kThreadError_NoBufs Insufficient available buffers to restore all children information.
|
||||
*
|
||||
*/
|
||||
ThreadError RestoreChildren(void);
|
||||
|
||||
/**
|
||||
* This method remove a stored child information from non-volatile memory.
|
||||
*
|
||||
* @param[in] aChildRloc16 The child RLOC16 to remove.
|
||||
*
|
||||
* @retval kThreadErrorNone Successfully remove child.
|
||||
* @retval kThreadError_NotFound There is no specified child stored in non-volatile memory.
|
||||
*
|
||||
*/
|
||||
ThreadError RemoveStoredChild(uint16_t aChildRloc16);
|
||||
|
||||
/**
|
||||
* This method store a child infomation into non-volatile memory.
|
||||
*
|
||||
* @param[in] aChildRloc16 The child RLOC16 to store.
|
||||
*
|
||||
* @retval kThreadErrorNone Successfully store child.
|
||||
* @retval kThreadError_NoBufs Insufficient available buffers to store child.
|
||||
*
|
||||
*/
|
||||
ThreadError StoreChild(uint16_t aChildRloc16);
|
||||
|
||||
/**
|
||||
* This method returns a pointer to a Neighbor object.
|
||||
*
|
||||
@@ -678,6 +717,8 @@ private:
|
||||
ThreadError HandleChildIdRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
|
||||
uint32_t aKeySequence);
|
||||
ThreadError HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleChildUpdateResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
|
||||
uint32_t aKeySequence);
|
||||
ThreadError HandleDataRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleNetworkDataUpdateRouter(void);
|
||||
ThreadError HandleDiscoveryRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
@@ -695,6 +736,7 @@ private:
|
||||
const TlvRequestTlv &aTlvRequest, const ChallengeTlv &aChallenge);
|
||||
ThreadError SendParentResponse(Child *aChild, const ChallengeTlv &aChallenge, bool aRoutersOnlyRequest);
|
||||
ThreadError SendChildIdResponse(Child *aChild);
|
||||
ThreadError SendChildUpdateRequest(Child *aChild);
|
||||
ThreadError SendChildUpdateResponse(Child *aChild, const Ip6::MessageInfo &aMessageInfo,
|
||||
const uint8_t *aTlvs, uint8_t aTlvsLength, const ChallengeTlv *challenge);
|
||||
ThreadError SendDataResponse(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength);
|
||||
@@ -737,6 +779,8 @@ private:
|
||||
void HandleStateUpdateTimer(void);
|
||||
static void HandleDelayedResponseTimer(void *aContext);
|
||||
void HandleDelayedResponseTimer(void);
|
||||
static void HandleChildUpdateRequestTimer(void *aContext);
|
||||
void HandleChildUpdateRequestTimer(void);
|
||||
|
||||
ThreadError AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay);
|
||||
|
||||
@@ -745,6 +789,7 @@ private:
|
||||
TrickleTimer mAdvertiseTimer;
|
||||
Timer mStateUpdateTimer;
|
||||
Timer mDelayedResponseTimer;
|
||||
Timer mChildUpdateRequestTimer;
|
||||
|
||||
Coap::Resource mAddressSolicit;
|
||||
Coap::Resource mAddressRelease;
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
void SetLeaderPartitionId(uint32_t) { }
|
||||
|
||||
ThreadError SetPreferredRouterId(uint8_t) { return kThreadError_NotImplemented; }
|
||||
void SetRouterId(uint8_t) { }
|
||||
|
||||
uint16_t GetNextHop(uint16_t aDestination) const { return Mle::GetNextHop(aDestination); }
|
||||
|
||||
@@ -107,6 +108,10 @@ public:
|
||||
|
||||
ThreadError SetMaxAllowedChildren(uint8_t) { return kThreadError_NotImplemented; }
|
||||
|
||||
ThreadError RestoreChildren(void) {return kThreadError_NotImplemented; }
|
||||
ThreadError RemoveStoredChild(uint16_t) {return kThreadError_NotImplemented; }
|
||||
ThreadError StoreChild(uint16_t) {return kThreadError_NotImplemented; }
|
||||
|
||||
Neighbor *GetNeighbor(uint16_t aAddress) { return Mle::GetNeighbor(aAddress); }
|
||||
Neighbor *GetNeighbor(const Mac::ExtAddress &aAddress) { return Mle::GetNeighbor(aAddress); }
|
||||
Neighbor *GetNeighbor(const Mac::Address &aAddress) { return Mle::GetNeighbor(aAddress); }
|
||||
@@ -150,6 +155,7 @@ private:
|
||||
ThreadError HandleParentRequest(const Message &, const Ip6::MessageInfo &) { return kThreadError_Drop; }
|
||||
ThreadError HandleChildIdRequest(const Message &, const Ip6::MessageInfo &, uint32_t) { return kThreadError_Drop; }
|
||||
ThreadError HandleChildUpdateRequest(const Message &, const Ip6::MessageInfo &) { return kThreadError_Drop; }
|
||||
ThreadError HandleChildUpdateResponse(const Message &, const Ip6::MessageInfo &, uint32_t) { return kThreadError_Drop; }
|
||||
ThreadError HandleDataRequest(const Message &, const Ip6::MessageInfo &) { return kThreadError_Drop; }
|
||||
ThreadError HandleNetworkDataUpdateRouter(void) { return kThreadError_None; }
|
||||
ThreadError HandleDiscoveryRequest(const Message &, const Ip6::MessageInfo &) { return kThreadError_Drop; }
|
||||
|
||||
@@ -78,9 +78,11 @@ public:
|
||||
#endif
|
||||
{
|
||||
kStateInvalid, ///< Neighbor link is invalid
|
||||
kStateRestored, ///< Neighbor is restored from non-volatile memory
|
||||
kStateParentRequest, ///< Received an MLE Parent Request message
|
||||
kStateChildIdRequest, ///< Received an MLE Child ID Request message
|
||||
kStateLinkRequest, ///< Sent a MLE Link Request message
|
||||
kStateLinkRequest, ///< Sent an MLE Link Request message
|
||||
kStateChildUpdateRequest, ///< Sent an MLE Child Update Request message
|
||||
kStateValid, ///< Link is valid
|
||||
};
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ import serial
|
||||
import socket
|
||||
import logging
|
||||
from IThci import IThci
|
||||
from pexpect_serial import SerialSpawn
|
||||
from GRLLibs.UtilityModules.Test import Thread_Device_Role, Device_Data_Requirement, MacType
|
||||
from GRLLibs.UtilityModules.enums import PlatformDiagnosticPacket_Direction, PlatformDiagnosticPacket_Type, AddressType
|
||||
from GRLLibs.UtilityModules.ModuleHelper import ModuleHelper, ThreadRunner
|
||||
@@ -448,6 +447,7 @@ class ARM(IThci):
|
||||
print 'call startOpenThread'
|
||||
try:
|
||||
if self.__sendCommand('ifconfig up')[0] == 'Done':
|
||||
self.__setRouterSelectionJitter(1)
|
||||
return self.__sendCommand('thread start')[0] == 'Done'
|
||||
else:
|
||||
return False
|
||||
@@ -991,7 +991,6 @@ class ARM(IThci):
|
||||
if eRoleId == Thread_Device_Role.Leader:
|
||||
print 'join as leader'
|
||||
mode = 'rsdn'
|
||||
self.__setRouterSelectionJitter(1)
|
||||
if self.AutoDUTEnable is False:
|
||||
# set ROUTER_UPGRADE_THRESHOLD
|
||||
self.__setRouterUpgradeThreshold(32)
|
||||
@@ -1000,7 +999,6 @@ class ARM(IThci):
|
||||
elif eRoleId == Thread_Device_Role.Router:
|
||||
print 'join as router'
|
||||
mode = 'rsdn'
|
||||
self.__setRouterSelectionJitter(1)
|
||||
if self.AutoDUTEnable is False:
|
||||
# set ROUTER_UPGRADE_THRESHOLD
|
||||
self.__setRouterUpgradeThreshold(33)
|
||||
@@ -1087,8 +1085,6 @@ class ARM(IThci):
|
||||
print '%s call powerDown' % self.port
|
||||
self.isPowerDown = True
|
||||
self._sendline('reset')
|
||||
time.sleep(5)
|
||||
self.setMAC(self.mac)
|
||||
|
||||
def powerUp(self):
|
||||
"""power up the Thread device"""
|
||||
@@ -1110,11 +1106,10 @@ class ARM(IThci):
|
||||
"""
|
||||
print '%s call reboot' % self.port
|
||||
try:
|
||||
# stop OpenThread
|
||||
self.__stopOpenThread()
|
||||
# start OpenThread
|
||||
self.__startOpenThread()
|
||||
self._sendline('reset')
|
||||
time.sleep(3)
|
||||
|
||||
self.__startOpenThread()
|
||||
time.sleep(3)
|
||||
|
||||
if self.__sendCommand('state')[0] == 'disabled':
|
||||
@@ -1356,13 +1351,10 @@ class ARM(IThci):
|
||||
print '%s call resetAndRejoin' % self.port
|
||||
print timeout
|
||||
try:
|
||||
# start OpenThread
|
||||
self.__stopOpenThread()
|
||||
# wait timeout
|
||||
self._sendline('reset')
|
||||
time.sleep(timeout)
|
||||
# stop OpenThread
|
||||
self.__startOpenThread()
|
||||
|
||||
self.__startOpenThread()
|
||||
time.sleep(3)
|
||||
|
||||
if self.__sendCommand('state')[0] == 'disabled':
|
||||
|
||||
Reference in New Issue
Block a user