[routing-manager] track discovered entries per router in prefix table (#7830)

This commit updates the data model used by `DiscoveredPrefixTable` in
`RoutingManager` to track the router which added each prefix entry.
This change ensures correct behavior when multiple routers on the
infra link advertise the same set of prefixes. The routers can
potentially advertise the same prefixes (in RIOs) with different
preference levels and/or stop/start advertising the prefixes
independently of each other. We publish the prefixes in Network Data
with highest seen preference. The published entries in Network Data
are also updated as the table entries changes.
This commit is contained in:
Abtin Keshavarzian
2022-06-28 08:37:19 -07:00
committed by GitHub
parent dbcebd2ed4
commit 827006b2e2
3 changed files with 329 additions and 128 deletions
+257 -106
View File
@@ -556,21 +556,13 @@ Error RoutingManager::PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePref
LogWarn("Failed to publish external route %s: %s", aPrefix.ToString().AsCString(), ErrorToString(error));
}
return (error == kErrorAlready) ? kErrorNone : error;
return error;
}
void RoutingManager::UnpublishExternalRoute(const Ip6::Prefix &aPrefix)
{
Error error = kErrorNone;
VerifyOrExit(mIsRunning);
error = Get<NetworkData::Publisher>().UnpublishPrefix(aPrefix);
if (error != kErrorNone)
{
LogWarn("Failed to unpublish route %s: %s", aPrefix.ToString().AsCString(), ErrorToString(error));
}
IgnoreError(Get<NetworkData::Publisher>().UnpublishPrefix(aPrefix));
exit:
return;
@@ -1234,27 +1226,47 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const Ip6
{
// Process a received RA message and update the prefix table.
OT_UNUSED_VARIABLE(aSrcAddress);
Router *router = mRouters.FindMatching(aSrcAddress);
if (router == nullptr)
{
router = mRouters.PushBack();
if (router == nullptr)
{
LogWarn("Received RA from too many routers, ignore RA from %s", aSrcAddress.ToString().AsCString());
ExitNow();
}
router->mAddress = aSrcAddress;
router->mEntries.Clear();
}
for (const Ip6::Nd::Option &option : aRaMessage)
{
switch (option.GetType())
{
case Ip6::Nd::Option::kTypePrefixInfo:
ProcessPrefixInfoOption(static_cast<const Ip6::Nd::PrefixInfoOption &>(option));
ProcessPrefixInfoOption(static_cast<const Ip6::Nd::PrefixInfoOption &>(option), *router);
break;
case Ip6::Nd::Option::kTypeRouteInfo:
ProcessRouteInfoOption(static_cast<const Ip6::Nd::RouteInfoOption &>(option));
ProcessRouteInfoOption(static_cast<const Ip6::Nd::RouteInfoOption &>(option), *router);
break;
default:
break;
}
}
RemoveRoutersWithNoEntries();
exit:
return;
}
void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio)
void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio,
Router & aRouter)
{
Ip6::Prefix prefix;
Entry * entry;
@@ -1266,21 +1278,22 @@ void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const Ip6::N
LogInfo("Processing PIO (%s, %u seconds)", prefix.ToString().AsCString(), aPio.GetValidLifetime());
entry = mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeOnLink));
entry = aRouter.mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeOnLink));
if (entry == nullptr)
{
VerifyOrExit(aPio.GetValidLifetime() != 0);
if (mEntries.IsFull())
entry = AllocateEntry();
if (entry == nullptr)
{
LogWarn("Discovered too many prefixes, ignore on-link prefix %s", prefix.ToString().AsCString());
ExitNow();
}
SuccessOrExit(Get<RoutingManager>().PublishExternalRoute(prefix, NetworkData::kRoutePreferenceMedium));
entry = mEntries.PushBack();
entry->InitFrom(aPio);
aRouter.mEntries.Push(*entry);
}
else
{
@@ -1290,6 +1303,7 @@ void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const Ip6::N
entry->AdoptValidAndPreferredLiftimesFrom(newEntry);
}
UpdateNetworkDataOnChangeTo(*entry);
mTimer.FireAtIfEarlier(entry->GetExpireTime());
SignalTableChanged();
@@ -1297,7 +1311,8 @@ exit:
return;
}
void RoutingManager::DiscoveredPrefixTable::ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio)
void RoutingManager::DiscoveredPrefixTable::ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio,
Router & aRouter)
{
Ip6::Prefix prefix;
Entry * entry;
@@ -1309,32 +1324,29 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouteInfoOption(const Ip6::Nd
LogInfo("Processing RIO (%s, %u seconds)", prefix.ToString().AsCString(), aRio.GetRouteLifetime());
entry = mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeRoute));
if (aRio.GetRouteLifetime() == 0)
{
VerifyOrExit(entry != nullptr);
Get<RoutingManager>().UnpublishExternalRoute(entry->GetPrefix());
mEntries.Remove(*entry);
ExitNow();
}
entry = aRouter.mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeRoute));
if (entry == nullptr)
{
if (mEntries.IsFull())
VerifyOrExit(aRio.GetRouteLifetime() != 0);
entry = AllocateEntry();
if (entry == nullptr)
{
LogWarn("Discovered too many prefixes, ignore new prefix %s", prefix.ToString().AsCString());
LogWarn("Discovered too many prefixes, ignore route prefix %s", prefix.ToString().AsCString());
ExitNow();
}
SuccessOrExit(Get<RoutingManager>().PublishExternalRoute(prefix, aRio.GetPreference()));
entry = mEntries.PushBack();
entry->InitFrom(aRio);
aRouter.mEntries.Push(*entry);
}
else
{
entry->InitFrom(aRio);
}
entry->InitFrom(aRio);
UpdateNetworkDataOnChangeTo(*entry);
mTimer.FireAtIfEarlier(entry->GetExpireTime());
SignalTableChanged();
@@ -1350,59 +1362,83 @@ void RoutingManager::DiscoveredPrefixTable::FindFavoredOnLinkPrefix(Ip6::Prefix
aPrefix.Clear();
for (const Entry &entry : mEntries)
for (const Router &router : mRouters)
{
if (!entry.IsOnLinkPrefix() || entry.IsDeprecated())
for (const Entry &entry : router.mEntries)
{
continue;
}
if (!entry.IsOnLinkPrefix() || entry.IsDeprecated())
{
continue;
}
if ((aPrefix.GetLength() == 0) || (entry.GetPrefix() < aPrefix))
{
aPrefix = entry.GetPrefix();
if ((aPrefix.GetLength() == 0) || (entry.GetPrefix() < aPrefix))
{
aPrefix = entry.GetPrefix();
}
}
}
}
bool RoutingManager::DiscoveredPrefixTable::ContainsOnLinkPrefix(const Ip6::Prefix &aPrefix) const
{
return mEntries.ContainsMatching(Entry::Matcher(aPrefix, Entry::kTypeOnLink));
return ContainsPrefix(Entry::Matcher(aPrefix, Entry::kTypeOnLink));
}
bool RoutingManager::DiscoveredPrefixTable::ContainsRoutePrefix(const Ip6::Prefix &aPrefix) const
{
return mEntries.ContainsMatching(Entry::Matcher(aPrefix, Entry::kTypeRoute));
return ContainsPrefix(Entry::Matcher(aPrefix, Entry::kTypeRoute));
}
bool RoutingManager::DiscoveredPrefixTable::ContainsPrefix(const Entry::Matcher &aMatcher) const
{
bool contains = false;
for (const Router &router : mRouters)
{
if (router.mEntries.ContainsMatching(aMatcher))
{
contains = true;
break;
}
}
return contains;
}
void RoutingManager::DiscoveredPrefixTable::RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode)
{
RemovePrefix(aPrefix, Entry::kTypeOnLink, aNetDataMode);
RemovePrefix(Entry::Matcher(aPrefix, Entry::kTypeOnLink), aNetDataMode);
}
void RoutingManager::DiscoveredPrefixTable::RemoveRoutePrefix(const Ip6::Prefix &aPrefix, NetDataMode aNetDataMode)
{
RemovePrefix(aPrefix, Entry::kTypeRoute, aNetDataMode);
RemovePrefix(Entry::Matcher(aPrefix, Entry::kTypeRoute), aNetDataMode);
}
void RoutingManager::DiscoveredPrefixTable::RemovePrefix(const Ip6::Prefix &aPrefix,
Entry::Type aType,
NetDataMode aNetDataMode)
void RoutingManager::DiscoveredPrefixTable::RemovePrefix(const Entry::Matcher &aMatcher, NetDataMode aNetDataMode)
{
// Remove a prefix of given type from the table if there is any.
// Removes all entries matching a given prefix from the table.
// `aNetDataMode` specifies behavior when a match is found and
// removed. It indicates whether or not to unpublish it from
// Network Data.
Entry *entry = mEntries.FindMatching(Entry::Matcher(aPrefix, aType));
LinkedList<Entry> removedEntries;
VerifyOrExit(entry != nullptr);
for (Router &router : mRouters)
{
router.mEntries.RemoveAllMatching(aMatcher, removedEntries);
}
VerifyOrExit(!removedEntries.IsEmpty());
if (aNetDataMode == kUnpublishFromNetData)
{
Get<RoutingManager>().UnpublishExternalRoute(aPrefix);
UnpublishEntry(*removedEntries.GetHead());
}
mEntries.Remove(*entry);
FreeEntries(removedEntries);
RemoveRoutersWithNoEntries();
SignalTableChanged();
exit:
@@ -1414,14 +1450,19 @@ void RoutingManager::DiscoveredPrefixTable::RemoveAllEntries(void)
// Remove all entries from the table and unpublish them
// from Network Data.
Entry *entry;
while ((entry = mEntries.PopBack()) != nullptr)
for (Router &router : mRouters)
{
Get<RoutingManager>().UnpublishExternalRoute(entry->GetPrefix());
SignalTableChanged();
Entry *entry;
while ((entry = router.mEntries.Pop()) != nullptr)
{
UnpublishEntry(*entry);
FreeEntry(*entry);
SignalTableChanged();
}
}
RemoveRoutersWithNoEntries();
mTimer.Stop();
}
@@ -1430,20 +1471,23 @@ void RoutingManager::DiscoveredPrefixTable::RemoveOrDeprecateOldEntries(TimeMill
// Remove route prefix entries and deprecate on-link entries in
// the table that are old (not updated since `aTimeThreshold`).
for (Entry &entry : mEntries)
for (Router &router : mRouters)
{
if (entry.GetLastUpdateTime() <= aTimeThreshold)
for (Entry &entry : router.mEntries)
{
if (entry.IsOnLinkPrefix())
if (entry.GetLastUpdateTime() <= aTimeThreshold)
{
entry.ClearPreferredLifetime();
}
else
{
entry.ClearValidLifetime();
}
if (entry.IsOnLinkPrefix())
{
entry.ClearPreferredLifetime();
}
else
{
entry.ClearValidLifetime();
}
SignalTableChanged();
SignalTableChanged();
}
}
}
@@ -1460,25 +1504,99 @@ TimeMilli RoutingManager::DiscoveredPrefixTable::CalculateNextStaleTime(TimeMill
// prefixes become stale (the latest stale time) but for route
// prefixes we consider the earliest stale time.
for (const Entry &entry : mEntries)
for (const Router &router : mRouters)
{
TimeMilli entryStaleTime = OT_MAX(aNow, entry.GetStaleTime());
if (entry.IsOnLinkPrefix() && !entry.IsDeprecated())
for (const Entry &entry : router.mEntries)
{
onLinkStaleTime = OT_MAX(onLinkStaleTime, entryStaleTime);
foundOnLink = true;
}
TimeMilli entryStaleTime = OT_MAX(aNow, entry.GetStaleTime());
if (!entry.IsOnLinkPrefix())
{
routeStaleTime = OT_MIN(routeStaleTime, entryStaleTime);
if (entry.IsOnLinkPrefix() && !entry.IsDeprecated())
{
onLinkStaleTime = OT_MAX(onLinkStaleTime, entryStaleTime);
foundOnLink = true;
}
if (!entry.IsOnLinkPrefix())
{
routeStaleTime = OT_MIN(routeStaleTime, entryStaleTime);
}
}
}
return foundOnLink ? OT_MIN(onLinkStaleTime, routeStaleTime) : routeStaleTime;
}
void RoutingManager::DiscoveredPrefixTable::RemoveRoutersWithNoEntries(void)
{
mRouters.RemoveAllMatching(Router::kContainsNoEntries);
}
void RoutingManager::DiscoveredPrefixTable::FreeEntries(LinkedList<Entry> &aEntries)
{
// Frees all entries in the given list `aEntries` (put them back
// in the entry pool).
Entry *entry;
while ((entry = aEntries.Pop()) != nullptr)
{
FreeEntry(*entry);
}
}
RoutingManager::DiscoveredPrefixTable::Entry *RoutingManager::DiscoveredPrefixTable::FindFavoredEntryToPublish(
const Ip6::Prefix &aPrefix)
{
// Finds the favored entry matching a given `aPrefix` in the table
// to publish in the Network Data. We can have multiple entries
// in the table matching the same `aPrefix` from different
// routers and potentially with different preference values. We
// select the one with the highest preference as the favored
// entry to publish.
Entry *favoredEntry = nullptr;
for (Router &router : mRouters)
{
for (Entry &entry : router.mEntries)
{
if (entry.GetPrefix() != aPrefix)
{
continue;
}
if ((favoredEntry == nullptr) || (entry.GetPreference() > favoredEntry->GetPreference()))
{
favoredEntry = &entry;
}
}
}
return favoredEntry;
}
void RoutingManager::DiscoveredPrefixTable::UpdateNetworkDataOnChangeTo(Entry &aEntry)
{
// Updates Network Data when there is a change to `aEntry` which
// can be a newly added entry or an existing entry that is
// modified due to processing of a received RA message.
Entry *favoredEntry = FindFavoredEntryToPublish(aEntry.GetPrefix());
OT_ASSERT(favoredEntry != nullptr);
PublishEntry(*favoredEntry);
}
void RoutingManager::DiscoveredPrefixTable::PublishEntry(const Entry &aEntry)
{
IgnoreError(Get<RoutingManager>().PublishExternalRoute(aEntry.GetPrefix(), aEntry.GetPreference()));
}
void RoutingManager::DiscoveredPrefixTable::UnpublishEntry(const Entry &aEntry)
{
Get<RoutingManager>().UnpublishExternalRoute(aEntry.GetPrefix());
}
void RoutingManager::DiscoveredPrefixTable::HandleTimer(Timer &aTimer)
{
aTimer.Get<RoutingManager>().mDiscoveredPrefixTable.HandleTimer();
@@ -1491,28 +1609,48 @@ void RoutingManager::DiscoveredPrefixTable::HandleTimer(void)
void RoutingManager::DiscoveredPrefixTable::RemoveExpiredEntries(void)
{
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextExpireTime = now.GetDistantFuture();
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextExpireTime = now.GetDistantFuture();
LinkedList<Entry> expiredEntries;
for (EntryArray::IndexType index = 0; index < mEntries.GetLength();)
for (Router &router : mRouters)
{
Entry &entry = mEntries[index];
router.mEntries.RemoveAllMatching(Entry::ExpirationChecker(now), expiredEntries);
}
if (entry.GetExpireTime() <= now)
RemoveRoutersWithNoEntries();
// Determine if we need to publish/unpublish any prefixes in
// the Network Data.
for (const Entry &expiredEntry : expiredEntries)
{
Entry *favoredEntry = FindFavoredEntryToPublish(expiredEntry.GetPrefix());
if (favoredEntry == nullptr)
{
Get<RoutingManager>().UnpublishExternalRoute(entry.GetPrefix());
// Remove the prefix from the array (which replaces it with
// last entry in the array). So in this case, we do not
// increment the `index`.
mEntries.Remove(entry);
SignalTableChanged();
UnpublishEntry(expiredEntry);
}
else
{
PublishEntry(*favoredEntry);
}
}
if (!expiredEntries.IsEmpty())
{
SignalTableChanged();
}
FreeEntries(expiredEntries);
// Determine the next expire time and schedule timer.
for (const Router &router : mRouters)
{
for (const Entry &entry : router.mEntries)
{
nextExpireTime = OT_MIN(nextExpireTime, entry.GetExpireTime());
index++;
}
}
@@ -1539,20 +1677,20 @@ void RoutingManager::DiscoveredPrefixTable::Entry::InitFrom(const Ip6::Nd::Prefi
{
Clear();
aPio.GetPrefix(mPrefix);
mType = kTypeOnLink;
mValidLifetime = aPio.GetValidLifetime();
mPreferredLifetime = aPio.GetPreferredLifetime();
mLastUpdateTime = TimerMilli::GetNow();
mType = kTypeOnLink;
mValidLifetime = aPio.GetValidLifetime();
mShared.mPreferredLifetime = aPio.GetPreferredLifetime();
mLastUpdateTime = TimerMilli::GetNow();
}
void RoutingManager::DiscoveredPrefixTable::Entry::InitFrom(const Ip6::Nd::RouteInfoOption &aRio)
{
Clear();
aRio.GetPrefix(mPrefix);
mType = kTypeRoute;
mValidLifetime = aRio.GetRouteLifetime();
mRoutePreference = aRio.GetPreference();
mLastUpdateTime = TimerMilli::GetNow();
mType = kTypeRoute;
mValidLifetime = aRio.GetRouteLifetime();
mShared.mRoutePreference = aRio.GetPreference();
mLastUpdateTime = TimerMilli::GetNow();
}
bool RoutingManager::DiscoveredPrefixTable::Entry::operator==(const Entry &aOther) const
@@ -1565,6 +1703,11 @@ bool RoutingManager::DiscoveredPrefixTable::Entry::Matches(const Matcher &aMatch
return (mType == aMatcher.mType) && (mPrefix == aMatcher.mPrefix);
}
bool RoutingManager::DiscoveredPrefixTable::Entry::Matches(const ExpirationChecker &aCheker) const
{
return GetExpireTime() <= aCheker.mNow;
}
TimeMilli RoutingManager::DiscoveredPrefixTable::Entry::GetExpireTime(void) const
{
return mLastUpdateTime + CalculateExpireDelay(mValidLifetime);
@@ -1572,7 +1715,7 @@ TimeMilli RoutingManager::DiscoveredPrefixTable::Entry::GetExpireTime(void) cons
TimeMilli RoutingManager::DiscoveredPrefixTable::Entry::GetStaleTime(void) const
{
uint32_t delay = OT_MIN(kRtrAdvStaleTime, IsOnLinkPrefix() ? mPreferredLifetime : mValidLifetime);
uint32_t delay = OT_MIN(kRtrAdvStaleTime, IsOnLinkPrefix() ? GetPreferredLifetime() : mValidLifetime);
return mLastUpdateTime + TimeMilli::SecToMsec(delay);
}
@@ -1581,7 +1724,15 @@ bool RoutingManager::DiscoveredPrefixTable::Entry::IsDeprecated(void) const
{
OT_ASSERT(IsOnLinkPrefix());
return mLastUpdateTime + TimeMilli::SecToMsec(mPreferredLifetime) <= TimerMilli::GetNow();
return mLastUpdateTime + TimeMilli::SecToMsec(GetPreferredLifetime()) <= TimerMilli::GetNow();
}
RoutingManager::RoutePreference RoutingManager::DiscoveredPrefixTable::Entry::GetPreference(void) const
{
// Returns the preference level to use when we publish
// the prefix entry in Network Data.
return IsOnLinkPrefix() ? NetworkData::kRoutePreferenceMedium : GetRoutePreference();
}
void RoutingManager::DiscoveredPrefixTable::Entry::AdoptValidAndPreferredLiftimesFrom(const Entry &aEntry)
@@ -1608,8 +1759,8 @@ void RoutingManager::DiscoveredPrefixTable::Entry::AdoptValidAndPreferredLiftime
mValidLifetime = kTwoHoursInSeconds;
}
mPreferredLifetime = aEntry.GetPreferredLifetime();
mLastUpdateTime = aEntry.GetLastUpdateTime();
mShared.mPreferredLifetime = aEntry.GetPreferredLifetime();
mLastUpdateTime = aEntry.GetLastUpdateTime();
}
uint32_t RoutingManager::DiscoveredPrefixTable::Entry::CalculateExpireDelay(uint32_t aValidLifetime)
+61 -21
View File
@@ -52,8 +52,10 @@
#include "border_router/infra_if.hpp"
#include "common/array.hpp"
#include "common/error.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/notifier.hpp"
#include "common/pool.hpp"
#include "common/string.hpp"
#include "common/timer.hpp"
#include "net/ip6.hpp"
@@ -200,9 +202,6 @@ private:
// The maximum number of the OMR prefixes to advertise.
static constexpr uint8_t kMaxOmrPrefixNum = OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES;
// The maximum number of prefixes to discover on the infra link.
static constexpr uint8_t kMaxDiscoveredPrefixNum = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
static constexpr uint8_t kOmrPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an OMR prefix. In bits.
static constexpr uint8_t kOnLinkPrefixLength = OT_IP6_PREFIX_BITSIZE; // The length of an On-link prefix. In bits.
static constexpr uint8_t kBrUlaPrefixLength = 48; // The length of a BR ULA prefix. In bits.
@@ -289,10 +288,13 @@ private:
TimeMilli CalculateNextStaleTime(TimeMilli aNow) const;
private:
static constexpr uint8_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS;
static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
struct Entry : private Clearable<Entry>, public Unequatable<Entry>
class Entry : public LinkedListEntry<Entry>, public Unequatable<Entry>, private Clearable<Entry>
{
friend class LinkedListEntry<Entry>;
public:
enum Type : uint8_t
{
@@ -312,8 +314,19 @@ private:
bool mType;
};
struct ExpirationChecker
{
explicit ExpirationChecker(TimeMilli aNow)
: mNow(aNow)
{
}
TimeMilli mNow;
};
void InitFrom(const Ip6::Nd::PrefixInfoOption &aPio);
void InitFrom(const Ip6::Nd::RouteInfoOption &aRio);
Type GetType(void) const { return mType; }
bool IsOnLinkPrefix(void) const { return (mType == kTypeOnLink); }
const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
const TimeMilli & GetLastUpdateTime(void) const { return mLastUpdateTime; }
@@ -321,44 +334,71 @@ private:
void ClearValidLifetime(void) { mValidLifetime = 0; }
TimeMilli GetExpireTime(void) const;
TimeMilli GetStaleTime(void) const;
RoutePreference GetPreference(void) const;
bool operator==(const Entry &aOther) const;
bool Matches(const Matcher &aMatcher) const;
bool Matches(const ExpirationChecker &aCheker) const;
// Methods to use when `IsOnLinkPrefix()`
uint32_t GetPreferredLifetime(void) const { return mPreferredLifetime; }
void ClearPreferredLifetime(void) { mPreferredLifetime = 0; }
uint32_t GetPreferredLifetime(void) const { return mShared.mPreferredLifetime; }
void ClearPreferredLifetime(void) { mShared.mPreferredLifetime = 0; }
bool IsDeprecated(void) const;
void AdoptValidAndPreferredLiftimesFrom(const Entry &aEntry);
// Method to use when `!IsOnlinkPrefix()`
RoutePreference GetRoutePreference(void) const { return mRoutePreference; }
RoutePreference GetRoutePreference(void) const { return mShared.mRoutePreference; }
private:
static uint32_t CalculateExpireDelay(uint32_t aValidLifetime);
Ip6::Prefix mPrefix;
TimeMilli mLastUpdateTime;
uint32_t mValidLifetime;
uint32_t mPreferredLifetime; // Applicable when prefix is on-link.
RoutePreference mRoutePreference; // Applicable when prefix is not on-link
Type mType;
Entry * mNext;
Ip6::Prefix mPrefix;
Type mType;
TimeMilli mLastUpdateTime;
uint32_t mValidLifetime;
union
{
uint32_t mPreferredLifetime; // Applicable when prefix is on-link.
RoutePreference mRoutePreference; // Applicable when prefix is not on-link
} mShared;
};
typedef Array<Entry, kMaxEntries> EntryArray;
struct Router
{
enum EmptyChecker : uint8_t
{
kContainsNoEntries
};
void RemovePrefix(const Ip6::Prefix &aPrefix, Entry::Type aType, NetDataMode aNetDataMode);
bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
bool Matches(EmptyChecker) const { return mEntries.IsEmpty(); }
void ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio);
void ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio);
Ip6::Address mAddress;
LinkedList<Entry> mEntries;
};
void ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, Router &aRouter);
void ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, Router &aRouter);
bool ContainsPrefix(const Entry::Matcher &aMatcher) const;
void RemovePrefix(const Entry::Matcher &aMatcher, NetDataMode aNetDataMode);
void RemoveRoutersWithNoEntries(void);
Entry * AllocateEntry(void) { return mEntryPool.Allocate(); }
void FreeEntry(Entry &aEntry) { mEntryPool.Free(aEntry); }
void FreeEntries(LinkedList<Entry> &aEntries);
void UpdateNetworkDataOnChangeTo(Entry &aEntry);
Entry * FindFavoredEntryToPublish(const Ip6::Prefix &aPrefix);
void PublishEntry(const Entry &aEntry);
void UnpublishEntry(const Entry &aEntry);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
void RemoveExpiredEntries(void);
void SignalTableChanged(void);
static void HandleSignalTask(Tasklet &aTasklet);
EntryArray mEntries;
TimerMilli mTimer;
Tasklet mSignalTask;
Array<Router, kMaxRouters> mRouters;
Pool<Entry, kMaxEntries> mEntryPool;
TimerMilli mTimer;
Tasklet mSignalTask;
};
class OmrPrefix // An OMR Prefix
+11 -1
View File
@@ -91,6 +91,16 @@
#define OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 0
#endif
/**
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS
*
* Specifies maximum number of routers (on infra link) to track by routing manager.
*
*/
#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS
#define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS 16
#endif
/**
* @def OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES
*
@@ -98,7 +108,7 @@
*
*/
#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES
#define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES 8
#define OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES 64
#endif
/**