diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 63f96a4ba..bb6b822a3 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -76,7 +76,6 @@ Mle::Mle(ThreadNetif &aThreadNetif) : mLastPartitionRouterIdSequence(0), mLastPartitionId(0), mParentRequestMode(kMleAttachAnyPartition), - mParentLinkQuality(0), mParentPriority(0), mParentLinkQuality3(0), mParentLinkQuality2(0), @@ -493,7 +492,7 @@ ThreadError Mle::BecomeChild(otMleAttachFilter aFilter) mNetif.GetMeshForwarder().SetRxOnWhenIdle(true); - mParentRequestTimer.Start(kParentRequestRouterTimeout); + mParentRequestTimer.Start((otPlatRandomGet() % kParentRequestRouterTimeout) + 1); exit: otLogFuncExitErr(error); @@ -2474,13 +2473,17 @@ exit: return error; } -bool Mle::IsBetterParent(uint16_t aRloc16, uint8_t aLinkQuality, ConnectivityTlv &aConnectivityTlv) const +bool Mle::IsBetterParent(uint16_t aRloc16, uint8_t aLinkQuality, ConnectivityTlv &aConnectivityTlv) { bool rval = false; - if (aLinkQuality != mParentLinkQuality) + uint8_t candidateLinkQualityIn = mParentCandidate.mLinkInfo.GetLinkQuality(mNetif.GetMac().GetNoiseFloor()); + uint8_t candidateTwoWayLinkQuality = (candidateLinkQualityIn < mParentCandidate.mLinkQualityOut) + ? candidateLinkQualityIn : mParentCandidate.mLinkQualityOut; + + if (aLinkQuality != candidateTwoWayLinkQuality) { - ExitNow(rval = (aLinkQuality > mParentLinkQuality)); + ExitNow(rval = (aLinkQuality > candidateTwoWayLinkQuality)); } if (IsActiveRouter(aRloc16) != IsActiveRouter(mParentCandidate.mValid.mRloc16)) @@ -2641,14 +2644,15 @@ ThreadError Mle::HandleParentResponse(const Message &aMessage, const Ip6::Messag mParentCandidate.mLinkInfo.Clear(); mParentCandidate.mLinkInfo.AddRss(mNetif.GetMac().GetNoiseFloor(), threadMessageInfo->mRss); mParentCandidate.mLinkFailures = 0; + mParentCandidate.mLinkQualityOut = LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMarginTlv.GetLinkMargin()); mParentCandidate.mState = Neighbor::kStateValid; mParentCandidate.mKeySequence = aKeySequence; - mParentLinkQuality = linkQuality; mParentPriority = connectivity.GetParentPriority(); mParentLinkQuality3 = connectivity.GetLinkQuality3(); mParentLinkQuality2 = connectivity.GetLinkQuality2(); mParentLinkQuality1 = connectivity.GetLinkQuality1(); + mParentLeaderCost = connectivity.GetLeaderCost(); mParentLeaderData = leaderData; mParentIsSingleton = connectivity.GetActiveRouters() <= 1; diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 49fbe6cc2..d8d8fbc87 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1355,6 +1355,10 @@ protected: uint8_t mLastPartitionRouterIdSequence; uint32_t mLastPartitionId; + +protected: + uint8_t mParentLeaderCost; + private: enum { @@ -1391,7 +1395,7 @@ private: ThreadError SendChildIdRequest(void); void SendOrphanAnnounce(void); - bool IsBetterParent(uint16_t aRloc16, uint8_t aLinkQuality, ConnectivityTlv &aConnectivityTlv) const; + bool IsBetterParent(uint16_t aRloc16, uint8_t aLinkQuality, ConnectivityTlv &aConnectivityTlv); void ResetParentCandidate(void); MessageQueue mDelayedResponses; @@ -1426,7 +1430,6 @@ private: } mParentRequest; otMleAttachFilter mParentRequestMode; - uint8_t mParentLinkQuality; int8_t mParentPriority; uint8_t mParentLinkQuality3; uint8_t mParentLinkQuality2; diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 75843721a..294d75108 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -936,6 +936,7 @@ ThreadError MleRouter::HandleLinkAccept(const Message &aMessage, const Ip6::Mess break; case Neighbor::kStateInvalid: + case Neighbor::kStateValid: VerifyOrExit((mChallengeTimeout > 0) && (memcmp(mChallenge, response.GetResponse(), sizeof(mChallenge)) == 0), error = kThreadError_Error); break; @@ -3826,6 +3827,18 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Header *aHeader, Message *aMe } } + // Keep route path to the Leader reported by the parent before it is updated. + if (mRouters[GetLeaderId()].mCost == 0) + { + mRouters[GetLeaderId()].mCost = mParentLeaderCost; + } + + mRouters[GetLeaderId()].mNextHop = GetRouterId(mParent.mValid.mRloc16); + + // Keep link to the parent in order to response to Parent Requests before new link is established. + mRouters[GetRouterId(mParent.mValid.mRloc16)] = mParent; + mRouters[GetRouterId(mParent.mValid.mRloc16)].mAllocated = true; + // send link request SendLinkRequest(NULL);