mirror of
https://github.com/espressif/openthread.git
synced 2026-08-01 08:37:47 +00:00
[address-resolver] implement ramp-down mechanism for retry delay (#9162)
Address resolver retry delay determines how long the device needs to wait after a failed address query for a target address to allow a next query attempt. This is tracked per target (in `CacheEntry`). The retry delay starts with an initial value (15 seconds). If consecutive queries fail, the retry delay doubles each time, up to a maximum value (120 seconds). In the current code, the retry delay is only reset to the initial value after a successful address resolution. This commit implements a new mechanism to reduce the retry delay over time when there is no activity (no queries for the target address). The ramp-down countdown starts after a previous retry delay has expired. If no query is requested within the maximum retry delay interval (120 seconds), the retry delay is divided by two. This process is repeated until the retry delay reaches the initial (minimum) value. If a query is requested during the ramp-down process, the ramp-down is stopped. The next actions are determined based on whether the query is successful or fails. If the query is successful, the retry delay is reset to the initial value. If the query fails, the retry delay timeout is applied and the ramp-down process is started again after the retry delay duration has expired. This commit also updates the `test-014-address-resolver` to validate the newly added ramp-down behavior.
This commit is contained in:
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (337)
|
||||
#define OPENTHREAD_API_VERSION (338)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -104,6 +104,7 @@ typedef struct otCacheEntryInfo
|
||||
otShortAddress mRloc16; ///< RLOC16
|
||||
otCacheEntryState mState; ///< Entry state
|
||||
bool mCanEvict : 1; ///< Indicates whether the entry can be evicted.
|
||||
bool mRampDown : 1; ///< Whether in ramp-down mode while in `OT_CACHE_ENTRY_STATE_RETRY_QUERY`.
|
||||
bool mValidLastTrans : 1; ///< Indicates whether last transaction time and ML-EID are valid.
|
||||
uint32_t mLastTransTime; ///< Last transaction time (applicable in cached state).
|
||||
otIp6Address mMeshLocalEid; ///< Mesh Local EID (applicable if entry in cached state).
|
||||
|
||||
+1
-1
@@ -2580,7 +2580,7 @@ void Interpreter::OutputEidCacheEntry(const otCacheEntryInfo &aEntry)
|
||||
|
||||
if (aEntry.mState == OT_CACHE_ENTRY_STATE_RETRY_QUERY)
|
||||
{
|
||||
OutputFormat(" retryDelay=%u", aEntry.mRetryDelay);
|
||||
OutputFormat(" retryDelay=%u rampDown=%d", aEntry.mRetryDelay, aEntry.mRampDown);
|
||||
}
|
||||
|
||||
OutputNewLine();
|
||||
|
||||
@@ -152,7 +152,8 @@ Error AddressResolver::GetNextCacheEntry(EntryInfo &aInfo, Iterator &aIterator)
|
||||
}
|
||||
else
|
||||
{
|
||||
aInfo.mState = MapEnum(EntryInfo::kStateRetryQuery);
|
||||
aInfo.mState = MapEnum(EntryInfo::kStateRetryQuery);
|
||||
aInfo.mRampDown = entry->IsInRampDown();
|
||||
}
|
||||
|
||||
aInfo.mCanEvict = entry->CanEvict();
|
||||
@@ -542,10 +543,10 @@ Error AddressResolver::Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRlo
|
||||
if (list == &mQueryRetryList)
|
||||
{
|
||||
// Allow an entry in query-retry mode to resend an Address
|
||||
// Query again only if the timeout (retry delay interval) is
|
||||
// expired.
|
||||
// Query again only if it is in ramp down mode, i.e., the
|
||||
// retry delay timeout is expired.
|
||||
|
||||
VerifyOrExit(entry->IsTimeoutZero(), error = kErrorDrop);
|
||||
VerifyOrExit(entry->IsInRampDown(), error = kErrorDrop);
|
||||
mQueryRetryList.PopAfter(prev);
|
||||
}
|
||||
|
||||
@@ -939,6 +940,33 @@ void AddressResolver::HandleTimeTick(void)
|
||||
|
||||
continueRxingTicks = true;
|
||||
entry.DecrementTimeout();
|
||||
|
||||
if (entry.IsTimeoutZero())
|
||||
{
|
||||
if (!entry.IsInRampDown())
|
||||
{
|
||||
entry.SetRampDown(true);
|
||||
entry.SetTimeout(kAddressQueryMaxRetryDelay);
|
||||
|
||||
LogInfo("Starting ramp down of %s retry-delay:%u", entry.GetTarget().ToString().AsCString(),
|
||||
entry.GetTimeout());
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t retryDelay = entry.GetRetryDelay();
|
||||
|
||||
retryDelay >>= 1;
|
||||
retryDelay = Max(retryDelay, kAddressQueryInitialRetryDelay);
|
||||
|
||||
if (retryDelay != entry.GetRetryDelay())
|
||||
{
|
||||
entry.SetRetryDelay(retryDelay);
|
||||
entry.SetTimeout(kAddressQueryMaxRetryDelay);
|
||||
|
||||
LogInfo("Ramping down %s retry-delay:%u", entry.GetTarget().ToString().AsCString(), retryDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -963,6 +991,7 @@ void AddressResolver::HandleTimeTick(void)
|
||||
|
||||
entry->SetRetryDelay(retryDelay);
|
||||
entry->SetCanEvict(true);
|
||||
entry->SetRampDown(false);
|
||||
|
||||
// Move the entry from `mQueryList` to `mQueryRetryList`
|
||||
mQueryList.PopAfter(prev);
|
||||
|
||||
@@ -285,6 +285,9 @@ private:
|
||||
bool CanEvict(void) const { return mInfo.mOther.mCanEvict; }
|
||||
void SetCanEvict(bool aCanEvict) { mInfo.mOther.mCanEvict = aCanEvict; }
|
||||
|
||||
bool IsInRampDown(void) const { return mInfo.mOther.mRampDown; }
|
||||
void SetRampDown(bool aRampDown) { mInfo.mOther.mRampDown = aRampDown; }
|
||||
|
||||
bool Matches(const Ip6::Address &aEid) const { return GetTarget() == aEid; }
|
||||
|
||||
private:
|
||||
@@ -308,6 +311,7 @@ private:
|
||||
uint16_t mTimeout;
|
||||
uint16_t mRetryDelay;
|
||||
bool mCanEvict;
|
||||
bool mRampDown;
|
||||
} mOther;
|
||||
|
||||
} mInfo;
|
||||
|
||||
@@ -201,17 +201,18 @@ verify_within(check_cache_entry_switch_to_retry_state, 20)
|
||||
# Now wait for all entries to reach zero timeout.
|
||||
|
||||
|
||||
def check_cache_entry_in_retry_state_to_get_to_zero_timeout():
|
||||
def check_cache_entry_in_retry_state_to_enter_rampdown():
|
||||
cache_table = r1.get_eidcache()
|
||||
for entry in cache_table:
|
||||
fields = entry.strip().split(' ')
|
||||
verify(fields[2] == 'retry')
|
||||
verify(fields[3] == 'canEvict=1')
|
||||
verify(fields[4].startswith('timeout='))
|
||||
verify(int(fields[4].split('=')[1]) == 0)
|
||||
verify(fields[5].startswith('retryDelay='))
|
||||
verify(fields[6] == 'rampDown=1')
|
||||
|
||||
|
||||
verify_within(check_cache_entry_in_retry_state_to_get_to_zero_timeout, 20)
|
||||
verify_within(check_cache_entry_in_retry_state_to_enter_rampdown, 20)
|
||||
|
||||
# Now send again to the same addresses.
|
||||
|
||||
@@ -231,6 +232,37 @@ def check_cache_entry_switch_to_query_state():
|
||||
|
||||
verify_within(check_cache_entry_switch_to_query_state, 20)
|
||||
|
||||
|
||||
def check_cache_entry_switch_to_retry_state_with_double_retry_delay():
|
||||
cache_table = r1.get_eidcache()
|
||||
for entry in cache_table:
|
||||
fields = entry.strip().split(' ')
|
||||
verify(fields[2] == 'retry')
|
||||
verify(fields[3] == 'canEvict=1')
|
||||
verify(fields[4].startswith('timeout='))
|
||||
verify(fields[5].startswith('retryDelay='))
|
||||
verify(int(fields[5].split('=')[1]) == 2 * initial_retry_delay)
|
||||
|
||||
|
||||
verify_within(check_cache_entry_switch_to_retry_state_with_double_retry_delay, 40)
|
||||
|
||||
verify_within(check_cache_entry_in_retry_state_to_enter_rampdown, 40)
|
||||
|
||||
|
||||
def check_cache_entry_ramp_down_to_initial_retry_delay():
|
||||
cache_table = r1.get_eidcache()
|
||||
for entry in cache_table:
|
||||
fields = entry.strip().split(' ')
|
||||
verify(fields[2] == 'retry')
|
||||
verify(fields[3] == 'canEvict=1')
|
||||
verify(fields[4].startswith('timeout='))
|
||||
verify(fields[5].startswith('retryDelay='))
|
||||
verify(int(fields[5].split('=')[1]) == initial_retry_delay)
|
||||
verify(fields[6] == 'rampDown=1')
|
||||
|
||||
|
||||
verify_within(check_cache_entry_ramp_down_to_initial_retry_delay, 60)
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Verify snoop optimization behavior.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user