diff --git a/src/core/config/mle.h b/src/core/config/mle.h index 5c2ee78a0..e6131bd49 100644 --- a/src/core/config/mle.h +++ b/src/core/config/mle.h @@ -163,6 +163,26 @@ #define OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_JITTER_INTERVAL 2000 #endif +/** + * @def OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL + * + * Specifies the delay wait interval (in milliseconds) used by attach backoff feature after a successful attach before + * it resets the current backoff interval back to the minimum value. + * + * If it is set to zero then the device resets its backoff attach interval immediately after a successful attach. With + * a non-zero value, if after a successful attach, the device happens to detach within the delay interval, the reattach + * process resumes with the previous backoff interval (as if the attach did not happen). + * + * This behavior is helpful in the situation where a battery-powered device has poor link quality to its parent and + * therefore attaches and detaches frequently from the parent. Using a non-zero wait interval ensures that the attach + * backoff interval does not reset on each attach and that the device does not drain its battery quickly trying to + * re-attach too frequently. + * + */ +#ifndef OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL +#define OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL 20000 +#endif + /** * @def OPENTHREAD_CONFIG_MLE_SEND_LINK_REQUEST_ON_ADV_TIMEOUT * diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 7161e8b5a..341f6010a 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -502,6 +502,11 @@ otError Mle::BecomeChild(AttachMode aMode) VerifyOrExit(!IsDisabled(), error = OT_ERROR_INVALID_STATE); VerifyOrExit(!IsAttaching(), error = OT_ERROR_BUSY); + if (!IsDetached()) + { + mAttachCounter = 0; + } + if (mReattachState == kReattachStart) { if (Get().Restore() == OT_ERROR_NONE) @@ -652,8 +657,7 @@ void Mle::SetStateChild(uint16_t aRloc16) SetRloc16(aRloc16); SetRole(kRoleChild); SetAttachState(kAttachStateIdle); - mAttachTimer.Stop(); - mAttachCounter = 0; + mAttachTimer.Start(kAttachBackoffDelayToResetCounter); mReattachState = kReattachStop; mChildUpdateAttempts = 0; mDataRequestAttempts = 0; @@ -1667,8 +1671,8 @@ void Mle::HandleAttachTimer(void) switch (mAttachState) { case kAttachStateIdle: - OT_ASSERT(false); - OT_UNREACHABLE_CODE(break); + mAttachCounter = 0; + break; case kAttachStateProcessAnnounce: ProcessAnnounce(); @@ -3795,6 +3799,7 @@ void Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessa mAlternatePanId = panId; SetAttachState(kAttachStateProcessAnnounce); mAttachTimer.Start(kAnnounceProcessTimeout); + mAttachCounter = 0; otLogNoteMle("Delay processing Announce - channel %d, panid 0x%02x", channel, panId); } diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 5f3e488d9..aed45f18c 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1575,11 +1575,15 @@ private: kParentSearchBackoffInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_BACKOFF_INTERVAL * 1000u), kParentSearchJitterInterval = (15 * 1000u), kParentSearchRssThreadhold = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD, + }; - // Parameters for "attach backoff" feature (CONFIG_ENABLE_ATTACH_BACKOFF) - Intervals are in milliseconds. - kAttachBackoffMinInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MINIMUM_INTERVAL, - kAttachBackoffMaxInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL, - kAttachBackoffJitter = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_JITTER_INTERVAL, + // Parameters for "attach backoff" feature (CONFIG_ENABLE_ATTACH_BACKOFF) - Intervals are in milliseconds. + enum : uint32_t + { + kAttachBackoffMinInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MINIMUM_INTERVAL, + kAttachBackoffMaxInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL, + kAttachBackoffJitter = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_JITTER_INTERVAL, + kAttachBackoffDelayToResetCounter = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL, }; enum ParentRequestType