Skip to content

Commit

Permalink
[routing-manager] learn and copy M & O flags from discovered rout…
Browse files Browse the repository at this point in the history
…ers (openthread#9607)

This commit implements a mechanism in `RoutingManager` to learn the
Managed Address Config `M` and Other Config `O` flags in received RA
message from discovered routers on the infrastructure link and copy
the same flags in the emitted RA message from BR.

If any discovered router on the infrastructure that is not itself a
stub router (i.e., does not include the Stub Router flag) includes
the `M` or `O` flags, the same flag are included in the emitted RA
message. If a discovered router has failed to respond to the maximum
number of NS probe attempts, we consider it as offline and ignore its
flags.

This commit also adds a detailed test case in `test_routing_manager`
to validate the newly added mechanism.
  • Loading branch information
abtink authored Nov 21, 2023
1 parent 364e315 commit 34dd612
Show file tree
Hide file tree
Showing 4 changed files with 428 additions and 37 deletions.
85 changes: 72 additions & 13 deletions src/core/border_router/routing_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,12 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)

LogInfo("Preparing RA");

mDiscoveredPrefixTable.DetermineAndSetFlags(raMsg);

LogInfo("- RA Header - flags - M:%u O:%u", raMsg.GetHeader().IsManagedAddressConfigFlagSet(),
raMsg.GetHeader().IsOtherConfigFlagSet());
LogInfo("- RA Header - default route - lifetime:%u", raMsg.GetHeader().GetRouterLifetime());

#if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
SuccessOrAssert(raMsg.AppendFlagsExtensionOption(/* aStubRouterFlag */ true));
LogInfo("- FlagsExt - StubRouter:1");
Expand Down Expand Up @@ -1242,7 +1248,7 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const Ip6

UpdateRouterOnRx(*router);

RemoveRoutersWithNoEntries();
RemoveRoutersWithNoEntriesOrFlags();

exit:
return;
Expand Down Expand Up @@ -1472,7 +1478,7 @@ void RoutingManager::DiscoveredPrefixTable::RemovePrefix(const Entry::Matcher &a
VerifyOrExit(!removedEntries.IsEmpty());

FreeEntries(removedEntries);
RemoveRoutersWithNoEntries();
RemoveRoutersWithNoEntriesOrFlags();

SignalTableChanged();

Expand All @@ -1482,21 +1488,17 @@ void RoutingManager::DiscoveredPrefixTable::RemovePrefix(const Entry::Matcher &a

void RoutingManager::DiscoveredPrefixTable::RemoveAllEntries(void)
{
// Remove all entries from the table and unpublish them
// from Network Data.
// Remove all entries from the table.

for (Router &router : mRouters)
{
if (!router.mEntries.IsEmpty())
{
SignalTableChanged();
}

FreeEntries(router.mEntries);
}

RemoveRoutersWithNoEntries();
FreeRouters(mRouters);
mEntryTimer.Stop();

SignalTableChanged();
}

void RoutingManager::DiscoveredPrefixTable::RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold)
Expand Down Expand Up @@ -1592,11 +1594,11 @@ TimeMilli RoutingManager::DiscoveredPrefixTable::CalculateNextStaleTime(TimeMill
return foundOnLink ? Min(onLinkStaleTime, routeStaleTime) : routeStaleTime;
}

void RoutingManager::DiscoveredPrefixTable::RemoveRoutersWithNoEntries(void)
void RoutingManager::DiscoveredPrefixTable::RemoveRoutersWithNoEntriesOrFlags(void)
{
LinkedList<Router> routersToFree;

mRouters.RemoveAllMatching(Router::kContainsNoEntries, routersToFree);
mRouters.RemoveAllMatching(Router::kContainsNoEntriesOrFlags, routersToFree);
FreeRouters(routersToFree);
}

Expand Down Expand Up @@ -1668,7 +1670,7 @@ void RoutingManager::DiscoveredPrefixTable::RemoveExpiredEntries(void)
router.mEntries.RemoveAllMatching(Entry::ExpirationChecker(now), expiredEntries);
}

RemoveRoutersWithNoEntries();
RemoveRoutersWithNoEntriesOrFlags();

