From 762c3c4d1efd7bc3b85779f6c65402743731a5fb Mon Sep 17 00:00:00 2001 From: kangping Date: Tue, 16 Mar 2021 23:35:45 +0800 Subject: [PATCH] [border-router] add random delay before chaning routing policies (#6247) Also fixes an issue that a border router may adds the OMR prefix of current network as an external route. --- src/core/border_router/routing_manager.cpp | 59 ++++++++++++++++--- src/core/border_router/routing_manager.hpp | 11 +++- .../test_plat_udp_accessiblity.py | 2 +- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 063ac3ce8..1a09bbabb 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -48,7 +48,6 @@ #include "common/random.hpp" #include "common/settings.hpp" #include "net/ip6.hpp" -#include "thread/network_data.hpp" #include "thread/network_data_leader.hpp" #include "thread/network_data_local.hpp" #include "thread/network_data_notifier.hpp" @@ -71,6 +70,7 @@ RoutingManager::RoutingManager(Instance &aInstance) , mRouterAdvertisementCount(0) , mRouterSolicitTimer(aInstance, HandleRouterSolicitTimer) , mRouterSolicitCount(0) + , mRoutingPolicyTimer(aInstance, HandleRoutingPolicyTimer) { mInfraIfLinkLocalAddress.Clear(); @@ -192,7 +192,7 @@ void RoutingManager::Start(void) otLogInfoBr("Border Routing manager started"); mIsRunning = true; - StartRouterSolicitation(); + StartRouterSolicitationDelay(); } } @@ -225,6 +225,8 @@ void RoutingManager::Stop(void) mRouterSolicitTimer.Stop(); mRouterSolicitCount = 0; + mRoutingPolicyTimer.Stop(); + otLogInfoBr("Border Routing manager stopped"); mIsRunning = false; @@ -313,7 +315,7 @@ void RoutingManager::HandleNotifierEvents(Events aEvents) if (aEvents.Contains(kEventThreadNetdataChanged)) { - EvaluateRoutingPolicy(); + StartRoutingPolicyEvaluationDelay(); } exit: @@ -334,7 +336,7 @@ uint8_t RoutingManager::EvaluateOmrPrefix(Ip6::Prefix *aNewOmrPrefixes, uint8_t { uint8_t newPrefixIndex; - if (!IsValidOmrPrefix(onMeshPrefixConfig.GetPrefix()) || !onMeshPrefixConfig.mSlaac || onMeshPrefixConfig.mDp) + if (!IsValidOmrPrefix(onMeshPrefixConfig)) { continue; } @@ -621,9 +623,20 @@ exit: return; } +void RoutingManager::StartRoutingPolicyEvaluationDelay(void) +{ + uint32_t randomDelay; + + static_assert(kMaxRoutingPolicyDelay > 0, "invalid maximum routing policy evaluation delay"); + randomDelay = Random::NonCrypto::GetUint32InRange(0, Time::SecToMsec(kMaxRoutingPolicyDelay)); + + otLogInfoBr("start evaluating routing policy, scheduled in %u milliseconds", randomDelay); + mRoutingPolicyTimer.Start(randomDelay); +} + // starts sending Router Solicitations in random delay // between 0 and kMaxRtrSolicitationDelay. -void RoutingManager::StartRouterSolicitation(void) +void RoutingManager::StartRouterSolicitationDelay(void) { uint32_t randomDelay; @@ -788,6 +801,11 @@ bool RoutingManager::IsPrefixSmallerThan(const Ip6::Prefix &aFirstPrefix, const aFirstPrefix.GetBytes()[matchedLength / CHAR_BIT] < aSecondPrefix.GetBytes()[matchedLength / CHAR_BIT]; } +bool RoutingManager::IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig) +{ + return IsValidOmrPrefix(aOnMeshPrefixConfig.GetPrefix()) && aOnMeshPrefixConfig.mSlaac && !aOnMeshPrefixConfig.mDp; +} + bool RoutingManager::IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix) { // Accept ULA prefix with length of 64 bits and GUA prefix. @@ -863,6 +881,11 @@ void RoutingManager::HandleDiscoveredPrefixInvalidTimer(void) InvalidateDiscoveredPrefixes(); } +void RoutingManager::HandleRoutingPolicyTimer(Timer &aTimer) +{ + aTimer.Get().EvaluateRoutingPolicy(); +} + void RoutingManager::HandleRouterSolicit(const Ip6::Address &aSrcAddress, const uint8_t * aBuffer, uint16_t aBufferLength) @@ -961,7 +984,7 @@ void RoutingManager::HandleRouterAdvertisement(const Ip6::Address &aSrcAddress, if (needReevaluate) { - EvaluateRoutingPolicy(); + StartRoutingPolicyEvaluationDelay(); } exit: @@ -1006,8 +1029,8 @@ bool RoutingManager::UpdateDiscoveredPrefixes(const RouterAdv::RouteInfoOption & ExitNow(); } - // Ignore the OMR prefix that matches what we have advertised. - VerifyOrExit(!ContainsPrefix(prefix, mAdvertisedOmrPrefixes, mAdvertisedOmrPrefixNum)); + // Ignore the OMR prefix in current Thread Network. + VerifyOrExit(!NetworkDataContainsOmrPrefix(prefix)); otLogInfoBr("discovered OMR prefix (%s, %u seconds) from interface %u", prefix.ToString().AsCString(), aRio.GetRouteLifetime(), mInfraIfIndex); @@ -1064,7 +1087,7 @@ bool RoutingManager::InvalidateDiscoveredPrefixes(const Ip6::Prefix *aPrefix, bo // There are no valid on-link prefixes on infra link now, start Router Solicitation // To find out more on-link prefixes or timeout to advertise my local on-link prefix. - StartRouterSolicitation(); + StartRouterSolicitationDelay(); } else { @@ -1148,6 +1171,24 @@ exit: return added; } +bool RoutingManager::NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const +{ + NetworkData::Iterator iterator = NetworkData::kIteratorInit; + NetworkData::OnMeshPrefixConfig onMeshPrefixConfig; + bool contain = false; + + while (Get().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == OT_ERROR_NONE) + { + if (IsValidOmrPrefix(onMeshPrefixConfig) && onMeshPrefixConfig.GetPrefix() == aPrefix) + { + contain = true; + break; + } + } + + return contain; +} + } // namespace BorderRouter } // namespace ot diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index 8cdb25f3f..8d5410fec 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -56,6 +56,7 @@ #include "common/notifier.hpp" #include "common/timer.hpp" #include "net/ip6.hpp" +#include "thread/network_data.hpp" namespace ot { @@ -170,6 +171,7 @@ private: kMaxRaDelayTime = 500, // The maximum delay of sending RA after receiving RS. In milliseconds. kRtrSolicitationInterval = 4, // The interval between Router Solicitations. In seconds. kMaxRtrSolicitationDelay = 1, // The maximum delay for initial solicitation. In seconds. + kMaxRoutingPolicyDelay = 1, // The maximum delay for routing policy evaluation. In seconds. }; static_assert(kMinRtrAdvInterval <= 3 * kMaxRtrAdvInterval / 4, "invalid RA intervals"); @@ -203,12 +205,13 @@ private: const Ip6::Prefix *EvaluateOnLinkPrefix(void); void EvaluateRoutingPolicy(void); + void StartRoutingPolicyEvaluationDelay(void); uint8_t EvaluateOmrPrefix(Ip6::Prefix *aNewOmrPrefixes, uint8_t aMaxOmrPrefixNum); Error PublishLocalOmrPrefix(void); void UnpublishLocalOmrPrefix(void); Error AddExternalRoute(const Ip6::Prefix &aPrefix, otRoutePreference aRoutePreference); void RemoveExternalRoute(const Ip6::Prefix &aPrefix); - void StartRouterSolicitation(void); + void StartRouterSolicitationDelay(void); Error SendRouterSolicitation(void); void SendRouterAdvertisement(const Ip6::Prefix *aNewOmrPrefixes, uint8_t aNewOmrPrefixNum, @@ -223,6 +226,8 @@ private: static void HandleDiscoveredPrefixInvalidTimer(Timer &aTimer); void HandleDiscoveredPrefixInvalidTimer(void); + static void HandleRoutingPolicyTimer(Timer &aTimer); + void HandleRouterSolicit(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength); void HandleRouterAdvertisement(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength); bool UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio); @@ -233,9 +238,11 @@ private: bool aIsOnLinkPrefix, uint32_t aLifetime, otRoutePreference aRoutePreference = OT_ROUTE_PREFERENCE_MED); + bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const; // Decides the first prefix is numerically smaller than the second one. static bool IsPrefixSmallerThan(const Ip6::Prefix &aFirstPrefix, const Ip6::Prefix &aSecondPrefix); + static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix); static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix); static bool ContainsPrefix(const Ip6::Prefix &aPrefix, const Ip6::Prefix *aPrefixList, uint8_t aPrefixNum); @@ -296,6 +303,8 @@ private: TimerMilli mRouterSolicitTimer; uint8_t mRouterSolicitCount; + + TimerMilli mRoutingPolicyTimer; }; } // namespace BorderRouter diff --git a/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py b/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py index 32b8cde5a..180e70cb4 100644 --- a/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py +++ b/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py @@ -105,7 +105,7 @@ class TestPlatUdpAccessibility(thread_cert.TestCase): self.nodes[reset_device].start() self.simulator.go(5) self.assertIn(self.nodes[reset_device].get_state(), ['leader', 'router']) - self.simulator.go(3) + self.simulator.go(5) if reset_device == server: # Reconfigure DHCP6 server if necessary