[routing-manager] new API to get list of discovered routers (#9601)

This commit adds `otBorderRoutingGetNextRouterEntry` as a new API to
iterate over discovered routers on the infrastructure link and get
information about them such as their address, their Managed Address
Configuration (`M`), Other Configuration (`O`), and Stub Router
flags.

The `otBorderRoutingPrefixTableEntry` is also updated to contain
the same information.

This commit also updates the CLI `br` sub-commands to provide this
information, adding `br routers` to obtain a list of discovered
routers.
This commit is contained in:
Abtin Keshavarzian
2023-11-20 11:49:26 -08:00
committed by GitHub
parent 0bb9eeb500
commit 6f3b4317d6
9 changed files with 253 additions and 44 deletions
+38 -8
View File
@@ -88,22 +88,34 @@ typedef struct otBorderRoutingPrefixTableIterator
uint32_t mData32;
} otBorderRoutingPrefixTableIterator;
/**
* Represents a discovered router on the infrastructure link.
*
*/
typedef struct otBorderRoutingRouterEntry
{
otIp6Address mAddress; ///< IPv6 address of the router.
bool mManagedAddressConfigFlag : 1; ///< The router's Managed Address Config flag (`M` flag).
bool mOtherConfigFlag : 1; ///< The router's Other Config flag (`O` flag).
bool mStubRouterFlag : 1; ///< The router's Stub Router flag.
} otBorderRoutingRouterEntry;
/**
* Represents an entry from the discovered prefix table.
*
* The entries in the discovered table track the Prefix/Route Info Options in the received Router Advertisement messages
* from other routers on infrastructure link.
* from other routers on the infrastructure link.
*
*/
typedef struct otBorderRoutingPrefixTableEntry
{
otIp6Address mRouterAddress; ///< IPv6 address of the router.
otIp6Prefix mPrefix; ///< The discovered IPv6 prefix.
bool mIsOnLink; ///< Indicates whether the prefix is on-link or route prefix.
uint32_t mMsecSinceLastUpdate; ///< Milliseconds since last update of this prefix.
uint32_t mValidLifetime; ///< Valid lifetime of the prefix (in seconds).
otRoutePreference mRoutePreference; ///< Route preference when `mIsOnlink` is false.
uint32_t mPreferredLifetime; ///< Preferred lifetime of the on-link prefix when `mIsOnLink` is true.
otBorderRoutingRouterEntry mRouter; ///< Information about the router advertising this prefix.
otIp6Prefix mPrefix; ///< The discovered IPv6 prefix.
bool mIsOnLink; ///< Indicates whether the prefix is on-link or route prefix.
uint32_t mMsecSinceLastUpdate; ///< Milliseconds since last update of this prefix.
uint32_t mValidLifetime; ///< Valid lifetime of the prefix (in seconds).
otRoutePreference mRoutePreference; ///< Route preference when `mIsOnlink` is false.
uint32_t mPreferredLifetime; ///< Preferred lifetime of the on-link prefix when `mIsOnLink`.
} otBorderRoutingPrefixTableEntry;
/**
@@ -391,6 +403,9 @@ void otBorderRoutingPrefixTableInitIterator(otInstance *aInstance, otBorderRouti
/**
* Iterates over the entries in the Border Router's discovered prefix table.
*
* Prefix entries associated with the same discovered router on an infrastructure link are guaranteed to be grouped
* together (retrieved back-to-back).
*
* @param[in] aInstance The OpenThread instance.
* @param[in,out] aIterator A pointer to the iterator.
* @param[out] aEntry A pointer to the entry to populate.
@@ -403,6 +418,21 @@ otError otBorderRoutingGetNextPrefixTableEntry(otInstance
otBorderRoutingPrefixTableIterator *aIterator,
otBorderRoutingPrefixTableEntry *aEntry);
/**
* Iterates over the discovered router entries on the infrastructure link.
*
* @param[in] aInstance The OpenThread instance.
* @param[in,out] aIterator A pointer to the iterator.
* @param[out] aEntry A pointer to the entry to populate.
*
* @retval OT_ERROR_NONE Iterated to the next router, @p aEntry and @p aIterator are updated.
* @retval OT_ERROR_NOT_FOUND No more router entries.
*
*/
otError otBorderRoutingGetNextRouterEntry(otInstance *aInstance,
otBorderRoutingPrefixTableIterator *aIterator,
otBorderRoutingRouterEntry *aEntry);
/**
* Enables / Disables DHCPv6 Prefix Delegation.
*
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (374)
#define OPENTHREAD_API_VERSION (375)
/**
* @addtogroup api-instance
+38 -2
View File
@@ -15,6 +15,7 @@ Usage : `br [command] ...`
- [prefixtable](#prefixtable)
- [rioprf](#rioprf)
- [routeprf](#routeprf)
- [routers](#routers)
- [state](#state)
## Command Details
@@ -35,6 +36,7 @@ onlinkprefix
prefixtable
rioprf
routeprf
routers
state
Done
```
@@ -180,10 +182,24 @@ Usage: `br prefixtable`
Get the discovered prefixes by Border Routing Manager on the infrastructure link.
Info per prefix entry:
- The prefix
- Whether the prefix is on-link or route
- Milliseconds since last received Router Advertisement containing this prefix
- Prefix lifetime in seconds
- Preferred lifetime in seconds only if prefix is on-link
- Route preference (low, med, high) only if prefix is route (not on-link)
- The router IPv6 address which advertising this prefix
- Flags in received Router Advertisement header:
- M: Managed Address Config flag
- O: Other Config flag
- Stub: Stub Router flag (indicates whether the router is a stub router)
```bash
> br prefixtable
prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med, router:ff02:0:0:0:0:0:0:1
prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800, router:ff02:0:0:0:0:0:0:1
prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med, router:ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800, router:ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
Done
```
@@ -254,3 +270,23 @@ Clear a previously set preference value for publishing routes in Thread Network
> br routeprf clear
Done
```
### routers
Usage: `br routers`
Get the list of discovered routers by Border Routing Manager on the infrastructure link.
Info per router:
- The router IPv6 address
- Flags in received Router Advertisement header:
- M: Managed Address Config flag
- O: Other Config flag
- Stub: Stub Router flag (indicates whether the router is a stub router)
```bash
> br routers
ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
Done
```
+63 -8
View File
@@ -37,8 +37,6 @@
#include <string.h>
#include <openthread/border_routing.h>
#include "cli/cli.hpp"
namespace ot {
@@ -381,13 +379,26 @@ exit:
* @code
* br prefixtable
* prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med,
* router:ff02:0:0:0:0:0:0:1
* router:ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
* prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800,
* router:ff02:0:0:0:0:0:0:1
* router:ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
* Done
* @endcode
* @par api_copy
* #otBorderRoutingGetNextPrefixTableEntry
* @par
* Get the discovered prefixes by Border Routing Manager on the infrastructure link.
* Info per prefix entry:
* - The prefix
* - Whether the prefix is on-link or route
* - Milliseconds since last received Router Advertisement containing this prefix
* - Prefix lifetime in seconds
* - Preferred lifetime in seconds only if prefix is on-link
* - Route preference (low, med, high) only if prefix is route (not on-link)
* - The router IPv6 address which advertising this prefix
* - Flags in received Router Advertisement header:
* - M: Managed Address Config flag
* - O: Other Config flag
* - Stub: Stub Router flag (indicates whether the router is a stub router)
* @sa otBorderRoutingGetNextPrefixTableEntry
*/
template <> otError Br::Process<Cmd("prefixtable")>(Arg aArgs[])
{
@@ -416,14 +427,57 @@ template <> otError Br::Process<Cmd("prefixtable")>(Arg aArgs[])
OutputFormat("route-prf:%s, ", Interpreter::PreferenceToString(entry.mRoutePreference));
}
otIp6AddressToString(&entry.mRouterAddress, string, sizeof(string));
OutputLine("router:%s", string);
OutputFormat("router:");
OutputRouterInfo(entry.mRouter);
}
exit:
return error;
}
/**
* @cli br routers
* @code
* br routers
* ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
* Done
* @endcode
* @par
* Get the list of discovered routers by Border Routing Manager on the infrastructure link.
* Info per router:
* - The router IPv6 address
* - Flags in received Router Advertisement header:
* - M: Managed Address Config flag
* - O: Other Config flag
* - Stub: Stub Router flag (indicates whether the router is a stub router)
* @sa otBorderRoutingGetNextRouterEntry
*/
template <> otError Br::Process<Cmd("routers")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otBorderRoutingPrefixTableIterator iterator;
otBorderRoutingRouterEntry entry;
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
while (otBorderRoutingGetNextRouterEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
{
OutputRouterInfo(entry);
}
exit:
return error;
}
void Br::OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry)
{
OutputIp6Address(aEntry.mAddress);
OutputLine(" (M:%u O:%u Stub:%u)", aEntry.mManagedAddressConfigFlag, aEntry.mOtherConfigFlag,
aEntry.mStubRouterFlag);
}
template <> otError Br::Process<Cmd("rioprf")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -587,6 +641,7 @@ otError Br::Process(Arg aArgs[])
CmdEntry("prefixtable"),
CmdEntry("rioprf"),
CmdEntry("routeprf"),
CmdEntry("routers"),
CmdEntry("state"),
};
+3
View File
@@ -36,6 +36,8 @@
#include "openthread-core-config.h"
#include <openthread/border_routing.h>
#include "cli/cli_config.h"
#include "cli/cli_output.hpp"
@@ -92,6 +94,7 @@ private:
template <CommandId kCommandId> otError Process(Arg aArgs[]);
otError ParsePrefixTypeArgs(Arg aArgs[], PrefixType &aFlags);
void OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry);
};
} // namespace Cli
+10
View File
@@ -172,6 +172,16 @@ otError otBorderRoutingGetNextPrefixTableEntry(otInstance
return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetNextPrefixTableEntry(*aIterator, *aEntry);
}
otError otBorderRoutingGetNextRouterEntry(otInstance *aInstance,
otBorderRoutingPrefixTableIterator *aIterator,
otBorderRoutingRouterEntry *aEntry)
{
AssertPointerIsNotNull(aIterator);
AssertPointerIsNotNull(aEntry);
return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetNextRouterEntry(*aIterator, *aEntry);
}
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
void otBorderRoutingDhcp6PdSetEnabled(otInstance *aInstance, bool aEnabled)
{
+64 -18
View File
@@ -1794,11 +1794,7 @@ exit:
void RoutingManager::DiscoveredPrefixTable::InitIterator(PrefixTableIterator &aIterator) const
{
Iterator &iterator = static_cast<Iterator &>(aIterator);
iterator.SetInitTime();
iterator.SetRouter(mRouters.GetHead());
iterator.SetEntry(mRouters.IsEmpty() ? nullptr : mRouters.GetHead()->mEntries.GetHead());
static_cast<Iterator &>(aIterator).Init(mRouters);
}
Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &aIterator,
@@ -1810,7 +1806,7 @@ Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &a
VerifyOrExit(iterator.GetRouter() != nullptr, error = kErrorNotFound);
OT_ASSERT(iterator.GetEntry() != nullptr);
aEntry.mRouterAddress = iterator.GetRouter()->mAddress;
iterator.GetRouter()->CopyInfoTo(aEntry.mRouter);
aEntry.mPrefix = iterator.GetEntry()->GetPrefix();
aEntry.mIsOnLink = iterator.GetEntry()->IsOnLinkPrefix();
aEntry.mMsecSinceLastUpdate = iterator.GetInitTime() - iterator.GetEntry()->GetLastUpdateTime();
@@ -1819,23 +1815,62 @@ Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &a
aEntry.mRoutePreference =
static_cast<otRoutePreference>(aEntry.mIsOnLink ? 0 : iterator.GetEntry()->GetRoutePreference());
// Advance the iterator
iterator.SetEntry(iterator.GetEntry()->GetNext());
if (iterator.GetEntry() == nullptr)
{
iterator.SetRouter(iterator.GetRouter()->GetNext());
if (iterator.GetRouter() != nullptr)
{
iterator.SetEntry(iterator.GetRouter()->mEntries.GetHead());
}
}
iterator.Advance(Iterator::kToNextEntry);
exit:
return error;
}
Error RoutingManager::DiscoveredPrefixTable::GetNextRouter(PrefixTableIterator &aIterator, RouterEntry &aEntry) const
{
Error error = kErrorNone;
Iterator &iterator = static_cast<Iterator &>(aIterator);
VerifyOrExit(iterator.GetRouter() != nullptr, error = kErrorNotFound);
iterator.GetRouter()->CopyInfoTo(aEntry);
iterator.Advance(Iterator::kToNextRouter);
exit:
return error;
}
//---------------------------------------------------------------------------------------------------------------------
// DiscoveredPrefixTable::Iterator
void RoutingManager::DiscoveredPrefixTable::Iterator::Init(const LinkedList<Router> &aRouters)
{
SetInitTime();
SetRouter(aRouters.GetHead());
SetEntry(aRouters.IsEmpty() ? nullptr : aRouters.GetHead()->mEntries.GetHead());
}
void RoutingManager::DiscoveredPrefixTable::Iterator::Advance(AdvanceMode aMode)
{
switch (aMode)
{
case kToNextEntry:
SetEntry(GetEntry()->GetNext());
if (GetEntry() != nullptr)
{
break;
}
OT_FALL_THROUGH;
case kToNextRouter:
SetRouter(GetRouter()->GetNext());
if (GetRouter() != nullptr)
{
SetEntry(GetRouter()->mEntries.GetHead());
}
break;
}
}
//---------------------------------------------------------------------------------------------------------------------
// DiscoveredPrefixTable::Entry
@@ -1957,6 +1992,17 @@ uint32_t RoutingManager::DiscoveredPrefixTable::Entry::CalculateExpireDelay(uint
return delay;
}
//---------------------------------------------------------------------------------------------------------------------
// DiscoveredPrefixTable::Router
void RoutingManager::DiscoveredPrefixTable::Router::CopyInfoTo(RouterEntry &aEntry) const
{
aEntry.mAddress = mAddress;
aEntry.mManagedAddressConfigFlag = mManagedAddressConfigFlag;
aEntry.mOtherConfigFlag = mOtherConfigFlag;
aEntry.mStubRouterFlag = mStubRouterFlag;
}
//---------------------------------------------------------------------------------------------------------------------
// FavoredOmrPrefix
+32 -3
View File
@@ -87,6 +87,7 @@ public:
typedef NetworkData::RoutePreference RoutePreference; ///< Route preference (high, medium, low).
typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator.
typedef otBorderRoutingPrefixTableEntry PrefixTableEntry; ///< Prefix Table Entry.
typedef otBorderRoutingRouterEntry RouterEntry; ///< Router Entry.
/**
* This constant specifies the maximum number of route prefixes that may be published by `RoutingManager`
@@ -466,6 +467,21 @@ public:
return mDiscoveredPrefixTable.GetNextEntry(aIterator, aEntry);
}
/**
* Iterates over discovered router entries on infrastructure link.
*
* @param[in,out] aIterator An iterator.
* @param[out] aEntry A reference to the entry to populate.
*
* @retval kErrorNone Got the next router info, @p aEntry is updated and @p aIterator is advanced.
* @retval kErrorNotFound No more routers.
*
*/
Error GetNextRouterEntry(PrefixTableIterator &aIterator, RouterEntry &aEntry) const
{
return mDiscoveredPrefixTable.GetNextRouter(aIterator, aEntry);
}
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
/**
* Determines whether to enable/disable SRP server when the auto-enable mode is changed on SRP server.
@@ -621,6 +637,7 @@ private:
void InitIterator(PrefixTableIterator &aIterator) const;
Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const;
Error GetNextRouter(PrefixTableIterator &aIterator, RouterEntry &aEntry) const;
void HandleEntryTimer(void);
void HandleRouterTimer(void);
@@ -758,6 +775,7 @@ private:
bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
bool Matches(EmptyChecker) const { return mEntries.IsEmpty(); }
void CopyInfoTo(RouterEntry &aEntry) const;
Router *mNext;
Ip6::Address mAddress;
@@ -772,12 +790,23 @@ private:
class Iterator : public PrefixTableIterator
{
public:
enum AdvanceMode : uint8_t
{
kToNextEntry,
kToNextRouter,
};
void Init(const LinkedList<Router> &aRouters);
void Advance(AdvanceMode aMode);
const Router *GetRouter(void) const { return static_cast<const Router *>(mPtr1); }
void SetRouter(const Router *aRouter) { mPtr1 = aRouter; }
const Entry *GetEntry(void) const { return static_cast<const Entry *>(mPtr2); }
void SetEntry(const Entry *aEntry) { mPtr2 = aEntry; }
TimeMilli GetInitTime(void) const { return TimeMilli(mData32); }
void SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); }
private:
void SetRouter(const Router *aRouter) { mPtr1 = aRouter; }
void SetEntry(const Entry *aEntry) { mPtr2 = aEntry; }
void SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); }
};
void ProcessRaHeader(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader, Router &aRouter);
+4 -4
View File
@@ -945,7 +945,7 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
{
Log(" on-link prefix:%s, valid:%u, preferred:%u, router:%s, age:%u",
AsCoreType(&entry.mPrefix).ToString().AsCString(), entry.mValidLifetime, entry.mPreferredLifetime,
AsCoreType(&entry.mRouterAddress).ToString().AsCString(), entry.mMsecSinceLastUpdate / 1000);
AsCoreType(&entry.mRouter.mAddress).ToString().AsCString(), entry.mMsecSinceLastUpdate / 1000);
onLinkPrefixCount++;
@@ -954,7 +954,7 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
const OnLinkPrefix &onLinkPrefix = aOnLinkPrefixes[index];
if ((onLinkPrefix.mPrefix == AsCoreType(&entry.mPrefix)) &&
(AsCoreType(&entry.mRouterAddress) == onLinkPrefix.mRouterAddress))
(AsCoreType(&entry.mRouter.mAddress) == onLinkPrefix.mRouterAddress))
{
VerifyOrQuit(entry.mValidLifetime == onLinkPrefix.mValidLifetime);
VerifyOrQuit(entry.mPreferredLifetime == onLinkPrefix.mPreferredLifetime);
@@ -967,7 +967,7 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
{
Log(" route prefix:%s, valid:%u, prf:%s, router:%s, age:%u",
AsCoreType(&entry.mPrefix).ToString().AsCString(), entry.mValidLifetime,
PreferenceToString(entry.mRoutePreference), AsCoreType(&entry.mRouterAddress).ToString().AsCString(),
PreferenceToString(entry.mRoutePreference), AsCoreType(&entry.mRouter.mAddress).ToString().AsCString(),
entry.mMsecSinceLastUpdate / 1000);
routePrefixCount++;
@@ -977,7 +977,7 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
const RoutePrefix &routePrefix = aRoutePrefixes[index];
if ((routePrefix.mPrefix == AsCoreType(&entry.mPrefix)) &&
(AsCoreType(&entry.mRouterAddress) == routePrefix.mRouterAddress))
(AsCoreType(&entry.mRouter.mAddress) == routePrefix.mRouterAddress))
{
VerifyOrQuit(entry.mValidLifetime == routePrefix.mValidLifetime);
VerifyOrQuit(static_cast<int8_t>(entry.mRoutePreference) == routePrefix.mPreference);