mirror of
https://github.com/espressif/openthread.git
synced 2026-08-01 00:27:47 +00:00
[border-routing] fix stale prefixes checking timer (#7241)
Current implementation will reschedule the Stale Timer when discovered
on-link or OMR prefixes or RA messages are updated, but it has a few
issues:
1. It's counting the maximum stale time of all on-link prefixes so
that we will schedule Router Solicitation when all on-link
prefixes become stale. But it failed to filter out OMR prefixes in
the `mDiscoveredPrefixes` list. This results in incorrect stale
time calculation.
2. A deprecated on-link-prefix is not removed from
`mDiscoveredPrefixes` directly but the preferred lifetime is set
to zero. We are not filtering out deprecated on-link prefixes when
calculating stale time and this results in zero stale timer delay
if there are no non-deprecated on-link prefixes.
This commit fixes those issues by having a dedicated
`ResetDiscoveredPrefixStaleTimer` to reschedule the stale timer with
following rules whenever discovered prefixes or learnt RA messages are
updated:
1. If BR learns RA header from Host daemons, it should send RS when
the RA header is stale.
2. If BR discovered any on-link prefix, it should send RS when all
on-link prefixes are stale.
3. If BR discovered any OMR prefix, it should send RS when the first
OMR prefix is stale.
`ResetDiscoveredPrefixStaleTimer` is supposed to correctly calculate
stale timer timeout whenever it's called.
This commit is contained in:
@@ -65,6 +65,7 @@ RoutingManager::RoutingManager(Instance &aInstance)
|
||||
, mIsAdvertisingLocalOnLinkPrefix(false)
|
||||
, mOnLinkPrefixDeprecateTimer(aInstance, HandleOnLinkPrefixDeprecateTimer)
|
||||
, mTimeRouterAdvMessageLastUpdate(TimerMilli::GetNow())
|
||||
, mLearntRouterAdvMessageFromHost(false)
|
||||
, mDiscoveredPrefixInvalidTimer(aInstance, HandleDiscoveredPrefixInvalidTimer)
|
||||
, mDiscoveredPrefixStaleTimer(aInstance, HandleDiscoveredPrefixStaleTimer)
|
||||
, mRouterAdvertisementTimer(aInstance, HandleRouterAdvertisementTimer)
|
||||
@@ -917,6 +918,9 @@ void RoutingManager::HandleRouterSolicitTimer(void)
|
||||
|
||||
// Re-evaluate our routing policy and send Router Advertisement if necessary.
|
||||
EvaluateRoutingPolicy();
|
||||
|
||||
// Reset prefix stale timer because `mDiscoveredPrefixes` may change.
|
||||
ResetDiscoveredPrefixStaleTimer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,7 +931,7 @@ void RoutingManager::HandleDiscoveredPrefixStaleTimer(Timer &aTimer)
|
||||
|
||||
void RoutingManager::HandleDiscoveredPrefixStaleTimer(void)
|
||||
{
|
||||
otLogInfoBr("All on-link prefixes are stale");
|
||||
otLogInfoBr("Stale On-Link or OMR Prefixes or RA messages are detected");
|
||||
StartRouterSolicitationDelay();
|
||||
}
|
||||
|
||||
@@ -1072,7 +1076,6 @@ bool RoutingManager::UpdateDiscoveredOnLinkPrefix(const RouterAdv::PrefixInfoOpt
|
||||
{
|
||||
Ip6::Prefix prefix = aPio.GetPrefix();
|
||||
bool needReevaluate = false;
|
||||
TimeMilli staleTime;
|
||||
ExternalPrefix onLinkPrefix;
|
||||
ExternalPrefix *existingPrefix = nullptr;
|
||||
|
||||
@@ -1093,16 +1096,12 @@ bool RoutingManager::UpdateDiscoveredOnLinkPrefix(const RouterAdv::PrefixInfoOpt
|
||||
onLinkPrefix.mPreferredLifetime = aPio.GetPreferredLifetime();
|
||||
onLinkPrefix.mTimeLastUpdate = TimerMilli::GetNow();
|
||||
|
||||
staleTime = TimerMilli::GetNow();
|
||||
|
||||
for (ExternalPrefix &externalPrefix : mDiscoveredPrefixes)
|
||||
{
|
||||
if (externalPrefix == onLinkPrefix)
|
||||
{
|
||||
existingPrefix = &externalPrefix;
|
||||
}
|
||||
|
||||
staleTime = OT_MAX(staleTime, externalPrefix.GetStaleTime());
|
||||
}
|
||||
|
||||
if (existingPrefix == nullptr)
|
||||
@@ -1158,8 +1157,7 @@ bool RoutingManager::UpdateDiscoveredOnLinkPrefix(const RouterAdv::PrefixInfoOpt
|
||||
}
|
||||
|
||||
mDiscoveredPrefixInvalidTimer.FireAtIfEarlier(existingPrefix->GetExpireTime());
|
||||
staleTime = OT_MAX(staleTime, existingPrefix->GetStaleTime());
|
||||
mDiscoveredPrefixStaleTimer.FireAtIfEarlier(staleTime);
|
||||
ResetDiscoveredPrefixStaleTimer();
|
||||
|
||||
exit:
|
||||
return needReevaluate;
|
||||
@@ -1213,8 +1211,6 @@ void RoutingManager::UpdateDiscoveredOmrPrefix(const RouterAdv::RouteInfoOption
|
||||
{
|
||||
existingPrefix = &externalPrefix;
|
||||
}
|
||||
|
||||
mDiscoveredPrefixStaleTimer.FireAtIfEarlier(externalPrefix.GetStaleTime());
|
||||
}
|
||||
|
||||
if (existingPrefix == nullptr)
|
||||
@@ -1239,7 +1235,7 @@ void RoutingManager::UpdateDiscoveredOmrPrefix(const RouterAdv::RouteInfoOption
|
||||
*existingPrefix = omrPrefix;
|
||||
|
||||
mDiscoveredPrefixInvalidTimer.FireAtIfEarlier(existingPrefix->GetExpireTime());
|
||||
mDiscoveredPrefixStaleTimer.FireAtIfEarlier(existingPrefix->GetStaleTime());
|
||||
ResetDiscoveredPrefixStaleTimer();
|
||||
|
||||
exit:
|
||||
return;
|
||||
@@ -1325,17 +1321,82 @@ bool RoutingManager::UpdateRouterAdvMessage(const RouterAdv::RouterAdvMessage *a
|
||||
if (aRouterAdvMessage == nullptr || aRouterAdvMessage->GetRouterLifetime() == 0)
|
||||
{
|
||||
mRouterAdvMessage.SetToDefault();
|
||||
mLearntRouterAdvMessageFromHost = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mRouterAdvMessage = *aRouterAdvMessage;
|
||||
mDiscoveredPrefixStaleTimer.FireAtIfEarlier(mTimeRouterAdvMessageLastUpdate +
|
||||
Time::SecToMsec(kRtrAdvStaleTime));
|
||||
mRouterAdvMessage = *aRouterAdvMessage;
|
||||
mLearntRouterAdvMessageFromHost = true;
|
||||
}
|
||||
|
||||
ResetDiscoveredPrefixStaleTimer();
|
||||
|
||||
return (mRouterAdvMessage != oldRouterAdvMessage);
|
||||
}
|
||||
|
||||
void RoutingManager::ResetDiscoveredPrefixStaleTimer(void)
|
||||
{
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
TimeMilli nextStaleTime = now.GetDistantFuture();
|
||||
TimeMilli maxOnlinkPrefixStaleTime = now;
|
||||
bool requireCheckStaleOnlinkPrefix = false;
|
||||
|
||||
OT_ASSERT(mIsRunning);
|
||||
|
||||
// The stale timer triggers sending RS to check the state of On-Link/OMR prefixes and host RA messages.
|
||||
// The rules for calculating the next stale time:
|
||||
// 1. If BR learns RA header from Host daemons, it should send RS when the RA header is stale.
|
||||
// 2. If BR discovered any on-link prefix, it should send RS when all on-link prefixes are stale.
|
||||
// 3. If BR discovered any OMR prefix, it should send RS when the first OMR prefix is stale.
|
||||
|
||||
// Check for stale Router Advertisement Message if learnt from Host.
|
||||
if (mLearntRouterAdvMessageFromHost)
|
||||
{
|
||||
TimeMilli routerAdvMessageStaleTime = mTimeRouterAdvMessageLastUpdate + Time::SecToMsec(kRtrAdvStaleTime);
|
||||
|
||||
nextStaleTime = OT_MIN(nextStaleTime, routerAdvMessageStaleTime);
|
||||
}
|
||||
|
||||
for (ExternalPrefix &externalPrefix : mDiscoveredPrefixes)
|
||||
{
|
||||
TimeMilli prefixStaleTime = externalPrefix.GetStaleTime();
|
||||
|
||||
if (externalPrefix.mIsOnLinkPrefix)
|
||||
{
|
||||
if (!externalPrefix.IsDeprecated())
|
||||
{
|
||||
// Check for least recent stale On-Link Prefixes if BR is not advertising local On-Link Prefix.
|
||||
maxOnlinkPrefixStaleTime = OT_MAX(maxOnlinkPrefixStaleTime, prefixStaleTime);
|
||||
requireCheckStaleOnlinkPrefix = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for most recent stale OMR Prefixes
|
||||
nextStaleTime = OT_MIN(nextStaleTime, prefixStaleTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (requireCheckStaleOnlinkPrefix)
|
||||
{
|
||||
nextStaleTime = OT_MIN(nextStaleTime, maxOnlinkPrefixStaleTime);
|
||||
}
|
||||
|
||||
if (nextStaleTime == now.GetDistantFuture())
|
||||
{
|
||||
if (mDiscoveredPrefixStaleTimer.IsRunning())
|
||||
{
|
||||
otLogDebgBr("Prefix stale timer stopped");
|
||||
}
|
||||
mDiscoveredPrefixStaleTimer.Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
mDiscoveredPrefixStaleTimer.FireAt(nextStaleTime);
|
||||
otLogDebgBr("Prefix stale timer scheduled in %lu ms", nextStaleTime - now);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace BorderRouter
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -315,6 +315,7 @@ private:
|
||||
void InvalidateAllDiscoveredPrefixes(void);
|
||||
bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const;
|
||||
bool UpdateRouterAdvMessage(const RouterAdv::RouterAdvMessage *aRouterAdvMessage);
|
||||
void ResetDiscoveredPrefixStaleTimer(void);
|
||||
|
||||
static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
|
||||
static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix);
|
||||
@@ -370,6 +371,7 @@ private:
|
||||
// and updated with RA messages initiated from infra interface.
|
||||
RouterAdv::RouterAdvMessage mRouterAdvMessage;
|
||||
TimeMilli mTimeRouterAdvMessageLastUpdate;
|
||||
bool mLearntRouterAdvMessageFromHost;
|
||||
|
||||
TimerMilli mDiscoveredPrefixInvalidTimer;
|
||||
TimerMilli mDiscoveredPrefixStaleTimer;
|
||||
|
||||
Reference in New Issue
Block a user