[routing-manager] introduce RoutePrefix and OnLinkPrefix types (#10216)

This commit refactors and simplifies `RoutingManager`:

- Introduces `OnLinkPrefix` and `RoutePrefix` classes, both derived
  from a common base class `LifetimedPrefix` (representing a prefix
  and its valid lifetime).
- Replaces the originally dual-purpose `DiscoveredPrefixTable::Entry`
  (used for both route and on-link prefixes) with a new template
  `Entry<Type>`, specifically used with `OnLinkPrefix`, `RoutePrefix`,
  and also `Router`.
- Updates `Router` to maintain separate lists for on-link and route
  prefixes.
- Utilizes `OnLinkPrefix` in `PdPrefixManager` for tracking DHCPv6-PD
  prefixes.
This commit is contained in:
Abtin Keshavarzian
2024-05-13 09:38:22 -07:00
committed by GitHub
parent 39ce8117a5
commit 68b8c88e18
4 changed files with 520 additions and 422 deletions
+3 -1
View File
@@ -85,7 +85,9 @@ typedef struct otBorderRoutingPrefixTableIterator
{
const void *mPtr1;
const void *mPtr2;
uint32_t mData32;
uint32_t mData1;
uint8_t mData2;
uint8_t mData3;
} otBorderRoutingPrefixTableIterator;
/**
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (411)
#define OPENTHREAD_API_VERSION (412)
/**
* @addtogroup api-instance
+343 -258
View File
@@ -50,6 +50,7 @@
#include "common/numeric_limits.hpp"
#include "common/random.hpp"
#include "common/settings.hpp"
#include "common/type_traits.hpp"
#include "instance/instance.hpp"
#include "meshcop/extended_panid.hpp"
#include "net/ip6.hpp"
@@ -987,6 +988,124 @@ void RoutingManager::LogPrefixInfoOption(const Ip6::Prefix &, uint32_t, uint32_t
void RoutingManager::LogRouteInfoOption(const Ip6::Prefix &, uint32_t, RoutePreference) {}
#endif
//---------------------------------------------------------------------------------------------------------------------
// LifetimedPrefix
TimeMilli RoutingManager::LifetimedPrefix::CalculateExpirationTime(uint32_t aLifetime) const
{
// `aLifetime` is in unit of seconds. We clamp the lifetime to max
// interval supported by `Timer` (`2^31` msec or ~24.8 days).
static constexpr uint32_t kMaxLifetime = Time::MsecToSec(Timer::kMaxDelay);
return mLastUpdateTime + Time::SecToMsec(Min(aLifetime, kMaxLifetime));
}
//---------------------------------------------------------------------------------------------------------------------
// OnLinkPrefix
void RoutingManager::OnLinkPrefix::SetFrom(const PrefixInfoOption &aPio)
{
aPio.GetPrefix(mPrefix);
mValidLifetime = aPio.GetValidLifetime();
mPreferredLifetime = aPio.GetPreferredLifetime();
mLastUpdateTime = TimerMilli::GetNow();
}
void RoutingManager::OnLinkPrefix::SetFrom(const PrefixTableEntry &aPrefixTableEntry)
{
mPrefix = AsCoreType(&aPrefixTableEntry.mPrefix);
mValidLifetime = aPrefixTableEntry.mValidLifetime;
mPreferredLifetime = aPrefixTableEntry.mPreferredLifetime;
mLastUpdateTime = TimerMilli::GetNow();
}
bool RoutingManager::OnLinkPrefix::IsDeprecated(void) const
{
return CalculateExpirationTime(mPreferredLifetime) <= TimerMilli::GetNow();
}
TimeMilli RoutingManager::OnLinkPrefix::GetStaleTime(void) const
{
return CalculateExpirationTime(Min(kRtrAdvStaleTime, mPreferredLifetime));
}
TimeMilli RoutingManager::OnLinkPrefix::GetStaleTimeFromPreferredLifetime(void) const
{
return CalculateExpirationTime(mPreferredLifetime);
}
void RoutingManager::OnLinkPrefix::AdoptValidAndPreferredLifetimesFrom(const OnLinkPrefix &aPrefix)
{
constexpr uint32_t kTwoHoursInSeconds = 2 * 3600;
// Per RFC 4862 section 5.5.3.e:
//
// 1. If the received Valid Lifetime is greater than 2 hours or
// greater than RemainingLifetime, set the valid lifetime of the
// corresponding address to the advertised Valid Lifetime.
// 2. If RemainingLifetime is less than or equal to 2 hours, ignore
// the Prefix Information option with regards to the valid
// lifetime, unless ...
// 3. Otherwise, reset the valid lifetime of the corresponding
// address to 2 hours.
if (aPrefix.mValidLifetime > kTwoHoursInSeconds || aPrefix.GetExpireTime() > GetExpireTime())
{
mValidLifetime = aPrefix.mValidLifetime;
}
else if (GetExpireTime() > TimerMilli::GetNow() + TimeMilli::SecToMsec(kTwoHoursInSeconds))
{
mValidLifetime = kTwoHoursInSeconds;
}
mPreferredLifetime = aPrefix.GetPreferredLifetime();
mLastUpdateTime = aPrefix.GetLastUpdateTime();
}
void RoutingManager::OnLinkPrefix::CopyInfoTo(PrefixTableEntry &aEntry, TimeMilli aNow) const
{
aEntry.mPrefix = GetPrefix();
aEntry.mIsOnLink = true;
aEntry.mMsecSinceLastUpdate = aNow - GetLastUpdateTime();
aEntry.mValidLifetime = GetValidLifetime();
aEntry.mPreferredLifetime = GetPreferredLifetime();
}
//---------------------------------------------------------------------------------------------------------------------
// RoutePrefix
void RoutingManager::RoutePrefix::SetFrom(const RouteInfoOption &aRio)
{
aRio.GetPrefix(mPrefix);
mValidLifetime = aRio.GetRouteLifetime();
mRoutePreference = aRio.GetPreference();
mLastUpdateTime = TimerMilli::GetNow();
}
void RoutingManager::RoutePrefix::SetFrom(const RouterAdvert::Header &aRaHeader)
{
mPrefix.Clear();
mValidLifetime = aRaHeader.GetRouterLifetime();
mRoutePreference = aRaHeader.GetDefaultRouterPreference();
mLastUpdateTime = TimerMilli::GetNow();
}
TimeMilli RoutingManager::RoutePrefix::GetStaleTime(void) const
{
return CalculateExpirationTime(Min(kRtrAdvStaleTime, mValidLifetime));
}
void RoutingManager::RoutePrefix::CopyInfoTo(PrefixTableEntry &aEntry, TimeMilli aNow) const
{
aEntry.mPrefix = GetPrefix();
aEntry.mIsOnLink = false;
aEntry.mMsecSinceLastUpdate = aNow - GetLastUpdateTime();
aEntry.mValidLifetime = GetValidLifetime();
aEntry.mPreferredLifetime = 0;
aEntry.mRoutePreference = static_cast<otRoutePreference>(GetRoutePreference());
}
//---------------------------------------------------------------------------------------------------------------------
// DiscoveredPrefixTable
@@ -1007,18 +1126,19 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const Rou
if (router == nullptr)
{
router = AllocateRouter();
Entry<Router> *newEntry = AllocateEntry<Router>();
if (router == nullptr)
if (newEntry == nullptr)
{
LogWarn("Received RA from too many routers, ignore RA from %s", aSrcAddress.ToString().AsCString());
ExitNow();
}
router = newEntry;
router->Clear();
router->mAddress = aSrcAddress;
mRouters.Push(*router);
mRouters.Push(*newEntry);
}
// RA message can indicate router provides default route in the RA
@@ -1060,15 +1180,15 @@ exit:
void RoutingManager::DiscoveredPrefixTable::ProcessRaHeader(const RouterAdvert::Header &aRaHeader, Router &aRouter)
{
Entry *entry;
Ip6::Prefix prefix;
Entry<RoutePrefix> *entry;
Ip6::Prefix prefix;
aRouter.mManagedAddressConfigFlag = aRaHeader.IsManagedAddressConfigFlagSet();
aRouter.mOtherConfigFlag = aRaHeader.IsOtherConfigFlagSet();
LogInfo("- RA Header - flags - M:%u O:%u", aRouter.mManagedAddressConfigFlag, aRouter.mOtherConfigFlag);
prefix.Clear();
entry = aRouter.mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeRoute));
entry = aRouter.mRoutePrefixes.FindMatching(prefix);
LogInfo("- RA Header - default route - lifetime:%u", aRaHeader.GetRouterLifetime());
@@ -1076,7 +1196,7 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRaHeader(const RouterAdvert::
{
VerifyOrExit(aRaHeader.GetRouterLifetime() != 0);
entry = AllocateEntry();
entry = AllocateEntry<RoutePrefix>();
if (entry == nullptr)
{
@@ -1085,7 +1205,7 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRaHeader(const RouterAdvert::
}
entry->SetFrom(aRaHeader);
aRouter.mEntries.Push(*entry);
aRouter.mRoutePrefixes.Push(*entry);
}
else
{
@@ -1102,8 +1222,8 @@ exit:
void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const PrefixInfoOption &aPio, Router &aRouter)
{
Ip6::Prefix prefix;
Entry *entry;
Ip6::Prefix prefix;
Entry<OnLinkPrefix> *entry;
VerifyOrExit(aPio.IsValid());
aPio.GetPrefix(prefix);
@@ -1112,13 +1232,13 @@ void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const Prefix
LogPrefixInfoOption(prefix, aPio.GetValidLifetime(), aPio.GetPreferredLifetime());
entry = aRouter.mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeOnLink));
entry = aRouter.mOnLinkPrefixes.FindMatching(prefix);
if (entry == nullptr)
{
VerifyOrExit(aPio.GetValidLifetime() != 0);
entry = AllocateEntry();
entry = AllocateEntry<OnLinkPrefix>();
if (entry == nullptr)
{
@@ -1127,14 +1247,14 @@ void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const Prefix
}
entry->SetFrom(aPio);
aRouter.mEntries.Push(*entry);
aRouter.mOnLinkPrefixes.Push(*entry);
}
else
{
Entry newEntry;
OnLinkPrefix newPrefix;
newEntry.SetFrom(aPio);
entry->AdoptValidAndPreferredLifetimesFrom(newEntry);
newPrefix.SetFrom(aPio);
entry->AdoptValidAndPreferredLifetimesFrom(newPrefix);
}
mEntryTimer.FireAtIfEarlier(entry->GetExpireTime());
@@ -1147,8 +1267,8 @@ exit:
void RoutingManager::DiscoveredPrefixTable::ProcessRouteInfoOption(const RouteInfoOption &aRio, Router &aRouter)
{
Ip6::Prefix prefix;
Entry *entry;
Ip6::Prefix prefix;
Entry<RoutePrefix> *entry;
VerifyOrExit(aRio.IsValid());
aRio.GetPrefix(prefix);
@@ -1157,13 +1277,13 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouteInfoOption(const RouteIn
LogRouteInfoOption(prefix, aRio.GetRouteLifetime(), aRio.GetPreference());
entry = aRouter.mEntries.FindMatching(Entry::Matcher(prefix, Entry::kTypeRoute));
entry = aRouter.mRoutePrefixes.FindMatching(prefix);
if (entry == nullptr)
{
VerifyOrExit(aRio.GetRouteLifetime() != 0);
entry = AllocateEntry();
entry = AllocateEntry<RoutePrefix>();
if (entry == nullptr)
{
@@ -1172,7 +1292,7 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouteInfoOption(const RouteIn
}
entry->SetFrom(aRio);
aRouter.mEntries.Push(*entry);
aRouter.mRoutePrefixes.Push(*entry);
}
else
{
@@ -1201,9 +1321,11 @@ exit:
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
RoutingManager::DiscoveredPrefixTable::Router *RoutingManager::DiscoveredPrefixTable::AllocateRouter(void)
template <>
RoutingManager::DiscoveredPrefixTable::Entry<RoutingManager::DiscoveredPrefixTable::Router>
*RoutingManager::DiscoveredPrefixTable::AllocateEntry(void)
{
Router *router = mRouterPool.Allocate();
Entry<Router> *router = mRouterPool.Allocate();
VerifyOrExit(router != nullptr);
router->Init(GetInstance());
@@ -1212,26 +1334,49 @@ exit:
return router;
}
RoutingManager::DiscoveredPrefixTable::Entry *RoutingManager::DiscoveredPrefixTable::AllocateEntry(void)
template <class PrefixType>
RoutingManager::DiscoveredPrefixTable::Entry<PrefixType> *RoutingManager::DiscoveredPrefixTable::AllocateEntry(void)
{
Entry *entry = mEntryPool.Allocate();
static_assert(TypeTraits::IsSame<PrefixType, OnLinkPrefix>::kValue ||
TypeTraits::IsSame<PrefixType, RoutePrefix>::kValue,
"PrefixType MSUT be either RoutePrefix or OnLinkPrefix");
VerifyOrExit(entry != nullptr);
Entry<PrefixType> *entry = nullptr;
SharedEntry *sharedEntry = mEntryPool.Allocate();
VerifyOrExit(sharedEntry != nullptr);
entry = &sharedEntry->GetEntry<PrefixType>();
entry->Init(GetInstance());
exit:
return entry;
}
template <> void RoutingManager::DiscoveredPrefixTable::Entry<RoutingManager::DiscoveredPrefixTable::Router>::Free(void)
{
mOnLinkPrefixes.Free();
mRoutePrefixes.Free();
Get<RoutingManager>().mDiscoveredPrefixTable.mRouterPool.Free(*this);
}
template <class PrefixType> void RoutingManager::DiscoveredPrefixTable::Entry<PrefixType>::Free(void)
{
static_assert(TypeTraits::IsSame<PrefixType, OnLinkPrefix>::kValue ||
TypeTraits::IsSame<PrefixType, RoutePrefix>::kValue,
"PrefixType MSUT be either RoutePrefix or OnLinkPrefix");
Get<RoutingManager>().mDiscoveredPrefixTable.mEntryPool.Free(*reinterpret_cast<SharedEntry *>(this));
}
#endif // !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
bool RoutingManager::DiscoveredPrefixTable::Contains(const Entry::Checker &aChecker) const
bool RoutingManager::DiscoveredPrefixTable::ContainsDefaultOrNonUlaRoutePrefix(void) const
{
bool contains = false;
for (const Router &router : mRouters)
{
if (router.mEntries.ContainsMatching(aChecker))
if (router.mRoutePrefixes.ContainsMatching(RoutePrefix::kIsNotUla))
{
contains = true;
break;
@@ -1241,19 +1386,30 @@ bool RoutingManager::DiscoveredPrefixTable::Contains(const Entry::Checker &aChec
return contains;
}
bool RoutingManager::DiscoveredPrefixTable::ContainsDefaultOrNonUlaRoutePrefix(void) const
bool RoutingManager::DiscoveredPrefixTable::ContainsOnLinkPrefix(OnLinkPrefix::UlaChecker aUlaChecker) const
{
return Contains(Entry::Checker(Entry::Checker::kIsNotUla, Entry::kTypeRoute));
bool contains = false;
for (const Router &router : mRouters)
{
if (router.mOnLinkPrefixes.ContainsMatching(aUlaChecker))
{
contains = true;
break;
}
}
return contains;
}
bool RoutingManager::DiscoveredPrefixTable::ContainsNonUlaOnLinkPrefix(void) const
{
return Contains(Entry::Checker(Entry::Checker::kIsNotUla, Entry::kTypeOnLink));
return ContainsOnLinkPrefix(OnLinkPrefix::kIsNotUla);
}
bool RoutingManager::DiscoveredPrefixTable::ContainsUlaOnLinkPrefix(void) const
{
return Contains(Entry::Checker(Entry::Checker::kIsUla, Entry::kTypeOnLink));
return ContainsOnLinkPrefix(OnLinkPrefix::kIsUla);
}
void RoutingManager::DiscoveredPrefixTable::FindFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const
@@ -1266,10 +1422,9 @@ void RoutingManager::DiscoveredPrefixTable::FindFavoredOnLinkPrefix(Ip6::Prefix
for (const Router &router : mRouters)
{
for (const Entry &entry : router.mEntries)
for (const OnLinkPrefix &entry : router.mOnLinkPrefixes)
{
if (!entry.IsOnLinkPrefix() || entry.IsDeprecated() ||
(entry.GetPreferredLifetime() < kFavoredOnLinkPrefixMinPreferredLifetime))
if (entry.IsDeprecated() || (entry.GetPreferredLifetime() < kFavoredOnLinkPrefixMinPreferredLifetime))
{
continue;
}
@@ -1284,23 +1439,30 @@ void RoutingManager::DiscoveredPrefixTable::FindFavoredOnLinkPrefix(Ip6::Prefix
void RoutingManager::DiscoveredPrefixTable::RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix)
{
RemovePrefix(Entry::Matcher(aPrefix, Entry::kTypeOnLink));
}
void RoutingManager::DiscoveredPrefixTable::RemoveRoutePrefix(const Ip6::Prefix &aPrefix)
{
RemovePrefix(Entry::Matcher(aPrefix, Entry::kTypeRoute));
}
void RoutingManager::DiscoveredPrefixTable::RemovePrefix(const Entry::Matcher &aMatcher)
{
// Removes all entries matching a given prefix from the table.
bool didRemove = false;
for (Router &router : mRouters)
{
didRemove |= router.mEntries.RemoveAndFreeAllMatching(aMatcher);
didRemove |= router.mOnLinkPrefixes.RemoveAndFreeAllMatching(aPrefix);
}
VerifyOrExit(didRemove);
RemoveRoutersWithNoEntriesOrFlags();
SignalTableChanged();
exit:
return;
}
void RoutingManager::DiscoveredPrefixTable::RemoveRoutePrefix(const Ip6::Prefix &aPrefix)
{
bool didRemove = false;
for (Router &router : mRouters)
{
didRemove |= router.mRoutePrefixes.RemoveAndFreeAllMatching(aPrefix);
}
VerifyOrExit(didRemove);
@@ -1330,19 +1492,20 @@ void RoutingManager::DiscoveredPrefixTable::RemoveOrDeprecateOldEntries(TimeMill
for (Router &router : mRouters)
{
for (Entry &entry : router.mEntries)
for (OnLinkPrefix &entry : router.mOnLinkPrefixes)
{
if (entry.GetLastUpdateTime() <= aTimeThreshold)
{
if (entry.IsOnLinkPrefix())
{
entry.ClearPreferredLifetime();
}
else
{
entry.ClearValidLifetime();
}
entry.ClearPreferredLifetime();
SignalTableChanged();
}
}
for (RoutePrefix &entry : router.mRoutePrefixes)
{
if (entry.GetLastUpdateTime() <= aTimeThreshold)
{
entry.ClearValidLifetime();
SignalTableChanged();
}
}
@@ -1364,21 +1527,19 @@ void RoutingManager::DiscoveredPrefixTable::RemoveOrDeprecateEntriesFromInactive
continue;
}
for (Entry &entry : router.mEntries)
for (OnLinkPrefix &entry : router.mOnLinkPrefixes)
{
if (entry.IsOnLinkPrefix())
if (!entry.IsDeprecated())
{
if (!entry.IsDeprecated())
{
entry.ClearPreferredLifetime();
SignalTableChanged();
}
}
else
{
entry.ClearValidLifetime();
entry.ClearPreferredLifetime();
SignalTableChanged();
}
}
for (RoutePrefix &entry : router.mRoutePrefixes)
{
entry.ClearValidLifetime();
}
}
RemoveExpiredEntries();
@@ -1396,20 +1557,22 @@ TimeMilli RoutingManager::DiscoveredPrefixTable::CalculateNextStaleTime(TimeMill
for (const Router &router : mRouters)
{
for (const Entry &entry : router.mEntries)
for (const OnLinkPrefix &entry : router.mOnLinkPrefixes)
{
TimeMilli entryStaleTime = Max(aNow, entry.GetStaleTime());
if (entry.IsOnLinkPrefix() && !entry.IsDeprecated())
if (!entry.IsDeprecated())
{
TimeMilli entryStaleTime = Max(aNow, entry.GetStaleTime());
onLinkStaleTime = Max(onLinkStaleTime, entryStaleTime);
foundOnLink = true;
}
}
if (!entry.IsOnLinkPrefix())
{
routeStaleTime = Min(routeStaleTime, entryStaleTime);
}
for (const RoutePrefix &entry : router.mRoutePrefixes)
{
TimeMilli entryStaleTime = Max(aNow, entry.GetStaleTime());
routeStaleTime = Min(routeStaleTime, entryStaleTime);
}
}
@@ -1425,13 +1588,15 @@ void RoutingManager::DiscoveredPrefixTable::HandleEntryTimer(void) { RemoveExpir
void RoutingManager::DiscoveredPrefixTable::RemoveExpiredEntries(void)
{
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextExpireTime = now.GetDistantFuture();
bool didRemove = false;
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextExpireTime = now.GetDistantFuture();
LifetimedPrefix::ExpirationChecker expirationChecker(now);
bool didRemove = false;
for (Router &router : mRouters)
{
didRemove |= router.mEntries.RemoveAndFreeAllMatching(Entry::ExpirationChecker(now));
didRemove |= router.mOnLinkPrefixes.RemoveAndFreeAllMatching(expirationChecker);
didRemove |= router.mRoutePrefixes.RemoveAndFreeAllMatching(expirationChecker);
}
RemoveRoutersWithNoEntriesOrFlags();
@@ -1445,7 +1610,12 @@ void RoutingManager::DiscoveredPrefixTable::RemoveExpiredEntries(void)
for (const Router &router : mRouters)
{
for (const Entry &entry : router.mEntries)
for (const OnLinkPrefix &entry : router.mOnLinkPrefixes)
{
nextExpireTime = Min(nextExpireTime, entry.GetExpireTime());
}
for (const RoutePrefix &entry : router.mRoutePrefixes)
{
nextExpireTime = Min(nextExpireTime, entry.GetExpireTime());
}
@@ -1593,7 +1763,7 @@ void RoutingManager::DiscoveredPrefixTable::DetermineAndSetFlags(RouterAdvert::H
void RoutingManager::DiscoveredPrefixTable::InitIterator(PrefixTableIterator &aIterator) const
{
static_cast<Iterator &>(aIterator).Init(mRouters);
static_cast<Iterator &>(aIterator).Init(mRouters.GetHead());
}
Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &aIterator,
@@ -1602,19 +1772,21 @@ Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &a
Error error = kErrorNone;
Iterator &iterator = static_cast<Iterator &>(aIterator);
VerifyOrExit(iterator.GetRouter() != nullptr, error = kErrorNotFound);
OT_ASSERT(iterator.GetEntry() != nullptr);
ClearAllBytes(aEntry);
SuccessOrExit(error = iterator.AdvanceToNextEntry());
iterator.GetRouter()->CopyInfoTo(aEntry.mRouter);
aEntry.mPrefix = iterator.GetEntry()->GetPrefix();
aEntry.mIsOnLink = iterator.GetEntry()->IsOnLinkPrefix();
aEntry.mMsecSinceLastUpdate = iterator.GetInitTime() - iterator.GetEntry()->GetLastUpdateTime();
aEntry.mValidLifetime = iterator.GetEntry()->GetValidLifetime();
aEntry.mPreferredLifetime = aEntry.mIsOnLink ? iterator.GetEntry()->GetPreferredLifetime() : 0;
aEntry.mRoutePreference =
static_cast<otRoutePreference>(aEntry.mIsOnLink ? 0 : iterator.GetEntry()->GetRoutePreference());
iterator.Advance(Iterator::kToNextEntry);
switch (iterator.GetEntryType())
{
case Iterator::kOnLinkPrefix:
iterator.GetEntry<OnLinkPrefix>()->CopyInfoTo(aEntry, iterator.GetInitTime());
break;
case Iterator::kRoutePrefix:
iterator.GetEntry<RoutePrefix>()->CopyInfoTo(aEntry, iterator.GetInitTime());
break;
}
exit:
return error;
@@ -1625,10 +1797,10 @@ Error RoutingManager::DiscoveredPrefixTable::GetNextRouter(PrefixTableIterator &
Error error = kErrorNone;
Iterator &iterator = static_cast<Iterator &>(aIterator);
VerifyOrExit(iterator.GetRouter() != nullptr, error = kErrorNotFound);
ClearAllBytes(aEntry);
SuccessOrExit(error = iterator.AdvanceToNextRouter(Iterator::kRouterIterator));
iterator.GetRouter()->CopyInfoTo(aEntry);
iterator.Advance(Iterator::kToNextRouter);
exit:
return error;
@@ -1637,175 +1809,96 @@ exit:
//---------------------------------------------------------------------------------------------------------------------
// DiscoveredPrefixTable::Iterator
void RoutingManager::DiscoveredPrefixTable::Iterator::Init(const LinkedList<Router> &aRouters)
void RoutingManager::DiscoveredPrefixTable::Iterator::Init(const Entry<Router> *aRoutersHead)
{
SetInitTime();
SetRouter(aRouters.GetHead());
SetEntry(aRouters.IsEmpty() ? nullptr : aRouters.GetHead()->mEntries.GetHead());
SetType(kUnspecified);
SetRouter(aRoutersHead);
SetEntry(nullptr);
SetEntryType(kRoutePrefix);
}
void RoutingManager::DiscoveredPrefixTable::Iterator::Advance(AdvanceMode aMode)
Error RoutingManager::DiscoveredPrefixTable::Iterator::AdvanceToNextRouter(Type aType)
{
switch (aMode)
{
case kToNextEntry:
SetEntry(GetEntry()->GetNext());
Error error = kErrorNone;
if (GetEntry() != nullptr)
if (GetType() == kUnspecified)
{
// On the first call, when iterator type is `kUnspecified`, we
// set the type, and keep the `GetRouter()` as is so to start
// from the first router in the list.
SetType(aType);
}
else
{
// On subsequent call, we ensure that the iterator type
// matches what we expect and advance to the next router on
// the list.
VerifyOrExit(GetType() == aType, error = kErrorInvalidArgs);
VerifyOrExit(GetRouter() != nullptr, error = kErrorNone);
SetRouter(GetRouter()->GetNext());
}
VerifyOrExit(GetRouter() != nullptr, error = kErrorNotFound);
exit:
return error;
}
Error RoutingManager::DiscoveredPrefixTable::Iterator::AdvanceToNextEntry(void)
{
Error error = kErrorNone;
VerifyOrExit(GetRouter() != nullptr, error = kErrorNotFound);
if (HasEntry())
{
switch (GetEntryType())
{
case kOnLinkPrefix:
SetEntry(GetEntry<OnLinkPrefix>()->GetNext());
break;
case kRoutePrefix:
SetEntry(GetEntry<RoutePrefix>()->GetNext());
break;
}
}
OT_FALL_THROUGH;
case kToNextRouter:
SetRouter(GetRouter()->GetNext());
if (GetRouter() != nullptr)
while (!HasEntry())
{
switch (GetEntryType())
{
SetEntry(GetRouter()->mEntries.GetHead());
case kOnLinkPrefix:
// Transition from on-link prefixes to route prefixes of
// the current router.
SetEntry(GetRouter()->mRoutePrefixes.GetHead());
SetEntryType(kRoutePrefix);
break;
case kRoutePrefix:
// Transition to the next router and start with its on-link
// prefixes.
//
// On the first call when iterator type is `kUnspecified`,
// `AdvanceToNextRouter()` sets the type and starts from
// the first router.
SuccessOrExit(error = AdvanceToNextRouter(kPrefixIterator));
SetEntry(GetRouter()->mOnLinkPrefixes.GetHead());
SetEntryType(kOnLinkPrefix);
break;
}
break;
}
}
//---------------------------------------------------------------------------------------------------------------------
// DiscoveredPrefixTable::Entry
void RoutingManager::DiscoveredPrefixTable::Entry::SetFrom(const RouterAdvert::Header &aRaHeader)
{
mPrefix.Clear();
mType = kTypeRoute;
mValidLifetime = aRaHeader.GetRouterLifetime();
mShared.mRoutePreference = aRaHeader.GetDefaultRouterPreference();
mLastUpdateTime = TimerMilli::GetNow();
}
void RoutingManager::DiscoveredPrefixTable::Entry::SetFrom(const PrefixInfoOption &aPio)
{
aPio.GetPrefix(mPrefix);
mType = kTypeOnLink;
mValidLifetime = aPio.GetValidLifetime();
mShared.mPreferredLifetime = aPio.GetPreferredLifetime();
mLastUpdateTime = TimerMilli::GetNow();
}
void RoutingManager::DiscoveredPrefixTable::Entry::SetFrom(const RouteInfoOption &aRio)
{
aRio.GetPrefix(mPrefix);
mType = kTypeRoute;
mValidLifetime = aRio.GetRouteLifetime();
mShared.mRoutePreference = aRio.GetPreference();
mLastUpdateTime = TimerMilli::GetNow();
}
void RoutingManager::DiscoveredPrefixTable::Entry::SetFrom(const PrefixTableEntry &aPrefixTableEntry)
{
mPrefix = AsCoreType(&aPrefixTableEntry.mPrefix);
mType = aPrefixTableEntry.mIsOnLink ? kTypeOnLink : kTypeRoute;
mValidLifetime = aPrefixTableEntry.mValidLifetime;
mShared.mPreferredLifetime = aPrefixTableEntry.mPreferredLifetime;
mLastUpdateTime = TimerMilli::GetNow();
}
bool RoutingManager::DiscoveredPrefixTable::Entry::operator==(const Entry &aOther) const
{
return (mType == aOther.mType) && (mPrefix == aOther.mPrefix);
}
bool RoutingManager::DiscoveredPrefixTable::Entry::Matches(const Matcher &aMatcher) const
{
return (mType == aMatcher.mType) && (mPrefix == aMatcher.mPrefix);
}
bool RoutingManager::DiscoveredPrefixTable::Entry::Matches(const Checker &aChecker) const
{
return (mType == aChecker.mType) && (mPrefix.IsUniqueLocal() == (aChecker.mMode == Checker::kIsUla));
}
bool RoutingManager::DiscoveredPrefixTable::Entry::Matches(const ExpirationChecker &aChecker) const
{
return GetExpireTime() <= aChecker.mNow;
}
TimeMilli RoutingManager::DiscoveredPrefixTable::Entry::GetExpireTime(void) const
{
return CalculateExpirationTime(mValidLifetime);
}
TimeMilli RoutingManager::DiscoveredPrefixTable::Entry::GetStaleTime(void) const
{
uint32_t delay = Min(kRtrAdvStaleTime, IsOnLinkPrefix() ? GetPreferredLifetime() : mValidLifetime);
return mLastUpdateTime + TimeMilli::SecToMsec(delay);
}
TimeMilli RoutingManager::DiscoveredPrefixTable::Entry::GetStaleTimeFromPreferredLifetime(void) const
{
return CalculateExpirationTime(GetPreferredLifetime());
}
bool RoutingManager::DiscoveredPrefixTable::Entry::IsDeprecated(void) const
{
OT_ASSERT(IsOnLinkPrefix());
return CalculateExpirationTime(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::AdoptValidAndPreferredLifetimesFrom(const Entry &aEntry)
{
constexpr uint32_t kTwoHoursInSeconds = 2 * 3600;
// Per RFC 4862 section 5.5.3.e:
//
// 1. If the received Valid Lifetime is greater than 2 hours or
// greater than RemainingLifetime, set the valid lifetime of the
// corresponding address to the advertised Valid Lifetime.
// 2. If RemainingLifetime is less than or equal to 2 hours, ignore
// the Prefix Information option with regards to the valid
// lifetime, unless ...
// 3. Otherwise, reset the valid lifetime of the corresponding
// address to 2 hours.
if (aEntry.mValidLifetime > kTwoHoursInSeconds || aEntry.GetExpireTime() > GetExpireTime())
{
mValidLifetime = aEntry.mValidLifetime;
}
else if (GetExpireTime() > TimerMilli::GetNow() + TimeMilli::SecToMsec(kTwoHoursInSeconds))
{
mValidLifetime = kTwoHoursInSeconds;
}
mShared.mPreferredLifetime = aEntry.GetPreferredLifetime();
mLastUpdateTime = aEntry.GetLastUpdateTime();
exit:
return error;
}
TimeMilli RoutingManager::DiscoveredPrefixTable::Entry::CalculateExpirationTime(uint32_t aLifetime) const
{
// `aLifetime` is in unit of seconds. We clamp the lifetime to max
// interval supported by `Timer` (`2^31` msec or ~24.8 days).
static constexpr uint32_t kMaxLifetime = Time::MsecToSec(Timer::kMaxDelay);
return mLastUpdateTime + Time::SecToMsec(Min(aLifetime, kMaxLifetime));
}
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
void RoutingManager::DiscoveredPrefixTable::Entry::Free(void)
{
Get<RoutingManager>().mDiscoveredPrefixTable.mEntryPool.Free(*this);
}
#endif
//---------------------------------------------------------------------------------------------------------------------
// DiscoveredPrefixTable::Router
@@ -1827,7 +1920,7 @@ bool RoutingManager::DiscoveredPrefixTable::Router::Matches(EmptyChecker aChecke
hasFlags = (mManagedAddressConfigFlag || mOtherConfigFlag);
}
return !hasFlags && mEntries.IsEmpty();
return !hasFlags && mOnLinkPrefixes.IsEmpty() && mRoutePrefixes.IsEmpty();
}
void RoutingManager::DiscoveredPrefixTable::Router::CopyInfoTo(RouterEntry &aEntry) const
@@ -1838,14 +1931,6 @@ void RoutingManager::DiscoveredPrefixTable::Router::CopyInfoTo(RouterEntry &aEnt
aEntry.mStubRouterFlag = mStubRouterFlag;
}
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
void RoutingManager::DiscoveredPrefixTable::Router::Free(void)
{
mEntries.Free();
Get<RoutingManager>().mDiscoveredPrefixTable.mRouterPool.Free(*this);
}
#endif
//---------------------------------------------------------------------------------------------------------------------
// FavoredOmrPrefix
@@ -3761,8 +3846,8 @@ bool RoutingManager::PdPrefixManager::ProcessPrefixEntry(PrefixEntry &aEntry, Pr
ExitNow();
}
aEntry.mPrefix.Tidy();
aEntry.mPrefix.SetLength(kOmrPrefixLength);
aEntry.GetPrefix().Tidy();
aEntry.GetPrefix().SetLength(kOmrPrefixLength);
// Check if there is an update to the current prefix. The valid or
// preferred lifetime may have changed.
+173 -162
View File
@@ -628,14 +628,79 @@ private:
kToReplyToRs,
};
class LifetimedPrefix
{
// Represents an IPv6 prefix with its valid lifetime. Used as
// base class for `OnLinkPrefix` or `RoutePrefix`.
public:
enum UlaChecker : bool
{
kIsNotUla = false,
kIsUla = true,
};
struct ExpirationChecker
{
explicit ExpirationChecker(TimeMilli aNow) { mNow = aNow; }
TimeMilli mNow;
};
const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
Ip6::Prefix &GetPrefix(void) { return mPrefix; }
const TimeMilli &GetLastUpdateTime(void) const { return mLastUpdateTime; }
uint32_t GetValidLifetime(void) const { return mValidLifetime; }
TimeMilli GetExpireTime(void) const { return CalculateExpirationTime(mValidLifetime); }
bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); }
bool Matches(const UlaChecker &aIsUla) const { return (mPrefix.IsUniqueLocal() == aIsUla); }
bool Matches(const ExpirationChecker &aChecker) const { return (GetExpireTime() <= aChecker.mNow); }
protected:
LifetimedPrefix(void) = default;
TimeMilli CalculateExpirationTime(uint32_t aLifetime) const;
Ip6::Prefix mPrefix;
uint32_t mValidLifetime;
TimeMilli mLastUpdateTime;
};
class OnLinkPrefix : public LifetimedPrefix, public Clearable<OnLinkPrefix>
{
public:
void SetFrom(const PrefixInfoOption &aPio);
void SetFrom(const PrefixTableEntry &aPrefixTableEntry);
uint32_t GetPreferredLifetime(void) const { return mPreferredLifetime; }
void ClearPreferredLifetime(void) { mPreferredLifetime = 0; }
bool IsDeprecated(void) const;
TimeMilli GetStaleTime(void) const;
TimeMilli GetStaleTimeFromPreferredLifetime(void) const;
void AdoptValidAndPreferredLifetimesFrom(const OnLinkPrefix &aPrefix);
void CopyInfoTo(PrefixTableEntry &aEntry, TimeMilli aNow) const;
private:
uint32_t mPreferredLifetime;
};
class RoutePrefix : public LifetimedPrefix, public Clearable<RoutePrefix>
{
public:
void SetFrom(const RouteInfoOption &aRio);
void SetFrom(const RouterAdvert::Header &aRaHeader);
void ClearValidLifetime(void) { mValidLifetime = 0; }
TimeMilli GetStaleTime(void) const;
RoutePreference GetRoutePreference(void) const { return mRoutePreference; }
void CopyInfoTo(PrefixTableEntry &aEntry, TimeMilli aNow) const;
private:
RoutePreference mRoutePreference;
};
void HandleDiscoveredPrefixTableChanged(void); // Declare early so we can use in `mSignalTask`
void HandleDiscoveredPrefixTableEntryTimer(void) { mDiscoveredPrefixTable.HandleEntryTimer(); }
void HandleDiscoveredPrefixTableRouterTimer(void) { mDiscoveredPrefixTable.HandleRouterTimer(); }
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
class PdPrefixManager; // For DiscoveredPrefixTable::Entry
#endif
class DiscoveredPrefixTable : public InstanceLocator
{
// This class maintains the discovered on-link and route prefixes
@@ -645,10 +710,6 @@ private:
// `RoutingManager` by calling its `ShouldProcessPrefixInfoOption()`
// and `ShouldProcessRouteInfoOption()` methods.
//
// It manages the lifetime of the discovered entries and publishes
// and unpublishes the prefixes in the Network Data (as external
// route) as they are added or removed.
//
// When there is any change in the table (an entry is added, removed,
// or modified), it signals the change to `RoutingManager` by calling
// `HandleDiscoveredPrefixTableChanged()` callback. A `Tasklet` is
@@ -656,10 +717,6 @@ private:
// changes within the same flow of execution, the callback is
// invoked after all the changes are processed.
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
friend class PdPrefixManager; // For DiscoveredPrefixTable::Entry
#endif
public:
explicit DiscoveredPrefixTable(Instance &aInstance);
@@ -692,129 +749,24 @@ private:
private:
static constexpr uint32_t kFavoredOnLinkPrefixMinPreferredLifetime = 1800; // In sec.
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS;
static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
#endif
class Entry : public LinkedListEntry<Entry>,
public Unequatable<Entry>,
template <class Type>
struct Entry : public Type,
public LinkedListEntry<Entry<Type>>,
#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
public Heap::Allocatable<Entry>,
public Heap::Allocatable<Entry<Type>>
#else
public InstanceLocatorInit,
public InstanceLocatorInit
#endif
private Clearable<Entry>
{
friend class LinkedListEntry<Entry>;
friend class Clearable<Entry>;
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
friend class PdPrefixManager;
#endif
public:
enum Type : uint8_t
{
kTypeOnLink,
kTypeRoute,
};
struct Matcher
{
Matcher(const Ip6::Prefix &aPrefix, Type aType)
: mPrefix(aPrefix)
, mType(aType)
{
}
const Ip6::Prefix &mPrefix;
Type mType;
};
struct Checker
{
enum Mode : uint8_t
{
kIsUla,
kIsNotUla,
};
Checker(Mode aMode, Type aType)
: mMode(aMode)
, mType(aType)
{
}
Mode mMode;
Type mType;
};
struct ExpirationChecker
{
explicit ExpirationChecker(TimeMilli aNow)
: mNow(aNow)
{
}
TimeMilli mNow;
};
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
void Init(Instance &aInstance) { InstanceLocatorInit::Init(aInstance); }
void Free(void);
#endif
void SetFrom(const RouterAdvert::Header &aRaHeader);
void SetFrom(const PrefixInfoOption &aPio);
void SetFrom(const RouteInfoOption &aRio);
void SetFrom(const PrefixTableEntry &aPrefixTableEntry);
Type GetType(void) const { return mType; }
bool IsOnLinkPrefix(void) const { return (mType == kTypeOnLink); }
bool IsRoutePrefix(void) const { return (mType == kTypeRoute); }
const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
const TimeMilli &GetLastUpdateTime(void) const { return mLastUpdateTime; }
uint32_t GetValidLifetime(void) const { return mValidLifetime; }
void ClearValidLifetime(void) { mValidLifetime = 0; }
TimeMilli GetExpireTime(void) const;
TimeMilli GetStaleTime(void) const;
TimeMilli GetStaleTimeFromPreferredLifetime(void) const;
RoutePreference GetPreference(void) const;
bool operator==(const Entry &aOther) const;
bool Matches(const Matcher &aMatcher) const;
bool Matches(const Checker &aChecker) const;
bool Matches(const ExpirationChecker &aChecker) const;
// Methods to use when `IsOnLinkPrefix()`
uint32_t GetPreferredLifetime(void) const { return mShared.mPreferredLifetime; }
void ClearPreferredLifetime(void) { mShared.mPreferredLifetime = 0; }
bool IsDeprecated(void) const;
void AdoptValidAndPreferredLifetimesFrom(const Entry &aEntry);
// Method to use when `!IsOnlinkPrefix()`
RoutePreference GetRoutePreference(void) const { return mShared.mRoutePreference; }
private:
TimeMilli CalculateExpirationTime(uint32_t aLifetime) const;
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;
Entry<Type> *mNext;
};
struct Router : public LinkedListEntry<Router>,
#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
public Heap::Allocatable<Router>,
#else
public InstanceLocatorInit,
#endif
public Clearable<Router>
struct Router : public Clearable<Router>
{
// The timeout (in msec) for router staying in active state
// before starting the Neighbor Solicitation (NS) probes.
@@ -832,79 +784,109 @@ private:
kContainsNoEntriesOrFlags
};
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
void Init(Instance &aInstance) { InstanceLocatorInit::Init(aInstance); }
void Free(void);
#endif
bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
bool Matches(EmptyChecker aChecker) const;
void CopyInfoTo(RouterEntry &aEntry) const;
Router *mNext;
Ip6::Address mAddress;
OwningList<Entry> mEntries;
TimeMilli mTimeout;
uint8_t mNsProbeCount;
bool mManagedAddressConfigFlag : 1;
bool mOtherConfigFlag : 1;
bool mStubRouterFlag : 1;
using OnLinkPrefixList = OwningList<Entry<OnLinkPrefix>>;
using RoutePrefixList = OwningList<Entry<RoutePrefix>>;
Ip6::Address mAddress;
OnLinkPrefixList mOnLinkPrefixes;
RoutePrefixList mRoutePrefixes;
TimeMilli mTimeout;
uint8_t mNsProbeCount;
bool mManagedAddressConfigFlag : 1;
bool mOtherConfigFlag : 1;
bool mStubRouterFlag : 1;
};
class Iterator : public PrefixTableIterator
{
public:
enum AdvanceMode : uint8_t
enum Type : uint8_t
{
kToNextEntry,
kToNextRouter,
kUnspecified,
kRouterIterator,
kPrefixIterator,
};
void Init(const LinkedList<Router> &aRouters);
void Advance(AdvanceMode aMode);
enum EntryType : uint8_t
{
kOnLinkPrefix,
kRoutePrefix,
};
const Router *GetRouter(void) const { return static_cast<const Router *>(mPtr1); }
const Entry *GetEntry(void) const { return static_cast<const Entry *>(mPtr2); }
TimeMilli GetInitTime(void) const { return TimeMilli(mData32); }
void Init(const Entry<Router> *aRoutersHead);
Error AdvanceToNextRouter(Type aType);
Error AdvanceToNextEntry(void);
TimeMilli GetInitTime(void) const { return TimeMilli(mData1); }
Type GetType(void) const { return static_cast<Type>(mData2); }
const Entry<Router> *GetRouter(void) const { return static_cast<const Entry<Router> *>(mPtr1); }
EntryType GetEntryType(void) const { return static_cast<EntryType>(mData3); }
template <class PrefixType> const Entry<PrefixType> *GetEntry(void) const
{
return static_cast<const Entry<PrefixType> *>(mPtr2);
}
private:
void SetRouter(const Router *aRouter) { mPtr1 = aRouter; }
void SetEntry(const Entry *aEntry) { mPtr2 = aEntry; }
void SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); }
void SetRouter(const Entry<Router> *aRouter) { mPtr1 = aRouter; }
void SetInitTime(void) { mData1 = TimerMilli::GetNow().GetValue(); }
void SetEntry(const void *aEntry) { mPtr2 = aEntry; }
bool HasEntry(void) const { return mPtr2 != nullptr; }
void SetEntryType(EntryType aType) { mData3 = aType; }
void SetType(Type aType) { mData2 = aType; }
};
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS;
static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
union SharedEntry
{
SharedEntry(void) { mNext = nullptr; }
void SetNext(SharedEntry *aNext) { mNext = aNext; }
SharedEntry *GetNext(void) { return mNext; }
const SharedEntry *GetNext(void) const { return mNext; }
template <class PrefixType> Entry<PrefixType> &GetEntry(void);
SharedEntry *mNext;
Entry<OnLinkPrefix> mOnLinkEntry;
Entry<RoutePrefix> mRouteEntry;
};
#endif
void ProcessRaHeader(const RouterAdvert::Header &aRaHeader, Router &aRouter);
void ProcessPrefixInfoOption(const PrefixInfoOption &aPio, Router &aRouter);
void ProcessRouteInfoOption(const RouteInfoOption &aRio, Router &aRouter);
void ProcessRaFlagsExtOption(const RaFlagsExtOption &aFlagsOption, Router &aRouter);
bool Contains(const Entry::Checker &aChecker) const;
void RemovePrefix(const Entry::Matcher &aMatcher);
bool ContainsOnLinkPrefix(OnLinkPrefix::UlaChecker aUlaChecker) const;
void RemoveOrDeprecateEntriesFromInactiveRouters(void);
void RemoveRoutersWithNoEntriesOrFlags(void);
void UpdateNetworkDataOnChangeTo(Entry &aEntry);
void RemoveExpiredEntries(void);
void SignalTableChanged(void);
void UpdateRouterOnRx(Router &aRouter);
void SendNeighborSolicitToRouter(const Router &aRouter);
#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
Router *AllocateRouter(void) { return Router::Allocate(); }
Entry *AllocateEntry(void) { return Entry::Allocate(); }
template <class Type> Entry<Type> *AllocateEntry(void) { return Entry<Type>::Allocate(); }
#else
Router *AllocateRouter(void);
Entry *AllocateEntry(void);
template <class Type> Entry<Type> *AllocateEntry(void);
#endif
using SignalTask = TaskletIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableChanged>;
using EntryTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableEntryTimer>;
using RouterTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandleDiscoveredPrefixTableRouterTimer>;
using RouterList = OwningList<Entry<Router>>;
OwningList<Router> mRouters;
EntryTimer mEntryTimer;
RouterTimer mRouterTimer;
SignalTask mSignalTask;
RouterList mRouters;
EntryTimer mEntryTimer;
RouterTimer mRouterTimer;
SignalTask mSignalTask;
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
Pool<Entry, kMaxEntries> mEntryPool;
Pool<Router, kMaxRouters> mRouterPool;
Pool<SharedEntry, kMaxEntries> mEntryPool;
Pool<Entry<Router>, kMaxRouters> mRouterPool;
#endif
};
@@ -1300,7 +1282,7 @@ private:
void SetStateCallback(PdCallback aCallback, void *aContext) { mStateCallback.Set(aCallback, aContext); }
private:
class PrefixEntry : public DiscoveredPrefixTable::Entry
class PrefixEntry : public OnLinkPrefix
{
public:
PrefixEntry(void) { Clear(); }
@@ -1410,6 +1392,35 @@ private:
RoutingPolicyTimer mRoutingPolicyTimer;
};
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
// Template specializations
template <>
inline RoutingManager::DiscoveredPrefixTable::Entry<RoutingManager::OnLinkPrefix>
&RoutingManager::DiscoveredPrefixTable::SharedEntry::GetEntry(void)
{
return mOnLinkEntry;
}
template <>
inline RoutingManager::DiscoveredPrefixTable::Entry<RoutingManager::RoutePrefix>
&RoutingManager::DiscoveredPrefixTable::SharedEntry::GetEntry(void)
{
return mRouteEntry;
}
// Declare template (full) specializations for `Router` type.
template <>
RoutingManager::DiscoveredPrefixTable::Entry<RoutingManager::DiscoveredPrefixTable::Router>
*RoutingManager::DiscoveredPrefixTable::AllocateEntry(void);
template <>
void RoutingManager::DiscoveredPrefixTable::Entry<RoutingManager::DiscoveredPrefixTable::Router>::Free(void);
#endif // #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
} // namespace BorderRouter
DefineMapEnum(otBorderRoutingState, BorderRouter::RoutingManager::State);