mirror of
https://github.com/espressif/openthread.git
synced 2026-09-08 10:10:06 +00:00
[routing-manager] add public API to get discovered prefix table (#7877)
This commit adds new public OT APIs to iterate over the Border Router discovered prefix table from received Router Advertisement messages. It also adds new CLI command to output the prefix table. The new APIs are primary intended for testing.
This commit is contained in:
committed by
Jonathan Hui
parent
75ecf8d260
commit
5876ff79ae
@@ -72,6 +72,40 @@ extern "C" {
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This structure represents an iterator to iterate through the Border Router's discovered prefix table.
|
||||
*
|
||||
* The fields in this type are opaque (intended for use by OpenThread core only) and therefore should not be
|
||||
* accessed or used by caller.
|
||||
*
|
||||
* Before using an iterator, it MUST be initialized using `otBorderRoutingPrefixTableInitIterator()`.
|
||||
*
|
||||
*/
|
||||
typedef struct otBorderRoutingPrefixTableIterator
|
||||
{
|
||||
const void *mPtr1;
|
||||
const void *mPtr2;
|
||||
uint32_t mData32;
|
||||
} otBorderRoutingPrefixTableIterator;
|
||||
|
||||
/**
|
||||
* This structure 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.
|
||||
*
|
||||
*/
|
||||
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.
|
||||
} otBorderRoutingPrefixTableEntry;
|
||||
|
||||
/**
|
||||
* This method initializes the Border Routing Manager on given infrastructure interface.
|
||||
*
|
||||
@@ -178,6 +212,37 @@ otError otBorderRoutingGetOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPref
|
||||
*/
|
||||
otError otBorderRoutingGetNat64Prefix(otInstance *aInstance, otIp6Prefix *aPrefix);
|
||||
|
||||
/**
|
||||
* This function initializes an `otBorderRoutingPrefixTableIterator`.
|
||||
*
|
||||
* An iterator MUST be initialized before it is used.
|
||||
*
|
||||
* An iterator can be initialized again to restart from the beginning of the table.
|
||||
*
|
||||
* When iterating over entries in the table, to ensure the update times `mMsecSinceLastUpdate` of entries are
|
||||
* consistent, they are given relative to the time the iterator was initialized.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
* @param[out] aIterator A pointer to the iterator to initialize.
|
||||
*
|
||||
*/
|
||||
void otBorderRoutingPrefixTableInitIterator(otInstance *aInstance, otBorderRoutingPrefixTableIterator *aIterator);
|
||||
|
||||
/**
|
||||
* This function iterates over the entries in the Border Router's discovered prefix table.
|
||||
*
|
||||
* @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 entry, @p aEntry and @p aIterator are updated.
|
||||
* @retval OT_ERROR_NOT_FOUND No more entries in the table.
|
||||
*
|
||||
*/
|
||||
otError otBorderRoutingGetNextPrefixTableEntry(otInstance * aInstance,
|
||||
otBorderRoutingPrefixTableIterator *aIterator,
|
||||
otBorderRoutingPrefixTableEntry * aEntry);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (224)
|
||||
#define OPENTHREAD_API_VERSION (225)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
+45
-1
@@ -605,7 +605,7 @@ template <> otError Interpreter::Process<Cmd("br")>(Arg aArgs[])
|
||||
* #otBorderRoutingSetRouteInfoOptionPreference
|
||||
*
|
||||
*/
|
||||
else if ((aArgs[0] == "rioprf"))
|
||||
else if (aArgs[0] == "rioprf")
|
||||
{
|
||||
if (aArgs[1].IsEmpty())
|
||||
{
|
||||
@@ -619,6 +619,50 @@ template <> otError Interpreter::Process<Cmd("br")>(Arg aArgs[])
|
||||
otBorderRoutingSetRouteInfoOptionPreference(GetInstancePtr(), preference);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @cli br prefixtable
|
||||
*
|
||||
* @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
|
||||
* 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
|
||||
* Done
|
||||
* @endcode
|
||||
*
|
||||
* @par api_copy
|
||||
* #otBorderRoutingGetNextPrefixTableEntry
|
||||
*
|
||||
*/
|
||||
else if (aArgs[0] == "prefixtable")
|
||||
{
|
||||
otBorderRoutingPrefixTableIterator iterator;
|
||||
otBorderRoutingPrefixTableEntry entry;
|
||||
|
||||
otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
|
||||
|
||||
while (otBorderRoutingGetNextPrefixTableEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
|
||||
{
|
||||
char string[OT_IP6_PREFIX_STRING_SIZE];
|
||||
|
||||
otIp6PrefixToString(&entry.mPrefix, string, sizeof(string));
|
||||
OutputFormat("prefix:%s, on-link:%s, ms-since-rx:%u, lifetime:%u, ", string, entry.mIsOnLink ? "yes" : "no",
|
||||
entry.mMsecSinceLastUpdate, entry.mValidLifetime);
|
||||
|
||||
if (entry.mIsOnLink)
|
||||
{
|
||||
OutputFormat("preferred:%u, ", entry.mPreferredLifetime);
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputFormat("route-prf:%s, ", PreferenceToString(entry.mRoutePreference));
|
||||
}
|
||||
|
||||
otIp6AddressToString(&entry.mRouterAddress, string, sizeof(string));
|
||||
OutputLine("router:%s", string);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_COMMAND;
|
||||
|
||||
@@ -81,4 +81,16 @@ otError otBorderRoutingGetNat64Prefix(otInstance *aInstance, otIp6Prefix *aPrefi
|
||||
}
|
||||
#endif
|
||||
|
||||
void otBorderRoutingPrefixTableInitIterator(otInstance *aInstance, otBorderRoutingPrefixTableIterator *aIterator)
|
||||
{
|
||||
AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().InitPrefixTableIterator(*aIterator);
|
||||
}
|
||||
|
||||
otError otBorderRoutingGetNextPrefixTableEntry(otInstance * aInstance,
|
||||
otBorderRoutingPrefixTableIterator *aIterator,
|
||||
otBorderRoutingPrefixTableEntry * aEntry)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetNextPrefixTableEntry(*aIterator, *aEntry);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
@@ -1805,6 +1805,53 @@ void RoutingManager::DiscoveredPrefixTable::HandleSignalTask(Tasklet &aTasklet)
|
||||
aTasklet.Get<RoutingManager>().HandleDiscoveredPrefixTableChanged();
|
||||
}
|
||||
|
||||
void RoutingManager::DiscoveredPrefixTable::InitIterator(PrefixTableIterator &aIterator) const
|
||||
{
|
||||
Iterator &iterator = static_cast<Iterator &>(aIterator);
|
||||
|
||||
iterator.SetInitTime();
|
||||
iterator.SetRouter(mRouters.Front());
|
||||
iterator.SetEntry(mRouters.IsEmpty() ? nullptr : mRouters[0].mEntries.GetHead());
|
||||
}
|
||||
|
||||
Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &aIterator,
|
||||
PrefixTableEntry & aEntry) const
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Iterator &iterator = static_cast<Iterator &>(aIterator);
|
||||
|
||||
VerifyOrExit(iterator.GetRouter() != nullptr, error = kErrorNotFound);
|
||||
OT_ASSERT(iterator.GetEntry() != nullptr);
|
||||
|
||||
aEntry.mRouterAddress = iterator.GetRouter()->mAddress;
|
||||
aEntry.mPrefix = iterator.GetEntry()->GetPrefix();
|
||||
aEntry.mIsOnLink = iterator.GetEntry()->IsOnLinkPrefix();
|
||||
aEntry.mMsecSinceLastUpdate = iterator.GetInitTime() - iterator.GetEntry()->GetLastUpdateTime();
|
||||
aEntry.mValidLifetime = iterator.GetEntry()->GetValidLifetime();
|
||||
aEntry.mPreferredLifetime = aEntry.mIsOnLink ? iterator.GetEntry()->GetPreferredLifetime() : 0;
|
||||
aEntry.mRoutePreference =
|
||||
static_cast<otRoutePreference>(aEntry.mIsOnLink ? 0 : iterator.GetEntry()->GetRoutePreference());
|
||||
|
||||
// Advance the iterator
|
||||
iterator.SetEntry(iterator.GetEntry()->GetNext());
|
||||
|
||||
if (iterator.GetEntry() == nullptr)
|
||||
{
|
||||
if (iterator.GetRouter() != mRouters.Back())
|
||||
{
|
||||
iterator.SetRouter(iterator.GetRouter() + 1);
|
||||
iterator.SetEntry(iterator.GetRouter()->mEntries.GetHead());
|
||||
}
|
||||
else
|
||||
{
|
||||
iterator.SetRouter(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// DiscoveredPrefixTable::Entry
|
||||
|
||||
|
||||
@@ -79,7 +79,9 @@ class RoutingManager : public InstanceLocator
|
||||
friend class ot::Instance;
|
||||
|
||||
public:
|
||||
typedef NetworkData::RoutePreference RoutePreference; ///< Route preference (high, medium, low).
|
||||
typedef NetworkData::RoutePreference RoutePreference; ///< Route preference (high, medium, low).
|
||||
typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator.
|
||||
typedef otBorderRoutingPrefixTableEntry PrefixTableEntry; ///< Prefix Table Entry.
|
||||
|
||||
/**
|
||||
* This constructor initializes the routing manager.
|
||||
@@ -219,6 +221,37 @@ public:
|
||||
*/
|
||||
static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix);
|
||||
|
||||
/**
|
||||
* This method initializes a `PrefixTableIterator`.
|
||||
*
|
||||
* An iterator can be initialized again to start from the beginning of the table.
|
||||
*
|
||||
* When iterating over entries in the table, to ensure the entry update times are consistent, they are given
|
||||
* relative to the time the iterator was initialized.
|
||||
*
|
||||
* @param[out] aIterator The iterator to initialize.
|
||||
*
|
||||
*/
|
||||
void InitPrefixTableIterator(PrefixTableIterator &aIterator) const
|
||||
{
|
||||
mDiscoveredPrefixTable.InitIterator(aIterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method iterates over entries in the discovered prefix table.
|
||||
*
|
||||
* @param[in,out] aIterator An iterator.
|
||||
* @param[out] aEntry A reference to the entry to populate.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Got the next entry, @p aEntry is updated and @p aIterator is advanced.
|
||||
* @retval OT_ERROR_NOT_FOUND No more entries in the table.
|
||||
*
|
||||
*/
|
||||
Error GetNextPrefixTableEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const
|
||||
{
|
||||
return mDiscoveredPrefixTable.GetNextEntry(aIterator, aEntry);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint16_t kMaxRouterAdvMessageLength = 256; // The maximum RA message length we can handle.
|
||||
|
||||
@@ -312,6 +345,9 @@ private:
|
||||
|
||||
TimeMilli CalculateNextStaleTime(TimeMilli aNow) const;
|
||||
|
||||
void InitIterator(PrefixTableIterator &aIterator) const;
|
||||
Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const;
|
||||
|
||||
private:
|
||||
static constexpr uint16_t kMaxRouters = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_ROUTERS;
|
||||
static constexpr uint16_t kMaxEntries = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES;
|
||||
@@ -403,6 +439,17 @@ private:
|
||||
LinkedList<Entry> mEntries;
|
||||
};
|
||||
|
||||
class Iterator : public PrefixTableIterator
|
||||
{
|
||||
public:
|
||||
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(); }
|
||||
};
|
||||
|
||||
void ProcessDefaultRoute(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader, Router &aRouter);
|
||||
void ProcessPrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio, Router &aRouter);
|
||||
void ProcessRouteInfoOption(const Ip6::Nd::RouteInfoOption &aRio, Router &aRouter);
|
||||
|
||||
Reference in New Issue
Block a user