From a21db36a5b58217436d7dee8cc31edb5f7b1c740 Mon Sep 17 00:00:00 2001 From: Shu Chen Date: Mon, 31 Oct 2016 23:56:52 +0800 Subject: [PATCH] Implement reattach process using stored dataset (#894) --- src/core/openthread.cpp | 4 +- src/core/thread/meshcop_dataset_manager.cpp | 198 ++++++++++-------- src/core/thread/meshcop_dataset_manager.hpp | 16 +- src/core/thread/mle.cpp | 109 +++++++--- src/core/thread/mle.hpp | 21 +- .../thread-cert/Cert_9_2_07_DelayTimer.py | 2 +- 6 files changed, 220 insertions(+), 130 deletions(-) diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index 4f2a5cf33..ee0ed04db 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -1140,7 +1140,7 @@ ThreadError otThreadStart(otInstance *aInstance) VerifyOrExit(aInstance->mThreadNetif.GetMac().GetPanId() != Mac::kPanIdBroadcast, error = kThreadError_InvalidState); - error = aInstance->mThreadNetif.GetMle().Start(); + error = aInstance->mThreadNetif.GetMle().Start(true); exit: otLogFuncExitErr(error); @@ -1153,7 +1153,7 @@ ThreadError otThreadStop(otInstance *aInstance) otLogFuncEntry(); - error = aInstance->mThreadNetif.GetMle().Stop(); + error = aInstance->mThreadNetif.GetMle().Stop(true); otLogFuncExitErr(error); return error; diff --git a/src/core/thread/meshcop_dataset_manager.cpp b/src/core/thread/meshcop_dataset_manager.cpp index 7da395d04..636e4c0d8 100644 --- a/src/core/thread/meshcop_dataset_manager.cpp +++ b/src/core/thread/meshcop_dataset_manager.cpp @@ -70,6 +70,79 @@ DatasetManager::DatasetManager(ThreadNetif &aThreadNetif, const Tlv::Type aType, { } +ThreadError DatasetManager::ApplyConfiguration(void) +{ + ThreadError error = kThreadError_None; + Dataset *dataset; + const Tlv *cur; + const Tlv *end; + + dataset = mMle.IsAttached() ? &mNetwork : &mLocal; + + cur = reinterpret_cast(dataset->GetBytes()); + end = reinterpret_cast(dataset->GetBytes() + dataset->GetSize()); + + while (cur < end) + { + switch (cur->GetType()) + { + case Tlv::kChannel: + { + const ChannelTlv *channel = static_cast(cur); + mNetif.GetMac().SetChannel(static_cast(channel->GetChannel())); + break; + } + + case Tlv::kPanId: + { + const PanIdTlv *panid = static_cast(cur); + mNetif.GetMac().SetPanId(panid->GetPanId()); + break; + } + + case Tlv::kExtendedPanId: + { + const ExtendedPanIdTlv *extpanid = static_cast(cur); + mNetif.GetMac().SetExtendedPanId(extpanid->GetExtendedPanId()); + break; + } + + case Tlv::kNetworkName: + { + const NetworkNameTlv *name = static_cast(cur); + otNetworkName networkName; + memset(networkName.m8, 0, sizeof(networkName)); + memcpy(networkName.m8, name->GetNetworkName(), name->GetLength()); + mNetif.GetMac().SetNetworkName(networkName.m8); + break; + } + + case Tlv::kNetworkMasterKey: + { + const NetworkMasterKeyTlv *key = static_cast(cur); + mNetif.GetKeyManager().SetMasterKey(key->GetNetworkMasterKey(), key->GetLength()); + break; + } + + case Tlv::kMeshLocalPrefix: + { + const MeshLocalPrefixTlv *prefix = static_cast(cur); + mMle.SetMeshLocalPrefix(prefix->GetMeshLocalPrefix()); + break; + } + + default: + { + break; + } + } + + cur = cur->GetNext(); + } + + return error; +} + ThreadError DatasetManager::Set(const otOperationalDataset &aDataset, uint8_t &aFlags) { ThreadError error = kThreadError_None; @@ -100,9 +173,9 @@ exit: return error; } -ThreadError DatasetManager::Clear(uint8_t &aFlags) +ThreadError DatasetManager::Clear(uint8_t &aFlags, bool aOnlyClearNetwork) { - if (mLocal.Compare(mNetwork) == 0) + if (!aOnlyClearNetwork && mLocal.Compare(mNetwork) == 0) { mLocal.Clear(true); } @@ -651,10 +724,15 @@ ActiveDataset::ActiveDataset(ThreadNetif &aThreadNetif): { } -void ActiveDataset::Restore(void) +ThreadError ActiveDataset::Restore(void) { - mLocal.Restore(); - ApplyConfiguration(); + ThreadError error = kThreadError_None; + + SuccessOrExit(error = mLocal.Restore()); + SuccessOrExit(error = DatasetManager::ApplyConfiguration()); + +exit: + return error; } void ActiveDataset::StartLeader(void) @@ -715,12 +793,12 @@ void ActiveDataset::StopLeader(void) mCoapServer.RemoveResource(mResourceSet); } -ThreadError ActiveDataset::Clear(void) +ThreadError ActiveDataset::Clear(bool aOnlyClearNetwork) { ThreadError error = kThreadError_None; uint8_t flags; - SuccessOrExit(error = DatasetManager::Clear(flags)); + SuccessOrExit(error = DatasetManager::Clear(flags, aOnlyClearNetwork)); exit: return error; @@ -732,7 +810,7 @@ ThreadError ActiveDataset::Set(const otOperationalDataset &aDataset) uint8_t flags; SuccessOrExit(error = DatasetManager::Set(aDataset, flags)); - ApplyConfiguration(); + DatasetManager::ApplyConfiguration(); exit: return error; @@ -743,7 +821,7 @@ ThreadError ActiveDataset::Set(const Dataset &aDataset) ThreadError error = kThreadError_None; SuccessOrExit(error = DatasetManager::Set(aDataset)); - ApplyConfiguration(); + DatasetManager::ApplyConfiguration(); exit: return error; @@ -756,7 +834,7 @@ ThreadError ActiveDataset::Set(const Timestamp &aTimestamp, const Message &aMess uint8_t flags; SuccessOrExit(error = DatasetManager::Set(aTimestamp, aMessage, aOffset, aLength, flags)); - ApplyConfiguration(); + DatasetManager::ApplyConfiguration(); exit: return error; @@ -788,79 +866,6 @@ exit: return; } -ThreadError ActiveDataset::ApplyConfiguration(void) -{ - ThreadError error = kThreadError_None; - Dataset *dataset; - const Tlv *cur; - const Tlv *end; - - dataset = mMle.IsAttached() ? &mNetwork : &mLocal; - - cur = reinterpret_cast(dataset->GetBytes()); - end = reinterpret_cast(dataset->GetBytes() + dataset->GetSize()); - - while (cur < end) - { - switch (cur->GetType()) - { - case Tlv::kChannel: - { - const ChannelTlv *channel = static_cast(cur); - mNetif.GetMac().SetChannel(static_cast(channel->GetChannel())); - break; - } - - case Tlv::kPanId: - { - const PanIdTlv *panid = static_cast(cur); - mNetif.GetMac().SetPanId(panid->GetPanId()); - break; - } - - case Tlv::kExtendedPanId: - { - const ExtendedPanIdTlv *extpanid = static_cast(cur); - mNetif.GetMac().SetExtendedPanId(extpanid->GetExtendedPanId()); - break; - } - - case Tlv::kNetworkName: - { - const NetworkNameTlv *name = static_cast(cur); - otNetworkName networkName; - memset(networkName.m8, 0, sizeof(networkName)); - memcpy(networkName.m8, name->GetNetworkName(), name->GetLength()); - mNetif.GetMac().SetNetworkName(networkName.m8); - break; - } - - case Tlv::kNetworkMasterKey: - { - const NetworkMasterKeyTlv *key = static_cast(cur); - mNetif.GetKeyManager().SetMasterKey(key->GetNetworkMasterKey(), key->GetLength()); - break; - } - - case Tlv::kMeshLocalPrefix: - { - const MeshLocalPrefixTlv *prefix = static_cast(cur); - mMle.SetMeshLocalPrefix(prefix->GetMeshLocalPrefix()); - break; - } - - default: - { - break; - } - } - - cur = cur->GetNext(); - } - - return error; -} - PendingDataset::PendingDataset(ThreadNetif &aThreadNetif): DatasetManager(aThreadNetif, Tlv::kPendingTimestamp, OPENTHREAD_URI_PENDING_SET, OPENTHREAD_URI_PENDING_GET), mResourceGet(OPENTHREAD_URI_PENDING_GET, &PendingDataset::HandleGet, this), @@ -869,10 +874,16 @@ PendingDataset::PendingDataset(ThreadNetif &aThreadNetif): { } -void PendingDataset::Restore(void) +ThreadError PendingDataset::Restore(void) { - mLocal.Restore(); + ThreadError error = kThreadError_None; + + SuccessOrExit(error = mLocal.Restore()); + ResetDelayTimer(kFlagLocalUpdated); + +exit: + return error; } void PendingDataset::StartLeader(void) @@ -892,12 +903,12 @@ void PendingDataset::StopLeader(void) mCoapServer.RemoveResource(mResourceSet); } -ThreadError PendingDataset::Clear(void) +ThreadError PendingDataset::Clear(bool aOnlyClearNetwork) { ThreadError error = kThreadError_None; uint8_t flags; - SuccessOrExit(error = DatasetManager::Clear(flags)); + SuccessOrExit(error = DatasetManager::Clear(flags, aOnlyClearNetwork)); ResetDelayTimer(flags); exit: @@ -916,6 +927,17 @@ exit: return error; } +ThreadError PendingDataset::Set(const Dataset &aDataset) +{ + ThreadError error = kThreadError_None; + + SuccessOrExit(error = DatasetManager::Set(aDataset)); + ResetDelayTimer(kFlagLocalUpdated | kFlagNetworkUpdated); + +exit: + return error; +} + ThreadError PendingDataset::Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength) { @@ -1037,7 +1059,7 @@ void PendingDataset::HandleTimer(void) mNetif.GetActiveDataset().Set(mNetwork); - Clear(); + Clear(false); } } // namespace MeshCoP diff --git a/src/core/thread/meshcop_dataset_manager.hpp b/src/core/thread/meshcop_dataset_manager.hpp index f8de12ac1..daa2dc06b 100644 --- a/src/core/thread/meshcop_dataset_manager.hpp +++ b/src/core/thread/meshcop_dataset_manager.hpp @@ -56,6 +56,8 @@ public: Dataset &GetLocal(void) { return mLocal; } Dataset &GetNetwork(void) { return mNetwork; } + ThreadError ApplyConfiguration(void); + ThreadError SendSetRequest(const otOperationalDataset &aDataset, const uint8_t *aTlvs, uint8_t aLength); ThreadError SendGetRequest(const uint8_t *aTlvTypes, uint8_t aLength); @@ -68,7 +70,7 @@ protected: DatasetManager(ThreadNetif &aThreadNetif, const Tlv::Type aType, const char *aUriSet, const char *aUriGet); - ThreadError Clear(uint8_t &aFlags); + ThreadError Clear(uint8_t &aFlags, bool aOnlyClearNetwork); ThreadError Set(const otOperationalDataset &aDataset, uint8_t &aFlags); @@ -115,13 +117,13 @@ class ActiveDataset: public DatasetManager public: ActiveDataset(ThreadNetif &aThreadNetif); - void Restore(void); + ThreadError Restore(void); void StartLeader(void); void StopLeader(void); - ThreadError Clear(void); + ThreadError Clear(bool aOnlyClearNetwork); ThreadError Set(const otOperationalDataset &aDataset); @@ -129,8 +131,6 @@ public: ThreadError Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength); - ThreadError ApplyConfiguration(void); - private: static void HandleGet(void *aContext, Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); @@ -149,16 +149,18 @@ class PendingDataset: public DatasetManager public: PendingDataset(ThreadNetif &aThreadNetif); - void Restore(void); + ThreadError Restore(void); void StartLeader(void); void StopLeader(void); - ThreadError Clear(void); + ThreadError Clear(bool aOnlyClearNetwork); ThreadError Set(const otOperationalDataset &aDataset); + ThreadError Set(const Dataset &aDataset); + ThreadError Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength); void UpdateDelayTimer(void); diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 5137d107d..c6b711fd9 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -80,6 +80,7 @@ Mle::Mle(ThreadNetif &aThreadNetif) : mParentLinkQuality1 = 0; mRetrieveNewNetworkData = false; mTimeout = kMleEndDeviceTimeout; + mReattachState = kReattachStop; memset(&mLeaderData, 0, sizeof(mLeaderData)); memset(&mParent, 0, sizeof(mParent)); @@ -190,14 +191,14 @@ ThreadError Mle::Disable(void) { ThreadError error = kThreadError_None; - SuccessOrExit(error = Stop()); + SuccessOrExit(error = Stop(false)); SuccessOrExit(error = mSocket.Close()); exit: return error; } -ThreadError Mle::Start(void) +ThreadError Mle::Start(bool aEnableReattach) { ThreadError error = kThreadError_None; @@ -213,6 +214,11 @@ ThreadError Mle::Start(void) mKeyManager.Start(); + if (aEnableReattach) + { + mReattachState = kReattachStart; + } + if (GetRloc16() == Mac::kShortAddrInvalid) { BecomeChild(kMleAttachAnyPartition); @@ -233,7 +239,7 @@ exit: return error; } -ThreadError Mle::Stop(void) +ThreadError Mle::Stop(bool aClearNetworkDatasets) { otLogFuncEntry(); mKeyManager.Stop(); @@ -246,6 +252,12 @@ ThreadError Mle::Stop(void) mNetif.RemoveUnicastAddress(mLeaderAloc); } + if (aClearNetworkDatasets) + { + mNetif.GetActiveDataset().Clear(true); + mNetif.GetPendingDataset().Clear(true); + } + mDeviceState = kDeviceStateDisabled; otLogFuncExit(); return kThreadError_None; @@ -343,6 +355,18 @@ ThreadError Mle::BecomeChild(otMleAttachFilter aFilter) VerifyOrExit(mDeviceState != kDeviceStateDisabled, error = kThreadError_InvalidState); VerifyOrExit(mParentRequestState == kParentIdle, error = kThreadError_Busy); + if (mReattachState == kReattachStart) + { + if (mNetif.GetActiveDataset().Restore() == kThreadError_None) + { + mReattachState = kReattachActive; + } + else + { + mReattachState = kReattachStop; + } + } + mParentRequestState = kParentRequestStart; mParentRequestMode = aFilter; memset(&mParent, 0, sizeof(mParent)); @@ -1157,37 +1181,61 @@ void Mle::HandleParentRequestTimer(void) } else { - switch (mParentRequestMode) + if (mReattachState == kReattachActive) { - case kMleAttachAnyPartition: - if (mPreviousPanId != Mac::kPanIdBroadcast) + if (mNetif.GetPendingDataset().Restore() == kThreadError_None) { - mMac.SetChannel(mPreviousChannel); - mMac.SetPanId(mPreviousPanId); - mPreviousPanId = Mac::kPanIdBroadcast; - BecomeDetached(); + mNetif.GetPendingDataset().ApplyConfiguration(); + mReattachState = kReattachPending; + mParentRequestState = kParentRequestStart; + mParentRequestTimer.Start(kParentRequestRouterTimeout); } - else if ((mDeviceMode & ModeTlv::kModeFFD) == 0) + else { - SendOrphanAnnounce(); - BecomeDetached(); + mReattachState = kReattachStop; } - else if (mMleRouter.BecomeLeader() != kThreadError_None) + } + else if (mReattachState == kReattachPending) + { + mReattachState = kReattachStop; + mNetif.GetActiveDataset().Restore(); + mNetif.GetPendingDataset().Set(mNetif.GetPendingDataset().GetLocal()); + } + + if (mReattachState == kReattachStop) + { + switch (mParentRequestMode) { + case kMleAttachAnyPartition: + if (mPreviousPanId != Mac::kPanIdBroadcast) + { + mMac.SetChannel(mPreviousChannel); + mMac.SetPanId(mPreviousPanId); + mPreviousPanId = Mac::kPanIdBroadcast; + BecomeDetached(); + } + else if ((mDeviceMode & ModeTlv::kModeFFD) == 0) + { + SendOrphanAnnounce(); + BecomeDetached(); + } + else if (mMleRouter.BecomeLeader() != kThreadError_None) + { + mParentRequestState = kParentIdle; + BecomeDetached(); + } + + break; + + case kMleAttachSamePartition: mParentRequestState = kParentIdle; - BecomeDetached(); + BecomeChild(kMleAttachAnyPartition); + break; + + case kMleAttachBetterPartition: + mParentRequestState = kParentIdle; + break; } - - break; - - case kMleAttachSamePartition: - mParentRequestState = kParentIdle; - BecomeChild(kMleAttachAnyPartition); - break; - - case kMleAttachBetterPartition: - mParentRequestState = kParentIdle; - break; } } @@ -2007,7 +2055,7 @@ ThreadError Mle::HandleDataResponse(const Message &aMessage, const Ip6::MessageI } else { - mNetif.GetActiveDataset().Clear(); + mNetif.GetActiveDataset().Clear(false); } // Pending Dataset @@ -2022,7 +2070,7 @@ ThreadError Mle::HandleDataResponse(const Message &aMessage, const Ip6::MessageI } else { - mNetif.GetPendingDataset().Clear(); + mNetif.GetPendingDataset().Clear(false); } if (mPreviousPanId != Mac::kPanIdBroadcast && ((mDeviceMode & ModeTlv::kModeFFD) == 0)) @@ -2293,6 +2341,7 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa // Parent Attach Success mParentRequestTimer.Stop(); + mReattachState = kReattachStop; SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId()); @@ -2491,12 +2540,12 @@ ThreadError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo mRetrieveNewNetworkData = true; } - Stop(); + Stop(false); mPreviousChannel = mMac.GetChannel(); mPreviousPanId = mMac.GetPanId(); mMac.SetChannel(static_cast(channel.GetChannel())); mMac.SetPanId(panid.GetPanId()); - Start(); + Start(false); } else { diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index db3b09877..0eeb68076 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -374,19 +374,23 @@ public: /** * This method starts the MLE protocol operation. * + * @param[in] aEnableReattach True to enable reattach process using stored dataset, False not. + * * @retval kThreadError_None Successfully started the protocol operation. * @retval kThreadError_Already The protocol operation was already started. * */ - ThreadError Start(void); + ThreadError Start(bool aEnableReattach); /** * This method stops the MLE protocol operation. * + * @param[in] aClearNetworkDatasets True to clear network datasets, False not. + * * @retval kThreadError_None Successfully stopped the protocol operation. * */ - ThreadError Stop(void); + ThreadError Stop(bool aClearNetworkDatasets); /** * This function pointer is called on receiving an MLE Discovery Response message. @@ -1160,6 +1164,19 @@ protected: }; ParentRequestState mParentRequestState; ///< The parent request state. + /** + * States when reattaching network using stored dataset + * + */ + enum ReattachState + { + kReattachStop = 0, ///< Reattach process is disabled or finished + kReattachStart = 1, ///< Start reattach process + kReattachActive = 2, ///< Reattach using stored Active Dataset + kReattachPending = 3, ///< Reattach using stored Pending Dataset + }; + ReattachState mReattachState; + Timer mParentRequestTimer; ///< The timer for driving the Parent Request process. uint8_t mRouterSelectionJitter; ///< The variable to save the assigned jitter value. diff --git a/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py b/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py index ea3dbeafd..3120e2bf9 100755 --- a/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py +++ b/tests/scripts/thread-cert/Cert_9_2_07_DelayTimer.py @@ -86,7 +86,7 @@ class Cert_9_2_7_DelayTimer(unittest.TestCase): self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router') self.nodes[ROUTER].start() - time.sleep(5) + time.sleep(10) self.assertEqual(self.nodes[ROUTER].get_state(), 'leader') self.nodes[LEADER].add_whitelist(self.nodes[ROUTER].get_addr64())