diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index e981af508..cb81f9d7c 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -72,8 +72,7 @@ RoutingManager::RoutingManager(Instance &aInstance) , mIsEnabled(false) , mInfraIf(aInstance) , mOmrPrefixManager(aInstance) - , mRioPreference(NetworkData::kRoutePreferenceLow) - , mUserSetRioPreference(false) + , mRioAdvertiser(aInstance) , mOnLinkPrefixManager(aInstance) , mDiscoveredPrefixTable(aInstance) , mRoutePublisher(aInstance) @@ -153,45 +152,6 @@ exit: return state; } -void RoutingManager::SetRouteInfoOptionPreference(RoutePreference aPreference) -{ - LogInfo("User explicitly set RIO Preference to %s", RoutePreferenceToString(aPreference)); - mUserSetRioPreference = true; - UpdateRioPreference(aPreference); -} - -void RoutingManager::ClearRouteInfoOptionPreference(void) -{ - VerifyOrExit(mUserSetRioPreference); - - LogInfo("User cleared explicitly set RIO Preference"); - mUserSetRioPreference = false; - SetRioPreferenceBasedOnRole(); - -exit: - return; -} - -void RoutingManager::SetRioPreferenceBasedOnRole(void) -{ - UpdateRioPreference(Get().IsRouterOrLeader() ? NetworkData::kRoutePreferenceMedium - : NetworkData::kRoutePreferenceLow); -} - -void RoutingManager::UpdateRioPreference(RoutePreference aPreference) -{ - VerifyOrExit(mRioPreference != aPreference); - - LogInfo("RIO Preference changed: %s -> %s", RoutePreferenceToString(mRioPreference), - RoutePreferenceToString(aPreference)); - mRioPreference = aPreference; - - ScheduleRoutingPolicyEvaluation(kAfterRandomDelay); - -exit: - return; -} - Error RoutingManager::GetOmrPrefix(Ip6::Prefix &aPrefix) const { Error error = kErrorNone; @@ -377,12 +337,6 @@ void RoutingManager::Stop(void) SendRouterAdvertisement(kInvalidateAllPrevPrefixes); -#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE - mAdvertisedPrefixes.Free(); -#else - mAdvertisedPrefixes.Clear(); -#endif - mDiscoveredPrefixTable.RemoveAllEntries(); mDiscoveredPrefixStaleTimer.Stop(); @@ -457,9 +411,9 @@ exit: void RoutingManager::HandleNotifierEvents(Events aEvents) { - if (aEvents.Contains(kEventThreadRoleChanged) && !mUserSetRioPreference) + if (aEvents.Contains(kEventThreadRoleChanged)) { - SetRioPreferenceBasedOnRole(); + mRioAdvertiser.HandleRoleChanged(); } mRoutePublisher.HandleNotifierEvents(aEvents); @@ -620,19 +574,18 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode) // - One RA Flags Extensions Option (with stub router flag). // - One PIO for current local on-link prefix. // - At most `kMaxOldPrefixes` for old deprecating on-link prefixes. - // - At most twice `kMaxOnMeshPrefixes` RIO for on-mesh prefixes. - // Factor two is used for RIO to account for entries invalidating - // previous prefixes while adding new ones. + // - At most 3 times `kMaxOnMeshPrefixes` RIO for on-mesh prefixes. + // Factor three is used for RIOs to account for any new prefix + // with older prefixes entries being deprecated and prefixes + // being invalidated. static constexpr uint16_t kMaxRaLength = sizeof(Ip6::Nd::RouterAdvertMessage::Header) + sizeof(Ip6::Nd::RaFlagsExtOption) + sizeof(Ip6::Nd::PrefixInfoOption) + sizeof(Ip6::Nd::PrefixInfoOption) * OnLinkPrefixManager::kMaxOldPrefixes + - 2 * kMaxOnMeshPrefixes * (sizeof(Ip6::Nd::RouteInfoOption) + sizeof(Ip6::Prefix)); + 3 * kMaxOnMeshPrefixes * (sizeof(Ip6::Nd::RouteInfoOption) + sizeof(Ip6::Prefix)); - uint8_t buffer[kMaxRaLength]; - Ip6::Nd::RouterAdvertMessage raMsg(mRaInfo.mHeader, buffer); - NetworkData::Iterator iterator; - NetworkData::OnMeshPrefixConfig prefixConfig; + uint8_t buffer[kMaxRaLength]; + Ip6::Nd::RouterAdvertMessage raMsg(mRaInfo.mHeader, buffer); LogInfo("Preparing RA"); @@ -653,119 +606,13 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode) mOnLinkPrefixManager.AppendAsPiosTo(raMsg); - // Determine which previously advertised prefixes need to be - // invalidated. Under `kInvalidateAllPrevPrefixes` mode we need - // to invalidate all. Under `kAdvPrefixesFromNetData` mode, we - // check Network Data entries and invalidate any previously - // advertised prefix that is no longer present in the Network - // Data. We go through all Network Data prefixes and mark the - // ones we find in `mAdvertisedPrefixes` as deleted by setting - // the prefix length to zero). By the end, the remaining entries - // in the array with a non-zero prefix length are invalidated. - - if (aRaTxMode != kInvalidateAllPrevPrefixes) + if (aRaTxMode == kInvalidateAllPrevPrefixes) { - iterator = NetworkData::kIteratorInit; - - while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone) - { - if (!prefixConfig.mOnMesh || prefixConfig.mDp || - (prefixConfig.GetPrefix() == mOmrPrefixManager.GetLocalPrefix().GetPrefix())) - { - continue; - } - - mAdvertisedPrefixes.MarkAsDeleted(prefixConfig.GetPrefix()); - } - - if (mOmrPrefixManager.IsLocalAddedInNetData()) - { - mAdvertisedPrefixes.MarkAsDeleted(mOmrPrefixManager.GetLocalPrefix().GetPrefix()); - } + mRioAdvertiser.InvalidatPrevRios(raMsg); } - - for (const OnMeshPrefix &prefix : mAdvertisedPrefixes) + else { - if (prefix.GetLength() != 0) - { - SuccessOrAssert(raMsg.AppendRouteInfoOption(prefix, /* aRouteLifetime */ 0, mRioPreference)); - LogRouteInfoOption(prefix, 0, mRioPreference); - } - } - - // Discover and add prefixes from Network Data to advertise as - // RIO in the Router Advertisement message. - - mAdvertisedPrefixes.Clear(); - - if (aRaTxMode == kAdvPrefixesFromNetData) - { - // `mAdvertisedPrefixes` array has a limited size. We add more - // important prefixes first in the array to ensure they are - // advertised in the RA message. Note that `Add()` method - // will ensure to add a prefix only once (will check if - // prefix is already present in the array). - - // (1) Local OMR prefix. - - if (mOmrPrefixManager.IsLocalAddedInNetData()) - { - mAdvertisedPrefixes.Add(mOmrPrefixManager.GetLocalPrefix().GetPrefix()); - } - - // (2) Favored OMR prefix. - - if (!mOmrPrefixManager.GetFavoredPrefix().IsEmpty() && !mOmrPrefixManager.GetFavoredPrefix().IsDomainPrefix()) - { - mAdvertisedPrefixes.Add(mOmrPrefixManager.GetFavoredPrefix().GetPrefix()); - } - - // (3) All other OMR prefixes. - - iterator = NetworkData::kIteratorInit; - - while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone) - { - // Local OMR prefix is added to the array depending on - // `mOmrPrefixManager.IsLocalAddedInNetData()` at step (1). - // As we iterate through the Network Data prefixes, we skip - // over entries matching the local OMR prefix. This - // ensures that we stop including it in emitted RA - // message as soon as we decide to remove it from Network - // Data. Note that upon requesting it to be removed from - // Network Data the change needs to be registered with - // leader and can take some time to be updated in Network - // Data. - - if (prefixConfig.mDp) - { - continue; - } - - if (IsValidOmrPrefix(prefixConfig) && - (prefixConfig.GetPrefix() != mOmrPrefixManager.GetLocalPrefix().GetPrefix())) - { - mAdvertisedPrefixes.Add(prefixConfig.GetPrefix()); - } - } - - // (4) All other on-mesh prefixes (excluding Domain Prefix). - - iterator = NetworkData::kIteratorInit; - - while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone) - { - if (prefixConfig.mOnMesh && !prefixConfig.mDp && !IsValidOmrPrefix(prefixConfig)) - { - mAdvertisedPrefixes.Add(prefixConfig.GetPrefix()); - } - } - - for (const OnMeshPrefix &prefix : mAdvertisedPrefixes) - { - SuccessOrAssert(raMsg.AppendRouteInfoOption(prefix, kDefaultOmrPrefixLifetime, mRioPreference)); - LogRouteInfoOption(prefix, kDefaultOmrPrefixLifetime, mRioPreference); - } + mRioAdvertiser.AppendRios(raMsg); } if (raMsg.ContainsAnyOptions()) @@ -831,9 +678,9 @@ bool RoutingManager::IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdve case Ip6::Nd::Option::kTypeRouteInfo: { // RIO (with non-zero lifetime) should match entries from - // `mAdvertisedPrefixes`. We keep track of the number - // of matched RIOs and check after the loop ends that all - // entries were seen. + // `mRioAdvertiser`. We keep track of the number of matched + // RIOs and check after the loop ends that all entries were + // seen. const Ip6::Nd::RouteInfoOption &rio = static_cast(option); @@ -842,7 +689,7 @@ bool RoutingManager::IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdve if (rio.GetRouteLifetime() != 0) { - VerifyOrExit(mAdvertisedPrefixes.Contains(prefix)); + VerifyOrExit(mRioAdvertiser.HasAdvertised(prefix)); rioCount++; } @@ -854,7 +701,7 @@ bool RoutingManager::IsReceivedRouterAdvertFromManager(const Ip6::Nd::RouterAdve } } - VerifyOrExit(rioCount == mAdvertisedPrefixes.GetLength()); + VerifyOrExit(rioCount == mRioAdvertiser.GetAdvertisedRioCount()); isFromManager = true; @@ -1023,16 +870,16 @@ bool RoutingManager::ShouldProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption VerifyOrExit(mOmrPrefixManager.GetLocalPrefix().GetPrefix() != aPrefix); // Ignore OMR prefixes advertised by ourselves or in current Thread Network Data. - // The `mAdvertisedPrefixes` and the OMR prefix set in Network Data should eventually + // The `RioAdvertiser` prefixes and the OMR prefix set in Network Data should eventually // be equal, but there is time that they are not synchronized immediately: - // 1. Network Data could contain more OMR prefixes than `mAdvertisedPrefixes` because + // 1. Network Data could contain more OMR prefixes than `RioAdvertiser` because // we added random delay before Evaluating routing policy when Network Data is changed. - // 2. `mAdvertisedPrefixes` could contain more OMR prefixes than Network Data because + // 2. `RioAdvertiser` prefixes could contain more OMR prefixes than Network Data because // it takes time to sync a new OMR prefix into Network Data (multicast loopback RA // messages are usually faster than Thread Network Data propagation). // They are the reasons why we need both the checks. - VerifyOrExit(!mAdvertisedPrefixes.Contains(aPrefix)); + VerifyOrExit(!mRioAdvertiser.HasAdvertised(aPrefix)); VerifyOrExit(!Get().NetworkDataContainsOmrPrefix(aPrefix)); shouldProcess = true; @@ -2878,18 +2725,235 @@ const char *RoutingManager::OnLinkPrefixManager::StateToString(State aState) } //--------------------------------------------------------------------------------------------------------------------- -// OnMeshPrefixArray +// RioAdvertiser -void RoutingManager::OnMeshPrefixArray::Add(const OnMeshPrefix &aPrefix) +RoutingManager::RioAdvertiser::RioAdvertiser(Instance &aInstance) + : InstanceLocator(aInstance) + , mTimer(aInstance) + , mPreference(NetworkData::kRoutePreferenceLow) + , mUserSetPreference(false) +{ +} + +void RoutingManager::RioAdvertiser::SetPreference(RoutePreference aPreference) +{ + LogInfo("User explicitly set RIO Preference to %s", RoutePreferenceToString(aPreference)); + mUserSetPreference = true; + UpdatePreference(aPreference); +} + +void RoutingManager::RioAdvertiser::ClearPreference(void) +{ + VerifyOrExit(mUserSetPreference); + + LogInfo("User cleared explicitly set RIO Preference"); + mUserSetPreference = false; + SetPreferenceBasedOnRole(); + +exit: + return; +} + +void RoutingManager::RioAdvertiser::HandleRoleChanged(void) +{ + if (!mUserSetPreference) + { + SetPreferenceBasedOnRole(); + } +} + +void RoutingManager::RioAdvertiser::SetPreferenceBasedOnRole(void) +{ + UpdatePreference(Get().IsRouterOrLeader() ? NetworkData::kRoutePreferenceMedium + : NetworkData::kRoutePreferenceLow); +} + +void RoutingManager::RioAdvertiser::UpdatePreference(RoutePreference aPreference) +{ + VerifyOrExit(mPreference != aPreference); + + LogInfo("RIO Preference changed: %s -> %s", RoutePreferenceToString(mPreference), + RoutePreferenceToString(aPreference)); + mPreference = aPreference; + + Get().ScheduleRoutingPolicyEvaluation(kAfterRandomDelay); + +exit: + return; +} + +void RoutingManager::RioAdvertiser::InvalidatPrevRios(Ip6::Nd::RouterAdvertMessage &aRaMessage) +{ + for (const RioPrefix &prefix : mPrefixes) + { + AppendRio(prefix.mPrefix, /* aRouteLifetime */ 0, aRaMessage); + } + +#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE + mPrefixes.Free(); +#endif + + mPrefixes.Clear(); + mTimer.Stop(); +} + +void RoutingManager::RioAdvertiser::AppendRios(Ip6::Nd::RouterAdvertMessage &aRaMessage) +{ + TimeMilli now = TimerMilli::GetNow(); + TimeMilli nextTime = now.GetDistantFuture(); + RioPrefixArray oldPrefixes; + NetworkData::Iterator iterator = NetworkData::kIteratorInit; + NetworkData::OnMeshPrefixConfig prefixConfig; + const OmrPrefixManager &omrPrefixManager = Get().mOmrPrefixManager; + +#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE + oldPrefixes.TakeFrom(static_cast(mPrefixes)); +#else + oldPrefixes = mPrefixes; +#endif + + mPrefixes.Clear(); + + // `mPrefixes` array can have a limited size. We add more + // important prefixes first in the array to ensure they are + // advertised in the RA message. Note that `Add()` method + // will ensure to add a prefix only once (will check if + // prefix is already present in the array). + + // (1) Local OMR prefix. + + if (omrPrefixManager.IsLocalAddedInNetData()) + { + mPrefixes.Add(omrPrefixManager.GetLocalPrefix().GetPrefix()); + } + + // (2) Favored OMR prefix. + + if (!omrPrefixManager.GetFavoredPrefix().IsEmpty() && !omrPrefixManager.GetFavoredPrefix().IsDomainPrefix()) + { + mPrefixes.Add(omrPrefixManager.GetFavoredPrefix().GetPrefix()); + } + + // (3) All other OMR prefixes. + + iterator = NetworkData::kIteratorInit; + + while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone) + { + // Local OMR prefix is added to the array depending on + // `omrPrefixManager.IsLocalAddedInNetData()` at step (1). + // As we iterate through the Network Data prefixes, we skip + // over entries matching the local OMR prefix. This + // ensures that we start deprecating it in emitted RA + // message as soon as we decide to remove it from Network + // Data. Note that upon requesting it to be removed from + // Network Data the change needs to be registered with + // leader and can take some time to be updated in Network + // Data. + + if (prefixConfig.mDp) + { + continue; + } + + if (IsValidOmrPrefix(prefixConfig) && + (prefixConfig.GetPrefix() != omrPrefixManager.GetLocalPrefix().GetPrefix())) + { + mPrefixes.Add(prefixConfig.GetPrefix()); + } + } + + // (4) All other on-mesh prefixes (excluding Domain Prefix). + + iterator = NetworkData::kIteratorInit; + + while (Get().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone) + { + if (prefixConfig.mOnMesh && !prefixConfig.mDp && !IsValidOmrPrefix(prefixConfig)) + { + mPrefixes.Add(prefixConfig.GetPrefix()); + } + } + + // Determine deprecating prefixes + + for (RioPrefix &prefix : oldPrefixes) + { + if (mPrefixes.ContainsMatching(prefix.mPrefix)) + { + continue; + } + + if (prefix.mIsDeprecating) + { + if (now >= prefix.mExpirationTime) + { + AppendRio(prefix.mPrefix, /* aRouteLifetime */ 0, aRaMessage); + continue; + } + } + else + { + prefix.mIsDeprecating = true; + prefix.mExpirationTime = now + kDeprecationTime; + } + + if (mPrefixes.PushBack(prefix) != kErrorNone) + { + LogWarn("Too many deprecating on-mesh prefixes, removing %s", prefix.mPrefix.ToString().AsCString()); + AppendRio(prefix.mPrefix, /* aRouteLifetime */ 0, aRaMessage); + } + + nextTime = Min(nextTime, prefix.mExpirationTime); + } + + // Advertise all prefixes in `mPrefixes` + + for (const RioPrefix &prefix : mPrefixes) + { + uint32_t lifetime = kDefaultOmrPrefixLifetime; + + if (prefix.mIsDeprecating) + { + lifetime = TimeMilli::MsecToSec(prefix.mExpirationTime - now); + } + + AppendRio(prefix.mPrefix, lifetime, aRaMessage); + } + + if (nextTime != now.GetDistantFuture()) + { + mTimer.FireAtIfEarlier(nextTime); + } +} + +void RoutingManager::RioAdvertiser::AppendRio(const Ip6::Prefix &aPrefix, + uint32_t aRouteLifetime, + Ip6::Nd::RouterAdvertMessage &aRaMessage) +{ + SuccessOrAssert(aRaMessage.AppendRouteInfoOption(aPrefix, aRouteLifetime, mPreference)); + LogRouteInfoOption(aPrefix, aRouteLifetime, mPreference); +} + +void RoutingManager::RioAdvertiser::HandleTimer(void) +{ + Get().ScheduleRoutingPolicyEvaluation(kImmediately); +} + +void RoutingManager::RioAdvertiser::RioPrefixArray::Add(const Ip6::Prefix &aPrefix) { // Checks if `aPrefix` is already present in the array and if not - // adds it as new entry. + // adds it as a new entry. - Error error; + Error error; + RioPrefix newEntry; - VerifyOrExit(!Contains(aPrefix)); + VerifyOrExit(!ContainsMatching(aPrefix)); - error = PushBack(aPrefix); + newEntry.Clear(); + newEntry.mPrefix = aPrefix; + + error = PushBack(newEntry); if (error != kErrorNone) { @@ -2900,19 +2964,6 @@ exit: return; } -void RoutingManager::OnMeshPrefixArray::MarkAsDeleted(const OnMeshPrefix &aPrefix) -{ - // Searches for a matching entry to `aPrefix` and if found marks - // it as deleted by setting prefix length to zero. - - OnMeshPrefix *entry = Find(aPrefix); - - if (entry != nullptr) - { - entry->SetLength(0); - } -} - //--------------------------------------------------------------------------------------------------------------------- // RoutePublisher diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index 95a86f0e0..4f1511c26 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -209,7 +209,7 @@ public: * @returns The current Route Info Option preference. * */ - RoutePreference GetRouteInfoOptionPreference(void) const { return mRioPreference; } + RoutePreference GetRouteInfoOptionPreference(void) const { return mRioAdvertiser.GetPreference(); } /** * Explicitly sets the preference to use when advertising Route Info Options (RIO) in Router @@ -221,7 +221,7 @@ public: * @param[in] aPreference The route preference to use. * */ - void SetRouteInfoOptionPreference(RoutePreference aPreference); + void SetRouteInfoOptionPreference(RoutePreference aPreference) { mRioAdvertiser.SetPreference(aPreference); } /** * Clears a previously set preference value for advertised Route Info Options. @@ -230,7 +230,7 @@ public: * in router/leader role and low preference when in child role. * */ - void ClearRouteInfoOptionPreference(void); + void ClearRouteInfoOptionPreference(void) { mRioAdvertiser.ClearPreference(); } /** * Gets the current preference used for published routes in Network Data. @@ -997,18 +997,60 @@ private: ExpireTimer mTimer; }; - typedef Ip6::Prefix OnMeshPrefix; + void HandleRioAdvertiserimer(void) { mRioAdvertiser.HandleTimer(); } - class OnMeshPrefixArray : -#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE - public Heap::Array -#else - public Array -#endif + class RioAdvertiser : public InstanceLocator { + // Manages the list of prefixes advertised as RIO in emitted + // RA. The RIO prefixes are discovered from on-mesh prefixes in + // network data including OMR prefix from `OmrPrefixManager`. + // It also handles deprecating removed prefixes. + public: - void Add(const OnMeshPrefix &aPrefix); - void MarkAsDeleted(const OnMeshPrefix &aPrefix); + explicit RioAdvertiser(Instance &aInstance); + + RoutePreference GetPreference(void) const { return mPreference; } + void SetPreference(RoutePreference aPreference); + void ClearPreference(void); + void HandleRoleChanged(void); + void AppendRios(Ip6::Nd::RouterAdvertMessage &aRaMessage); + void InvalidatPrevRios(Ip6::Nd::RouterAdvertMessage &aRaMessage); + bool HasAdvertised(const Ip6::Prefix &aPrefix) const { return mPrefixes.ContainsMatching(aPrefix); } + uint16_t GetAdvertisedRioCount(void) const { return mPrefixes.GetLength(); } + void HandleTimer(void); + + private: + static constexpr uint32_t kDeprecationTime = TimeMilli::SecToMsec(300); + + struct RioPrefix : public Clearable + { + bool Matches(const Ip6::Prefix &aPrefix) const { return (mPrefix == aPrefix); } + + Ip6::Prefix mPrefix; + bool mIsDeprecating; + TimeMilli mExpirationTime; + }; + + struct RioPrefixArray : +#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE + public Heap::Array +#else + public Array +#endif + { + void Add(const Ip6::Prefix &aPrefix); + }; + + void SetPreferenceBasedOnRole(void); + void UpdatePreference(RoutePreference aPreference); + void AppendRio(const Ip6::Prefix &aPrefix, uint32_t aRouteLifetime, Ip6::Nd::RouterAdvertMessage &aRaMessage); + + using RioTimer = TimerMilliIn; + + RioPrefixArray mPrefixes; + RioTimer mTimer; + RoutePreference mPreference; + bool mUserSetPreference; }; #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE @@ -1227,8 +1269,6 @@ private: void HandleNotifierEvents(Events aEvents); bool IsInitialized(void) const { return mInfraIf.IsInitialized(); } bool IsEnabled(void) const { return mIsEnabled; } - void SetRioPreferenceBasedOnRole(void); - void UpdateRioPreference(RoutePreference aPreference); Error LoadOrGenerateRandomBrUlaPrefix(void); void EvaluateRoutingPolicy(void); @@ -1276,10 +1316,7 @@ private: OmrPrefixManager mOmrPrefixManager; - // List of on-mesh prefixes (discovered from Network Data) which - // were advertised as RIO in the last sent RA message. - OnMeshPrefixArray mAdvertisedPrefixes; - + RioAdvertiser mRioAdvertiser; RoutePreference mRioPreference; bool mUserSetRioPreference; diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp index ef2a53bf1..39659c430 100644 --- a/tests/unit/test_routing_manager.cpp +++ b/tests/unit/test_routing_manager.cpp @@ -58,6 +58,9 @@ static const char kInfraIfAddress[] = "fe80::1"; static constexpr uint32_t kValidLitime = 2000; static constexpr uint32_t kPreferredLifetime = 1800; +static constexpr uint32_t kRioValidLifetime = 1800; +static constexpr uint32_t kRioDeprecatingLifetime = 300; + static constexpr uint16_t kMaxRaSize = 800; static constexpr uint16_t kMaxDeprecatingPrefixes = 16; @@ -1382,6 +1385,8 @@ void TestOmrSelection(void) VerifyOrQuit(sRsEmitted); VerifyOrQuit(sRaValidated); VerifyOrQuit(sExpectedRios.SawAll()); + VerifyOrQuit(sExpectedRios[0].mLifetime == kRioValidLifetime); + Log("Received RA was validated"); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1409,17 +1414,20 @@ void TestOmrSelection(void) AdvanceTime(100); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Make sure BR emits RA with new OMR prefix now. + // Make sure BR emits RA with the new OMR prefix now, and deprecates the old OMR prefix. sRaValidated = false; sExpectedPio = kPioAdvertisingLocalOnLink; sExpectedRios.Clear(); sExpectedRios.Add(omrPrefix); + sExpectedRios.Add(localOmr); AdvanceTime(20000); VerifyOrQuit(sRaValidated); VerifyOrQuit(sExpectedRios.SawAll()); + VerifyOrQuit(sExpectedRios[0].mLifetime == kRioValidLifetime); + VerifyOrQuit(sExpectedRios[1].mLifetime <= kRioDeprecatingLifetime); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data. We should now see that the local OMR prefix @@ -1437,16 +1445,20 @@ void TestOmrSelection(void) AdvanceTime(100); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Make sure BR emits RA with local OMR prefix again. + // Make sure BR emits RA with local OMR prefix again and start + // deprecating the previously added OMR prefix. sRaValidated = false; sExpectedRios.Clear(); + sExpectedRios.Add(omrPrefix); sExpectedRios.Add(localOmr); AdvanceTime(20000); VerifyOrQuit(sRaValidated); VerifyOrQuit(sExpectedRios.SawAll()); + VerifyOrQuit(sExpectedRios[0].mLifetime <= kRioDeprecatingLifetime); + VerifyOrQuit(sExpectedRios[1].mLifetime == kRioValidLifetime); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Check Network Data. We should see that the local OMR prefix is @@ -1455,6 +1467,21 @@ void TestOmrSelection(void) VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false); VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Wait enough for old deprecating OMR prefix deprecating to expire. + + sRaValidated = false; + sExpectedRios.Clear(); + sExpectedRios.Add(omrPrefix); + sExpectedRios.Add(localOmr); + + AdvanceTime(310000); + + VerifyOrQuit(sRaValidated); + VerifyOrQuit(sExpectedRios.SawAll()); + VerifyOrQuit(sExpectedRios[0].mLifetime == 0); + VerifyOrQuit(sExpectedRios[1].mLifetime == kRioValidLifetime); + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SuccessOrQuit(sInstance->Get().SetEnabled(false)); @@ -2023,7 +2050,10 @@ void TestDomainPrefixAsOmr(void) VerifyOrQuit(sExpectedRios[1].mPrefix == localOmr); VerifyOrQuit(sExpectedRios[1].mSawInRa); - VerifyOrQuit(sExpectedRios[1].mLifetime == 0); + VerifyOrQuit(sExpectedRios[1].mLifetime <= kRioDeprecatingLifetime); + + // Wait long enough for deprecating RIO prefix to expire + AdvanceTime(3200000); sRaValidated = false; sExpectedPio = kPioAdvertisingLocalOnLink;