mirror of
https://github.com/espressif/openthread.git
synced 2026-08-12 21:57:47 +00:00
[history-tracker] add support for tracking favored on-link prefix (#11807)
This commit adds support to `HistoryTracker` to record the history of favored on-link prefixes on the AIL. It introduces the `otHistoryTrackerFavoredOnLinkPrefix` structure and a new API, `otHistoryTrackerIterateFavoredOnLinkPrefixHistory()`, to access the recorded data. The new CLI command `history onlinkprefix` is added to display the tracked history, showing the prefix, its age, and whether it is local to the Border Router.
This commit is contained in:
@@ -302,6 +302,18 @@ typedef struct otHistoryTrackerFavoredOmrPrefix
|
||||
bool mIsLocal : 1; ///< `true` if the prefix is the local OMR prefix; `false` otherwise.
|
||||
} otHistoryTrackerFavoredOmrPrefix;
|
||||
|
||||
/**
|
||||
* Represents a favored on-link prefix on AIL tracked by a device acting as a Border Router (BR).
|
||||
*
|
||||
* The `mIsLocal` field indicates whether the favored on-link prefix is the same as the local one maintained by this
|
||||
* BR.
|
||||
*/
|
||||
typedef struct otHistoryTrackerFavoredOnLinkPrefix
|
||||
{
|
||||
otIp6Prefix mOnLinkPrefix; ///< The on-link prefix.
|
||||
bool mIsLocal : 1; ///< `true` if the prefix is the local on-link prefix; `false` otherwise.
|
||||
} otHistoryTrackerFavoredOnLinkPrefix;
|
||||
|
||||
/**
|
||||
* Initializes an `otHistoryTrackerIterator`.
|
||||
*
|
||||
@@ -516,6 +528,25 @@ const otHistoryTrackerFavoredOmrPrefix *otHistoryTrackerIterateFavoredOmrPrefixH
|
||||
otHistoryTrackerIterator *aIterator,
|
||||
uint32_t *aEntryAge);
|
||||
|
||||
/**
|
||||
* Iterates over the entries in the favored on-link prefix history list.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` (device acting as Border Router).
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
* @param[in,out] aIterator A pointer to an iterator. MUST be initialized or the behavior is undefined.
|
||||
* @param[out] aEntryAge A pointer to a variable to output the entry's age. MUST NOT be NULL.
|
||||
* Age is provided as the duration (in milliseconds) from when the entry was recorded to
|
||||
* @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
|
||||
* older than the max age.
|
||||
*
|
||||
* @returns The `otHistoryTrackerFavoredOnLinkPrefix` entry or `NULL` if no more entries in the list.
|
||||
*/
|
||||
const otHistoryTrackerFavoredOnLinkPrefix *otHistoryTrackerIterateFavoredOnLinkPrefixHistory(
|
||||
otInstance *aInstance,
|
||||
otHistoryTrackerIterator *aIterator,
|
||||
uint32_t *aEntryAge);
|
||||
|
||||
/**
|
||||
* Converts a given entry age to a human-readable string.
|
||||
*
|
||||
|
||||
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (525)
|
||||
#define OPENTHREAD_API_VERSION (526)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -17,6 +17,7 @@ Usage : `history [command] ...`
|
||||
- [neighbor](#neighbor)
|
||||
- [netinfo](#netinfo)
|
||||
- [omrprefix](#omrprefix)
|
||||
- [onlinkprefix](#onlinkprefix)
|
||||
- [prefix](#prefix)
|
||||
- [route](#route)
|
||||
- [router](#router)
|
||||
@@ -317,7 +318,7 @@ Print the OMR prefix history as a table.
|
||||
Done
|
||||
```
|
||||
|
||||
Print the OMR prefix history as a list
|
||||
Print the OMR prefix history as a list.
|
||||
|
||||
```bash
|
||||
> history omrprefix list
|
||||
@@ -327,6 +328,37 @@ Print the OMR prefix history as a list
|
||||
Done
|
||||
```
|
||||
|
||||
### onlinkprefix
|
||||
|
||||
Usage `history onlinkprefix [list] [<num-entries>]`
|
||||
|
||||
Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE`.
|
||||
|
||||
Print the favored on-link prefix history. Each entry provides:
|
||||
|
||||
- The favored on-link prefix (on AIL).
|
||||
- IsLocal as boolean `yes`/`no` indicating whether the favored on-link prefix is the same as the local one maintained by this BR.
|
||||
|
||||
Print the on-link prefix history as a table.
|
||||
|
||||
```bash
|
||||
> history onlinkprefix
|
||||
| Age | On-link Prefix |IsLocal |
|
||||
+----------------------+--------------------------------------------------+--------+
|
||||
| 00:00:50.600 | 2001:efc6:75a8:efee::/64 | no |
|
||||
| 00:11:04.327 | fd74:fe69:9f21:437::/64 | yes |
|
||||
Done
|
||||
```
|
||||
|
||||
Print the on-link prefix history as a list.
|
||||
|
||||
```bash
|
||||
> history onlinkprefix list
|
||||
00:00:50.600 -> on-link-prefix:2001:efc6:75a8:efee::/64 is-local:no
|
||||
00:11:04.327 -> on-link-prefix:fd74:fe69:9f21:437::/64 is-local:yes
|
||||
Done
|
||||
```
|
||||
|
||||
### prefix
|
||||
|
||||
Usage `history prefix [list] [<num-entries>]`
|
||||
|
||||
+75
-4
@@ -1614,6 +1614,76 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @cli history onlinkprefix
|
||||
* @code
|
||||
* history onlinkprefix
|
||||
* | Age | On-link Prefix |IsLocal |
|
||||
* +----------------------+--------------------------------------------------+--------+
|
||||
* | 00:00:50.600 | 2001:efc6:75a8:efee::/64 | no |
|
||||
* | 00:11:04.327 | fd74:fe69:9f21:437::/64 | yes |
|
||||
* Done
|
||||
* @endcode
|
||||
* @code
|
||||
* history onlinkprefix list
|
||||
* 00:00:50.600 -> on-link-prefix:2001:efc6:75a8:efee::/64 is-local:no
|
||||
* 00:11:04.327 -> on-link-prefix:fd74:fe69:9f21:437::/64 is-local:yes
|
||||
* Done
|
||||
* @endcode
|
||||
* @cparam history onlinkprefix [@ca{list}] [@ca{num-entries}]
|
||||
* * Use the `list` option to display the output in list format. Otherwise, the output is shown in table format.
|
||||
* * Use the `num-entries` option to limit the output to the number of most-recent entries specified. If this option
|
||||
* is not used, all stored entries are shown in the output.
|
||||
* @par
|
||||
* Displays the favored on-link prefix history in table or list format.
|
||||
* @par
|
||||
* Each table or list entry provides:
|
||||
* * Age: Time elapsed since the command was issued, and given in the format:
|
||||
* `hours`:`minutes`:`seconds`.`milliseconds`
|
||||
* * On-link Prefix: The favored on-link prefix on AIL.
|
||||
* * IsLocal: Indicates whether the favored on-link prefix is the same as the local one maintained by this BR.
|
||||
* @sa otHistoryTrackerIterateFavoredOnLinkPrefixHistory
|
||||
*/
|
||||
template <> otError History::Process<Cmd("onlinkprefix")>(Arg aArgs[])
|
||||
{
|
||||
otError error;
|
||||
bool isList;
|
||||
uint16_t numEntries;
|
||||
otHistoryTrackerIterator iterator;
|
||||
const otHistoryTrackerFavoredOnLinkPrefix *info;
|
||||
uint32_t entryAge;
|
||||
char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
|
||||
char prefixString[OT_IP6_PREFIX_STRING_SIZE];
|
||||
|
||||
SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
|
||||
|
||||
if (!isList)
|
||||
{
|
||||
static const char *const kTitles[] = {"Age", "On-link Prefix", "IsLocal"};
|
||||
static const uint8_t kColumnWidths[] = {22, 50, 8};
|
||||
|
||||
OutputTableHeader(kTitles, kColumnWidths);
|
||||
}
|
||||
|
||||
otHistoryTrackerInitIterator(&iterator);
|
||||
|
||||
for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
|
||||
{
|
||||
info = otHistoryTrackerIterateFavoredOnLinkPrefixHistory(GetInstancePtr(), &iterator, &entryAge);
|
||||
VerifyOrExit(info != nullptr);
|
||||
|
||||
otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
|
||||
|
||||
otIp6PrefixToString(&info->mOnLinkPrefix, prefixString, sizeof(prefixString));
|
||||
|
||||
OutputLine(isList ? "%s -> on-link-prefix:%s is-local:%s" : "| %20s | %-48s | %-6s |", ageString, prefixString,
|
||||
info->mIsLocal ? "yes" : "no");
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
const char *History::DnsSrpAddrTypeToString(otHistoryTrackerDnsSrpAddrType aType)
|
||||
@@ -1636,12 +1706,13 @@ otError History::Process(Arg aArgs[])
|
||||
#define CmdEntry(aCommandString) {aCommandString, &History::Process<Cmd(aCommandString)>}
|
||||
|
||||
static constexpr Command kCommands[] = {
|
||||
CmdEntry("dnssrpaddr"), CmdEntry("ipaddr"), CmdEntry("ipmaddr"), CmdEntry("neighbor"), CmdEntry("netinfo"),
|
||||
CmdEntry("dnssrpaddr"), CmdEntry("ipaddr"), CmdEntry("ipmaddr"),
|
||||
CmdEntry("neighbor"), CmdEntry("netinfo"),
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
CmdEntry("omrprefix"),
|
||||
CmdEntry("omrprefix"), CmdEntry("onlinkprefix"),
|
||||
#endif
|
||||
CmdEntry("prefix"), CmdEntry("route"), CmdEntry("router"), CmdEntry("rx"), CmdEntry("rxtx"),
|
||||
CmdEntry("tx"),
|
||||
CmdEntry("prefix"), CmdEntry("route"), CmdEntry("router"),
|
||||
CmdEntry("rx"), CmdEntry("rxtx"), CmdEntry("tx"),
|
||||
};
|
||||
|
||||
#undef CmdEntry
|
||||
|
||||
@@ -153,6 +153,7 @@ const otHistoryTrackerBorderAgentEpskcEvent *otHistoryTrackerIterateBorderAgentE
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
const otHistoryTrackerFavoredOmrPrefix *otHistoryTrackerIterateFavoredOmrPrefixHistory(
|
||||
otInstance *aInstance,
|
||||
otHistoryTrackerIterator *aIterator,
|
||||
@@ -163,6 +164,18 @@ const otHistoryTrackerFavoredOmrPrefix *otHistoryTrackerIterateFavoredOmrPrefixH
|
||||
return AsCoreType(aInstance).Get<HistoryTracker::Local>().IterateFavoredOmrPrefixHistory(AsCoreType(aIterator),
|
||||
*aEntryAge);
|
||||
}
|
||||
|
||||
const otHistoryTrackerFavoredOnLinkPrefix *otHistoryTrackerIterateFavoredOnLinkPrefixHistory(
|
||||
otInstance *aInstance,
|
||||
otHistoryTrackerIterator *aIterator,
|
||||
uint32_t *aEntryAge)
|
||||
{
|
||||
AssertPointerIsNotNull(aEntryAge);
|
||||
|
||||
return AsCoreType(aInstance).Get<HistoryTracker::Local>().IterateFavoredOnLinkPrefixHistory(AsCoreType(aIterator),
|
||||
*aEntryAge);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void otHistoryTrackerEntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize)
|
||||
|
||||
@@ -3072,6 +3072,10 @@ void RoutingManager::OnLinkPrefixManager::SetFavoredPrefix(const Ip6::Prefix &aP
|
||||
|
||||
mFavoredPrefix = aPrefix;
|
||||
|
||||
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
|
||||
Get<HistoryTracker::Local>().RecordFavoredOnLinkPrefix(mFavoredPrefix, mFavoredPrefix == mLocalPrefix);
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -193,6 +193,17 @@
|
||||
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_OMR_PREFIX_LIST_SIZE 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_LINK_PREFIX_LIST_SIZE
|
||||
*
|
||||
* Specifies the maximum number of entries in On-Link Prefix (on AIL) history.
|
||||
*
|
||||
* Can be set to zero to configure History Tracker module not to collect any on-link prefix info.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_LINK_PREFIX_LIST_SIZE
|
||||
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_LINK_PREFIX_LIST_SIZE 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -595,6 +595,19 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Local::RecordFavoredOnLinkPrefix(const Ip6::Prefix &aPrefix, bool aIsLocal)
|
||||
{
|
||||
FavoredOnLinkPrefix *entry = mFavoredOnLinkPrefixHistory.AddNewEntry();
|
||||
|
||||
VerifyOrExit(entry != nullptr);
|
||||
|
||||
entry->mOnLinkPrefix = aPrefix;
|
||||
entry->mIsLocal = aIsLocal;
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
void Local::HandleNotifierEvents(Events aEvents)
|
||||
@@ -629,6 +642,7 @@ void Local::HandleTimer(void)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
mFavoredOmrPrefixHistory.UpdateAgedEntries();
|
||||
mFavoredOnLinkPrefixHistory.UpdateAgedEntries();
|
||||
#endif
|
||||
mTimer.Start(kAgeCheckPeriod);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,8 @@ typedef otHistoryTrackerDnsSrpAddrInfo DnsSrpAddrInfo; ///< Network
|
||||
typedef otHistoryTrackerBorderAgentEpskcEvent EpskcEvent; ///< Border Agent ePSKc Event.
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
typedef otHistoryTrackerFavoredOmrPrefix FavoredOmrPrefix; ///< Favored OMR Prefix
|
||||
typedef otHistoryTrackerFavoredOmrPrefix FavoredOmrPrefix; ///< Favored OMR Prefix
|
||||
typedef otHistoryTrackerFavoredOnLinkPrefix FavoredOnLinkPrefix; ///< Favored On-link Prefix
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -279,6 +280,11 @@ public:
|
||||
{
|
||||
return mFavoredOmrPrefixHistory.Iterate(aIterator, aEntryAge);
|
||||
}
|
||||
|
||||
const FavoredOnLinkPrefix *IterateFavoredOnLinkPrefixHistory(Iterator &aIterator, uint32_t &aEntryAge) const
|
||||
{
|
||||
return mFavoredOnLinkPrefixHistory.Iterate(aIterator, aEntryAge);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -315,6 +321,7 @@ private:
|
||||
static constexpr uint16_t kDnsSrpAddrListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_DNSSRP_ADDR_LIST_SIZE;
|
||||
static constexpr uint16_t kEpskcEventListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_EPSKC_EVENT_SIZE;
|
||||
static constexpr uint16_t kOmrPrefixListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_OMR_PREFIX_LIST_SIZE;
|
||||
static constexpr uint16_t kOnLinkPrefixListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_LINK_PREFIX_LIST_SIZE;
|
||||
|
||||
typedef otHistoryTrackerAddressEvent AddressEvent;
|
||||
|
||||
@@ -496,6 +503,7 @@ private:
|
||||
void RecordFavoredOmrPrefix(const Ip6::Prefix &aPrefix,
|
||||
BorderRouter::RoutingManager::RoutePreference aPreference,
|
||||
bool aIsLocal);
|
||||
void RecordFavoredOnLinkPrefix(const Ip6::Prefix &aPrefix, bool aIsLocal);
|
||||
#endif
|
||||
|
||||
using TrackerTimer = TimerMilliIn<Local, &Local::HandleTimer>;
|
||||
@@ -514,7 +522,8 @@ private:
|
||||
EntryList<EpskcEvent, kEpskcEventListSize> mEpskcEventHistory;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
EntryList<FavoredOmrPrefix, kOmrPrefixListSize> mFavoredOmrPrefixHistory;
|
||||
EntryList<FavoredOmrPrefix, kOmrPrefixListSize> mFavoredOmrPrefixHistory;
|
||||
EntryList<FavoredOnLinkPrefix, kOnLinkPrefixListSize> mFavoredOnLinkPrefixHistory;
|
||||
#endif
|
||||
|
||||
TrackerTimer mTimer;
|
||||
|
||||
@@ -100,13 +100,15 @@ verify(br1_favored_onlink == br2_favored_onlink)
|
||||
# Check that the two BRs discover and track each other (not as peer BR since
|
||||
# connected to different networks).
|
||||
|
||||
for br in [br1, br1]:
|
||||
for br in [br1, br2]:
|
||||
routers = br.br_get_routers()
|
||||
verify(len(routers) > 0)
|
||||
for router in routers:
|
||||
verify('reachable:yes' in router)
|
||||
verify('S:1' in router)
|
||||
verify(not router.endswith('(peer BR)'))
|
||||
hist_list = br.cli('history onlinkprefix list')
|
||||
verify(len(hist_list) == 1)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
Reference in New Issue
Block a user