diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 8563c1fb4..be0d6a4ec 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -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().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().PublishExternalRoute( - routeConfig, NetworkData::Publisher::kFromRoutingManager)); - } - else - { - UnpublishExternalRoute(aPrefix); - } - -exit: - return; -} - -void RoutingManager::UnpublishExternalRoute(const Ip6::Prefix &aPrefix) -{ - VerifyOrExit(mIsRunning); - IgnoreError(Get().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().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().EvaluatePublishingPrefix(entry->GetPrefix()); SignalTableChanged(); @@ -1358,7 +1294,6 @@ void RoutingManager::DiscoveredPrefixTable::ProcessPrefixInfoOption(const Ip6::N } mEntryTimer.FireAtIfEarlier(entry->GetExpireTime()); - Get().EvaluatePublishingPrefix(entry->GetPrefix()); SignalTableChanged(); @@ -1402,7 +1337,6 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouteInfoOption(const Ip6::Nd } mEntryTimer.FireAtIfEarlier(entry->GetExpireTime()); - Get().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().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().EvaluatePublishingPrefix(aMatcher.mPrefix); - SignalTableChanged(); exit: @@ -1523,7 +1443,6 @@ void RoutingManager::DiscoveredPrefixTable::RemoveAllEntries(void) while ((entry = router.mEntries.Pop()) != nullptr) { - Get().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().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().EvaluatePublishingPrefix(mLocalPrefix); - - for (const OldPrefix &oldPrefix : mOldLocalPrefixes) - { - Get().EvaluatePublishingPrefix(oldPrefix.mPrefix); - } -} +void RoutingManager::OnLinkPrefixManager::Start(void) {} void RoutingManager::OnLinkPrefixManager::Stop(void) { mFavoredDiscoveredPrefix.Clear(); - for (const OldPrefix &oldPrefix : mOldLocalPrefixes) - { - Get().UnpublishExternalRoute(oldPrefix.mPrefix); - } - switch (mState) { case kIdle: @@ -2255,7 +2144,6 @@ void RoutingManager::OnLinkPrefixManager::Stop(void) case kPublishing: case kAdvertising: case kDeprecating: - Get().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().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().NetworkDataContainsExternalRoute(mLocalPrefix)) + if (Get().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().NetworkDataContainsExternalRoute(mLocalPrefix)) + if (Get().NetworkDataContainsUlaRoute()) { EnterAdvertisingState(); Get().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().EvaluatePublishingPrefix(oldPrefix); break; case kAdvertising: @@ -2558,6 +2425,7 @@ void RoutingManager::OnLinkPrefixManager::HandleExtPanIdChange(void) if (Get().mIsRunning) { + Get().mRoutePublisher.Evaluate(); Get().ScheduleRoutingPolicyEvaluation(kAfterRandomDelay); } @@ -2606,13 +2474,6 @@ void RoutingManager::OnLinkPrefixManager::DeprecateOldPrefix(const Ip6::Prefix & SavePrefix(aPrefix, aExpireTime); - Get().EvaluatePublishingPrefix(aPrefix); - - if (removedPrefix.GetLength() != 0) - { - Get().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().RemoveBrOnLinkPrefix(mLocalPrefix)); mState = kIdle; - Get().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().RemoveBrOnLinkPrefix(prefix)); mOldLocalPrefixes.RemoveMatching(prefix); - - Get().EvaluatePublishingPrefix(prefix); } if (nextExpireTime != now.GetDistantFuture()) { mTimer.FireAtIfEarlier(nextExpireTime); } + + Get().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().IsRunning()); + + if (Get().mFavoredOmrPrefix.IsInfrastructureDerived() && + Get().mDiscoveredPrefixTable.ContainsDefaultOrNonUlaRoutePrefix()) + { + newState = kPublishDefault; + } + else if (Get().mDiscoveredPrefixTable.ContainsNonUlaOnLinkPrefix()) + { + newState = kPublishDefault; + } + else if (Get().mDiscoveredPrefixTable.ContainsUlaOnLinkPrefix() || + Get().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().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().PublishExternalRoute( + routeConfig, NetworkData::Publisher::kFromRoutingManager)); + } + else + { + SuccessOrAssert(Get().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().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().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().UnpublishExternalRoute(mPublishedPrefix); + IgnoreError(Get().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().UnpublishPrefix(mPublishedPrefix)); mPublishedPrefix.Clear(); - Get().EvaluatePublishingPrefix(prevPrefix); } if (shouldPublish && ((prefix != mPublishedPrefix) || (preference != mPublishedPreference))) { mPublishedPrefix = prefix; mPublishedPreference = preference; - Get().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().PublishExternalRoute(routeConfig, NetworkData::Publisher::kFromRoutingManager)); } void RoutingManager::Nat64PrefixManager::HandleTimer(void) diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index 1e365f2c5..5e3fe9d3c 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -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; @@ -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 diff --git a/src/core/thread/network_data_publisher.cpp b/src/core/thread/network_data_publisher.cpp index 22c31d9e5..056765cb9 100644 --- a/src/core/thread/network_data_publisher.cpp +++ b/src/core/thread/network_data_publisher.cpp @@ -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(); } } diff --git a/src/core/thread/network_data_publisher.hpp b/src/core/thread/network_data_publisher.hpp index d042311e7..025462d5a 100644 --- a/src/core/thread/network_data_publisher.hpp +++ b/src/core/thread/network_data_publisher.hpp @@ -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. diff --git a/tests/scripts/thread-cert/border_router/test_manual_maddress.py b/tests/scripts/thread-cert/border_router/test_manual_maddress.py index 1bbe19007..536d3adca 100644 --- a/tests/scripts/thread-cert/border_router/test_manual_maddress.py +++ b/tests/scripts/thread-cert/border_router/test_manual_maddress.py @@ -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() diff --git a/tests/scripts/thread-cert/border_router/test_multi_border_routers.py b/tests/scripts/thread-cert/border_router/test_multi_border_routers.py index 2e5855b59..ab354d171 100755 --- a/tests/scripts/thread-cert/border_router/test_multi_border_routers.py +++ b/tests/scripts/thread-cert/border_router/test_multi_border_routers.py @@ -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) diff --git a/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py b/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py index d7ebc8066..bc2bb38a8 100755 --- a/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py +++ b/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py @@ -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() diff --git a/tests/scripts/thread-cert/border_router/test_on_link_prefix.py b/tests/scripts/thread-cert/border_router/test_on_link_prefix.py index 4ff831ac4..406723623 100755 --- a/tests/scripts/thread-cert/border_router/test_on_link_prefix.py +++ b/tests/scripts/thread-cert/border_router/test_on_link_prefix.py @@ -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. diff --git a/tests/scripts/thread-cert/border_router/test_single_border_router.py b/tests/scripts/thread-cert/border_router/test_single_border_router.py index 1028629df..a660345fc 100755 --- a/tests/scripts/thread-cert/border_router/test_single_border_router.py +++ b/tests/scripts/thread-cert/border_router/test_single_border_router.py @@ -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])) diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp index a463c1328..9692b4ae8 100644 --- a/tests/unit/test_routing_manager.cpp +++ b/tests/unit/test_routing_manager.cpp @@ -550,60 +550,43 @@ void VerifyNoOmrPrefixInNetData(void) using NetworkData::RoutePreference; -struct ExternalRoute +enum ExternalRouteMode : uint8_t { - ExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aPreference) - : mPrefix(aPrefix) - , mPreference(aPreference) - { - } - - const Ip6::Prefix &mPrefix; - RoutePreference mPreference; + kNoRoute, + kDefaultRoute, + kUlaRoute, }; -template void VerifyExternalRoutesInNetData(const ExternalRoute (&aExternRoutes)[kLength]) +void VerifyExternalRouteInNetData(ExternalRouteMode aMode) { - otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; - NetworkData::ExternalRouteConfig routeConfig; - uint16_t counter; + Error error; + otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; + otExternalRouteConfig routeConfig; - Log("VerifyExternalRoutesInNetData()"); + error = otNetDataGetNextRoute(sInstance, &iterator, &routeConfig); - counter = 0; - - while (otNetDataGetNextRoute(sInstance, &iterator, &routeConfig) == kErrorNone) + switch (aMode) { - bool didFind = false; + case kNoRoute: + Log("VerifyExternalRouteInNetData(kNoRoute)"); + VerifyOrQuit(error != kErrorNone); + break; - counter++; + case kDefaultRoute: + Log("VerifyExternalRouteInNetData(kDefaultRoute)"); + VerifyOrQuit(error == kErrorNone); + VerifyOrQuit(routeConfig.mPrefix.mLength == 0); + VerifyOrQuit(otNetDataGetNextRoute(sInstance, &iterator, &routeConfig) != kErrorNone); + break; - Log(" prefix:%s, prf:%s", routeConfig.GetPrefix().ToString().AsCString(), - PreferenceToString(routeConfig.mPreference)); - - for (const ExternalRoute &externalRoute : aExternRoutes) - { - if (externalRoute.mPrefix == routeConfig.GetPrefix()) - { - VerifyOrQuit(static_cast(routeConfig.mPreference) == externalRoute.mPreference); - didFind = true; - break; - } - } - - VerifyOrQuit(didFind); + case kUlaRoute: + Log("VerifyExternalRouteInNetData(kUlaRoute)"); + VerifyOrQuit(error == kErrorNone); + VerifyOrQuit(routeConfig.mPrefix.mLength == 7); + VerifyOrQuit(routeConfig.mPrefix.mPrefix.mFields.m8[0] == 0xfc); + VerifyOrQuit(otNetDataGetNextRoute(sInstance, &iterator, &routeConfig) != kErrorNone); + break; } - - VerifyOrQuit(counter == kLength); -} - -void VerifyNoExternalRouteInNetData(void) -{ - otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; - NetworkData::ExternalRouteConfig routeConfig; - - Log("VerifyNoExternalRouteInNetData()"); - VerifyOrQuit(otNetDataGetNextRoute(sInstance, &iterator, &routeConfig) != kErrorNone); } struct Pio @@ -749,6 +732,11 @@ template void VerifyPrefixTable(const OnLinkPrefix VerifyPrefixTable(aOnLinkPrefixes, kNumOnLinkPrefixes, nullptr, 0); } +template void VerifyPrefixTable(const RoutePrefix (&aRoutePrefixes)[kNumRoutePrefixes]) +{ + VerifyPrefixTable(nullptr, 0, aRoutePrefixes, kNumRoutePrefixes); +} + void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes, uint16_t aNumOnLinkPrefixes, const RoutePrefix *aRoutePrefixes, @@ -820,6 +808,8 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes, VerifyOrQuit(routePrefixCount == aNumRoutePrefixes); } +void VerifyPrefixTableIsEmpty(void) { VerifyPrefixTable(nullptr, 0, nullptr, 0); } + void InitTest(bool aEnablBorderRouting = false, bool aAfterReset = false) { //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -917,7 +907,7 @@ void TestSamePrefixesFromMultipleRouters(void) // Check Network Data to include the local OMR and on-link prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A with a new on-link (PIO) and route prefix (RIO). @@ -945,9 +935,7 @@ void TestSamePrefixesFromMultipleRouters(void) // Check Network Data to include new prefixes from router A. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send the same RA again from router A with the on-link (PIO) and route prefix (RIO). @@ -982,14 +970,7 @@ void TestSamePrefixesFromMultipleRouters(void) // Check Network Data. VerifyOmrPrefixInNetData(localOmr); - - // We expect to see 3 entries, our local on link and new prefixes - // from router A and B. The `routePrefix` now should have high - // preference. - - VerifyExternalRoutesInNetData({ExternalRoute(routePrefix, NetworkData::kRoutePreferenceHigh), - ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router B removing the route prefix. @@ -1006,11 +987,9 @@ void TestSamePrefixesFromMultipleRouters(void) {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data, all prefixes should be again at medium preference. + // Check Network Data. - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1060,7 +1039,7 @@ void TestOmrSelection(void) // Check Network Data to include the local OMR and on-link prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Add a new OMR prefix directly into net data. The new prefix should @@ -1098,8 +1077,7 @@ void TestOmrSelection(void) // is removed. VerifyOmrPrefixInNetData(omrPrefix); - - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Remove the OMR prefix previously added in net data. @@ -1126,8 +1104,7 @@ void TestOmrSelection(void) // added again. VerifyOmrPrefixInNetData(localOmr); - - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1139,12 +1116,9 @@ void TestDefaultRoute(void) { Ip6::Prefix localOnLink; Ip6::Prefix localOmr; - Ip6::Prefix onLinkPrefix = PrefixFromString("2000:abba:baba::", 64); - Ip6::Prefix routePrefix = PrefixFromString("2000:1234:5678::", 64); Ip6::Prefix omrPrefix = PrefixFromString("2000:0000:1111:4444::", 64); Ip6::Prefix defaultRoute = PrefixFromString("::", 0); Ip6::Address routerAddressA = AddressFromString("fd00::aaaa"); - Ip6::Address routerAddressB = AddressFromString("fd00::bbbb"); NetworkData::OnMeshPrefixConfig prefixConfig; Log("--------------------------------------------------------------------------------------------"); @@ -1153,53 +1127,60 @@ void TestDefaultRoute(void) InitTest(); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Start Routing Manager + // Start Routing Manager. Check emitted RS and RA messages. + + sRsEmitted = false; + sRaValidated = false; + sExpectedPio = kPioAdvertisingLocalOnLink; + sExpectedRios.Clear(); SuccessOrQuit(sInstance->Get().SetEnabled(true)); SuccessOrQuit(sInstance->Get().GetOnLinkPrefix(localOnLink)); SuccessOrQuit(sInstance->Get().GetOmrPrefix(localOmr)); - AdvanceTime(500); - Log("Local on-link prefix is %s", localOnLink.ToString().AsCString()); Log("Local OMR prefix is %s", localOmr.ToString().AsCString()); + sExpectedRios.Add(localOmr); + + AdvanceTime(30000); + + VerifyOrQuit(sRsEmitted); + VerifyOrQuit(sRaValidated); + VerifyOrQuit(sExpectedRios.SawAll()); + Log("Received RA was validated"); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A and B adding an onlink prefix - // and routePrefix from A, and a default route from B. + // Check Network Data to include the local OMR and ULA prefix. - SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)}, - {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)}); + VerifyOmrPrefixInNetData(localOmr); + VerifyExternalRouteInNetData(kUlaRoute); - SendRouterAdvert(routerAddressB, DefaultRoute(kValidLitime, NetworkData::kRoutePreferenceLow)); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Send RA from router A advertising a default route. - sRsEmitted = false; - sRaValidated = false; - sExpectedPio = kNoPio; - sExpectedRios.Clear(); + SendRouterAdvert(routerAddressA, DefaultRoute(kValidLitime, NetworkData::kRoutePreferenceLow)); AdvanceTime(10000); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check the discovered prefix table and ensure info from router B - // is now included in the table. + // Check the discovered prefix table and ensure default route + // from router A is in the table. - VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)}, - {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA), - RoutePrefix(defaultRoute, kValidLitime, NetworkData::kRoutePreferenceLow, routerAddressB)}); + VerifyPrefixTable({RoutePrefix(defaultRoute, kValidLitime, NetworkData::kRoutePreferenceLow, routerAddressA)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data. We should not see default route in - // Network Data yet (since there is no OMR prefix with default - // route flag). + // Network Data yet since there is no infrastructure-derived + // OMR prefix (with preference medium or higher). - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyOmrPrefixInNetData(localOmr); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Add an OMR prefix directly into Network Data with default route - // flag. + // Add an OMR prefix directly into Network Data with + // preference medium (infrastructure-derived). prefixConfig.Clear(); prefixConfig.mPrefix = omrPrefix; @@ -1207,7 +1188,7 @@ void TestDefaultRoute(void) prefixConfig.mSlaac = true; prefixConfig.mPreferred = true; prefixConfig.mOnMesh = true; - prefixConfig.mDefaultRoute = true; + prefixConfig.mDefaultRoute = false; prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium; SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig)); @@ -1216,42 +1197,14 @@ void TestDefaultRoute(void) AdvanceTime(10000); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data. We should now see default route from - // router B. + // Check Network Data. Now that we have an infrastructure-derived + // OMR prefix, the default route should be published. - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(defaultRoute, NetworkData::kRoutePreferenceLow)}); + VerifyOmrPrefixInNetData(omrPrefix); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router B adding a default route - // now also as ::/0 prefix RIO with a high preference. - - SendRouterAdvert(routerAddressB, {Rio(defaultRoute, kValidLitime, NetworkData::kRoutePreferenceHigh)}, - DefaultRoute(kValidLitime, NetworkData::kRoutePreferenceLow)); - - AdvanceTime(10000); - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check the discovered prefix table and ensure default route - // entry from router B is now correctly updated to use high - // preference (RIO overrides the default route info from header). - - VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)}, - {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA), - RoutePrefix(defaultRoute, kValidLitime, NetworkData::kRoutePreferenceHigh, routerAddressB)}); - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data. We should now see default route from - // router B included with high preference. - - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(defaultRoute, NetworkData::kRoutePreferenceHigh)}); - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Remove the OMR prefix previously added with default route - // flag. + // Remove the OMR prefix from Network Data. SuccessOrQuit(otBorderRouterRemoveOnMeshPrefix(sInstance, &omrPrefix)); SuccessOrQuit(otBorderRouterRegister(sInstance)); @@ -1259,14 +1212,136 @@ void TestDefaultRoute(void) AdvanceTime(10000); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data. The default route ::/0 should be now - // removed since the OMR prefix with default route is removed. + // Check Network Data. We should again go back to ULA prefix. The + // default route advertised by router A should be still present in + // the discovered prefix table. - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyOmrPrefixInNetData(localOmr); + VerifyExternalRouteInNetData(kUlaRoute); + + VerifyPrefixTable({RoutePrefix(defaultRoute, kValidLitime, NetworkData::kRoutePreferenceLow, routerAddressA)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Re-add the OMR prefix with default route flag. + // Add the OMR prefix again. + + SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig)); + SuccessOrQuit(otBorderRouterRegister(sInstance)); + + AdvanceTime(10000); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check Network Data. Again the default route should be published. + + VerifyOmrPrefixInNetData(omrPrefix); + VerifyExternalRouteInNetData(kDefaultRoute); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Send RA from router A removing the default route. + + SendRouterAdvert(routerAddressA, DefaultRoute(0, NetworkData::kRoutePreferenceLow)); + + AdvanceTime(10000); + + VerifyPrefixTableIsEmpty(); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check Network Data. Now that router A no longer advertised + // a default-route, we should go back to publishing ULA route. + + VerifyOmrPrefixInNetData(omrPrefix); + VerifyExternalRouteInNetData(kUlaRoute); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Send RA from router A again advertising a default route. + + SendRouterAdvert(routerAddressA, DefaultRoute(kValidLitime, NetworkData::kRoutePreferenceLow)); + + AdvanceTime(10000); + + VerifyPrefixTable({RoutePrefix(defaultRoute, kValidLitime, NetworkData::kRoutePreferenceLow, routerAddressA)}); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check Network Data. We should see default route published. + + VerifyOmrPrefixInNetData(omrPrefix); + VerifyExternalRouteInNetData(kDefaultRoute); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Log("End of TestDefaultRoute"); + + FinalizeTest(); +} + +void TestAdvNonUlaRoute(void) +{ + Ip6::Prefix localOnLink; + Ip6::Prefix localOmr; + Ip6::Prefix omrPrefix = PrefixFromString("2000:0000:1111:4444::", 64); + Ip6::Prefix routePrefix = PrefixFromString("2000:1234:5678::", 64); + Ip6::Address routerAddressA = AddressFromString("fd00::aaaa"); + NetworkData::OnMeshPrefixConfig prefixConfig; + + Log("--------------------------------------------------------------------------------------------"); + Log("TestAdvNonUlaRoute"); + + InitTest(); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Start Routing Manager. Check emitted RS and RA messages. + + sRsEmitted = false; + sRaValidated = false; + sExpectedPio = kPioAdvertisingLocalOnLink; + sExpectedRios.Clear(); + + SuccessOrQuit(sInstance->Get().SetEnabled(true)); + + SuccessOrQuit(sInstance->Get().GetOnLinkPrefix(localOnLink)); + SuccessOrQuit(sInstance->Get().GetOmrPrefix(localOmr)); + + Log("Local on-link prefix is %s", localOnLink.ToString().AsCString()); + Log("Local OMR prefix is %s", localOmr.ToString().AsCString()); + + sExpectedRios.Add(localOmr); + + AdvanceTime(30000); + + VerifyOrQuit(sRsEmitted); + VerifyOrQuit(sRaValidated); + VerifyOrQuit(sExpectedRios.SawAll()); + Log("Received RA was validated"); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check Network Data to include the local OMR and ULA prefix. + + VerifyOmrPrefixInNetData(localOmr); + VerifyExternalRouteInNetData(kUlaRoute); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Send RA from router A advertising a non-ULA. + + SendRouterAdvert(routerAddressA, {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)}); + + AdvanceTime(10000); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check the discovered prefix table and ensure the non-ULA + // from router A is in the table. + + VerifyPrefixTable({RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)}); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check Network Data. We should not see default route in + // Network Data yet since there is no infrastructure-derived + // OMR prefix (with preference medium or higher). + + VerifyOmrPrefixInNetData(localOmr); + VerifyExternalRouteInNetData(kUlaRoute); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Add an OMR prefix directly into Network Data with + // preference medium (infrastructure-derived). prefixConfig.Clear(); prefixConfig.mPrefix = omrPrefix; @@ -1274,7 +1349,7 @@ void TestDefaultRoute(void) prefixConfig.mSlaac = true; prefixConfig.mPreferred = true; prefixConfig.mOnMesh = true; - prefixConfig.mDefaultRoute = true; + prefixConfig.mDefaultRoute = false; prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium; SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig)); @@ -1283,38 +1358,78 @@ void TestDefaultRoute(void) AdvanceTime(10000); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data. We should again see the default route from - // router B included with high preference. + // Check Network Data. Now that we have an infrastructure-derived + // OMR prefix, the default route should be published. - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(defaultRoute, NetworkData::kRoutePreferenceHigh)}); + VerifyOmrPrefixInNetData(omrPrefix); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router B removing default route - // in both header and in RIO. + // Remove the OMR prefix from Network Data. + + SuccessOrQuit(otBorderRouterRemoveOnMeshPrefix(sInstance, &omrPrefix)); + SuccessOrQuit(otBorderRouterRegister(sInstance)); - SendRouterAdvert(routerAddressB, {Rio(defaultRoute, 0, NetworkData::kRoutePreferenceHigh)}, - DefaultRoute(0, NetworkData::kRoutePreferenceMedium)); AdvanceTime(10000); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check the discovered prefix table and ensure default route - // entry from router B is no longer present. + // Check Network Data. We should again go back to ULA prefix. The + // non-ULA route advertised by router A should be still present in + // the discovered prefix table. - VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)}, - {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)}); + VerifyOmrPrefixInNetData(localOmr); + VerifyExternalRouteInNetData(kUlaRoute); + + VerifyPrefixTable({RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data. The default route ::/0 should be now - // removed since router B stopped advertising it. + // Add the OMR prefix again. - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium), - ExternalRoute(routePrefix, NetworkData::kRoutePreferenceMedium)}); + SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig)); + SuccessOrQuit(otBorderRouterRegister(sInstance)); + + AdvanceTime(10000); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check Network Data. Again the default route should be published. + + VerifyOmrPrefixInNetData(omrPrefix); + VerifyExternalRouteInNetData(kDefaultRoute); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Send RA from router A removing the route. + + SendRouterAdvert(routerAddressA, {Rio(routePrefix, 0, NetworkData::kRoutePreferenceMedium)}); + + AdvanceTime(10000); + + VerifyPrefixTableIsEmpty(); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check Network Data. Now that router A no longer advertised + // the route, we should go back to publishing the ULA route. + + VerifyOmrPrefixInNetData(omrPrefix); + VerifyExternalRouteInNetData(kUlaRoute); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Send RA from router A again advertising the route again. + + SendRouterAdvert(routerAddressA, {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)}); + + AdvanceTime(10000); + + VerifyPrefixTable({RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)}); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Check Network Data. We should see default route published. + + VerifyOmrPrefixInNetData(omrPrefix); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Log("End of TestDefaultRoute"); + Log("End of TestAdvNonUlaRoute"); FinalizeTest(); } @@ -1325,7 +1440,7 @@ void TestLocalOnLinkPrefixDeprecation(void) Ip6::Prefix localOnLink; Ip6::Prefix localOmr; - Ip6::Prefix onLinkPrefix = PrefixFromString("2000:abba:baba::", 64); + Ip6::Prefix onLinkPrefix = PrefixFromString("fd00:abba:baba::", 64); Ip6::Address routerAddressA = AddressFromString("fd00::aaaa"); uint32_t localOnLinkLifetime; @@ -1363,7 +1478,7 @@ void TestLocalOnLinkPrefixDeprecation(void) // Check Network Data to include the local OMR and on-link prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A with a new on-link (PIO) which is preferred over @@ -1391,8 +1506,7 @@ void TestLocalOnLinkPrefixDeprecation(void) // along with the deprecating local on-link prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Wait for local on-link prefix to expire @@ -1407,8 +1521,7 @@ void TestLocalOnLinkPrefixDeprecation(void) // see the deprecating local on-link prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); // Keep checking the emitted RAs and make sure on-link prefix // is included with smaller lifetime every time. @@ -1443,11 +1556,10 @@ void TestLocalOnLinkPrefixDeprecation(void) Log("On-link prefix is now expired"); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data and make sure the the expired local on-link prefix - // is removed. + // Check Network Data. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1498,7 +1610,7 @@ void TestDomainPrefixAsOmr(void) // Check Network Data to include the local OMR and on-link prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Add a domain prefix directly into net data. The new prefix should @@ -1567,7 +1679,7 @@ void TestDomainPrefixAsOmr(void) // is removed. VerifyOmrPrefixInNetData(domainPrefix); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Remove the domain prefix from net data. @@ -1594,7 +1706,7 @@ void TestDomainPrefixAsOmr(void) // added again. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1690,12 +1802,10 @@ void TestExtPanIdChange(void) oldPrefixLifetime = sDeprecatingPrefixes[0].mLifetime; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Validate the Network Data to contain both the current and old - // local on-link prefixes. + // Validate Network Data. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Stop BR and validate that a final RA is emitted deprecating @@ -1717,7 +1827,7 @@ void TestExtPanIdChange(void) VerifyOrQuit(!sRaValidated); VerifyNoOmrPrefixInNetData(); - VerifyNoExternalRouteInNetData(); + VerifyExternalRouteInNetData(kNoRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Start BR again and validate old prefix will continue to @@ -1740,11 +1850,9 @@ void TestExtPanIdChange(void) while (oldPrefixLifetime > 2 * kMaxRaTxInterval) { - // Ensure Network Data entries remain as before. Mainly we still - // see the deprecating local on-link prefix. + // Ensure Network Data entries remain as before. - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); // Keep checking the emitted RAs and make sure the prefix // is included with smaller lifetime every time. @@ -1766,18 +1874,17 @@ void TestExtPanIdChange(void) sRaValidated = false; - AdvanceTime(2 * kMaxRaTxInterval * 1000); + AdvanceTime(3 * kMaxRaTxInterval * 1000); VerifyOrQuit(sRaValidated); VerifyOrQuit(sDeprecatingPrefixes.IsEmpty()); Log("Old on-link prefix is now expired"); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Validate the Network Data now only contains the current local - // on-link prefix. + // Validate the Network Data. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Check behavior when ext PAN ID changes while the local on-link is being @@ -1827,12 +1934,10 @@ void TestExtPanIdChange(void) VerifyOrQuit(sDeprecatingPrefixes[0].mPrefix == oldLocalOnLink); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Validate that Network Data contains the old local on-link - // prefix along with entry from router A. + // Validate that Network Data. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Wait for old local on-link prefix to expire. @@ -1843,11 +1948,9 @@ void TestExtPanIdChange(void) SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)}); - // Ensure Network Data entries remain as before. Mainly we still - // see the deprecating old local on-link prefix. + // Ensure Network Data entries remain as before. - VerifyExternalRoutesInNetData({ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); // Keep checking the emitted RAs and make sure the prefix // is included with smaller lifetime every time. @@ -1868,19 +1971,24 @@ void TestExtPanIdChange(void) // longer be seen in the emitted RA message. SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)}); + sRaValidated = false; - AdvanceTime(2 * kMaxRaTxInterval * 1000); + AdvanceTime(kMaxRaTxInterval * 1000); + SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)}); + AdvanceTime(kMaxRaTxInterval * 1000); + SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)}); + AdvanceTime(kMaxRaTxInterval * 1000); VerifyOrQuit(sRaValidated); VerifyOrQuit(sDeprecatingPrefixes.IsEmpty()); Log("Old on-link prefix is now expired"); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Validate the Network Data to now only contains entry from router A. + // Validate the Network Data. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Check behavior when ext PAN ID changes while the local on-link is not @@ -1906,10 +2014,10 @@ void TestExtPanIdChange(void) VerifyOrQuit(sDeprecatingPrefixes.IsEmpty()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Validate the Network Data to now only contains entry from router A. + // Validate the Network Data. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Remove the on-link prefix PIO being advertised by router A @@ -1926,11 +2034,11 @@ void TestExtPanIdChange(void) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Wait for longer than valid lifetime of PIO entry from router A. - // Validate that it is unpublished from network data. + // Validate that default route is unpublished from network data. AdvanceTime(2000 * 1000); VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Multiple PAN ID changes and multiple deprecating old prefixes. @@ -1949,8 +2057,7 @@ void TestExtPanIdChange(void) VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1); VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[0])); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[0], NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Change the prefix again. We should see two deprecating prefixes. @@ -1970,9 +2077,7 @@ void TestExtPanIdChange(void) VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[0])); VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[1])); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[0], NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[1], NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Wait for 15 minutes and then change ext PAN ID again. @@ -1996,10 +2101,7 @@ void TestExtPanIdChange(void) VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[1])); VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[2])); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[0], NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[1], NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[2], NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Change ext PAN ID back to previous value of `kExtPanId1`. @@ -2023,10 +2125,7 @@ void TestExtPanIdChange(void) VerifyOrQuit(oldPrefixes[2] == localOnLink); VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[3])); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[0], NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[1], NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[3], NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Stop BR and validate the final emitted RA to contain @@ -2045,7 +2144,7 @@ void TestExtPanIdChange(void) VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[3])); VerifyNoOmrPrefixInNetData(); - VerifyNoExternalRouteInNetData(); + VerifyExternalRouteInNetData(kNoRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Wait for 15 minutes while BR stays disabled and validate @@ -2058,7 +2157,7 @@ void TestExtPanIdChange(void) VerifyOrQuit(!sRaValidated); VerifyNoOmrPrefixInNetData(); - VerifyNoExternalRouteInNetData(); + VerifyExternalRouteInNetData(kNoRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Start BR again, and check that we only see the last deprecating prefix @@ -2076,8 +2175,7 @@ void TestExtPanIdChange(void) VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1); VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[3])); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[3], NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Validate the oldest prefix is removed when we have too many @@ -2112,10 +2210,7 @@ void TestExtPanIdChange(void) VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[2])); VerifyOrQuit(!sDeprecatingPrefixes.ContainsMatching(oldLocalOnLink)); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[0], NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[1], NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldPrefixes[2], NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2317,7 +2412,7 @@ void TestConflictingPrefix(void) // Check Network Data to include the local OMR and on-link prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A with our local on-link prefix as RIO. @@ -2333,10 +2428,10 @@ void TestConflictingPrefix(void) VerifyOrQuit(sRaValidated); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data to still include the local OMR and on-link prefix. + // Check Network Data to still include the local OMR and ULA prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A removing local on-link prefix as RIO. @@ -2344,11 +2439,11 @@ void TestConflictingPrefix(void) SendRouterAdvert(routerAddressA, {Rio(localOnLink, 0, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Verify that on-link prefix is still included in Network Data and + // Verify that ULA prefix is still included in Network Data and // the change by router A did not cause it to be unpublished. AdvanceTime(10000); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check that the local on-link prefix is still being advertised. @@ -2357,7 +2452,7 @@ void TestConflictingPrefix(void) AdvanceTime(610000); VerifyOrQuit(sRaValidated); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send RA from router B advertising an on-link prefix. This @@ -2377,12 +2472,11 @@ void TestConflictingPrefix(void) Log("On-link prefix is deprecating, remaining lifetime:%d", sOnLinkLifetime); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data to include the new on-link prefix from router B and - // the deprecating local on-link prefix. + // Check Network Data to include the default route now due + // the new on-link prefix from router B. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A again adding local on-link prefix as RIO. @@ -2400,8 +2494,7 @@ void TestConflictingPrefix(void) //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data remains unchanged. - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A removing the previous RIO. @@ -2409,12 +2502,10 @@ void TestConflictingPrefix(void) SendRouterAdvert(routerAddressA, {Rio(localOnLink, 0, NetworkData::kRoutePreferenceMedium)}); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data remains unchanged and still contains - // the deprecating local on-link prefix. + // Check Network Data remains unchanged. AdvanceTime(60000); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send RA from router B removing its on-link prefix. @@ -2431,10 +2522,9 @@ void TestConflictingPrefix(void) VerifyOrQuit(sRaValidated); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data still contains both prefixes. + // Check Network Data to remain unchanged. - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Change the extended PAN ID. @@ -2456,12 +2546,10 @@ void TestConflictingPrefix(void) oldLocalOnLink.ToString().AsCString()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data contains old and new local on-link prefix - // and deprecating prefix from router B. + // Check Network Data contains default route due to the + // deprecating on-link prefix from router B. - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A again adding the old local on-link prefix @@ -2473,9 +2561,7 @@ void TestConflictingPrefix(void) // Check Network Data remains unchanged. AdvanceTime(10000); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send an RA from router A removing the previous RIO. @@ -2486,9 +2572,7 @@ void TestConflictingPrefix(void) // Check Network Data remains unchanged. AdvanceTime(10000); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2537,10 +2621,10 @@ void TestSavedOnLinkPrefixes(void) VerifyOrQuit(sExpectedRios.SawAll()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data to include the local OMR and on-link prefix. + // Check Network Data to include the local OMR and ULA prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Disable the instance and re-enable it. @@ -2562,10 +2646,10 @@ void TestSavedOnLinkPrefixes(void) VerifyOrQuit(sExpectedRios.SawAll()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data to include the local OMR and on-link prefix. + // Check Network Data to include the local OMR and ULA prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Send RA from router A advertising an on-link prefix. @@ -2598,10 +2682,10 @@ void TestSavedOnLinkPrefixes(void) VerifyOrQuit(sExpectedRios.SawAll()); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data to include the local OMR and on-link prefix. + // Check Network Data to include the local OMR and ULA prefix. VerifyOmrPrefixInNetData(localOmr); - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kUlaRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2659,12 +2743,10 @@ void TestSavedOnLinkPrefixes(void) VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check the saved prefixes are in netdata and being - // deprecated. + // Check Network Data to now use default route due to the + // on-link prefix from router A. - VerifyExternalRoutesInNetData({ExternalRoute(localOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(oldLocalOnLink, NetworkData::kRoutePreferenceMedium), - ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Wait for more than 1800 seconds to let the deprecating @@ -2676,7 +2758,7 @@ void TestSavedOnLinkPrefixes(void) AdvanceTime(10 * 1000); } - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Disable the instance and re-enable it and restart Routing Manager. @@ -2703,11 +2785,9 @@ void TestSavedOnLinkPrefixes(void) VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 0); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check that previously saved on-link prefixes are no longer - // seen in Network Data (indicating that they were removed from - // `Settings`). + // Check Network Data still contains the default route. - VerifyExternalRoutesInNetData({ExternalRoute(onLinkPrefix, NetworkData::kRoutePreferenceMedium)}); + VerifyExternalRouteInNetData(kDefaultRoute); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2931,6 +3011,7 @@ int main(void) TestSamePrefixesFromMultipleRouters(); TestOmrSelection(); TestDefaultRoute(); + TestAdvNonUlaRoute(); TestLocalOnLinkPrefixDeprecation(); #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE TestDomainPrefixAsOmr();