mirror of
https://github.com/espressif/openthread.git
synced 2026-08-28 04:49:54 +00:00
[routing-manager] enhance selection of prefixes to advertise as RIO (#7936)
This commit updated how `RoutingManager` selects the set of prefixes to advertise as RIO in emitted RA messages from the BR. The related code is now moved to `SendRouterAdvertisement()` method (instead of previously being in `EvaluateOmrPrefix()`). Since the array for storing the advertised prefixes has a limited size (configurable through an OT build-time setting), we add more important prefixes first in the array to ensure that they are advertised in the RA message. The following order is used: (1) Local OMR prefix (if added in Network Data), (2) currently favored OMR prefix, (3) any other OMR prefixes from Network Data, (4) any other on-mesh prefix (excluding Domain Prefix) from Network Data.
This commit is contained in:
@@ -295,8 +295,7 @@ void RoutingManager::Stop(void)
|
||||
mIsAdvertisingLocalNat64Prefix = false;
|
||||
}
|
||||
#endif
|
||||
// Use empty OMR & on-link prefixes to invalidate possible advertised prefixes.
|
||||
SendRouterAdvertisement(OnMeshPrefixArray());
|
||||
SendRouterAdvertisement(kInvalidateAllPrevPrefixes);
|
||||
|
||||
mAdvertisedPrefixes.Clear();
|
||||
mOnLinkPrefixDeprecateTimer.Stop();
|
||||
@@ -419,7 +418,7 @@ void RoutingManager::UpdateDiscoveredPrefixTableOnNetDataChange(void)
|
||||
mDiscoveredPrefixTable.SetAllowDefaultRouteInNetData(foundDefRouteOmrPrefix);
|
||||
}
|
||||
|
||||
void RoutingManager::EvaluateOmrPrefix(OnMeshPrefixArray &aNewPrefixes)
|
||||
void RoutingManager::EvaluateOmrPrefix(void)
|
||||
{
|
||||
NetworkData::Iterator iterator = NetworkData::kIteratorInit;
|
||||
NetworkData::OnMeshPrefixConfig onMeshPrefixConfig;
|
||||
@@ -430,22 +429,6 @@ void RoutingManager::EvaluateOmrPrefix(OnMeshPrefixArray &aNewPrefixes)
|
||||
|
||||
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == kErrorNone)
|
||||
{
|
||||
if (!onMeshPrefixConfig.mOnMesh || onMeshPrefixConfig.mDp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!aNewPrefixes.Contains(onMeshPrefixConfig.GetPrefix()))
|
||||
{
|
||||
Error error = aNewPrefixes.PushBack(onMeshPrefixConfig.GetPrefix());
|
||||
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
LogWarn("EvaluateOmrPrefix: Too many on-mesh prefixes, ignoring prefix %s",
|
||||
onMeshPrefixConfig.GetPrefix().ToString().AsCString());
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsValidOmrPrefix(onMeshPrefixConfig) || !onMeshPrefixConfig.mPreferred)
|
||||
{
|
||||
continue;
|
||||
@@ -468,11 +451,6 @@ void RoutingManager::EvaluateOmrPrefix(OnMeshPrefixArray &aNewPrefixes)
|
||||
SuccessOrExit(mLocalOmrPrefix.AddToNetData());
|
||||
|
||||
mFavoredOmrPrefix.SetFrom(mLocalOmrPrefix);
|
||||
|
||||
if (!aNewPrefixes.Contains(mLocalOmrPrefix.GetPrefix()))
|
||||
{
|
||||
SuccessOrExit(aNewPrefixes.PushBack(mLocalOmrPrefix.GetPrefix()));
|
||||
}
|
||||
}
|
||||
else if (mFavoredOmrPrefix.GetPrefix() == mLocalOmrPrefix.GetPrefix())
|
||||
{
|
||||
@@ -480,19 +458,10 @@ void RoutingManager::EvaluateOmrPrefix(OnMeshPrefixArray &aNewPrefixes)
|
||||
}
|
||||
else if (mLocalOmrPrefix.IsAddedInNetData())
|
||||
{
|
||||
OnMeshPrefix *entry;
|
||||
|
||||
LogInfo("EvaluateOmrPrefix: There is already a preferred OMR prefix %s in the Thread network",
|
||||
mFavoredOmrPrefix.GetPrefix().ToString().AsCString());
|
||||
|
||||
mLocalOmrPrefix.RemoveFromNetData();
|
||||
|
||||
entry = aNewPrefixes.Find(mLocalOmrPrefix.GetPrefix());
|
||||
|
||||
if (entry != nullptr)
|
||||
{
|
||||
aNewPrefixes.Remove(*entry);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -672,28 +641,17 @@ void RoutingManager::EvaluateRoutingPolicy(void)
|
||||
{
|
||||
OT_ASSERT(mIsRunning);
|
||||
|
||||
OnMeshPrefixArray newPrefixes;
|
||||
|
||||
LogInfo("Evaluating routing policy");
|
||||
|
||||
// 0. Evaluate on-link, OMR and NAT64 prefixes.
|
||||
EvaluateOnLinkPrefix();
|
||||
EvaluateOmrPrefix(newPrefixes);
|
||||
EvaluateOmrPrefix();
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE
|
||||
EvaluateNat64Prefix();
|
||||
#endif
|
||||
|
||||
// 1. Send Router Advertisement message if necessary.
|
||||
SendRouterAdvertisement(newPrefixes);
|
||||
|
||||
if (newPrefixes.IsEmpty())
|
||||
{
|
||||
// This is the very exceptional case and happens only when we failed to publish
|
||||
// our local OMR prefix to the Thread network. We schedule the routing policy
|
||||
// timer to re-evaluate our routing policy in the future.
|
||||
|
||||
LogWarn("No OMR prefix advertised! Start Routing Policy timer for future evaluation");
|
||||
}
|
||||
SendRouterAdvertisement(kAdvPrefixesFromNetData);
|
||||
|
||||
// 2. Schedule routing policy timer with random interval for the next Router Advertisement.
|
||||
{
|
||||
@@ -708,9 +666,6 @@ void RoutingManager::EvaluateRoutingPolicy(void)
|
||||
|
||||
StartRoutingPolicyEvaluationDelay(Time::SecToMsec(nextSendDelay));
|
||||
}
|
||||
|
||||
// 3. Update advertised prefixes.
|
||||
mAdvertisedPrefixes = newPrefixes;
|
||||
}
|
||||
|
||||
void RoutingManager::StartRoutingPolicyEvaluationJitter(uint32_t aJitterMilli)
|
||||
@@ -773,7 +728,7 @@ Error RoutingManager::SendRouterSolicitation(void)
|
||||
return mInfraIf.Send(packet, destAddress);
|
||||
}
|
||||
|
||||
void RoutingManager::SendRouterAdvertisement(const OnMeshPrefixArray &aNewPrefixes)
|
||||
void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)
|
||||
{
|
||||
// RA message max length is derived to accommodate:
|
||||
//
|
||||
@@ -787,8 +742,10 @@ void RoutingManager::SendRouterAdvertisement(const OnMeshPrefixArray &aNewPrefix
|
||||
sizeof(Ip6::Nd::RouterAdvertMessage::Header) + sizeof(Ip6::Nd::PrefixInfoOption) +
|
||||
2 * kMaxOnMeshPrefixes * (sizeof(Ip6::Nd::RouteInfoOption) + sizeof(Ip6::Prefix));
|
||||
|
||||
uint8_t buffer[kMaxRaLength];
|
||||
Ip6::Nd::RouterAdvertMessage raMsg(mRouterAdvertHeader, buffer);
|
||||
uint8_t buffer[kMaxRaLength];
|
||||
Ip6::Nd::RouterAdvertMessage raMsg(mRouterAdvertHeader, buffer);
|
||||
NetworkData::Iterator iterator;
|
||||
NetworkData::OnMeshPrefixConfig prefixConfig;
|
||||
|
||||
// Append PIO for local on-link prefix. Ensure it is either being
|
||||
// advertised or deprecated.
|
||||
@@ -815,25 +772,113 @@ void RoutingManager::SendRouterAdvertisement(const OnMeshPrefixArray &aNewPrefix
|
||||
validLifetime, preferredLifetime);
|
||||
}
|
||||
|
||||
// Invalidate previously advertised prefixes if they are no
|
||||
// longer in the new prefix array.
|
||||
// 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)
|
||||
{
|
||||
iterator = NetworkData::kIteratorInit;
|
||||
|
||||
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
|
||||
{
|
||||
if (!prefixConfig.mOnMesh || prefixConfig.mDp || (prefixConfig.GetPrefix() == mLocalOmrPrefix.GetPrefix()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
mAdvertisedPrefixes.MarkAsDeleted(prefixConfig.GetPrefix());
|
||||
}
|
||||
|
||||
if (mLocalOmrPrefix.IsAddedInNetData())
|
||||
{
|
||||
mAdvertisedPrefixes.MarkAsDeleted(mLocalOmrPrefix.GetPrefix());
|
||||
}
|
||||
}
|
||||
|
||||
for (const OnMeshPrefix &prefix : mAdvertisedPrefixes)
|
||||
{
|
||||
if (!aNewPrefixes.Contains(prefix))
|
||||
if (prefix.GetLength() != 0)
|
||||
{
|
||||
SuccessOrAssert(raMsg.AppendRouteInfoOption(prefix, /* aRouteLifetime */ 0, mRouteInfoOptionPreference));
|
||||
|
||||
LogInfo("RouterAdvert: Added RIO for %s (lifetime=0)", prefix.ToString().AsCString());
|
||||
}
|
||||
}
|
||||
|
||||
for (const OnMeshPrefix &prefix : aNewPrefixes)
|
||||
{
|
||||
SuccessOrAssert(raMsg.AppendRouteInfoOption(prefix, kDefaultOmrPrefixLifetime, mRouteInfoOptionPreference));
|
||||
// Discover and add prefixes from Network Data to advertise as
|
||||
// RIO in the Router Advertisement message.
|
||||
|
||||
LogInfo("RouterAdvert: Added RIO for %s (lifetime=%u)", prefix.ToString().AsCString(),
|
||||
kDefaultOmrPrefixLifetime);
|
||||
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 (mLocalOmrPrefix.IsAddedInNetData())
|
||||
{
|
||||
mAdvertisedPrefixes.Add(mLocalOmrPrefix.GetPrefix());
|
||||
}
|
||||
|
||||
// (2) Favored OMR prefix.
|
||||
|
||||
if (!mFavoredOmrPrefix.IsEmpty())
|
||||
{
|
||||
mAdvertisedPrefixes.Add(mFavoredOmrPrefix.GetPrefix());
|
||||
}
|
||||
|
||||
// (3) All other OMR prefixes.
|
||||
|
||||
iterator = NetworkData::kIteratorInit;
|
||||
|
||||
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefixConfig) == kErrorNone)
|
||||
{
|
||||
// Local OMR prefix is added to the array depending on
|
||||
// `mLocalOmrPrefix.IsAddedInNetData()` 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 (IsValidOmrPrefix(prefixConfig) && (prefixConfig.GetPrefix() != mLocalOmrPrefix.GetPrefix()))
|
||||
{
|
||||
mAdvertisedPrefixes.Add(prefixConfig.GetPrefix());
|
||||
}
|
||||
}
|
||||
|
||||
// (4) All other on-mesh prefixes (excluding Domain Prefix).
|
||||
|
||||
iterator = NetworkData::kIteratorInit;
|
||||
|
||||
while (Get<NetworkData::Leader>().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, mRouteInfoOptionPreference));
|
||||
LogInfo("RouterAdvert: Added RIO for %s (lifetime=%u)", prefix.ToString().AsCString(),
|
||||
kDefaultOmrPrefixLifetime);
|
||||
}
|
||||
}
|
||||
|
||||
if (raMsg.ContainsAnyOptions())
|
||||
@@ -2079,6 +2124,42 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// OnMeshPrefixArray
|
||||
|
||||
void RoutingManager::OnMeshPrefixArray::Add(const OnMeshPrefix &aPrefix)
|
||||
{
|
||||
// Checks if `aPrefix` is already present in the array and if not
|
||||
// adds it as new entry.
|
||||
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(!Contains(aPrefix));
|
||||
|
||||
error = PushBack(aPrefix);
|
||||
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
LogWarn("Too many on-mesh prefixes in net data, ignoring prefix %s", aPrefix.ToString().AsCString());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace BorderRouter
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -313,6 +313,12 @@ private:
|
||||
static_assert(kRtrAdvStaleTime >= 1800 && kRtrAdvStaleTime <= kDefaultOnLinkPrefixLifetime,
|
||||
"invalid RA STALE time");
|
||||
|
||||
enum RouterAdvTxMode : uint8_t // Used in `SendRouterAdvertisement()`
|
||||
{
|
||||
kInvalidateAllPrevPrefixes,
|
||||
kAdvPrefixesFromNetData,
|
||||
};
|
||||
|
||||
class DiscoveredPrefixTable : public InstanceLocator
|
||||
{
|
||||
// This class maintains the discovered on-link and route prefixes
|
||||
@@ -509,10 +515,6 @@ private:
|
||||
RoutePreference mPreference;
|
||||
};
|
||||
|
||||
typedef Ip6::Prefix OnMeshPrefix;
|
||||
|
||||
typedef Array<OnMeshPrefix, kMaxOnMeshPrefixes> OnMeshPrefixArray;
|
||||
|
||||
class LocalOmrPrefix : InstanceLocator
|
||||
{
|
||||
public:
|
||||
@@ -529,6 +531,15 @@ private:
|
||||
bool mIsAddedInNetData;
|
||||
};
|
||||
|
||||
typedef Ip6::Prefix OnMeshPrefix;
|
||||
|
||||
class OnMeshPrefixArray : public Array<OnMeshPrefix, kMaxOnMeshPrefixes>
|
||||
{
|
||||
public:
|
||||
void Add(const OnMeshPrefix &aPrefix);
|
||||
void MarkAsDeleted(const OnMeshPrefix &aPrefix);
|
||||
};
|
||||
|
||||
void EvaluateState(void);
|
||||
void Start(void);
|
||||
void Stop(void);
|
||||
@@ -548,12 +559,12 @@ private:
|
||||
void EvaluateRoutingPolicy(void);
|
||||
void StartRoutingPolicyEvaluationJitter(uint32_t aJitterMilli);
|
||||
void StartRoutingPolicyEvaluationDelay(uint32_t aDelayMilli);
|
||||
void EvaluateOmrPrefix(OnMeshPrefixArray &aNewPrefixes);
|
||||
void EvaluateOmrPrefix(void);
|
||||
Error PublishExternalRoute(const Ip6::Prefix &aPrefix, RoutePreference aRoutePreference, bool aNat64 = false);
|
||||
void UnpublishExternalRoute(const Ip6::Prefix &aPrefix);
|
||||
void StartRouterSolicitationDelay(void);
|
||||
Error SendRouterSolicitation(void);
|
||||
void SendRouterAdvertisement(const OnMeshPrefixArray &aNewPrefixes);
|
||||
void SendRouterAdvertisement(RouterAdvTxMode aRaTxMode);
|
||||
bool IsRouterSolicitationInProgress(void) const;
|
||||
|
||||
static void HandleRouterSolicitTimer(Timer &aTimer);
|
||||
|
||||
Reference in New Issue
Block a user