mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
[mle] attach backoff feature (#2713)
This commit adds "attach backoff" feature in MLE. When enabled, an exponentially increasing backoff wait time is added between attach attempts. If device is sleepy, the radio will be put to sleep during the wait time. This ensures that a battery-powered sleepy end-device does not drain its battery by continuously searching for a parent to attach to (when there is no router/parent for it to attach). `OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF` configuration option can be used to enable/disable this feature. It is enabled by default.
This commit is contained in:
committed by
Jonathan Hui
parent
98ed5ea2ad
commit
1e68d2bbe0
@@ -1342,6 +1342,71 @@
|
||||
#define OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD -65
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF
|
||||
*
|
||||
* Define as 1 to enable attach backoff feature
|
||||
*
|
||||
* When this feature is enabled, an exponentially increasing backoff wait time is added between attach attempts.
|
||||
* If device is sleepy, the radio will be put to sleep during the wait time. This ensures that a battery-powered sleepy
|
||||
* end-device does not drain its battery by continuously searching for a parent to attach to (when there is no
|
||||
* router/parent for it to attach).
|
||||
*
|
||||
* The backoff time starts from a minimum interval specified by `OPENTHREAD_CONFIG_ATTACH_BACKOFF_MINIMUM_INTERVAL`,
|
||||
* and every attach attempt the wait time is doubled up to `OPENTHREAD_CONFIG_ATTACH_BACKOFF_MAXIMUM_INTERVAL` which
|
||||
* specifies the maximum wait time.
|
||||
*
|
||||
* Once the wait time reaches the maximum, a random jitter interval is added to it. The maximum value for jitter is
|
||||
* specified by `OPENTHREAD_CONFIG_ATTACH_BACKOFF_JITTER_INTERVAL`. The random jitter is selected uniformly within
|
||||
* range `[-JITTER, +JITTER]`. It is only added when the backoff wait interval is at maximum value.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF
|
||||
#define OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ATTACH_BACKOFF_MINIMUM_INTERVAL
|
||||
*
|
||||
* Specifies the minimum backoff wait interval (in milliseconds) used by attach backoff feature.
|
||||
*
|
||||
* Applicable only if attach backoff feature is enabled (see `OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF`).
|
||||
*
|
||||
* Please see `OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF` description for more details.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ATTACH_BACKOFF_MINIMUM_INTERVAL
|
||||
#define OPENTHREAD_CONFIG_ATTACH_BACKOFF_MINIMUM_INTERVAL 251
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ATTACH_BACKOFF_MAXIMUM_INTERVAL
|
||||
*
|
||||
* Specifies the maximum backoff wait interval (in milliseconds) used by attach backoff feature.
|
||||
*
|
||||
* Applicable only if attach backoff feature is enabled (see `OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF`).
|
||||
*
|
||||
* Please see `OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF` description for more details.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ATTACH_BACKOFF_MAXIMUM_INTERVAL
|
||||
#define OPENTHREAD_CONFIG_ATTACH_BACKOFF_MAXIMUM_INTERVAL 1200000 // 1200 seconds = 20 minutes
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_ATTACH_BACKOFF_JITTER_INTERVAL
|
||||
*
|
||||
* Specifies the maximum jitter interval (in milliseconds) used by attach backoff feature.
|
||||
*
|
||||
* Applicable only if attach backoff feature is enabled (see `OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF`).
|
||||
*
|
||||
* Please see `OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF` description for more details.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_ATTACH_BACKOFF_JITTER_INTERVAL
|
||||
#define OPENTHREAD_CONFIG_ATTACH_BACKOFF_JITTER_INTERVAL 2000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_SEND_UNICAST_ANNOUNCE_RESPONSE
|
||||
*
|
||||
|
||||
+78
-6
@@ -520,6 +520,12 @@ otError Mle::BecomeDetached(void)
|
||||
|
||||
VerifyOrExit(mRole != OT_DEVICE_ROLE_DISABLED, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
// In case role is already detached and attach state is `kAttachStateStart`
|
||||
// (i.e., waiting to start an attach attempt), there is no need to make any
|
||||
// changes.
|
||||
|
||||
VerifyOrExit(mRole != OT_DEVICE_ROLE_DETACHED || mAttachState != kAttachStateStart);
|
||||
|
||||
// not in reattach stage after reset
|
||||
if (mReattachState == kReattachStop)
|
||||
{
|
||||
@@ -563,10 +569,6 @@ otError Mle::BecomeChild(AttachMode aMode)
|
||||
SetAttachState(kAttachStateStart);
|
||||
mParentRequestMode = aMode;
|
||||
|
||||
mAttachCounter++;
|
||||
otLogInfoMle(GetInstance(), "Attempt to attach - attempt %d, %s %s", mAttachCounter, AttachModeToString(aMode),
|
||||
ReattachStateToString(mReattachState));
|
||||
|
||||
if (aMode != kAttachBetter)
|
||||
{
|
||||
if (IsFullThreadDevice())
|
||||
@@ -575,12 +577,71 @@ otError Mle::BecomeChild(AttachMode aMode)
|
||||
}
|
||||
}
|
||||
|
||||
mAttachTimer.Start(1 + ((mAttachCounter == 1) ? Random::GetUint32InRange(0, kParentRequestRouterTimeout) : 0));
|
||||
mAttachTimer.Start(GetAttachStartDelay());
|
||||
|
||||
if (mRole == OT_DEVICE_ROLE_DETACHED)
|
||||
{
|
||||
mAttachCounter++;
|
||||
|
||||
if (mAttachCounter == 0)
|
||||
{
|
||||
mAttachCounter--;
|
||||
}
|
||||
|
||||
if (!IsRxOnWhenIdle())
|
||||
{
|
||||
netif.GetMac().SetRxOnWhenIdle(false);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t Mle::GetAttachStartDelay(void) const
|
||||
{
|
||||
uint32_t delay = 1;
|
||||
uint32_t jitter;
|
||||
|
||||
VerifyOrExit(mRole == OT_DEVICE_ROLE_DETACHED);
|
||||
|
||||
if (mAttachCounter == 0)
|
||||
{
|
||||
delay = 1 + Random::GetUint32InRange(0, kParentRequestRouterTimeout);
|
||||
ExitNow();
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF
|
||||
else
|
||||
{
|
||||
uint16_t counter = mAttachCounter - 1;
|
||||
const uint32_t ratio = kAttachBackoffMaxInterval / kAttachBackoffMinInterval;
|
||||
|
||||
if ((counter <= sizeof(ratio) * CHAR_BIT) && ((1U << counter) <= ratio))
|
||||
{
|
||||
delay = kAttachBackoffMinInterval;
|
||||
delay <<= counter;
|
||||
}
|
||||
else
|
||||
{
|
||||
delay = Random::AddJitter(kAttachBackoffMaxInterval, kAttachBackoffJitter);
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_ENABLE_ATTACH_BACKOFF
|
||||
|
||||
jitter = Random::GetUint32InRange(0, kAttachStartJitter);
|
||||
|
||||
if (jitter + delay > delay) // check for overflow
|
||||
{
|
||||
delay += jitter;
|
||||
}
|
||||
|
||||
otLogInfoMle(GetInstance(), "Attach attempt %d unsuccessful, will try again in %u.%03u seconds", mAttachCounter,
|
||||
delay / 1000, delay % 1000);
|
||||
|
||||
exit:
|
||||
return delay;
|
||||
}
|
||||
|
||||
bool Mle::IsAttached(void) const
|
||||
{
|
||||
return (mRole == OT_DEVICE_ROLE_CHILD || mRole == OT_DEVICE_ROLE_ROUTER || mRole == OT_DEVICE_ROLE_LEADER);
|
||||
@@ -1484,6 +1545,17 @@ void Mle::HandleAttachTimer(void)
|
||||
break;
|
||||
|
||||
case kAttachStateStart:
|
||||
if (mAttachCounter > 0)
|
||||
{
|
||||
otLogInfoMle(GetInstance(), "Attempt to attach - attempt %d, %s %s", mAttachCounter,
|
||||
AttachModeToString(mParentRequestMode), ReattachStateToString(mReattachState));
|
||||
}
|
||||
else
|
||||
{
|
||||
otLogInfoMle(GetInstance(), "Attempt to attach - %s %s", AttachModeToString(mParentRequestMode),
|
||||
ReattachStateToString(mReattachState));
|
||||
}
|
||||
|
||||
SetAttachState(kAttachStateParentRequestRouter);
|
||||
mParentCandidate.SetState(Neighbor::kStateInvalid);
|
||||
mReceivedResponseFromParent = false;
|
||||
@@ -1600,7 +1672,7 @@ uint32_t Mle::Reattach(void)
|
||||
netif.GetPendingDataset().ApplyConfiguration();
|
||||
mReattachState = kReattachPending;
|
||||
SetAttachState(kAttachStateStart);
|
||||
delay = 1 + Random::GetUint32InRange(0, kParentRequestJitter);
|
||||
delay = 1 + Random::GetUint32InRange(0, kAttachStartJitter);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+13
-11
@@ -1520,6 +1520,18 @@ private:
|
||||
{
|
||||
kMleMessagePriority = Message::kPriorityHigh,
|
||||
kMleHopLimit = 255,
|
||||
|
||||
// Parameters related to "periodic parent search" feature (CONFIG_ENABLE_PERIODIC_PARENT_SEARCH).
|
||||
// All timer intervals are converted to milliseconds.
|
||||
kParentSearchCheckInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_CHECK_INTERVAL * 1000u),
|
||||
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_ATTACH_BACKOFF_MINIMUM_INTERVAL,
|
||||
kAttachBackoffMaxInterval = OPENTHREAD_CONFIG_ATTACH_BACKOFF_MAXIMUM_INTERVAL,
|
||||
kAttachBackoffJitter = OPENTHREAD_CONFIG_ATTACH_BACKOFF_JITTER_INTERVAL,
|
||||
};
|
||||
|
||||
enum ParentRequestType
|
||||
@@ -1528,17 +1540,6 @@ private:
|
||||
kParentRequestTypeRoutersAndReeds, ///< Parent Request to all routers and REEDs.
|
||||
};
|
||||
|
||||
#if OPENTHREAD_CONFIG_ENABLE_PERIODIC_PARENT_SEARCH
|
||||
enum
|
||||
{
|
||||
// All timer intervals are converted to milliseconds
|
||||
kParentSearchCheckInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_CHECK_INTERVAL * 1000u),
|
||||
kParentSearchBackoffInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_BACKOFF_INTERVAL * 1000u),
|
||||
kParentSearchJitterInterval = (15 * 1000u),
|
||||
kParentSearchRssThreadhold = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD,
|
||||
};
|
||||
#endif
|
||||
|
||||
void GenerateNonce(const Mac::ExtAddress &aMacAddr,
|
||||
uint32_t aFrameCounter,
|
||||
uint8_t aSecurityLevel,
|
||||
@@ -1568,6 +1569,7 @@ private:
|
||||
otError HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void ProcessAnnounce(void);
|
||||
|
||||
uint32_t GetAttachStartDelay(void) const;
|
||||
otError SendParentRequest(ParentRequestType aType);
|
||||
otError SendChildIdRequest(void);
|
||||
otError SendOrphanAnnounce(void);
|
||||
|
||||
@@ -61,7 +61,7 @@ enum
|
||||
kUdpPort = 19788, ///< MLE UDP Port
|
||||
kParentRequestRouterTimeout = 750, ///< Router Parent Request timeout
|
||||
kParentRequestReedTimeout = 1250, ///< Router and REEDs Parent Request timeout
|
||||
kParentRequestJitter = 50, ///< Maximum jitter time added to Parent Request timeout
|
||||
kAttachStartJitter = 50, ///< Maximum jitter time added to start of attach.
|
||||
kAnnounceProcessTimeout = 250, ///< Timeout after receiving Announcement before channel/pan-id change
|
||||
kAnnounceTimeout = 1400, ///< Total timeout used for sending Announcement messages
|
||||
kMinAnnounceDelay = 80, ///< Minimum delay between Announcement messages
|
||||
|
||||
Reference in New Issue
Block a user