diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index fdf1947c6..0b90a4dac 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -4431,6 +4431,7 @@ Mle::Attacher::Attacher(Instance &aInstance) , mAddressRegistrationMode(kAppendAllAddresses) , mParentRequestCounter(0) , mAnnounceChannel(0) + , mChildIdRequestsRemaining(kMaxChildIdRequests) , mAttachCounter(0) , mAnnounceDelay(kAnnounceTimeout) , mTimer(aInstance) @@ -4667,15 +4668,15 @@ bool Mle::Attacher::HasAcceptableParentCandidate(void) const bool hasAcceptableParent = false; ParentRequestType parentReqType; - VerifyOrExit(mParentCandidate.IsStateParentResponse()); - switch (mState) { case kStateAnnounce: + VerifyOrExit(mParentCandidate.IsStateParentResponse()); VerifyOrExit(!HasMoreChannelsToAnnounce()); break; case kStateParentRequest: + VerifyOrExit(mParentCandidate.IsStateParentResponse()); SuccessOrAssert(DetermineParentRequestType(parentReqType)); if (parentReqType == kToRouters) @@ -4689,6 +4690,11 @@ bool Mle::Attacher::HasAcceptableParentCandidate(void) const break; + case kStateChildIdRequest: + VerifyOrExit(mParentCandidate.IsStateValid()); + VerifyOrExit(mChildIdRequestsRemaining > 0); + break; + default: ExitNow(); } @@ -4732,7 +4738,8 @@ void Mle::Attacher::HandleTimer(void) if (HasAcceptableParentCandidate() && (SendChildIdRequest() == kErrorNone)) { SetState(kStateChildIdRequest); - delay = kChildIdResponseTimeout; + mChildIdRequestsRemaining--; + delay = Random::NonCrypto::AddJitter(kChildIdResponseTimeout, kChildIdResponseJitter); ExitNow(); } @@ -4750,6 +4757,7 @@ void Mle::Attacher::HandleTimer(void) mParentCandidate.SetState(Neighbor::kStateInvalid); mReceivedResponseFromParent = false; mParentRequestCounter = 0; + mChildIdRequestsRemaining = kMaxChildIdRequests; Get().SetRxOnWhenIdle(true); OT_FALL_THROUGH; diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index d46372156..c957e02fb 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1264,6 +1264,7 @@ private: static constexpr uint32_t kParentRequestReedTimeout = 1250; // Wait timer after tx of Parent Req to REEDs static constexpr uint32_t kParentRequestDuplicateTimeout = 700; // Min time to detect duplicate Parent Req rx static constexpr uint32_t kChildIdResponseTimeout = 1250; // Wait time to receive Child ID Response + static constexpr uint32_t kChildIdResponseJitter = kChildIdResponseTimeout * 1 / 10; // Jitter 10% static constexpr uint32_t kAttachStartJitter = 50; // Max jitter time added to start of attach static constexpr uint32_t kAnnounceProcessTimeout = 250; // Delay after Announce rx before processing static constexpr uint32_t kAnnounceTimeout = 1400; // Total timeout for sending Announce messages @@ -1941,6 +1942,8 @@ private: kReattachModePending, // Reattach using stored Pending Dataset }; + static constexpr uint8_t kMaxChildIdRequests = 3; + void SetState(State aState); uint32_t GetStartDelay(void) const; bool HasAcceptableParentCandidate(void) const; @@ -1975,6 +1978,7 @@ private: AddressRegistrationMode mAddressRegistrationMode; uint8_t mParentRequestCounter; uint8_t mAnnounceChannel; + uint8_t mChildIdRequestsRemaining; uint16_t mAttachCounter; uint16_t mAnnounceDelay; TxChallenge mParentRequestChallenge;