if (!expiredEntries.IsEmpty())
{
Expand Down Expand Up @@ -1792,6 +1794,42 @@ void RoutingManager::DiscoveredPrefixTable::SendNeighborSolicitToRouter(const Ro
return;
}

void RoutingManager::DiscoveredPrefixTable::DetermineAndSetFlags(Ip6::Nd::RouterAdvertMessage &aRaMessage) const
{
// Determine the `M` and `O` flags to include in the RA message
// header `aRaMessage` to be emitted.
//
// If any discovered router on infrastructure which is not itself a
// stub router (e.g., another Thread BR) includes the `M` or `O`
// flag, we also include the same flag.
//
// If a router has failed to respond to max number of NS probe
// attempts, we consider it as offline and ignore its flags.

for (const Router &router : mRouters)
{
if (router.mStubRouterFlag)
{
continue;
}

if (router.mNsProbeCount > Router::kMaxNsProbes)
{
continue;
}

if (router.mManagedAddressConfigFlag)
{
aRaMessage.GetHeader().SetManagedAddressConfigFlag();
}

if (router.mOtherConfigFlag)
{
aRaMessage.GetHeader().SetOtherConfigFlag();
}
}
}

void RoutingManager::DiscoveredPrefixTable::InitIterator(PrefixTableIterator &aIterator) const
{
static_cast<Iterator &>(aIterator).Init(mRouters);
Expand Down Expand Up @@ -1995,6 +2033,27 @@ uint32_t RoutingManager::DiscoveredPrefixTable::Entry::CalculateExpireDelay(uint
//---------------------------------------------------------------------------------------------------------------------
// DiscoveredPrefixTable::Router

bool RoutingManager::DiscoveredPrefixTable::Router::Matches(EmptyChecker aChecker) const
{
// Checks whether or not a `Router` instance has any useful info. An
// entry can be removed if it does not advertise M or O flags and
// also does not have any advertised prefix entries (RIO/PIO). If
// the router already failed to respond to max NS probe attempts,
// we consider it as offline and therefore do not consider its
// flags anymore.

OT_UNUSED_VARIABLE(aChecker);

bool hasFlags = false;

if (mNsProbeCount <= kMaxNsProbes)
{
hasFlags = (mManagedAddressConfigFlag || mOtherConfigFlag);
}

return !hasFlags && mEntries.IsEmpty();
}

void RoutingManager::DiscoveredPrefixTable::Router::CopyInfoTo(RouterEntry &aEntry) const
{
aEntry.mAddress = mAddress;
Expand Down
8 changes: 5 additions & 3 deletions src/core/border_router/routing_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,8 @@ class RoutingManager : public InstanceLocator

TimeMilli CalculateNextStaleTime(TimeMilli aNow) const;

void DetermineAndSetFlags(Ip6::Nd::RouterAdvertMessage &aRaMessage) const;

void InitIterator(PrefixTableIterator &aIterator) const;
Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const;
Error GetNextRouter(PrefixTableIterator &aIterator, RouterEntry &aEntry) const;
Expand Down Expand Up @@ -770,11 +772,11 @@ class RoutingManager : public InstanceLocator

enum EmptyChecker : uint8_t
{
kContainsNoEntries
kContainsNoEntriesOrFlags
};

bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
bool Matches(EmptyChecker) const { return mEntries.IsEmpty(); }
bool Matches(EmptyChecker aChecker) const;
void CopyInfoTo(RouterEntry &aEntry) const;

Router *mNext;
Expand Down Expand Up @@ -816,7 +818,7 @@ class RoutingManager : public InstanceLocator
bool Contains(const Entry::Checker &aChecker) const;
void RemovePrefix(const Entry::Matcher &aMatcher);
void RemoveOrDeprecateEntriesFromInactiveRouters(void);
void RemoveRoutersWithNoEntries(void);
void RemoveRoutersWithNoEntriesOrFlags(void);
void FreeRouters(LinkedList<Router> &aRouters);
void FreeEntries(LinkedList<Entry> &aEntries);
void UpdateNetworkDataOnChangeTo(Entry &aEntry);
Expand Down
8 changes: 8 additions & 0 deletions src/core/net/nd6.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,14 @@ class RouterAdvertMessage
*/
const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); }

/**
* Gets the RA message's header.
*
* @returns The RA message's header.
*
*/
Header &GetHeader(void) { return *reinterpret_cast<Header *>(AsNonConst(mData.GetBytes())); }

/**
* Appends a Prefix Info Option to the RA message.
*
Expand Down
Loading

0 comments on commit 34dd612

Please sign in to comment.