mirror of
https://github.com/espressif/openthread.git
synced 2026-08-04 09:57:47 +00:00
[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:
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user