mirror of
https://github.com/espressif/openthread.git
synced 2026-09-13 20:50:05 +00:00
[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:
@@ -493,18 +493,31 @@ Error AddressResolver::Resolve(const Ip6::Address &aEid, uint16_t &aRloc16, bool
|
|||||||
|
|
||||||
if ((entry != nullptr) && ((list == &mCachedList) || (list == &mSnoopedList)))
|
if ((entry != nullptr) && ((list == &mCachedList) || (list == &mSnoopedList)))
|
||||||
{
|
{
|
||||||
|
bool isFresh;
|
||||||
|
|
||||||
list->PopAfter(prev);
|
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), it may be a stale entry. We
|
||||||
// If the `entry->GetRloc16()` is unreachable (there is no valid
|
// clear the entry to allow new address query to be sent for
|
||||||
// next hop towards it), we clear the entry so to start a new
|
// it, unless the entry has been recently updated, i.e., we
|
||||||
// address query.
|
// 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);
|
mCacheEntryPool.Free(*entry);
|
||||||
entry = nullptr;
|
entry = nullptr;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (entry != nullptr)
|
||||||
{
|
{
|
||||||
// Push the entry at the head of cached list.
|
// 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->SetRloc16(rloc16);
|
||||||
entry->SetMeshLocalIid(meshLocalIid);
|
entry->SetMeshLocalIid(meshLocalIid);
|
||||||
entry->SetLastTransactionTime(lastTransactionTime);
|
entry->SetLastTransactionTime(lastTransactionTime);
|
||||||
|
entry->ResetFreshnessTimeout();
|
||||||
|
Get<TimeTicker>().RegisterReceiver(TimeTicker::kAddressResolver);
|
||||||
|
|
||||||
list->PopAfter(prev);
|
list->PopAfter(prev);
|
||||||
mCachedList.Push(*entry);
|
mCachedList.Push(*entry);
|
||||||
@@ -926,6 +941,15 @@ void AddressResolver::HandleTimeTick(void)
|
|||||||
{
|
{
|
||||||
bool continueRxingTicks = false;
|
bool continueRxingTicks = false;
|
||||||
|
|
||||||
|
for (CacheEntry &entry : mCachedList)
|
||||||
|
{
|
||||||
|
if (!entry.IsFreshnessTimeoutZero())
|
||||||
|
{
|
||||||
|
entry.DecrementFreshnessTimeout();
|
||||||
|
continueRxingTicks = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (CacheEntry &entry : mSnoopedList)
|
for (CacheEntry &entry : mSnoopedList)
|
||||||
{
|
{
|
||||||
if (entry.IsTimeoutZero())
|
if (entry.IsTimeoutZero())
|
||||||
@@ -1128,7 +1152,8 @@ void AddressResolver::LogCacheEntryChange(EntryChange, Reason, const CacheEntry
|
|||||||
void AddressResolver::CacheEntry::Init(Instance &aInstance)
|
void AddressResolver::CacheEntry::Init(Instance &aInstance)
|
||||||
{
|
{
|
||||||
InstanceLocatorInit::Init(aInstance);
|
InstanceLocatorInit::Init(aInstance);
|
||||||
mNextIndex = kNoNextIndex;
|
mNextIndex = kNoNextIndex;
|
||||||
|
mFreshnessTimeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressResolver::CacheEntry *AddressResolver::CacheEntry::GetNext(void)
|
AddressResolver::CacheEntry *AddressResolver::CacheEntry::GetNext(void)
|
||||||
|
|||||||
@@ -283,6 +283,10 @@ private:
|
|||||||
uint16_t GetTimeout(void) const { return mInfo.mOther.mTimeout; }
|
uint16_t GetTimeout(void) const { return mInfo.mOther.mTimeout; }
|
||||||
void SetTimeout(uint16_t aTimeout) { mInfo.mOther.mTimeout = aTimeout; }
|
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; }
|
uint16_t GetRetryDelay(void) const { return mInfo.mOther.mRetryDelay; }
|
||||||
void SetRetryDelay(uint16_t aDelay) { mInfo.mOther.mRetryDelay = aDelay; }
|
void SetRetryDelay(uint16_t aDelay) { mInfo.mOther.mRetryDelay = aDelay; }
|
||||||
|
|
||||||
@@ -295,12 +299,16 @@ private:
|
|||||||
bool Matches(const Ip6::Address &aEid) const { return GetTarget() == aEid; }
|
bool Matches(const Ip6::Address &aEid) const { return GetTarget() == aEid; }
|
||||||
|
|
||||||
private:
|
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 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;
|
Ip6::Address mTarget;
|
||||||
uint16_t mRloc16;
|
uint16_t mRloc16;
|
||||||
uint16_t mNextIndex;
|
uint16_t mNextIndex : 14;
|
||||||
|
uint8_t mFreshnessTimeout : 2;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user