[address-resolver] freshness timeout mechanism for cache entries (#10575)

This commit introduces a freshness timeout mechanism for address cache
entries which is used to decide when removing stale entries when the
associated RLOC16 is unreachable.

In `AddressResolver`, when resolving an EID from an existing cache
entry, if the target RLOC16 is unreachable, the entry is typically
considered stale and removed to allow a new address query to be sent.
This commit adds a mechanism to skip this removal step if the entry
has been recently updated, i.e., an `AddressNotify` has been received
for it and its `FreshnessTimeout` has not yet expired.

The `FreshnessTimeout` check prevents repeated address query
transmissions when mesh routes are not yet discovered (e.g., after
initial attach) or if there is a temporary link issue.
This commit is contained in:
Abtin Keshavarzian
2024-08-14 12:58:04 -07:00
committed by GitHub
parent 9fd6596e7b
commit fd7284b0e9
2 changed files with 42 additions and 9 deletions
+32 -7
View File
@@ -493,18 +493,31 @@ Error AddressResolver::Resolve(const Ip6::Address &aEid, uint16_t &aRloc16, bool
if ((entry != nullptr) && ((list == &mCachedList) || (list == &mSnoopedList)))
{
bool isFresh;
list->PopAfter(prev);
if (Get<RouterTable>().GetNextHop(entry->GetRloc16()) == Mle::kInvalidRloc16)
{
// If the `entry->GetRloc16()` is unreachable (there is no valid
// next hop towards it), we clear the entry so to start a new
// address query.
// If the `entry->GetRloc16()` is unreachable (there is no
// valid next hop towards it), it may be a stale entry. We
// clear the entry to allow new address query to be sent for
// it, unless the entry has been recently updated, i.e., we
// have recently received an `AddressNotify` for it and its
// `FreshnessTimeout` has not expired yet.
//
// The `FreshnessTimeout` check prevents repeated address
// query transmissions when mesh routes are not yet
// discovered (e.g., after initial attach) or if there is a
// temporary link issue.
isFresh = (list == &mCachedList) && !entry->IsFreshnessTimeoutZero();
if (!isFresh && (Get<RouterTable>().GetNextHop(entry->GetRloc16()) == Mle::kInvalidRloc16))
{
mCacheEntryPool.Free(*entry);
entry = nullptr;
}
else
if (entry != nullptr)
{
// Push the entry at the head of cached list.
@@ -701,6 +714,8 @@ void AddressResolver::HandleTmf<kUriAddressNotify>(Coap::Message &aMessage, cons
entry->SetRloc16(rloc16);
entry->SetMeshLocalIid(meshLocalIid);
entry->SetLastTransactionTime(lastTransactionTime);
entry->ResetFreshnessTimeout();
Get<TimeTicker>().RegisterReceiver(TimeTicker::kAddressResolver);
list->PopAfter(prev);
mCachedList.Push(*entry);
@@ -926,6 +941,15 @@ void AddressResolver::HandleTimeTick(void)
{
bool continueRxingTicks = false;
for (CacheEntry &entry : mCachedList)
{
if (!entry.IsFreshnessTimeoutZero())
{
entry.DecrementFreshnessTimeout();
continueRxingTicks = true;
}
}
for (CacheEntry &entry : mSnoopedList)
{
if (entry.IsTimeoutZero())
@@ -1128,7 +1152,8 @@ void AddressResolver::LogCacheEntryChange(EntryChange, Reason, const CacheEntry
void AddressResolver::CacheEntry::Init(Instance &aInstance)
{
InstanceLocatorInit::Init(aInstance);
mNextIndex = kNoNextIndex;
mNextIndex = kNoNextIndex;
mFreshnessTimeout = 0;
}
AddressResolver::CacheEntry *AddressResolver::CacheEntry::GetNext(void)
+10 -2
View File
@@ -283,6 +283,10 @@ private:
uint16_t GetTimeout(void) const { return mInfo.mOther.mTimeout; }
void SetTimeout(uint16_t aTimeout) { mInfo.mOther.mTimeout = aTimeout; }
void DecrementFreshnessTimeout(void) { mFreshnessTimeout--; }
bool IsFreshnessTimeoutZero(void) const { return mFreshnessTimeout == 0; }
void ResetFreshnessTimeout(void) { mFreshnessTimeout = kFreshnessTimeout; }
uint16_t GetRetryDelay(void) const { return mInfo.mOther.mRetryDelay; }
void SetRetryDelay(uint16_t aDelay) { mInfo.mOther.mRetryDelay = aDelay; }
@@ -295,12 +299,16 @@ private:
bool Matches(const Ip6::Address &aEid) const { return GetTarget() == aEid; }
private:
static constexpr uint16_t kNoNextIndex = 0xffff; // `mNextIndex` value when at end of list.
static constexpr uint16_t kNoNextIndex = 0x3fff; // `mNextIndex` value when at end of list.
static constexpr uint32_t kInvalidLastTransTime = 0xffffffff; // Value when `mLastTransactionTime` is invalid.
static constexpr uint8_t kFreshnessTimeout = 3;
static_assert(kCacheEntries < kNoNextIndex, "kCacheEntries is too large and does not fit in 14 bit index");
Ip6::Address mTarget;
uint16_t mRloc16;
uint16_t mNextIndex;
uint16_t mNextIndex : 14;
uint8_t mFreshnessTimeout : 2;
union
{