[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.
This commit is contained in:
kangping
2021-03-16 08:35:45 -07:00
committed by GitHub
parent 2d101cfe28
commit 762c3c4d1e
3 changed files with 61 additions and 11 deletions
+50 -9
View File
@@ -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<RoutingManager>().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<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == OT_ERROR_NONE)
{
if (IsValidOmrPrefix(onMeshPrefixConfig) && onMeshPrefixConfig.GetPrefix() == aPrefix)
{
contain = true;
break;
}
}
return contain;
}
} // namespace BorderRouter
} // namespace ot
+10 -1
View File
@@ -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
@@ -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