From 68b8c88e18987da7a0dea33bd3193bc0c9859c73 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 13 May 2024 09:38:22 -0700 Subject: [PATCH] [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`, 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. --- include/openthread/border_routing.h | 4 +- include/openthread/instance.h | 2 +- src/core/border_router/routing_manager.cpp | 601 ++++++++++++--------- src/core/border_router/routing_manager.hpp | 335 ++++++------ 4 files changed, 520 insertions(+), 422 deletions(-) diff --git a/include/openthread/border_routing.h b/include/openthread/border_routing.h index 4a3b953f8..33ef275cf 100644 --- a/include/openthread/border_routing.h +++ b/include/openthread/border_routing.h @@ -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; /** diff --git a/include/openthread/instance.h b/include/openthread/instance.h index a117b7a8e..caf7ea94e 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -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 diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 84db52d54..f666c41b2 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -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(GetRoutePreference()); +} + //--------------------------------------------------------------------------------------------------------------------- // DiscoveredPrefixTable @@ -1007,18 +1126,19 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const Rou if (router == nullptr) { - router = AllocateRouter(); + Entry *newEntry = AllocateEntry(); - 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 *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(); 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 *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(); 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 *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(); 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::AllocateEntry(void) { - Router *router = mRouterPool.Allocate(); + Entry *router = mRouterPool.Allocate(); VerifyOrExit(router != nullptr); router->Init(GetInstance()); @@ -1212,26 +1334,49 @@ exit: return router; } -RoutingManager::DiscoveredPrefixTable::Entry *RoutingManager::DiscoveredPrefixTable::AllocateEntry(void) +template +RoutingManager::DiscoveredPrefixTable::Entry *RoutingManager::DiscoveredPrefixTable::AllocateEntry(void) { - Entry *entry = mEntryPool.Allocate(); + static_assert(TypeTraits::IsSame::kValue || + TypeTraits::IsSame::kValue, + "PrefixType MSUT be either RoutePrefix or OnLinkPrefix"); - VerifyOrExit(entry != nullptr); + Entry *entry = nullptr; + SharedEntry *sharedEntry = mEntryPool.Allocate(); + + VerifyOrExit(sharedEntry != nullptr); + entry = &sharedEntry->GetEntry(); entry->Init(GetInstance()); exit: return entry; } +template <> void RoutingManager::DiscoveredPrefixTable::Entry::Free(void) +{ + mOnLinkPrefixes.Free(); + mRoutePrefixes.Free(); + Get().mDiscoveredPrefixTable.mRouterPool.Free(*this); +} + +template void RoutingManager::DiscoveredPrefixTable::Entry::Free(void) +{ + static_assert(TypeTraits::IsSame::kValue || + TypeTraits::IsSame::kValue, + "PrefixType MSUT be either RoutePrefix or OnLinkPrefix"); + + Get().mDiscoveredPrefixTable.mEntryPool.Free(*reinterpret_cast(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(aIterator).Init(mRouters); + static_cast(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(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(aEntry.mIsOnLink ? 0 : iterator.GetEntry()->GetRoutePreference()); - iterator.Advance(Iterator::kToNextEntry); + switch (iterator.GetEntryType()) + { + case Iterator::kOnLinkPrefix: + iterator.GetEntry()->CopyInfoTo(aEntry, iterator.GetInitTime()); + break; + case Iterator::kRoutePrefix: + iterator.GetEntry()->CopyInfoTo(aEntry, iterator.GetInitTime()); + break; + } exit: return error; @@ -1625,10 +1797,10 @@ Error RoutingManager::DiscoveredPrefixTable::GetNextRouter(PrefixTableIterator & Error error = kErrorNone; Iterator &iterator = static_cast(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 &aRouters) +void RoutingManager::DiscoveredPrefixTable::Iterator::Init(const Entry *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()->GetNext()); + break; + case kRoutePrefix: + SetEntry(GetEntry()->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().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().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. diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index ec68ae734..09490c1d9 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -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 + { + 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 + { + 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, - public Unequatable, + template + struct Entry : public Type, + public LinkedListEntry>, #if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE - public Heap::Allocatable, + public Heap::Allocatable> #else - public InstanceLocatorInit, + public InstanceLocatorInit #endif - private Clearable { - friend class LinkedListEntry; - friend class Clearable; -#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 *mNext; }; - struct Router : public LinkedListEntry, -#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE - public Heap::Allocatable, -#else - public InstanceLocatorInit, -#endif - public Clearable + struct Router : public Clearable { // 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 mEntries; - TimeMilli mTimeout; - uint8_t mNsProbeCount; - bool mManagedAddressConfigFlag : 1; - bool mOtherConfigFlag : 1; - bool mStubRouterFlag : 1; + using OnLinkPrefixList = OwningList>; + using RoutePrefixList = OwningList>; + + 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 &aRouters); - void Advance(AdvanceMode aMode); + enum EntryType : uint8_t + { + kOnLinkPrefix, + kRoutePrefix, + }; - const Router *GetRouter(void) const { return static_cast(mPtr1); } - const Entry *GetEntry(void) const { return static_cast(mPtr2); } - TimeMilli GetInitTime(void) const { return TimeMilli(mData32); } + void Init(const Entry *aRoutersHead); + Error AdvanceToNextRouter(Type aType); + Error AdvanceToNextEntry(void); + TimeMilli GetInitTime(void) const { return TimeMilli(mData1); } + Type GetType(void) const { return static_cast(mData2); } + const Entry *GetRouter(void) const { return static_cast *>(mPtr1); } + EntryType GetEntryType(void) const { return static_cast(mData3); } + + template const Entry *GetEntry(void) const + { + return static_cast *>(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 *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 Entry &GetEntry(void); + + SharedEntry *mNext; + Entry mOnLinkEntry; + Entry 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 Entry *AllocateEntry(void) { return Entry::Allocate(); } #else - Router *AllocateRouter(void); - Entry *AllocateEntry(void); + template Entry *AllocateEntry(void); #endif using SignalTask = TaskletIn; using EntryTimer = TimerMilliIn; using RouterTimer = TimerMilliIn; + using RouterList = OwningList>; - OwningList mRouters; - EntryTimer mEntryTimer; - RouterTimer mRouterTimer; - SignalTask mSignalTask; + RouterList mRouters; + EntryTimer mEntryTimer; + RouterTimer mRouterTimer; + SignalTask mSignalTask; #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE - Pool mEntryPool; - Pool mRouterPool; + Pool mEntryPool; + Pool, 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::DiscoveredPrefixTable::SharedEntry::GetEntry(void) +{ + return mOnLinkEntry; +} + +template <> +inline RoutingManager::DiscoveredPrefixTable::Entry + &RoutingManager::DiscoveredPrefixTable::SharedEntry::GetEntry(void) +{ + return mRouteEntry; +} + +// Declare template (full) specializations for `Router` type. + +template <> +RoutingManager::DiscoveredPrefixTable::Entry + *RoutingManager::DiscoveredPrefixTable::AllocateEntry(void); + +template <> +void RoutingManager::DiscoveredPrefixTable::Entry::Free(void); + +#endif // #if !OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE + } // namespace BorderRouter DefineMapEnum(otBorderRoutingState, BorderRouter::RoutingManager::State);