From e25f97d0fbb94b9354c1f572a187531ea7828a89 Mon Sep 17 00:00:00 2001 From: rongli Date: Fri, 12 Jan 2018 01:01:58 +0800 Subject: [PATCH] [mle] fix some corner cases when trying to attach to a better partition (#2461) --- src/core/thread/mle.cpp | 20 ++++++++++++++++---- src/core/thread/mle_router.cpp | 9 ++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 445548466..e14099c24 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1647,11 +1647,23 @@ otError Mle::SendChildIdRequest(void) Message *message = NULL; Ip6::Address destination; - if (mRole == OT_DEVICE_ROLE_CHILD && - mParent.GetExtAddress() == mParentCandidate.GetExtAddress()) + if (mParent.GetExtAddress() == mParentCandidate.GetExtAddress()) { - otLogInfoMle(GetInstance(), "Already attached to candidate parent"); - ExitNow(error = OT_ERROR_ALREADY); + if (mRole == OT_DEVICE_ROLE_CHILD) + { + otLogInfoMle(GetInstance(), "Already attached to candidate parent"); + ExitNow(error = OT_ERROR_ALREADY); + } + else + { + // Invalidate stale parent state. + // + // Parent state is not normally invalidated after becoming a Router/Leader (see #1875). When trying to + // attach to a better partition, invalidating old parent state (especially when in kStateRestored) ensures + // that GetNeighbor() returns mParentCandidate when processing the Child ID Response. + mParent.SetState(Neighbor::kStateInvalid); + otPlatSettingsDelete(&GetInstance(), Settings::kKeyParentInfo, -1); + } } VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS); diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 709490955..582289b9a 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -551,7 +551,14 @@ otError MleRouter::SendAdvertisement(void) { otError error = OT_ERROR_NONE; Ip6::Address destination; - Message *message; + Message *message = NULL; + + // Suppress MLE Advertisements when trying to attach to a better partition. + // + // Without this suppression, a device may send an MLE Advertisement before receiving the MLE Child ID Response. + // The candidate parent then removes the attaching device because the Source Address TLV includes an RLOC16 that + // indicates a Router role (i.e. a Child ID equal to zero). + VerifyOrExit(mParentRequestState == kParentIdle); VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS); SuccessOrExit(error = AppendHeader(*message, Header::kCommandAdvertisement));