From 2fec3abdb051f176d3ef46287c9efc947da5ad9e Mon Sep 17 00:00:00 2001 From: rongli Date: Wed, 30 Nov 2016 04:14:54 +0800 Subject: [PATCH] Restrict the condition to SendAddressRelease (#1013) * Restrict the condition to SendAddressRelease * some enhancement for AttachSamePartition feature * code cleanup and implement PARENT_PARTITION_CHANGE --- src/core/thread/mle.cpp | 24 ++--- src/core/thread/mle.hpp | 1 + src/core/thread/mle_router.cpp | 160 ++++++++++++++++++++++------- src/core/thread/mle_router_ftd.hpp | 13 ++- src/core/thread/mle_router_mtd.hpp | 1 + src/core/thread/thread_tlvs.hpp | 1 + tools/harness-thci/ARM.py | 3 +- 7 files changed, 150 insertions(+), 53 deletions(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 6fe3083fb..6f4a54229 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -287,6 +287,7 @@ ThreadError Mle::Restore() else if (networkInfo.mDeviceState == kDeviceStateRouter || networkInfo.mDeviceState == kDeviceStateLeader) { mMleRouter.SetRouterId(GetRouterId(GetRloc16())); + mMleRouter.SetPreviousPartitionId(networkInfo.mPreviousPartitionId); mMleRouter.RestoreChildren(); } @@ -315,6 +316,7 @@ ThreadError Mle::Store() networkInfo.mKeySequence = mKeyManager.GetCurrentKeySequence(); networkInfo.mMleFrameCounter = mKeyManager.GetMleFrameCounter() + OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD; networkInfo.mMacFrameCounter = mKeyManager.GetMacFrameCounter() + OPENTHREAD_CONFIG_STORE_FRAME_COUNTER_AHEAD; + networkInfo.mPreviousPartitionId = mLeaderData.GetPartitionId(); memcpy(networkInfo.mExtAddress.m8, mMac.GetExtAddress(), sizeof(networkInfo.mExtAddress)); if (mDeviceState == kDeviceStateChild) @@ -2523,15 +2525,6 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa mMesh.SetRxOnWhenIdle(true); } - mParent.mValid.mRloc16 = sourceAddress.GetRloc16(); - SuccessOrExit(error = SetStateChild(shortAddress.GetRloc16())); - - mNetworkData.SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(), - (mDeviceMode & ModeTlv::kModeFullNetworkData) == 0, - networkData.GetNetworkData(), networkData.GetLength()); - - mNetif.GetActiveDataset().ApplyConfiguration(); - // Route if ((Tlv::GetTlv(aMessage, Tlv::kRoute, sizeof(route), route) == kThreadError_None) && (mDeviceMode & ModeTlv::kModeFFD)) @@ -2546,14 +2539,21 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa } } - if (mRouterSelectionJitterTimeout == 0 && - (mDeviceMode & ModeTlv::kModeFFD) && - (numRouters < mMleRouter.GetRouterUpgradeThreshold())) + if (mRouterSelectionJitterTimeout == 0 && numRouters < mMleRouter.GetRouterUpgradeThreshold()) { mRouterSelectionJitterTimeout = (otPlatRandomGet() % mRouterSelectionJitter) + 1; } } + mParent.mValid.mRloc16 = sourceAddress.GetRloc16(); + SuccessOrExit(error = SetStateChild(shortAddress.GetRloc16())); + + mNetworkData.SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(), + (mDeviceMode & ModeTlv::kModeFullNetworkData) == 0, + networkData.GetNetworkData(), networkData.GetLength()); + + mNetif.GetActiveDataset().ApplyConfiguration(); + exit: if (error != kThreadError_None) diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 8ad046758..64ed29bc6 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1263,6 +1263,7 @@ private: uint32_t mKeySequence; ///< Key Sequence uint32_t mMleFrameCounter; ///< MLE Frame Counter uint32_t mMacFrameCounter; ///< MAC Frame Counter + uint32_t mPreviousPartitionId; ///< PartitionId Mac::ExtAddress mExtAddress; ///< Extended Address } NetworkInfo; diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index d00025226..5ac34556c 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -75,8 +75,9 @@ MleRouter::MleRouter(ThreadNetif &aThreadNetif): mLeaderWeight = kLeaderWeight; mFixedLeaderPartitionId = 0; mMaxChildrenAllowed = kMaxChildren; - mRouterId = kInvalidRouterId; - mPreviousRouterId = kInvalidRouterId; + + SetRouterId(kInvalidRouterId); + mPreviousPartitionId = 0; mRouterIdSequenceLastUpdated = 0; mRouterRoleEnabled = true; } @@ -221,6 +222,7 @@ ThreadError MleRouter::BecomeRouter(ThreadStatusTlv::Status aStatus) mAdvertiseTimer.Stop(); mAddressResolver.Clear(); + mRouterSelectionJitterTimeout = 0; switch (mDeviceState) { @@ -268,8 +270,7 @@ ThreadError MleRouter::BecomeLeader(void) router = GetRouter(routerId); VerifyOrExit(router != NULL, error = kThreadError_NoBufs); - mRouterId = routerId; - mPreviousRouterId = mRouterId; + SetRouterId(routerId); memcpy(&router->mMacAddr, mMac.GetExtAddress(), sizeof(router->mMacAddr)); @@ -329,32 +330,57 @@ ThreadError MleRouter::HandleChildStart(otMleAttachFilter aFilter) StopLeader(); mStateUpdateTimer.Start(kStateUpdatePeriod); + mAdvertiseTimer.Start( + Timer::SecToMsec(kReedAdvertiseInterval), + Timer::SecToMsec(kReedAdvertiseInterval + kReedAdvertiseJitter), + TrickleTimer::kModePlainTimer); + mNetif.SubscribeAllRoutersMulticast(); + + VerifyOrExit(IsRouterIdValid(mPreviousRouterId), ;); + switch (aFilter) { - case kMleAttachAnyPartition: - break; - case kMleAttachSamePartition: - SendAddressRelease(); + + // downgrade + if (GetActiveRouterCount() > mRouterDowngradeThreshold) + { + SendAddressRelease(); + + // reset children info if any + if (HasChildren()) + { + RemoveChildren(); + } + + // reset routerId info + SetRouterId(kInvalidRouterId); + } + else if (HasChildren()) + { + BecomeRouter(ThreadStatusTlv::kHaveChildIdRequest); + } + break; + case kMleAttachAnyPartition: case kMleAttachBetterPartition: - // BecomeRouter(); + if (HasChildren() && + mPreviousPartitionId != mLeaderData.GetPartitionId()) + { + BecomeRouter(ThreadStatusTlv::kParentPartitionChange); + } + break; } - if (mDeviceMode & ModeTlv::kModeFFD) - { - mAdvertiseTimer.Start( - Timer::SecToMsec(kReedAdvertiseInterval), - Timer::SecToMsec(kReedAdvertiseInterval + kReedAdvertiseJitter), - TrickleTimer::kModePlainTimer); - mNetif.SubscribeAllRoutersMulticast(); +exit: - if (GetActiveRouterCount() >= mRouterUpgradeThreshold) - { - SendAdvertisement(); - } + if (GetActiveRouterCount() >= mRouterUpgradeThreshold && + (!IsRouterIdValid(mPreviousRouterId) || !HasChildren())) + { + SetRouterId(kInvalidRouterId); + SendAdvertisement(); } return kThreadError_None; @@ -374,6 +400,7 @@ ThreadError MleRouter::SetStateRouter(uint16_t aRloc16) mNetif.SubscribeAllRoutersMulticast(); mRouters[mRouterId].mNextHop = mRouterId; + mPreviousPartitionId = mLeaderData.GetPartitionId(); mNetworkData.Stop(); mStateUpdateTimer.Start(kStateUpdatePeriod); mNetif.GetIp6().SetForwardingEnabled(true); @@ -406,6 +433,7 @@ ThreadError MleRouter::SetStateLeader(uint16_t aRloc16) mNetif.SubscribeAllRoutersMulticast(); mRouters[mRouterId].mNextHop = mRouterId; + mPreviousPartitionId = mLeaderData.GetPartitionId(); mRouters[mRouterId].mLastHeard = Timer::GetNow(); mNetworkData.Start(); @@ -1257,7 +1285,7 @@ ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::M mLeaderData.GetWeighting(), mLeaderData.GetPartitionId()); if (GetDeviceState() == kDeviceStateChild && - memcmp(&mParent.mMacAddr, &macAddr, sizeof(mParent.mMacAddr)) == 0) + (memcmp(&mParent.mMacAddr, &macAddr, sizeof(mParent.mMacAddr)) == 0 || !(mDeviceMode & ModeTlv::kModeFFD))) { ExitNow(); } @@ -1693,6 +1721,7 @@ void MleRouter::HandleStateUpdateTimer(void) { // upgrade to Router BecomeRouter(ThreadStatusTlv::kTooFewRouters); + ExitNow(); } case kDeviceStateRouter: @@ -3240,9 +3269,15 @@ exit: return error; } +void MleRouter::SetPreviousPartitionId(uint32_t aPartitionId) +{ + mPreviousPartitionId = aPartitionId; +} + void MleRouter::SetRouterId(uint8_t aRouterId) { mRouterId = aRouterId; + mPreviousRouterId = mRouterId; } Router *MleRouter::GetRouters(uint8_t *aNumRouters) @@ -3652,7 +3687,22 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe otLogInfoMle("Received address reply"); SuccessOrExit(ThreadTlv::GetTlv(*aMessage, ThreadTlv::kStatus, sizeof(statusTlv), statusTlv)); - VerifyOrExit(statusTlv.IsValid() && statusTlv.GetStatus() == statusTlv.kSuccess, ;); + VerifyOrExit(statusTlv.IsValid(), ;); + + if (statusTlv.GetStatus() != statusTlv.kSuccess) + { + if (IsRouterIdValid(mPreviousRouterId)) + { + if (HasChildren()) + { + RemoveChildren(); + } + + SetRouterId(kInvalidRouterId); + } + + ExitNow(); + } SuccessOrExit(ThreadTlv::GetTlv(*aMessage, ThreadTlv::kRloc16, sizeof(rlocTlv), rlocTlv)); VerifyOrExit(rlocTlv.IsValid(), ;); @@ -3661,10 +3711,21 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe SuccessOrExit(ThreadTlv::GetTlv(*aMessage, ThreadTlv::kRouterMask, sizeof(routerMaskTlv), routerMaskTlv)); VerifyOrExit(routerMaskTlv.IsValid(), ;); + // if allocated routerId is different from previous routerId + if (IsRouterIdValid(mPreviousRouterId) && routerId != mPreviousRouterId) + { + // reset children info if any + if (HasChildren()) + { + RemoveChildren(); + } + } + // assign short address - mRouterId = routerId; - mPreviousRouterId = mRouterId; + SetRouterId(routerId); + SuccessOrExit(SetStateRouter(GetRloc16(mRouterId))); + mRouters[mRouterId].mCost = 0; // copy router id information @@ -3691,10 +3752,6 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe { switch (mChildren[i].mState) { - case Neighbor::kStateInvalid: - case Neighbor::kStateParentRequest: - break; - case Neighbor::kStateChildIdRequest: SendChildIdResponse(&mChildren[i]); break; @@ -3703,14 +3760,11 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe assert(false); break; + case Neighbor::kStateInvalid: + case Neighbor::kStateParentRequest: case Neighbor::kStateValid: case Neighbor::kStateRestored: case Neighbor::kStateChildUpdateRequest: - if (GetRouterId(mChildren[i].mValid.mRloc16) != mRouterId) - { - RemoveNeighbor(mChildren[i]); - } - break; } } @@ -3765,6 +3819,7 @@ void MleRouter::HandleAddressSolicit(Coap::Header &aHeader, Message &aMessage, c break; case ThreadStatusTlv::kHaveChildIdRequest: + case ThreadStatusTlv::kParentPartitionChange: break; default: @@ -4280,20 +4335,47 @@ exit: return rval; } +bool MleRouter::HasChildren(void) +{ + bool hasChildren = false; + + for (uint8_t i = 0; i < mMaxChildrenAllowed; i++) + { + if (mChildren[i].mState == Neighbor::kStateRestored || mChildren[i].mState >= Neighbor::kStateChildIdRequest) + { + ExitNow(hasChildren = true); + } + } + +exit: + return hasChildren; +} + +void MleRouter::RemoveChildren(void) +{ + for (uint8_t i = 0; i < mMaxChildrenAllowed; i++) + { + if (mChildren[i].mState == Neighbor::kStateRestored || + mChildren[i].mState == Neighbor::kStateChildUpdateRequest || + mChildren[i].mState == Neighbor::kStateValid) + { + RemoveStoredChild(mChildren[i].mValid.mRloc16); + } + + mChildren[i].mState = Neighbor::kStateInvalid; + } +} + bool MleRouter::HasSmallNumberOfChildren(void) { - Child *children; - uint8_t maxChildCount = 0; uint8_t numChildren = 0; uint8_t routerCount = GetActiveRouterCount(); VerifyOrExit(routerCount > mRouterDowngradeThreshold, ;); - children = GetChildren(&maxChildCount); - - for (uint8_t i = 0; i < maxChildCount; i++) + for (uint8_t i = 0; i < mMaxChildrenAllowed; i++) { - if (children[i].mState == Neighbor::kStateValid) + if (mChildren[i].mState == Neighbor::kStateValid) { numChildren++; } diff --git a/src/core/thread/mle_router_ftd.hpp b/src/core/thread/mle_router_ftd.hpp index e01a5306a..34a70a14f 100644 --- a/src/core/thread/mle_router_ftd.hpp +++ b/src/core/thread/mle_router_ftd.hpp @@ -299,7 +299,15 @@ public: ThreadError SetPreferredRouterId(uint8_t aRouterId); /** - * This method sets the Router Id from the stored network information. + * This method sets the Partition Id which the device joins successfully. + * + * @param[in] aPartitionId The Partition Id. + * + */ + void SetPreviousPartitionId(uint32_t aPartitionId); + + /** + * This method sets the Router Id. * * @param[in] aRouterId The Router Id. * @@ -764,6 +772,8 @@ private: Child *FindChild(uint16_t aChildId); Child *FindChild(const Mac::ExtAddress &aMacAddr); + bool HasChildren(void); + void RemoveChildren(void); bool HasMinDowngradeNeighborRouters(void); bool HasOneNeighborwithComparableConnectivity(const RouteTlv &aRoute, uint8_t aRouterId); bool HasSmallNumberOfChildren(void); @@ -812,6 +822,7 @@ private: uint8_t mRouterId; uint8_t mPreviousRouterId; + uint32_t mPreviousPartitionId; Coap::Server &mCoapServer; Coap::Client &mCoapClient; diff --git a/src/core/thread/mle_router_mtd.hpp b/src/core/thread/mle_router_mtd.hpp index c25be0e11..b722fe65d 100644 --- a/src/core/thread/mle_router_mtd.hpp +++ b/src/core/thread/mle_router_mtd.hpp @@ -69,6 +69,7 @@ public: void SetLeaderPartitionId(uint32_t) { } ThreadError SetPreferredRouterId(uint8_t) { return kThreadError_NotImplemented; } + void SetPreviousPartitionId(uint32_t) { } void SetRouterId(uint8_t) { } uint16_t GetNextHop(uint16_t aDestination) const { return Mle::GetNextHop(aDestination); } diff --git a/src/core/thread/thread_tlvs.hpp b/src/core/thread/thread_tlvs.hpp index 81003ad18..1e91090a2 100644 --- a/src/core/thread/thread_tlvs.hpp +++ b/src/core/thread/thread_tlvs.hpp @@ -329,6 +329,7 @@ public: kNoAddressAvailable = 1, ///< No address available. kTooFewRouters = 2, ///< Address Solicit due to too few routers. kHaveChildIdRequest = 3, ///< Address Solicit due to child ID request. + kParentPartitionChange = 4, ///< Address Solicit due to parent partition change }; /** diff --git a/tools/harness-thci/ARM.py b/tools/harness-thci/ARM.py index aba352da1..4f053f897 100644 --- a/tools/harness-thci/ARM.py +++ b/tools/harness-thci/ARM.py @@ -2485,7 +2485,8 @@ class ARM(IThci): """force update to router as if there is child id request""" print '%s call updateRouterStatus' % self.port cmd = 'state' - while state = self.__sendCommand(cmd)[0]: + while True: + state = self.__sendCommand(cmd)[0] if state == 'detached': continue elif state == 'child':