mirror of
https://github.com/espressif/openthread.git
synced 2026-08-06 02:37:47 +00:00
[routing-manager] RoutePublisher and new route publishing model (#8986)
This commit updates the `RoutingManager` module to implement a new model for publishing routes. The new model replaces the previous model, which explicitly published all discovered routes and on-link prefixes (from processing Router Advertisements on AIL) as external routes in the Network Data. The new model simplifies this logic by publishing either a `fc00::/7` (ULA) route or a `::/0` (default) route in the Network Data, depending on the set of discovered routes and on-link prefixes, and the currently favored OMR prefix. This commit adds the `RoutePublisher` class, a nested sub-component of the `RoutingManager` class. The `RoutePublisher` class is responsible for determining the route prefix to publish and its preference. The preference of the published route is determined based on the current role of the Border Router (BR): low preference if the BR is a child, and medium preference if the BR is acting as a router. This commit also updates `test_routing_manager` unit test validating the new behavior.
This commit is contained in:
@@ -72,6 +72,7 @@ RoutingManager::RoutingManager(Instance &aInstance)
|
||||
, mUserSetRioPreference(false)
|
||||
, mOnLinkPrefixManager(aInstance)
|
||||
, mDiscoveredPrefixTable(aInstance)
|
||||
, mRoutePublisher(aInstance)
|
||||
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
||||
, mNat64PrefixManager(aInstance)
|
||||
#endif
|
||||
@@ -308,6 +309,8 @@ void RoutingManager::Start(void)
|
||||
mIsRunning = true;
|
||||
UpdateDiscoveredPrefixTableOnNetDataChange();
|
||||
mOnLinkPrefixManager.Start();
|
||||
DetermineFavoredOmrPrefix();
|
||||
mRoutePublisher.Start();
|
||||
mRsSender.Start();
|
||||
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
||||
mNat64PrefixManager.Start();
|
||||
@@ -341,6 +344,8 @@ void RoutingManager::Stop(void)
|
||||
|
||||
mRoutingPolicyTimer.Stop();
|
||||
|
||||
mRoutePublisher.Stop();
|
||||
|
||||
LogInfo("Border Routing manager stopped");
|
||||
|
||||
mIsRunning = false;
|
||||
@@ -407,6 +412,7 @@ void RoutingManager::HandleNotifierEvents(Events aEvents)
|
||||
if (aEvents.Contains(kEventThreadRoleChanged) && !mUserSetRioPreference)
|
||||
{
|
||||
SetRioPreferenceBasedOnRole();
|
||||
mRoutePublisher.HandleRoleChanged();
|
||||
}
|
||||
|
||||
VerifyOrExit(IsInitialized() && IsEnabled());
|
||||
@@ -436,7 +442,6 @@ void RoutingManager::UpdateDiscoveredPrefixTableOnNetDataChange(void)
|
||||
{
|
||||
NetworkData::Iterator iterator = NetworkData::kIteratorInit;
|
||||
NetworkData::OnMeshPrefixConfig prefixConfig;
|
||||
bool foundDefRouteOmrPrefix = false;
|
||||
|
||||
// Remove all OMR prefixes in Network Data from the
|
||||
// discovered prefix table. Also check if we have
|
||||
@@ -450,33 +455,16 @@ void RoutingManager::UpdateDiscoveredPrefixTableOnNetDataChange(void)
|
||||
}
|
||||
|
||||
mDiscoveredPrefixTable.RemoveRoutePrefix(prefixConfig.GetPrefix());
|
||||
|
||||
if (prefixConfig.mDefaultRoute)
|
||||
{
|
||||
foundDefRouteOmrPrefix = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we find an OMR prefix with default route flag, it indicates
|
||||
// that this prefix can be used with default route (routable beyond
|
||||
// infra link).
|
||||
//
|
||||
// `DiscoveredPrefixTable` will always track which routers provide
|
||||
// default route when processing received RA messages, but only
|
||||
// if we see an OMR prefix with default route flag, we allow it
|
||||
// to publish the discovered default route (as ::/0 external
|
||||
// route) in Network Data.
|
||||
|
||||
mDiscoveredPrefixTable.SetAllowDefaultRouteInNetData(foundDefRouteOmrPrefix);
|
||||
}
|
||||
|
||||
void RoutingManager::EvaluateOmrPrefix(void)
|
||||
void RoutingManager::DetermineFavoredOmrPrefix(void)
|
||||
{
|
||||
// Determine the favored OMR prefix present in Network Data.
|
||||
|
||||
NetworkData::Iterator iterator = NetworkData::kIteratorInit;
|
||||
NetworkData::OnMeshPrefixConfig onMeshPrefixConfig;
|
||||
|
||||
OT_ASSERT(mIsRunning);
|
||||
|
||||
mFavoredOmrPrefix.Clear();
|
||||
|
||||
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == kErrorNone)
|
||||
@@ -491,6 +479,13 @@ void RoutingManager::EvaluateOmrPrefix(void)
|
||||
mFavoredOmrPrefix.SetFrom(onMeshPrefixConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RoutingManager::EvaluateOmrPrefix(void)
|
||||
{
|
||||
OT_ASSERT(mIsRunning);
|
||||
|
||||
DetermineFavoredOmrPrefix();
|
||||
|
||||
// Decide if we need to add or remove our local OMR prefix.
|
||||
|
||||
@@ -520,69 +515,6 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::EvaluatePublishingPrefix(const Ip6::Prefix &aPrefix)
|
||||
{
|
||||
// This method evaluates whether to publish or unpublish a given
|
||||
// `aPrefix` as an external route in the Network Data. It makes a
|
||||
// collective decision by checking with different sub-components to
|
||||
// see whether or not each wants this prefix published and if so
|
||||
// at what preference level and flags.
|
||||
//
|
||||
// Before calling this method, the sub-components need to make sure
|
||||
// to update their internal state such that their `ShouldPublish()`
|
||||
// provides the correct info.
|
||||
|
||||
bool shouldPublish = false;
|
||||
NetworkData::ExternalRouteConfig routeConfig;
|
||||
|
||||
routeConfig.Clear();
|
||||
routeConfig.SetPrefix(aPrefix);
|
||||
routeConfig.mPreference = NetworkData::kRoutePreferenceLow;
|
||||
routeConfig.mStable = true;
|
||||
|
||||
VerifyOrExit(mIsRunning);
|
||||
|
||||
// The order of checks is important. The Discovered Prefix Table is
|
||||
// first followed by Local On Link Prefix manager and finally NAT64
|
||||
// prefix manager.
|
||||
|
||||
shouldPublish = mDiscoveredPrefixTable.ShouldPublish(routeConfig);
|
||||
|
||||
if (mOnLinkPrefixManager.ShouldPublish(routeConfig))
|
||||
{
|
||||
shouldPublish = true;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
||||
if (mNat64PrefixManager.ShouldPublish(routeConfig))
|
||||
{
|
||||
shouldPublish = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (shouldPublish)
|
||||
{
|
||||
SuccessOrAssert(Get<NetworkData::Publisher>().PublishExternalRoute(
|
||||
routeConfig, NetworkData::Publisher::kFromRoutingManager));
|
||||
}
|
||||
else
|
||||
{
|
||||
UnpublishExternalRoute(aPrefix);
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::UnpublishExternalRoute(const Ip6::Prefix &aPrefix)
|
||||
{
|
||||
VerifyOrExit(mIsRunning);
|
||||
IgnoreError(Get<NetworkData::Publisher>().UnpublishPrefix(aPrefix));
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
// This method evaluate the routing policy depends on prefix and route
|
||||
// information on Thread Network and infra link. As a result, this
|
||||
// method May send RA messages on infra link and publish/unpublish
|
||||
@@ -595,6 +527,7 @@ void RoutingManager::EvaluateRoutingPolicy(void)
|
||||
|
||||
mOnLinkPrefixManager.Evaluate();
|
||||
EvaluateOmrPrefix();
|
||||
mRoutePublisher.Evaluate();
|
||||
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
||||
mNat64PrefixManager.Evaluate();
|
||||
#endif
|
||||
@@ -1090,6 +1023,7 @@ void RoutingManager::HandleDiscoveredPrefixTableChanged(void)
|
||||
|
||||
ResetDiscoveredPrefixStaleTimer();
|
||||
mOnLinkPrefixManager.HandleDiscoveredPrefixTableChanged();
|
||||
mRoutePublisher.Evaluate();
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -1113,15 +1047,19 @@ bool RoutingManager::NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) co
|
||||
return contains;
|
||||
}
|
||||
|
||||
bool RoutingManager::NetworkDataContainsExternalRoute(const Ip6::Prefix &aPrefix) const
|
||||
bool RoutingManager::NetworkDataContainsUlaRoute(void) const
|
||||
{
|
||||
// Determine whether leader Network Data contains a route
|
||||
// prefix which is either the ULA prefix `fc00::/7` or
|
||||
// a sub-prefix of it (e.g., default route).
|
||||
|
||||
NetworkData::Iterator iterator = NetworkData::kIteratorInit;
|
||||
NetworkData::ExternalRouteConfig routeConfig;
|
||||
bool contains = false;
|
||||
|
||||
while (Get<NetworkData::Leader>().GetNextExternalRoute(iterator, routeConfig) == kErrorNone)
|
||||
{
|
||||
if (routeConfig.mStable && routeConfig.GetPrefix() == aPrefix)
|
||||
if (routeConfig.mStable && RoutePublisher::GetUlaPrefix().ContainsPrefix(routeConfig.GetPrefix()))
|
||||
{
|
||||
contains = true;
|
||||
break;
|
||||
@@ -1223,7 +1161,6 @@ RoutingManager::DiscoveredPrefixTable::DiscoveredPrefixTable(Instance &aInstance
|
||||
, mEntryTimer(aInstance)
|
||||
, mRouterTimer(aInstance)
|
||||
, mSignalTask(aInstance)
|
||||
, mAllowDefaultRouteInNetData(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1311,7 +1248,6 @@ void RoutingManager::DiscoveredPrefixTable::ProcessDefaultRoute(const Ip6::Nd::R
|
||||
}
|
||||
|
||||
mEntryTimer.FireAtIfEarlier(entry->GetExpireTime());
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(entry->GetPrefix());
|
||||
|
||||
SignalTableChanged();
|
||||
|
||||
@@ -1358,7 +1294,6 @@ void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const Ip6::N
|
||||
}
|
||||
|
||||
mEntryTimer.FireAtIfEarlier(entry->GetExpireTime());
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(entry->GetPrefix());
|
||||
|
||||
SignalTableChanged();
|
||||
|
||||
@@ -1402,7 +1337,6 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouteInfoOption(const Ip6::Nd
|
||||
}
|
||||
|
||||
mEntryTimer.FireAtIfEarlier(entry->GetExpireTime());
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(entry->GetPrefix());
|
||||
|
||||
SignalTableChanged();
|
||||
|
||||
@@ -1410,21 +1344,35 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::SetAllowDefaultRouteInNetData(bool aAllow)
|
||||
bool RoutingManager::DiscoveredPrefixTable::Contains(const Entry::Checker &aChecker) const
|
||||
{
|
||||
Ip6::Prefix prefix;
|
||||
bool contains = false;
|
||||
|
||||
VerifyOrExit(aAllow != mAllowDefaultRouteInNetData);
|
||||
for (const Router &router : mRouters)
|
||||
{
|
||||
if (router.mEntries.ContainsMatching(aChecker))
|
||||
{
|
||||
contains = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LogInfo("Allow default route in netdata: %s -> %s", ToYesNo(mAllowDefaultRouteInNetData), ToYesNo(aAllow));
|
||||
return contains;
|
||||
}
|
||||
|
||||
mAllowDefaultRouteInNetData = aAllow;
|
||||
bool RoutingManager::DiscoveredPrefixTable::ContainsDefaultOrNonUlaRoutePrefix(void) const
|
||||
{
|
||||
return Contains(Entry::Checker(Entry::Checker::kIsNotUla, Entry::kTypeRoute));
|
||||
}
|
||||
|
||||
prefix.Clear();
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(prefix);
|
||||
bool RoutingManager::DiscoveredPrefixTable::ContainsNonUlaOnLinkPrefix(void) const
|
||||
{
|
||||
return Contains(Entry::Checker(Entry::Checker::kIsNotUla, Entry::kTypeOnLink));
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
bool RoutingManager::DiscoveredPrefixTable::ContainsUlaOnLinkPrefix(void) const
|
||||
{
|
||||
return Contains(Entry::Checker(Entry::Checker::kIsUla, Entry::kTypeOnLink));
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::FindFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const
|
||||
@@ -1452,32 +1400,6 @@ void RoutingManager::DiscoveredPrefixTable::FindFavoredOnLinkPrefix(Ip6::Prefix
|
||||
}
|
||||
}
|
||||
|
||||
bool RoutingManager::DiscoveredPrefixTable::ContainsOnLinkPrefix(const Ip6::Prefix &aPrefix) const
|
||||
{
|
||||
return ContainsPrefix(Entry::Matcher(aPrefix, Entry::kTypeOnLink));
|
||||
}
|
||||
|
||||
bool RoutingManager::DiscoveredPrefixTable::ContainsRoutePrefix(const Ip6::Prefix &aPrefix) const
|
||||
{
|
||||
return ContainsPrefix(Entry::Matcher(aPrefix, Entry::kTypeRoute));
|
||||
}
|
||||
|
||||
bool RoutingManager::DiscoveredPrefixTable::ContainsPrefix(const Entry::Matcher &aMatcher) const
|
||||
{
|
||||
bool contains = false;
|
||||
|
||||
for (const Router &router : mRouters)
|
||||
{
|
||||
if (router.mEntries.ContainsMatching(aMatcher))
|
||||
{
|
||||
contains = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return contains;
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix)
|
||||
{
|
||||
RemovePrefix(Entry::Matcher(aPrefix, Entry::kTypeOnLink));
|
||||
@@ -1504,8 +1426,6 @@ void RoutingManager::DiscoveredPrefixTable::RemovePrefix(const Entry::Matcher &a
|
||||
FreeEntries(removedEntries);
|
||||
RemoveRoutersWithNoEntries();
|
||||
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(aMatcher.mPrefix);
|
||||
|
||||
SignalTableChanged();
|
||||
|
||||
exit:
|
||||
@@ -1523,7 +1443,6 @@ void RoutingManager::DiscoveredPrefixTable::RemoveAllEntries(void)
|
||||
|
||||
while ((entry = router.mEntries.Pop()) != nullptr)
|
||||
{
|
||||
Get<RoutingManager>().UnpublishExternalRoute(entry->GetPrefix());
|
||||
FreeEntry(*entry);
|
||||
SignalTableChanged();
|
||||
}
|
||||
@@ -1672,29 +1591,6 @@ const RoutingManager::DiscoveredPrefixTable::Entry *RoutingManager::DiscoveredPr
|
||||
return favoredEntry;
|
||||
}
|
||||
|
||||
bool RoutingManager::DiscoveredPrefixTable::ShouldPublish(NetworkData::ExternalRouteConfig &aRouteConfig) const
|
||||
{
|
||||
bool shouldPublish = false;
|
||||
const Entry *favoredEntry;
|
||||
|
||||
if (aRouteConfig.GetPrefix().GetLength() == 0)
|
||||
{
|
||||
// If the change is to default route ::/0 prefix, make sure we
|
||||
// are allowed to publish default route in Network Data.
|
||||
|
||||
VerifyOrExit(mAllowDefaultRouteInNetData);
|
||||
}
|
||||
|
||||
favoredEntry = FindFavoredEntryToPublish(aRouteConfig.GetPrefix());
|
||||
VerifyOrExit(favoredEntry != nullptr);
|
||||
|
||||
shouldPublish = true;
|
||||
aRouteConfig.mPreference = favoredEntry->GetPreference();
|
||||
|
||||
exit:
|
||||
return shouldPublish;
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::HandleEntryTimer(void) { RemoveExpiredEntries(); }
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::RemoveExpiredEntries(void)
|
||||
@@ -1710,14 +1606,6 @@ void RoutingManager::DiscoveredPrefixTable::RemoveExpiredEntries(void)
|
||||
|
||||
RemoveRoutersWithNoEntries();
|
||||
|
||||
// Determine if we need to publish/unpublish any prefixes in
|
||||
// the Network Data.
|
||||
|
||||
for (const Entry &expiredEntry : expiredEntries)
|
||||
{
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(expiredEntry.GetPrefix());
|
||||
}
|
||||
|
||||
if (!expiredEntries.IsEmpty())
|
||||
{
|
||||
SignalTableChanged();
|
||||
@@ -1927,6 +1815,11 @@ bool RoutingManager::DiscoveredPrefixTable::Entry::Matches(const Matcher &aMatch
|
||||
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;
|
||||
@@ -2006,6 +1899,15 @@ uint32_t RoutingManager::DiscoveredPrefixTable::Entry::CalculateExpireDelay(uint
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// OmrPrefix
|
||||
|
||||
bool RoutingManager::OmrPrefix::IsInfrastructureDerived(void) const
|
||||
{
|
||||
// Indicate whether the OMR prefix is infrastructure-derived which
|
||||
// can be identified as a valid OMR prefix with preference of
|
||||
// medium or higher.
|
||||
|
||||
return !IsEmpty() && (mPreference >= NetworkData::kRoutePreferenceMedium);
|
||||
}
|
||||
|
||||
void RoutingManager::OmrPrefix::SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig)
|
||||
{
|
||||
mPrefix = aOnMeshPrefixConfig.GetPrefix();
|
||||
@@ -2228,25 +2130,12 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::OnLinkPrefixManager::Start(void)
|
||||
{
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(mLocalPrefix);
|
||||
|
||||
for (const OldPrefix &oldPrefix : mOldLocalPrefixes)
|
||||
{
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(oldPrefix.mPrefix);
|
||||
}
|
||||
}
|
||||
void RoutingManager::OnLinkPrefixManager::Start(void) {}
|
||||
|
||||
void RoutingManager::OnLinkPrefixManager::Stop(void)
|
||||
{
|
||||
mFavoredDiscoveredPrefix.Clear();
|
||||
|
||||
for (const OldPrefix &oldPrefix : mOldLocalPrefixes)
|
||||
{
|
||||
Get<RoutingManager>().UnpublishExternalRoute(oldPrefix.mPrefix);
|
||||
}
|
||||
|
||||
switch (mState)
|
||||
{
|
||||
case kIdle:
|
||||
@@ -2255,7 +2144,6 @@ void RoutingManager::OnLinkPrefixManager::Stop(void)
|
||||
case kPublishing:
|
||||
case kAdvertising:
|
||||
case kDeprecating:
|
||||
Get<RoutingManager>().UnpublishExternalRoute(mLocalPrefix);
|
||||
mState = kDeprecating;
|
||||
break;
|
||||
}
|
||||
@@ -2360,16 +2248,15 @@ void RoutingManager::OnLinkPrefixManager::PublishAndAdvertise(void)
|
||||
|
||||
mState = kPublishing;
|
||||
ResetExpireTime(TimerMilli::GetNow());
|
||||
LogInfo("Publishing local on-link prefix %s in netdata", mLocalPrefix.ToString().AsCString());
|
||||
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(mLocalPrefix);
|
||||
// We wait for the ULA `fc00::/7` route or a sub-prefix of it (e.g.,
|
||||
// default route) to be added in Network Data before
|
||||
// starting to advertise the local on-link prefix in RAs.
|
||||
// However, if it is already present in Network Data (e.g.,
|
||||
// added by another BR on the same Thread mesh), we can
|
||||
// immediately start advertising it.
|
||||
|
||||
// We wait for the prefix to be added in Network Data before
|
||||
// starting to advertise it in RAs. However, if it is already
|
||||
// present in Network Data (e.g., added by another BR on the same
|
||||
// Thread mesh), we can immediately start advertising it.
|
||||
|
||||
if (Get<RoutingManager>().NetworkDataContainsExternalRoute(mLocalPrefix))
|
||||
if (Get<RoutingManager>().NetworkDataContainsUlaRoute())
|
||||
{
|
||||
EnterAdvertisingState();
|
||||
}
|
||||
@@ -2401,31 +2288,14 @@ void RoutingManager::OnLinkPrefixManager::Deprecate(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool RoutingManager::OnLinkPrefixManager::ShouldPublish(NetworkData::ExternalRouteConfig &aRouteConfig) const
|
||||
bool RoutingManager::OnLinkPrefixManager::ShouldPublishUlaRoute(void) const
|
||||
{
|
||||
bool shouldPublish = false;
|
||||
// Determine whether or not we should publish ULA prefix. We need
|
||||
// to publish if we are in any of `kPublishing`, `kAdvertising`,
|
||||
// or `kDeprecating` states, or if there is at least one old local
|
||||
// prefix being deprecated.
|
||||
|
||||
if (aRouteConfig.GetPrefix() == mLocalPrefix)
|
||||
{
|
||||
switch (mState)
|
||||
{
|
||||
case kIdle:
|
||||
break;
|
||||
case kPublishing:
|
||||
case kAdvertising:
|
||||
case kDeprecating:
|
||||
shouldPublish = true;
|
||||
aRouteConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (mOldLocalPrefixes.ContainsMatching(aRouteConfig.GetPrefix()))
|
||||
{
|
||||
shouldPublish = true;
|
||||
aRouteConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
||||
}
|
||||
|
||||
return shouldPublish;
|
||||
return (mState != kIdle) || !mOldLocalPrefixes.IsEmpty();
|
||||
}
|
||||
|
||||
void RoutingManager::OnLinkPrefixManager::ResetExpireTime(TimeMilli aNow)
|
||||
@@ -2515,7 +2385,7 @@ void RoutingManager::OnLinkPrefixManager::HandleNetDataChange(void)
|
||||
{
|
||||
VerifyOrExit(mState == kPublishing);
|
||||
|
||||
if (Get<RoutingManager>().NetworkDataContainsExternalRoute(mLocalPrefix))
|
||||
if (Get<RoutingManager>().NetworkDataContainsUlaRoute())
|
||||
{
|
||||
EnterAdvertisingState();
|
||||
Get<RoutingManager>().ScheduleRoutingPolicyEvaluation(kAfterRandomDelay);
|
||||
@@ -2528,7 +2398,7 @@ exit:
|
||||
void RoutingManager::OnLinkPrefixManager::HandleExtPanIdChange(void)
|
||||
{
|
||||
// If the current local prefix is being advertised or deprecated,
|
||||
// we save it in `mOldLocalPrefixes` and keep deprecating it . It will
|
||||
// we save it in `mOldLocalPrefixes` and keep deprecating it. It will
|
||||
// be included in emitted RAs as PIO with zero preferred lifetime.
|
||||
// It will still be present in Network Data until its expire time
|
||||
// so to allow Thread nodes to continue to communicate with `InfraIf`
|
||||
@@ -2544,10 +2414,7 @@ void RoutingManager::OnLinkPrefixManager::HandleExtPanIdChange(void)
|
||||
switch (oldState)
|
||||
{
|
||||
case kIdle:
|
||||
break;
|
||||
|
||||
case kPublishing:
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(oldPrefix);
|
||||
break;
|
||||
|
||||
case kAdvertising:
|
||||
@@ -2558,6 +2425,7 @@ void RoutingManager::OnLinkPrefixManager::HandleExtPanIdChange(void)
|
||||
|
||||
if (Get<RoutingManager>().mIsRunning)
|
||||
{
|
||||
Get<RoutingManager>().mRoutePublisher.Evaluate();
|
||||
Get<RoutingManager>().ScheduleRoutingPolicyEvaluation(kAfterRandomDelay);
|
||||
}
|
||||
|
||||
@@ -2606,13 +2474,6 @@ void RoutingManager::OnLinkPrefixManager::DeprecateOldPrefix(const Ip6::Prefix &
|
||||
|
||||
SavePrefix(aPrefix, aExpireTime);
|
||||
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(aPrefix);
|
||||
|
||||
if (removedPrefix.GetLength() != 0)
|
||||
{
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(removedPrefix);
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
@@ -2644,7 +2505,6 @@ void RoutingManager::OnLinkPrefixManager::HandleTimer(void)
|
||||
LogInfo("Local on-link prefix %s expired", mLocalPrefix.ToString().AsCString());
|
||||
IgnoreError(Get<Settings>().RemoveBrOnLinkPrefix(mLocalPrefix));
|
||||
mState = kIdle;
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(mLocalPrefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2670,14 +2530,14 @@ void RoutingManager::OnLinkPrefixManager::HandleTimer(void)
|
||||
LogInfo("Old local on-link prefix %s expired", prefix.ToString().AsCString());
|
||||
IgnoreError(Get<Settings>().RemoveBrOnLinkPrefix(prefix));
|
||||
mOldLocalPrefixes.RemoveMatching(prefix);
|
||||
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(prefix);
|
||||
}
|
||||
|
||||
if (nextExpireTime != now.GetDistantFuture())
|
||||
{
|
||||
mTimer.FireAtIfEarlier(nextExpireTime);
|
||||
}
|
||||
|
||||
Get<RoutingManager>().mRoutePublisher.Evaluate();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2716,6 +2576,188 @@ void RoutingManager::OnMeshPrefixArray::MarkAsDeleted(const OnMeshPrefix &aPrefi
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// RoutePublisher
|
||||
|
||||
const otIp6Prefix RoutingManager::RoutePublisher::kUlaPrefix = {
|
||||
{{{0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
|
||||
7,
|
||||
};
|
||||
|
||||
RoutingManager::RoutePublisher::RoutePublisher(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mState(kDoNotPublish)
|
||||
, mPreference(NetworkData::kRoutePreferenceMedium)
|
||||
, mUserSetPreference(false)
|
||||
{
|
||||
}
|
||||
|
||||
void RoutingManager::RoutePublisher::Evaluate(void)
|
||||
{
|
||||
State newState = kDoNotPublish;
|
||||
|
||||
VerifyOrExit(Get<RoutingManager>().IsRunning());
|
||||
|
||||
if (Get<RoutingManager>().mFavoredOmrPrefix.IsInfrastructureDerived() &&
|
||||
Get<RoutingManager>().mDiscoveredPrefixTable.ContainsDefaultOrNonUlaRoutePrefix())
|
||||
{
|
||||
newState = kPublishDefault;
|
||||
}
|
||||
else if (Get<RoutingManager>().mDiscoveredPrefixTable.ContainsNonUlaOnLinkPrefix())
|
||||
{
|
||||
newState = kPublishDefault;
|
||||
}
|
||||
else if (Get<RoutingManager>().mDiscoveredPrefixTable.ContainsUlaOnLinkPrefix() ||
|
||||
Get<RoutingManager>().mOnLinkPrefixManager.ShouldPublishUlaRoute())
|
||||
{
|
||||
newState = kPublishUla;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (newState != mState)
|
||||
{
|
||||
LogInfo("RoutePublisher state: %s -> %s", StateToString(mState), StateToString(newState));
|
||||
UpdatePublishedRoute(newState);
|
||||
}
|
||||
}
|
||||
|
||||
void RoutingManager::RoutePublisher::DeterminePrefixFor(State aState, Ip6::Prefix &aPrefix) const
|
||||
{
|
||||
aPrefix.Clear();
|
||||
|
||||
switch (aState)
|
||||
{
|
||||
case kDoNotPublish:
|
||||
case kPublishDefault:
|
||||
// `Clear()` will set the prefix `::/0`.
|
||||
break;
|
||||
case kPublishUla:
|
||||
aPrefix = GetUlaPrefix();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RoutingManager::RoutePublisher::UpdatePublishedRoute(State aNewState)
|
||||
{
|
||||
// Updates the published route entry in Network Data, transitioning
|
||||
// from current `mState` to new `aNewState`. This method can be used
|
||||
// when there is no change to `mState` but a change to `mPreference`.
|
||||
|
||||
Ip6::Prefix oldPrefix;
|
||||
NetworkData::ExternalRouteConfig routeConfig;
|
||||
|
||||
DeterminePrefixFor(mState, oldPrefix);
|
||||
|
||||
if (aNewState == kDoNotPublish)
|
||||
{
|
||||
VerifyOrExit(mState != kDoNotPublish);
|
||||
IgnoreError(Get<NetworkData::Publisher>().UnpublishPrefix(oldPrefix));
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
routeConfig.Clear();
|
||||
routeConfig.mPreference = mPreference;
|
||||
routeConfig.mStable = true;
|
||||
DeterminePrefixFor(aNewState, routeConfig.GetPrefix());
|
||||
|
||||
// If we were not publishing a route prefix before, publish the new
|
||||
// `routeConfig`. Otherwise, use `ReplacePublishedExternalRoute()` to
|
||||
// replace the previously published prefix entry. This ensures that we do
|
||||
// not have a situation where the previous route is removed while the new
|
||||
// one is not yet added in the Network Data.
|
||||
|
||||
if (mState == kDoNotPublish)
|
||||
{
|
||||
SuccessOrAssert(Get<NetworkData::Publisher>().PublishExternalRoute(
|
||||
routeConfig, NetworkData::Publisher::kFromRoutingManager));
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrAssert(Get<NetworkData::Publisher>().ReplacePublishedExternalRoute(
|
||||
oldPrefix, routeConfig, NetworkData::Publisher::kFromRoutingManager));
|
||||
}
|
||||
|
||||
exit:
|
||||
mState = aNewState;
|
||||
}
|
||||
|
||||
void RoutingManager::RoutePublisher::Unpublish(void)
|
||||
{
|
||||
// Unpublish the previously published route based on `mState`
|
||||
// and update `mState`.
|
||||
|
||||
Ip6::Prefix prefix;
|
||||
|
||||
VerifyOrExit(mState != kDoNotPublish);
|
||||
DeterminePrefixFor(mState, prefix);
|
||||
IgnoreError(Get<NetworkData::Publisher>().UnpublishPrefix(prefix));
|
||||
mState = kDoNotPublish;
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::RoutePublisher::SetPreference(RoutePreference aPreference)
|
||||
{
|
||||
LogInfo("User explicitly set published route preference to %s", RoutePreferenceToString(aPreference));
|
||||
mUserSetPreference = true;
|
||||
UpdatePreference(aPreference);
|
||||
}
|
||||
|
||||
void RoutingManager::RoutePublisher::ClearPreference(void)
|
||||
{
|
||||
VerifyOrExit(mUserSetPreference);
|
||||
|
||||
LogInfo("User cleared explicitly set published route preference - set based on role");
|
||||
mUserSetPreference = false;
|
||||
SetPreferenceBasedOnRole();
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RoutingManager::RoutePublisher::SetPreferenceBasedOnRole(void)
|
||||
{
|
||||
UpdatePreference(Get<Mle::Mle>().IsRouterOrLeader() ? NetworkData::kRoutePreferenceMedium
|
||||
: NetworkData::kRoutePreferenceLow);
|
||||
}
|
||||
|
||||
void RoutingManager::RoutePublisher::HandleRoleChanged(void)
|
||||
{
|
||||
if (!mUserSetPreference)
|
||||
{
|
||||
SetPreferenceBasedOnRole();
|
||||
}
|
||||
}
|
||||
|
||||
void RoutingManager::RoutePublisher::UpdatePreference(RoutePreference aPreference)
|
||||
{
|
||||
VerifyOrExit(mPreference != aPreference);
|
||||
|
||||
LogInfo("Published route preference changed: %s -> %s", RoutePreferenceToString(mPreference),
|
||||
RoutePreferenceToString(aPreference));
|
||||
mPreference = aPreference;
|
||||
UpdatePublishedRoute(mState);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
const char *RoutingManager::RoutePublisher::StateToString(State aState)
|
||||
{
|
||||
static const char *const kStateStrings[] = {
|
||||
"none", // (0) kDoNotPublish
|
||||
"def-route", // (1) kPublishDefault
|
||||
"ula", // (2) kPublishUla
|
||||
};
|
||||
|
||||
static_assert(0 == kDoNotPublish, "kDoNotPublish value is incorrect");
|
||||
static_assert(1 == kPublishDefault, "kPublishDefault value is incorrect");
|
||||
static_assert(2 == kPublishUla, "kPublishUla value is incorrect");
|
||||
|
||||
return kStateStrings[aState];
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2768,7 +2810,7 @@ void RoutingManager::Nat64PrefixManager::Stop(void)
|
||||
|
||||
if (mPublishedPrefix.IsValidNat64())
|
||||
{
|
||||
Get<RoutingManager>().UnpublishExternalRoute(mPublishedPrefix);
|
||||
IgnoreError(Get<NetworkData::Publisher>().UnpublishPrefix(mPublishedPrefix));
|
||||
}
|
||||
|
||||
mPublishedPrefix.Clear();
|
||||
@@ -2843,18 +2885,15 @@ void RoutingManager::Nat64PrefixManager::Evaluate(void)
|
||||
|
||||
if (mPublishedPrefix.IsValidNat64() && (!shouldPublish || (prefix != mPublishedPrefix)))
|
||||
{
|
||||
Ip6::Prefix prevPrefix;
|
||||
|
||||
prevPrefix = mPublishedPrefix;
|
||||
IgnoreError(Get<NetworkData::Publisher>().UnpublishPrefix(mPublishedPrefix));
|
||||
mPublishedPrefix.Clear();
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(prevPrefix);
|
||||
}
|
||||
|
||||
if (shouldPublish && ((prefix != mPublishedPrefix) || (preference != mPublishedPreference)))
|
||||
{
|
||||
mPublishedPrefix = prefix;
|
||||
mPublishedPreference = preference;
|
||||
Get<RoutingManager>().EvaluatePublishingPrefix(mPublishedPrefix);
|
||||
Publish();
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
@@ -2874,19 +2913,18 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
bool RoutingManager::Nat64PrefixManager::ShouldPublish(NetworkData::ExternalRouteConfig &aRouteConfig) const
|
||||
void RoutingManager::Nat64PrefixManager::Publish(void)
|
||||
{
|
||||
bool shouldPublish = false;
|
||||
NetworkData::ExternalRouteConfig routeConfig;
|
||||
|
||||
VerifyOrExit(mPublishedPrefix.IsValidNat64());
|
||||
VerifyOrExit(mPublishedPrefix == aRouteConfig.GetPrefix());
|
||||
routeConfig.Clear();
|
||||
routeConfig.SetPrefix(mPublishedPrefix);
|
||||
routeConfig.mPreference = mPublishedPreference;
|
||||
routeConfig.mStable = true;
|
||||
routeConfig.mNat64 = true;
|
||||
|
||||
shouldPublish = true;
|
||||
aRouteConfig.mPreference = mPublishedPreference;
|
||||
aRouteConfig.mNat64 = true;
|
||||
|
||||
exit:
|
||||
return shouldPublish;
|
||||
SuccessOrAssert(
|
||||
Get<NetworkData::Publisher>().PublishExternalRoute(routeConfig, NetworkData::Publisher::kFromRoutingManager));
|
||||
}
|
||||
|
||||
void RoutingManager::Nat64PrefixManager::HandleTimer(void)
|
||||
|
||||
@@ -92,14 +92,12 @@ public:
|
||||
* This is used by `NetworkData::Publisher` to reserve entries for use by `RoutingManager`.
|
||||
*
|
||||
* The number of published entries accounts for:
|
||||
* - Max number of discovered prefix entries,
|
||||
* - One entry for local on-link prefixes,
|
||||
* - Max number of old (deprecating) local on-link prefixes,
|
||||
* - Route prefix `fc00::/7` or `::/0`
|
||||
* - One entry for NAT64 published prefix.
|
||||
* - One extra entry for transitions.
|
||||
*
|
||||
*/
|
||||
static constexpr uint16_t kMaxPublishedPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES + 1 +
|
||||
OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_OLD_ON_LINK_PREFIXES + 1;
|
||||
static constexpr uint16_t kMaxPublishedPrefixes = 3;
|
||||
|
||||
/**
|
||||
* This enumeration represents the states of `RoutingManager`.
|
||||
@@ -501,17 +499,15 @@ private:
|
||||
const Ip6::Address &aSrcAddress);
|
||||
void ProcessNeighborAdvertMessage(const Ip6::Nd::NeighborAdvertMessage &aNaMessage);
|
||||
|
||||
void SetAllowDefaultRouteInNetData(bool aAllow);
|
||||
bool ContainsDefaultOrNonUlaRoutePrefix(void) const;
|
||||
bool ContainsNonUlaOnLinkPrefix(void) const;
|
||||
bool ContainsUlaOnLinkPrefix(void) const;
|
||||
|
||||
void FindFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const;
|
||||
bool ContainsOnLinkPrefix(const Ip6::Prefix &aPrefix) const;
|
||||
|
||||
void RemoveOnLinkPrefix(const Ip6::Prefix &aPrefix);
|
||||
|
||||
bool ContainsRoutePrefix(const Ip6::Prefix &aPrefix) const;
|
||||
void RemoveRoutePrefix(const Ip6::Prefix &aPrefix);
|
||||
|
||||
bool ShouldPublish(NetworkData::ExternalRouteConfig &aRouteConfig) const;
|
||||
|
||||
void RemoveAllEntries(void);
|
||||
void RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold);
|
||||
|
||||
@@ -548,7 +544,26 @@ private:
|
||||
}
|
||||
|
||||
const Ip6::Prefix &mPrefix;
|
||||
bool mType;
|
||||
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
|
||||
@@ -566,6 +581,7 @@ private:
|
||||
void SetFrom(const Ip6::Nd::RouteInfoOption &aRio);
|
||||
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; }
|
||||
@@ -575,6 +591,7 @@ private:
|
||||
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()`
|
||||
@@ -642,7 +659,7 @@ private:
|
||||
void ProcessDefaultRoute(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader, Router &aRouter);
|
||||
void ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, Router &aRouter);
|
||||
void ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, Router &aRouter);
|
||||
bool ContainsPrefix(const Entry::Matcher &aMatcher) const;
|
||||
bool Contains(const Entry::Checker &aChecker) const;
|
||||
void RemovePrefix(const Entry::Matcher &aMatcher);
|
||||
void RemoveOrDeprecateEntriesFromInactiveRouters(void);
|
||||
void RemoveRoutersWithNoEntries(void);
|
||||
@@ -665,7 +682,6 @@ private:
|
||||
EntryTimer mEntryTimer;
|
||||
RouterTimer mRouterTimer;
|
||||
SignalTask mSignalTask;
|
||||
bool mAllowDefaultRouteInNetData;
|
||||
};
|
||||
|
||||
class LocalOmrPrefix;
|
||||
@@ -676,6 +692,7 @@ private:
|
||||
OmrPrefix(void) { Clear(); }
|
||||
|
||||
bool IsEmpty(void) const { return (mPrefix.GetLength() == 0); }
|
||||
bool IsInfrastructureDerived(void) const;
|
||||
void SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
|
||||
void SetFrom(const LocalOmrPrefix &aLocalOmrPrefix);
|
||||
const Ip6::Prefix &GetPrefix(void) const { return mPrefix; }
|
||||
@@ -723,7 +740,7 @@ private:
|
||||
const Ip6::Prefix &GetFavoredDiscoveredPrefix(void) const { return mFavoredDiscoveredPrefix; }
|
||||
bool IsInitalEvaluationDone(void) const;
|
||||
void HandleDiscoveredPrefixTableChanged(void);
|
||||
bool ShouldPublish(NetworkData::ExternalRouteConfig &aRouteConfig) const;
|
||||
bool ShouldPublishUlaRoute(void) const;
|
||||
void AppendAsPiosTo(Ip6::Nd::RouterAdvertMessage &aRaMessage);
|
||||
bool IsPublishingOrAdvertising(void) const;
|
||||
void HandleNetDataChange(void);
|
||||
@@ -803,12 +820,12 @@ private:
|
||||
const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; }
|
||||
const Ip6::Prefix &GetFavoredPrefix(RoutePreference &aPreference) const;
|
||||
void Evaluate(void);
|
||||
bool ShouldPublish(NetworkData::ExternalRouteConfig &aRouteConfig) const;
|
||||
void HandleDiscoverDone(const Ip6::Prefix &aPrefix);
|
||||
void HandleTimer(void);
|
||||
|
||||
private:
|
||||
void Discover(void);
|
||||
void Publish(void);
|
||||
|
||||
using Nat64Timer = TimerMilliIn<RoutingManager, &RoutingManager::HandleNat64PrefixManagerTimer>;
|
||||
|
||||
@@ -822,6 +839,46 @@ private:
|
||||
};
|
||||
#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
||||
|
||||
class RoutePublisher : public InstanceLocator // Manages the routes that are published in net data
|
||||
{
|
||||
public:
|
||||
explicit RoutePublisher(Instance &aInstance);
|
||||
|
||||
void Start(void) { Evaluate(); }
|
||||
void Stop(void) { Unpublish(); }
|
||||
void Evaluate(void);
|
||||
|
||||
RoutePreference GetPreference(void) const { return mPreference; }
|
||||
void SetPreference(RoutePreference aPreference);
|
||||
void ClearPreference(void);
|
||||
|
||||
void HandleRoleChanged(void);
|
||||
|
||||
static const Ip6::Prefix &GetUlaPrefix(void) { return AsCoreType(&kUlaPrefix); }
|
||||
|
||||
private:
|
||||
static const otIp6Prefix kUlaPrefix;
|
||||
|
||||
enum State : uint8_t
|
||||
{
|
||||
kDoNotPublish, // Do not publish any routes in network data.
|
||||
kPublishDefault, // Publish "::/0" route in network data.
|
||||
kPublishUla, // Publish "fc00::/7" route in network data.
|
||||
};
|
||||
|
||||
void DeterminePrefixFor(State aState, Ip6::Prefix &aPrefix) const;
|
||||
void UpdatePublishedRoute(State aNewState);
|
||||
void Unpublish(void);
|
||||
void SetPreferenceBasedOnRole(void);
|
||||
void UpdatePreference(RoutePreference aPreference);
|
||||
|
||||
static const char *StateToString(State aState);
|
||||
|
||||
State mState;
|
||||
RoutePreference mPreference;
|
||||
bool mUserSetPreference;
|
||||
};
|
||||
|
||||
struct RaInfo
|
||||
{
|
||||
// Tracks info about emitted RA messages: Number of RAs sent,
|
||||
@@ -895,9 +952,8 @@ private:
|
||||
void EvaluateRoutingPolicy(void);
|
||||
bool IsInitalPolicyEvaluationDone(void) const;
|
||||
void ScheduleRoutingPolicyEvaluation(ScheduleMode aMode);
|
||||
void DetermineFavoredOmrPrefix(void);
|
||||
void EvaluateOmrPrefix(void);
|
||||
void EvaluatePublishingPrefix(const Ip6::Prefix &aPrefix);
|
||||
void UnpublishExternalRoute(const Ip6::Prefix &aPrefix);
|
||||
void HandleRsSenderFinished(TimeMilli aStartTime);
|
||||
void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode);
|
||||
|
||||
@@ -910,7 +966,7 @@ private:
|
||||
bool ShouldProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, const Ip6::Prefix &aPrefix);
|
||||
void UpdateDiscoveredPrefixTableOnNetDataChange(void);
|
||||
bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const;
|
||||
bool NetworkDataContainsExternalRoute(const Ip6::Prefix &aPrefix) const;
|
||||
bool NetworkDataContainsUlaRoute(void) const;
|
||||
void UpdateRouterAdvertHeader(const Ip6::Nd::RouterAdvertMessage *aRouterAdvertMessage);
|
||||
bool IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdvertMessage &aRaMessage) const;
|
||||
void ResetDiscoveredPrefixStaleTimer(void);
|
||||
@@ -949,6 +1005,8 @@ private:
|
||||
|
||||
DiscoveredPrefixTable mDiscoveredPrefixTable;
|
||||
|
||||
RoutePublisher mRoutePublisher;
|
||||
|
||||
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
||||
Nat64PrefixManager mNat64PrefixManager;
|
||||
#endif
|
||||
|
||||
@@ -95,6 +95,13 @@ exit:
|
||||
}
|
||||
|
||||
Error Publisher::PublishExternalRoute(const ExternalRouteConfig &aConfig, Requester aRequester)
|
||||
{
|
||||
return ReplacePublishedExternalRoute(aConfig.GetPrefix(), aConfig, aRequester);
|
||||
}
|
||||
|
||||
Error Publisher::ReplacePublishedExternalRoute(const Ip6::Prefix &aPrefix,
|
||||
const ExternalRouteConfig &aConfig,
|
||||
Requester aRequester)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
PrefixEntry *entry;
|
||||
@@ -102,7 +109,7 @@ Error Publisher::PublishExternalRoute(const ExternalRouteConfig &aConfig, Reques
|
||||
VerifyOrExit(aConfig.IsValid(GetInstance()), error = kErrorInvalidArgs);
|
||||
VerifyOrExit(aConfig.mStable, error = kErrorInvalidArgs);
|
||||
|
||||
entry = FindOrAllocatePrefixEntry(aConfig.GetPrefix(), aRequester);
|
||||
entry = FindOrAllocatePrefixEntry(aPrefix, aRequester);
|
||||
VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
|
||||
|
||||
entry->Publish(aConfig, aRequester);
|
||||
@@ -806,23 +813,24 @@ void Publisher::PrefixEntry::Publish(const Ip6::Prefix &aPrefix,
|
||||
|
||||
if (GetState() != kNoEntry)
|
||||
{
|
||||
// If this is an existing entry, first we check that there is
|
||||
// a change in either type or flags. We remove the old entry
|
||||
// from Network Data if it was added. If the only change is
|
||||
// to flags (e.g., change to the preference level) and the
|
||||
// entry was previously added in Network Data, we re-add it
|
||||
// with the new flags. This ensures that changes to flags are
|
||||
// immediately reflected in the Network Data.
|
||||
// If this is an existing entry, check if there is a change in
|
||||
// type, flags, or the prefix itself. If not, everything is
|
||||
// as before. If something is different, first, remove the
|
||||
// old entry from Network Data if it was added. Then, re-add
|
||||
// the new prefix/flags (replacing the old entry). This
|
||||
// ensures the changes are immediately reflected in the
|
||||
// Network Data.
|
||||
|
||||
State oldState = GetState();
|
||||
|
||||
VerifyOrExit((mType != aNewType) || (mFlags != aNewFlags));
|
||||
VerifyOrExit((mType != aNewType) || (mFlags != aNewFlags) || (mPrefix != aPrefix));
|
||||
|
||||
Remove(/* aNextState */ kNoEntry);
|
||||
|
||||
if ((mType == aNewType) && ((oldState == kAdded) || (oldState == kRemoving)))
|
||||
{
|
||||
mFlags = aNewFlags;
|
||||
mPrefix = aPrefix;
|
||||
mFlags = aNewFlags;
|
||||
Add();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,6 +266,37 @@ public:
|
||||
*/
|
||||
Error PublishExternalRoute(const ExternalRouteConfig &aConfig, Requester aRequester);
|
||||
|
||||
/**
|
||||
* This method replaces a previously published external route.
|
||||
*
|
||||
* Only stable entries can be published (i.e.,`aConfig.mStable` MUST be `true`).
|
||||
*
|
||||
* If there is no previously published external route matching @p aPrefix, this method behaves similarly to
|
||||
* `PublishExternalRoute()`, i.e., it will start the process of publishing @a aConfig as an external route in the
|
||||
* Thread Network Data.
|
||||
*
|
||||
* If there is a previously published route entry matching @p aPrefix, it will be replaced with the new prefix from
|
||||
* @p aConfig. In particular, if the @p aPrefix was already added in the Network Data, the change to the new prefix
|
||||
* in @p aConfig is immediately reflected in the Network Data (i.e., @p aPrefix is removed and the new prefix is
|
||||
* added in the same Network Data registration request to leader). This ensures that route entries in the Network
|
||||
* Data are not abruptly removed and the transition from @p aPrefix to new prefix is smooth.
|
||||
*
|
||||
* @param[in] aPrefix The previously published external route prefix to replace.
|
||||
* @param[in] aConfig The external route config to publish.
|
||||
* @param[in] aRequester The requester (`kFromUser` or `kFromRoutingManager` module).
|
||||
*
|
||||
* @retval kErrorNone The external route is published successfully.
|
||||
* @retval kErrorInvalidArgs The @p aConfig is not valid (bad prefix, invalid flag combinations, or not stable).
|
||||
* @retval kErrorNoBufs Could not allocate an entry for the new request. Publisher supports a limited number
|
||||
* of entries (shared between on-mesh prefix and external route) determined by config
|
||||
* `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_MAX_PREFIX_ENTRIES`.
|
||||
*
|
||||
*
|
||||
*/
|
||||
Error ReplacePublishedExternalRoute(const Ip6::Prefix &aPrefix,
|
||||
const ExternalRouteConfig &aConfig,
|
||||
Requester aRequester);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not currently a published prefix entry (on-mesh or external route) is added to
|
||||
* the Thread Network Data.
|
||||
|
||||
@@ -108,8 +108,7 @@ class ManualMulticastAddressConfig(thread_cert.TestCase):
|
||||
# packet back to Host.
|
||||
# TD receives the MPL packet containing an encapsulated ping packet to
|
||||
# MA1, sent by Host, and unicasts a ping response packet back to Host.
|
||||
pkts.filter_eth_src(vars['TD_ETH']) \
|
||||
.filter_ipv6_dst(_pkt.ipv6.src) \
|
||||
pkts.filter_ipv6_dst(_pkt.ipv6.src) \
|
||||
.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier) \
|
||||
.must_next()
|
||||
|
||||
|
||||
@@ -147,8 +147,6 @@ class MultiBorderRouters(thread_cert.TestCase):
|
||||
self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 2)
|
||||
|
||||
br1_on_link_prefix = br1.get_br_on_link_prefix()
|
||||
self.assertEqual(br1_on_link_prefix, br1.get_netdata_non_nat64_prefixes()[0])
|
||||
self.assertEqual(br1_on_link_prefix, br1.get_netdata_non_nat64_prefixes()[0])
|
||||
|
||||
self.assertEqual(len(br1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
self.assertEqual(len(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
@@ -200,8 +198,6 @@ class MultiBorderRouters(thread_cert.TestCase):
|
||||
self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 1)
|
||||
|
||||
br2_on_link_prefix = br2.get_br_on_link_prefix()
|
||||
self.assertEqual(set(map(IPv6Network, br2.get_netdata_non_nat64_prefixes())),
|
||||
set(map(IPv6Network, [br1_on_link_prefix, br2_on_link_prefix])))
|
||||
|
||||
self.assertEqual(len(br1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
self.assertEqual(len(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
|
||||
@@ -130,10 +130,10 @@ class MultiThreadNetworks(thread_cert.TestCase):
|
||||
|
||||
# Each BR should independently register an external route for the on-link prefix
|
||||
# and OMR prefix in another Thread Network.
|
||||
self.assertTrue(len(br1.get_netdata_non_nat64_prefixes()) == 2)
|
||||
self.assertTrue(len(router1.get_netdata_non_nat64_prefixes()) == 2)
|
||||
self.assertTrue(len(br2.get_netdata_non_nat64_prefixes()) == 2)
|
||||
self.assertTrue(len(router2.get_netdata_non_nat64_prefixes()) == 2)
|
||||
self.assertTrue(len(br1.get_netdata_non_nat64_prefixes()) == 1)
|
||||
self.assertTrue(len(router1.get_netdata_non_nat64_prefixes()) == 1)
|
||||
self.assertTrue(len(br2.get_netdata_non_nat64_prefixes()) == 1)
|
||||
self.assertTrue(len(router2.get_netdata_non_nat64_prefixes()) == 1)
|
||||
|
||||
br1_external_routes = br1.get_routes()
|
||||
br2_external_routes = br2.get_routes()
|
||||
|
||||
@@ -127,10 +127,8 @@ class MultiThreadNetworks(thread_cert.TestCase):
|
||||
logging.info("HOST addrs: %r", host.get_addrs())
|
||||
|
||||
self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 1)
|
||||
on_link_prefix = br1.get_netdata_non_nat64_prefixes()[0]
|
||||
self.assertEqual(IPv6Network(on_link_prefix), IPv6Network(ON_LINK_PREFIX))
|
||||
|
||||
host_on_link_addr = host.get_matched_ula_addresses(on_link_prefix)[0]
|
||||
host_on_link_addr = host.get_matched_ula_addresses(ON_LINK_PREFIX)[0]
|
||||
self.assertTrue(router1.ping(host_on_link_addr))
|
||||
self.assertTrue(
|
||||
host.ping(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], backbone=True, interface=host_on_link_addr))
|
||||
@@ -164,18 +162,16 @@ class MultiThreadNetworks(thread_cert.TestCase):
|
||||
br2_omr_prefix = br2.get_br_omr_prefix()
|
||||
self.assertNotEqual(br1_omr_prefix, br2_omr_prefix)
|
||||
|
||||
# Verify that the Border Routers starts advertsing new on-link prefix
|
||||
# Verify that the Border Routers starts advertising new on-link prefix
|
||||
# but don't remove the external routes for the radvd on-link prefix
|
||||
# immediately, because the SLAAC addresses are still valid.
|
||||
self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 3)
|
||||
self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 3)
|
||||
self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 2)
|
||||
self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 2)
|
||||
|
||||
on_link_prefixes = list(
|
||||
set(br1.get_netdata_non_nat64_prefixes()).intersection(br2.get_netdata_non_nat64_prefixes()))
|
||||
self.assertEqual(len(on_link_prefixes), 1)
|
||||
self.assertEqual(IPv6Network(on_link_prefixes[0]), IPv6Network(br2.get_br_on_link_prefix()))
|
||||
self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 1)
|
||||
self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 1)
|
||||
self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 1)
|
||||
self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 1)
|
||||
|
||||
br2_on_link_prefix = br2.get_br_on_link_prefix()
|
||||
|
||||
router1_omr_addr = router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
|
||||
router2_omr_addr = router2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
|
||||
@@ -184,7 +180,7 @@ class MultiThreadNetworks(thread_cert.TestCase):
|
||||
# and preferred Border Router on-link prefix can be reached by Thread
|
||||
# devices in network of Border Router 1.
|
||||
for host_on_link_addr in [
|
||||
host.get_matched_ula_addresses(on_link_prefixes[0])[0],
|
||||
host.get_matched_ula_addresses(br2_on_link_prefix)[0],
|
||||
host.get_matched_ula_addresses(ON_LINK_PREFIX)[0]
|
||||
]:
|
||||
self.assertTrue(router1.ping(host_on_link_addr))
|
||||
@@ -192,11 +188,6 @@ class MultiThreadNetworks(thread_cert.TestCase):
|
||||
|
||||
host_on_link_addr = host.get_matched_ula_addresses(ON_LINK_PREFIX)[0]
|
||||
|
||||
# Make sure that addresses of the deprecated radvd `ON_LINK_PREFIX`
|
||||
# can't be reached by Thread devices in network of Border Router 2.
|
||||
self.assertFalse(router2.ping(host_on_link_addr))
|
||||
self.assertFalse(host.ping(router2_omr_addr, backbone=True, interface=host_on_link_addr))
|
||||
|
||||
# Wait 30 seconds for the radvd `ON_LINK_PREFIX` to be invalidated
|
||||
# and make sure that Thread devices in both networks can't reach
|
||||
# the on-link address.
|
||||
|
||||
@@ -177,8 +177,6 @@ class SingleBorderRouter(thread_cert.TestCase):
|
||||
# The same local OMR and on-link prefix should be re-register.
|
||||
self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix])
|
||||
self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix])
|
||||
self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix])
|
||||
self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix])
|
||||
|
||||
self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
@@ -231,8 +229,6 @@ class SingleBorderRouter(thread_cert.TestCase):
|
||||
# The same local OMR and on-link prefix should be re-registered.
|
||||
self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix])
|
||||
self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix])
|
||||
self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix])
|
||||
self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix])
|
||||
|
||||
self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
@@ -285,8 +281,6 @@ class SingleBorderRouter(thread_cert.TestCase):
|
||||
# The same local OMR and on-link prefix should be re-registered.
|
||||
self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix])
|
||||
self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix])
|
||||
self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix])
|
||||
self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix])
|
||||
|
||||
self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
|
||||
@@ -320,8 +314,8 @@ class SingleBorderRouter(thread_cert.TestCase):
|
||||
br.start_radvd_service(prefix=config.ONLINK_GUA_PREFIX, slaac=True)
|
||||
self.simulator.go(5)
|
||||
|
||||
self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 2)
|
||||
self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 2)
|
||||
self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1)
|
||||
self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1)
|
||||
|
||||
self.assertTrue(router.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_GUA)[0]))
|
||||
self.assertTrue(router.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
|
||||
|
||||
+337
-256
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user