mirror of
https://github.com/espressif/openthread.git
synced 2026-08-16 07:37:47 +00:00
[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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user