Evict least-recently-used address cache entry. (#1358)

- Maintain ordering of cache entries based on use.
- Evict least-recently-used cache entry when all are used.
This commit is contained in:
Jonathan Hui
2017-02-22 09:16:01 -08:00
committed by GitHub
parent 985e5360b8
commit 4c39f7c112
2 changed files with 74 additions and 9 deletions
+69 -9
View File
@@ -59,7 +59,7 @@ AddressResolver::AddressResolver(ThreadNetif &aThreadNetif) :
mTimer(aThreadNetif.GetIp6().mTimerScheduler, &AddressResolver::HandleTimer, this),
mNetif(aThreadNetif)
{
memset(&mCache, 0, sizeof(mCache));
Clear();
mNetif.GetCoapServer().AddResource(mAddressError);
mNetif.GetCoapServer().AddResource(mAddressQuery);
@@ -71,6 +71,11 @@ AddressResolver::AddressResolver(ThreadNetif &aThreadNetif) :
void AddressResolver::Clear()
{
memset(&mCache, 0, sizeof(mCache));
for (uint8_t i = 0; i < kCacheEntries; i++)
{
mCache[i].mAge = i;
}
}
ThreadError AddressResolver::GetEntry(uint8_t aIndex, otEidCacheEntry &aEntry) const
@@ -90,13 +95,66 @@ void AddressResolver::Remove(uint8_t routerId)
{
for (int i = 0; i < kCacheEntries; i++)
{
if ((mCache[i].mRloc16 >> 10) == routerId)
if (Mle::Mle::GetRouterId(mCache[i].mRloc16) == routerId)
{
mCache[i].mState = Cache::kStateInvalid;
InvalidateCacheEntry(mCache[i]);
}
}
}
AddressResolver::Cache *AddressResolver::NewCacheEntry(void)
{
Cache *rval = NULL;
for (int i = 0; i < kCacheEntries; i++)
{
if (mCache[i].mState == Cache::kStateQuery && mCache[i].mFailures == 0)
{
continue;
}
if (rval == NULL || rval->mAge < mCache[i].mAge)
{
rval = &mCache[i];
}
}
if (rval != NULL)
{
InvalidateCacheEntry(*rval);
}
return rval;
}
void AddressResolver::MarkCacheEntryAsUsed(Cache &aEntry)
{
for (int i = 0; i < kCacheEntries; i++)
{
if (mCache[i].mAge < aEntry.mAge)
{
mCache[i].mAge++;
}
}
aEntry.mAge = 0;
}
void AddressResolver::InvalidateCacheEntry(Cache &aEntry)
{
for (int i = 0; i < kCacheEntries; i++)
{
if (mCache[i].mAge > aEntry.mAge)
{
mCache[i].mAge--;
}
}
aEntry.mAge = kCacheEntries - 1;
aEntry.mState = Cache::kStateInvalid;
otLogInfoArp("cache entry removed!");
}
ThreadError AddressResolver::Resolve(const Ip6::Address &aEid, uint16_t &aRloc16)
{
ThreadError error = kThreadError_None;
@@ -112,10 +170,11 @@ ThreadError AddressResolver::Resolve(const Ip6::Address &aEid, uint16_t &aRloc16
break;
}
}
else if (entry == NULL)
{
entry = &mCache[i];
}
}
if (entry == NULL)
{
entry = NewCacheEntry();
}
VerifyOrExit(entry != NULL, error = kThreadError_NoBufs);
@@ -153,6 +212,7 @@ ThreadError AddressResolver::Resolve(const Ip6::Address &aEid, uint16_t &aRloc16
case Cache::kStateCached:
aRloc16 = entry->mRloc16;
MarkCacheEntryAsUsed(*entry);
break;
}
@@ -277,6 +337,7 @@ void AddressResolver::HandleAddressNotification(Coap::Header &aHeader, Message &
mCache[i].mTimeout = 0;
mCache[i].mFailures = 0;
mCache[i].mState = Cache::kStateCached;
MarkCacheEntryAsUsed(mCache[i]);
if (mNetif.GetCoapServer().SendEmptyAck(aHeader, aMessageInfo) == kThreadError_None)
{
@@ -605,8 +666,7 @@ void AddressResolver::HandleDstUnreach(Message &aMessage, const Ip6::MessageInfo
if (mCache[i].mState != Cache::kStateInvalid &&
memcmp(&mCache[i].mTarget, &ip6Header.GetDestination(), sizeof(mCache[i].mTarget)) == 0)
{
mCache[i].mState = Cache::kStateInvalid;
otLogInfoArp("cache entry removed!");
InvalidateCacheEntry(mCache[i]);
break;
}
}
+5
View File
@@ -138,6 +138,7 @@ private:
uint16_t mRetryTimeout;
uint8_t mTimeout;
uint8_t mFailures;
uint8_t mAge;
enum State
{
@@ -148,6 +149,10 @@ private:
State mState;
};
Cache *NewCacheEntry(void);
void MarkCacheEntryAsUsed(Cache &aEntry);
void InvalidateCacheEntry(Cache &aEntry);
ThreadError SendAddressQuery(const Ip6::Address &aEid);
ThreadError SendAddressError(const ThreadTargetTlv &aTarget, const ThreadMeshLocalEidTlv &aEid,
const Ip6::Address *aDestination);