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:
Shu Chen
2016-11-22 21:40:04 -08:00
committed by Jonathan Hui
parent 9d0cbbddc7
commit 70255e9347
16 changed files with 764 additions and 86 deletions
+3
View File
@@ -46,6 +46,9 @@ enum
{
kKeyActiveDataset = 0x0001,
kKeyPendingDataset = 0x0002,
kKeyNetworkInfo = 0x0003,
kKeyParentInfo = 0x0004,
kKeyChildInfo = 0x0005,
};
#ifdef __cplusplus
+62 -51
View File
@@ -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();
+2
View File
@@ -50,6 +50,8 @@ class ActiveDataset: public ActiveDatasetBase
public:
ActiveDataset(ThreadNetif &aThreadNetif);
ThreadError GenerateLocal(void);
void StartLeader(void);
void StopLeader(void);
+2
View File
@@ -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) { }
+10
View File
@@ -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
View File
@@ -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:
+32
View File
@@ -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
+34
View File
@@ -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
View File
@@ -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)
+48
View File
@@ -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];
+2
View File
@@ -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
+261 -6
View File
@@ -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]);
+45
View File
@@ -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;
+6
View File
@@ -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; }
+3 -1
View File
@@ -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
};
+6 -14
View File
@@ -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':