[history-tracker] record AIL router history (#11827)

This commit enhances the `HistoryTracker` to record information about
routers discovered on the Adjacent Infrastructure Link (AIL).

This feature is applicable when the device operates as a Border
Router, providing a mechanism to monitor the history of changes to
the discovered AIL routers for debugging and network analysis.

The history tracker records events when an AIL router is added,
removed, or when its tracked information changes. The recorded
information includes:
- The IPv6 address of the router
- Default router status and its preference
- RA flags: 'M' (Managed Addr), 'O' (Other), 'S' (SNAC Router)
- Operational information:
  - Whether the router is a local entity (on same device)
  - Reachability status
  - Whether it is a peer Border Router on the same Thread mesh
- The favored advertised on-link prefix by this router (if any)

A new public API, `otHistoryTrackerIterateAilRoutersHistory()`, is
added to iterate over the recorded AIL router history. A
corresponding CLI command, `history ailrouters`, is also included to
display this information.
This commit is contained in:
Abtin Keshavarzian
2025-08-22 17:15:02 -07:00
committed by GitHub
parent 2c697309b6
commit dd893ce001
12 changed files with 437 additions and 7 deletions
+61
View File
@@ -314,6 +314,49 @@ typedef struct otHistoryTrackerFavoredOnLinkPrefix
bool mIsLocal : 1; ///< `true` if the prefix is the local on-link prefix; `false` otherwise.
} otHistoryTrackerFavoredOnLinkPrefix;
/**
* Defines events for discovered routers on an Adjacent Infrastructure Link (AIL).
*
* This applies when a device is acting as a Border Router, processing received Router Advertisements and tracking
* AIL routers.
*
* `OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_CHANGED` is used if any of the properties in the `otHistoryTrackerAilRouter`
* structure associated with a specific router changes.
*/
typedef enum
{
OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_ADDED = 0, ///< A new AIL router is discovered.
OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_CHANGED = 1, ///< A property in the router's information has changed.
OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_REMOVED = 2, ///< The AIL router is removed and no longer tracked.
} otHistoryTrackerAilRouterEvent;
/**
* Represents information about a discovered router on an Adjacent Infrastructure Link (AIL).
*
* This applies when a device is acting as a Border Router, processing received Router Advertisements and tracking
* information about discovered AIL routers.
*
* `mProvidesDefaultRoute` indicates whether the router provides a default route. If it does, `mDefRoutePreference`
* specifies the route preference.
*
* `mFavoredOnLinkPrefix` indicates the favored on-link prefix advertised by the router. If there is no on-link prefix,
* this will be an empty prefix (i.e., its length will be zero).
*/
typedef struct otHistoryTrackerAilRouter
{
otHistoryTrackerAilRouterEvent mEvent; ///< The event type (e.g., added, changed, removed).
int8_t mDefRoutePreference; ///< Def route preference.
otIp6Address mAddress; ///< The IPv6 address of the AIL router.
otIp6Prefix mFavoredOnLinkPrefix; ///< The favored on-link prefix, if any.
bool mProvidesDefaultRoute : 1; ///< Whether the router provides a default route.
bool mManagedAddressConfigFlag : 1; ///< The Managed Address Config flag (`M` flag).
bool mOtherConfigFlag : 1; ///< The Other Config flag (`O` flag).
bool mSnacRouterFlag : 1; ///< The SNAC Router flag (`S` flag).
bool mIsLocalDevice : 1; ///< This router is the local device (this BR).
bool mIsReachable : 1; ///< This router is reachable.
bool mIsPeerBr : 1; ///< This router is (likely) a peer BR.
} otHistoryTrackerAilRouter;
/**
* Initializes an `otHistoryTrackerIterator`.
*
@@ -547,6 +590,24 @@ const otHistoryTrackerFavoredOnLinkPrefix *otHistoryTrackerIterateFavoredOnLinkP
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge);
/**
* Iterates over the entries in the BR AIL routers 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 `otHistoryTrackerAilRouter` entry or `NULL` if no more entries in the list.
*/
const otHistoryTrackerAilRouter *otHistoryTrackerIterateAilRoutersHistory(otInstance *aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge);
/**
* Converts a given entry age to a human-readable string.
*
+1 -1
View File
@@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (527)
#define OPENTHREAD_API_VERSION (528)
/**
* @addtogroup api-instance
+50
View File
@@ -11,6 +11,7 @@ The number of entries recorded for each history list is configurable through a s
Usage : `history [command] ...`
- [help](#help)
- [ailrouters](#ailrouters)
- [dnssrpaddr](#dnssrpaddr)
- [ipaddr](#ipaddr)
- [ipmaddr](#ipmaddr)
@@ -68,6 +69,55 @@ Done
>
```
### ailrouters
Usage `history ailrouters [list] [<num-entries>]`
Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE`.
Print the AIL routers history. Each entry provides:
- The event, possible values are `Added`, `Changed`, `Removed`.
- The IPv6 address of the AIL router.
- Flags
- `R`: Indicates whether or not this router is reachable.
- `M`: The Managed Address Config flag (from the received Router Advertisement (RA) header).
- `O`: The Other Config flag (from the RA header).
- `S`: The SNAC Router flag (from the RA header).
- `L`: Indicates whether or not this router is the local device (this BR).
- `P`: Indicates whether or not this router is a peer BR connected to same Thread mesh.
- `D`: Indicates whether or not this router provides a default route.
- The default route preference (`high`, `med`, `low`) if this router provides a default route. Otherwise `-`.
- The favored on-link prefix advertised by this router if any. If none, `-` is shown.
```bash
> history ailrouters
| Age | Event | IPv6 Address |R|M|O|S|L|P|D|RtPrf |
+----------------------+---------+------------------------------------------+-+-+-+-+-+-+-+------+
| | Favored on-link prefix | | | | | | | | |
+----------------------+----------------------------------------------------+-+-+-+-+-+-+-+------+
| 00:01:35.107 | Changed | fe80:0:0:0:0:0:0:2 |N|N|N|Y|N|Y|N| |
| | - | | | | | | | | |
| 00:05:01.115 | Changed | fe80:0:0:0:0:0:0:2 |Y|N|N|Y|N|Y|N| |
| | - | | | | | | | | |
| 00:08:01.804 | Added | fe80:0:0:0:0:0:0:2 |Y|N|N|Y|N|Y|N| |
| | fd99:4cdc:3b3d:56ef::/64 | | | | | | | | |
Done
```
Print the history as a list.
```bash
>history ailrouters list
00:01:35.161 -> event:Changed address:fe80:0:0:0:0:0:0:2 reachable:N M:N O:N S:Y local:N peer:Y def-route:N prf:
favored-on-link-prefix:-
00:05:01.169 -> event:Changed address:fe80:0:0:0:0:0:0:2 reachable:Y M:N O:N S:Y local:N peer:Y def-route:N prf:
favored-on-link-prefix:-
00:08:01.858 -> event:Added address:fe80:0:0:0:0:0:0:2 reachable:Y M:N O:N S:Y local:N peer:Y def-route:N prf:
favored-on-link-prefix:fd99:4cdc:3b3d:56ef::/64
Done
```
### dnssrpaddr
Usage `history dnssrpaddr [list] [<num-entries>]`
+123
View File
@@ -1684,6 +1684,126 @@ exit:
return error;
}
/**
* @cli history ailrouters
* @code
* history ailrouters
* | Age | Event | IPv6 Address |R|M|O|S|L|P|D|RtPrf |
* +----------------------+---------+------------------------------------------+-+-+-+-+-+-+-+------+
* | | Favored on-link prefix | | | | | | | | |
* +----------------------+----------------------------------------------------+-+-+-+-+-+-+-+------+
* | 00:01:35.107 | Changed | fe80:0:0:0:0:0:0:2 |N|N|N|Y|N|Y|N| |
* | | - | | | | | | | | |
* | 00:05:01.115 | Changed | fe80:0:0:0:0:0:0:2 |Y|N|N|Y|N|Y|N| |
* | | - | | | | | | | | |
* | 00:08:01.804 | Added | fe80:0:0:0:0:0:0:2 |Y|N|N|Y|N|Y|N| |
* | | fd99:4cdc:3b3d:56ef::/64 | | | | | | | | |
* Done
* @endcode
* @code
* history ailrouters list
* 00:01:35.161 -> event:Changed address:fe80:0:0:0:0:0:0:2 reachable:N M:N O:N S:Y local:N peer:Y def-route:N prf:
* favored-on-link-prefix:-
* 00:05:01.169 -> event:Changed address:fe80:0:0:0:0:0:0:2 reachable:Y M:N O:N S:Y local:N peer:Y def-route:N prf:
* favored-on-link-prefix:-
* 00:08:01.858 -> event:Added address:fe80:0:0:0:0:0:0:2 reachable:Y M:N O:N S:Y local:N peer:Y def-route:N prf:
* favored-on-link-prefix:fd99:4cdc:3b3d:56ef::/64
* Done
* @endcode
* @cparam history ailrouters [@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 AIL routers 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`
* * The event, possible values are `Added`, `Changed`, `Removed`.
* * The IPv6 address of the AIL router.
* * Flags
* * `R`: Indicates whether or not this router is reachable.
* * `M`: The Managed Address Config flag (from the Router Advertisement (RA) header).
* * `O`: The Other Config flag (from the RA header).
* * `S`: The SNAC Router flag (from the RA header).
* * `L`: Indicates whether or not this router is the local device (this BR).
* * `P`: Indicates whether or not this router is a peer BR connected to same Thread mesh.
* * `D`: Indicates whether or not this router provides a default route.
* * The default route preference (`high`, `med`, `low`) if this router provides a default route, otherwise `-`.
* * The favored on-link prefix advertised by this router if any. If none, `-` is shown.
* @sa otHistoryTrackerIterateAilRoutersHistory
*/
template <> otError History::Process<Cmd("ailrouters")>(Arg aArgs[])
{
otError error;
bool isList;
uint16_t numEntries;
otHistoryTrackerIterator iterator;
const otHistoryTrackerAilRouter *info;
uint32_t entryAge;
char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
char addrString[OT_IP6_ADDRESS_STRING_SIZE];
char prefixString[OT_IP6_PREFIX_STRING_SIZE];
SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
if (!isList)
{
static const char *const kTitles1[] = {"Age", "Event", "IPv6 Address", "R", "M", "O", "S", "L",
"P", "D", "RtPrf"};
static const uint8_t kColWidths1[] = {22, 9, 42, 1, 1, 1, 1, 1, 1, 1, 6};
static const char *const kTitles2[] = {"", "Favored on-link prefix", "", "", "", "", "", "", "", ""};
static const uint8_t kColWidths2[] = {22, 52, 1, 1, 1, 1, 1, 1, 1, 6};
OutputTableHeader(kTitles1, kColWidths1);
OutputTableHeader(kTitles2, kColWidths2);
}
otHistoryTrackerInitIterator(&iterator);
for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
{
info = otHistoryTrackerIterateAilRoutersHistory(GetInstancePtr(), &iterator, &entryAge);
VerifyOrExit(info != nullptr);
otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
otIp6AddressToString(&info->mAddress, addrString, sizeof(addrString));
otIp6PrefixToString(&info->mFavoredOnLinkPrefix, prefixString, sizeof(prefixString));
OutputLine(isList ? "%s -> event:%s address:%s reachable:%c M:%c O:%c S:%c local:%c peer:%c def-route:%c prf:%s"
: "| %20s | %-7s | %-40s |%c|%c|%c|%c|%c|%c|%c| %4s |",
ageString, AilRouterEventToString(info->mEvent), addrString, info->mIsReachable ? 'Y' : 'N',
info->mManagedAddressConfigFlag ? 'Y' : 'N', info->mOtherConfigFlag ? 'Y' : 'N',
info->mSnacRouterFlag ? 'Y' : 'N', info->mIsLocalDevice ? 'Y' : 'N', info->mIsPeerBr ? 'Y' : 'N',
info->mProvidesDefaultRoute ? 'Y' : 'N',
info->mProvidesDefaultRoute ? PreferenceToString(info->mDefRoutePreference) : "-");
OutputLine(isList ? " %sfavored-on-link-prefix:%s" : "| %20s | %-50s | | | | | | | | |", "",
info->mFavoredOnLinkPrefix.mLength == 0 ? "-" : prefixString);
}
exit:
return error;
}
const char *History::AilRouterEventToString(otHistoryTrackerAilRouterEvent aEvent)
{
static const char *const kAilRouterEventStrings[] = {
"Added", /* (0) OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_ADDED */
"Changed", /* (1) OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_CHANGED */
"Removed", /* (2) OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_REMOVED */
};
static_assert(OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_ADDED == 0, "AIL_ROUTER_EVENT_ADDED is incorrect");
static_assert(OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_CHANGED == 1, "AIL_ROUTER_EVENT_CHANGED is incorrect");
static_assert(OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_REMOVED == 2, "AIL_ROUTER_EVENT_REMOVED is incorrect");
return Stringify(aEvent, kAilRouterEventStrings, "--");
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
const char *History::DnsSrpAddrTypeToString(otHistoryTrackerDnsSrpAddrType aType)
@@ -1706,6 +1826,9 @@ otError History::Process(Arg aArgs[])
#define CmdEntry(aCommandString) {aCommandString, &History::Process<Cmd(aCommandString)>}
static constexpr Command kCommands[] = {
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
CmdEntry("ailrouters"),
#endif
CmdEntry("dnssrpaddr"), CmdEntry("ipaddr"), CmdEntry("ipmaddr"),
CmdEntry("neighbor"), CmdEntry("netinfo"),
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+1
View File
@@ -101,6 +101,7 @@ private:
static const char *RadioTypeToString(const otHistoryTrackerMessageInfo &aInfo);
static const char *MessageTypeToString(const otHistoryTrackerMessageInfo &aInfo);
static const char *DnsSrpAddrTypeToString(otHistoryTrackerDnsSrpAddrType aType);
static const char *AilRouterEventToString(otHistoryTrackerAilRouterEvent aEvent);
};
} // namespace Cli
+11 -1
View File
@@ -176,7 +176,17 @@ const otHistoryTrackerFavoredOnLinkPrefix *otHistoryTrackerIterateFavoredOnLinkP
*aEntryAge);
}
#endif
const otHistoryTrackerAilRouter *otHistoryTrackerIterateAilRoutersHistory(otInstance *aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge)
{
AssertPointerIsNotNull(aEntryAge);
return AsCoreType(aInstance).Get<HistoryTracker::Local>().IterateAilRoutersHistory(AsCoreType(aIterator),
*aEntryAge);
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
void otHistoryTrackerEntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize)
{
+118 -1
View File
@@ -1767,6 +1767,7 @@ void RoutingManager::RxRaTracker::Evaluate(void)
NextFireTime entryExpireTime(now);
NextFireTime staleTime(now);
NextFireTime rdnsssAddrExpireTime(now);
RouterList removedRouters;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Remove expired entries associated with each router
@@ -1788,7 +1789,16 @@ void RoutingManager::RxRaTracker::Evaluate(void)
// Remove any router entry that no longer has any valid on-link
// or route prefixes, RDNSS addresses, or other relevant flags set.
mRouters.RemoveAndFreeAllMatching(Router::EmptyChecker());
mRouters.RemoveAllMatching(removedRouters, Router::EmptyChecker());
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
for (Router &router : removedRouters)
{
ReportChangesToHistoryTracker(router, /* aRemoved */ true);
}
#endif
removedRouters.Free();
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Determine decision factors (favored on-link prefix, has any
@@ -1891,6 +1901,17 @@ void RoutingManager::RxRaTracker::Evaluate(void)
mExpirationTimer.FireAt(entryExpireTime);
mStaleTimer.FireAt(staleTime);
mRdnssAddrTimer.FireAt(rdnsssAddrExpireTime);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Report any changes to history tracker.
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
for (Router &router : mRouters)
{
ReportChangesToHistoryTracker(router, /* aRemoved */ false);
}
#endif
}
void RoutingManager::RxRaTracker::DetermineStaleTimeFor(const OnLinkPrefix &aPrefix, NextFireTime &aStaleTime)
@@ -2202,6 +2223,62 @@ uint16_t RoutingManager::RxRaTracker::CountReachablePeerBrs(void) const
}
#endif
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
void RoutingManager::RxRaTracker::ReportChangesToHistoryTracker(Router &aRouter, bool aRemoved)
{
// Report any changes in the `aRouter` to `HistoryTracker` only if
// something has changed since the last recorded event.
Router::HistoryInfo oldInfo;
HistoryTracker::AilRouter *entry;
if (aRemoved)
{
// If we have never recorded this router entry in the
// `HistoryTracker`, there is no point in reporting its
// removal. This can happen if we receive an RA from a router
// with no useful information that we want to track. In this
// case, the router entry is removed immediately during
// `Evaluate()`.
VerifyOrExit(aRouter.mHistoryInfo.mHistoryRecorded);
}
else
{
oldInfo = aRouter.mHistoryInfo;
}
aRouter.mHistoryInfo.DetermineFrom(aRouter);
VerifyOrExit(aRemoved || (aRouter.mHistoryInfo != oldInfo));
// Allocate and populate the new `HistoryTracker::AilRouter` entry.
entry = Get<HistoryTracker::Local>().RecordAilRouterEvent();
VerifyOrExit(entry != nullptr);
entry->mEvent = aRemoved ? HistoryTracker::Local::kAilRouterRemoved
: (oldInfo.mHistoryRecorded ? HistoryTracker::Local::kAilRouterChanged
: HistoryTracker::Local::kAilRouterAdded);
entry->mAddress = aRouter.mAddress;
entry->mDefRoutePreference = static_cast<int8_t>(aRouter.mHistoryInfo.mDefRoutePreference);
entry->mFavoredOnLinkPrefix = aRouter.mHistoryInfo.mFavoredOnLinkPrefix;
entry->mProvidesDefaultRoute = aRouter.mHistoryInfo.mProvidesDefaultRoute;
entry->mManagedAddressConfigFlag = aRouter.mHistoryInfo.mManagedAddressConfigFlag;
entry->mOtherConfigFlag = aRouter.mHistoryInfo.mOtherConfigFlag;
entry->mSnacRouterFlag = aRouter.mHistoryInfo.mSnacRouterFlag;
entry->mIsLocalDevice = aRouter.mHistoryInfo.mIsLocalDevice;
entry->mIsReachable = aRouter.mHistoryInfo.mIsReachable;
entry->mIsPeerBr = aRouter.mHistoryInfo.mIsPeerBr;
exit:
return;
}
#endif // OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
//---------------------------------------------------------------------------------------------------------------------
// RxRaTracker::Iterator
@@ -2430,6 +2507,46 @@ void RoutingManager::RxRaTracker::Router::CopyInfoTo(RouterEntry &aEntry, TimeMi
aEntry.mIsPeerBr = IsPeerBr();
}
//---------------------------------------------------------------------------------------------------------------------
// RxRaTracker::Router::HistoryInfo
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
void RoutingManager::RxRaTracker::Router::HistoryInfo::DetermineFrom(const Router &aRouter)
{
Ip6::Prefix emptyPrefix;
const RoutePrefix *defRoute;
Clear();
mHistoryRecorded = true;
mManagedAddressConfigFlag = aRouter.mManagedAddressConfigFlag;
mOtherConfigFlag = aRouter.mOtherConfigFlag;
mSnacRouterFlag = aRouter.mSnacRouterFlag;
mIsLocalDevice = aRouter.mIsLocalDevice;
mIsReachable = aRouter.IsReachable();
mIsPeerBr = aRouter.IsPeerBr();
emptyPrefix.Clear();
defRoute = aRouter.mRoutePrefixes.FindMatching(emptyPrefix);
if ((defRoute != nullptr) && (defRoute->GetValidLifetime() > 0))
{
mProvidesDefaultRoute = true;
mDefRoutePreference = defRoute->GetRoutePreference();
}
for (const OnLinkPrefix &onLinkPrefix : aRouter.mOnLinkPrefixes)
{
if (onLinkPrefix.IsFavoredOver(mFavoredOnLinkPrefix))
{
mFavoredOnLinkPrefix = onLinkPrefix.GetPrefix();
}
}
}
#endif // OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
//---------------------------------------------------------------------------------------------------------------------
// RxRaTracker::DecisionFactors
@@ -1123,6 +1123,24 @@ private:
{
};
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
struct HistoryInfo : public Equatable<HistoryInfo>, public Clearable<HistoryInfo>
{
void DetermineFrom(const Router &aRouter);
bool mHistoryRecorded : 1;
bool mManagedAddressConfigFlag : 1;
bool mOtherConfigFlag : 1;
bool mSnacRouterFlag : 1;
bool mIsLocalDevice : 1;
bool mIsReachable : 1;
bool mIsPeerBr : 1;
bool mProvidesDefaultRoute : 1;
RoutePreference mDefRoutePreference;
Ip6::Prefix mFavoredOnLinkPrefix;
};
#endif
bool IsReachable(void) const { return mNsProbeCount <= kMaxNsProbes; }
bool ShouldCheckReachability(void) const;
void ResetReachabilityState(void);
@@ -1159,6 +1177,9 @@ private:
bool mSnacRouterFlag : 1;
bool mIsLocalDevice : 1;
bool mAllEntriesDisregarded : 1;
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
HistoryInfo mHistoryInfo;
#endif
};
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1270,6 +1291,10 @@ private:
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
uint16_t CountReachablePeerBrs(void) const;
#endif
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
void ReportChangesToHistoryTracker(Router &aRouter, bool aRemoved);
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
template <class Type> Entry<Type> *AllocateEntry(void) { return Entry<Type>::Allocate(); }
#else
+11
View File
@@ -204,6 +204,17 @@
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_LINK_PREFIX_LIST_SIZE 16
#endif
/**
* @def OPENTHREAD_CONFIG_HISTORY_TRACKER_AIL_ROUTER_LIST_SIZE
*
* Specifies the maximum number of entries in BR AIL Router history.
*
* Can be set to zero to configure History Tracker module not to collect any BR AIL Router info.
*/
#ifndef OPENTHREAD_CONFIG_HISTORY_TRACKER_AIL_ROUTER_LIST_SIZE
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_AIL_ROUTER_LIST_SIZE 32
#endif
/**
* @}
*/
+3
View File
@@ -608,6 +608,8 @@ exit:
return;
}
AilRouter *Local::RecordAilRouterEvent(void) { return mAilRoutersHistory.AddNewEntry(); }
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
void Local::HandleNotifierEvents(Events aEvents)
@@ -643,6 +645,7 @@ void Local::HandleTimer(void)
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
mFavoredOmrPrefixHistory.UpdateAgedEntries();
mFavoredOnLinkPrefixHistory.UpdateAgedEntries();
mAilRoutersHistory.UpdateAgedEntries();
#endif
mTimer.Start(kAgeCheckPeriod);
}
+21 -4
View File
@@ -113,6 +113,7 @@ typedef otHistoryTrackerBorderAgentEpskcEvent EpskcEvent; ///< Border Agent ePSK
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
typedef otHistoryTrackerFavoredOmrPrefix FavoredOmrPrefix; ///< Favored OMR Prefix
typedef otHistoryTrackerFavoredOnLinkPrefix FavoredOnLinkPrefix; ///< Favored On-link Prefix
typedef otHistoryTrackerAilRouter AilRouter; ///< An AIL router tracked when acting as BR
#endif
/**
@@ -285,6 +286,11 @@ public:
{
return mFavoredOnLinkPrefixHistory.Iterate(aIterator, aEntryAge);
}
const AilRouter *IterateAilRoutersHistory(Iterator &aIterator, uint32_t &aEntryAge) const
{
return mAilRoutersHistory.Iterate(aIterator, aEntryAge);
}
#endif
/**
@@ -322,6 +328,7 @@ private:
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;
static constexpr uint16_t kAilRouterListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_AIL_ROUTER_LIST_SIZE;
typedef otHistoryTrackerAddressEvent AddressEvent;
@@ -357,6 +364,14 @@ private:
static constexpr uint16_t kAnycastServerPort = 53;
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
typedef otHistoryTrackerAilRouterEvent AilRouterEvent;
static constexpr AilRouterEvent kAilRouterAdded = OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_ADDED;
static constexpr AilRouterEvent kAilRouterChanged = OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_CHANGED;
static constexpr AilRouterEvent kAilRouterRemoved = OT_HISTORY_TRACKER_AIL_ROUTER_EVENT_REMOVED;
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
#define DefineEpskcEvent(aName, aPublicEnumName) \
static constexpr EpskcEvent kEpskc##aName = OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_##aPublicEnumName
@@ -500,10 +515,11 @@ private:
void RecordEpskcEvent(EpskcEvent aEvent);
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
void RecordFavoredOmrPrefix(const Ip6::Prefix &aPrefix,
BorderRouter::RoutingManager::RoutePreference aPreference,
bool aIsLocal);
void RecordFavoredOnLinkPrefix(const Ip6::Prefix &aPrefix, bool aIsLocal);
void RecordFavoredOmrPrefix(const Ip6::Prefix &aPrefix,
BorderRouter::RoutingManager::RoutePreference aPreference,
bool aIsLocal);
void RecordFavoredOnLinkPrefix(const Ip6::Prefix &aPrefix, bool aIsLocal);
AilRouter *RecordAilRouterEvent(void);
#endif
using TrackerTimer = TimerMilliIn<Local, &Local::HandleTimer>;
@@ -524,6 +540,7 @@ private:
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
EntryList<FavoredOmrPrefix, kOmrPrefixListSize> mFavoredOmrPrefixHistory;
EntryList<FavoredOnLinkPrefix, kOnLinkPrefixListSize> mFavoredOnLinkPrefixHistory;
EntryList<AilRouter, kAilRouterListSize> mAilRoutersHistory;
#endif
TrackerTimer mTimer;
@@ -203,6 +203,18 @@ verify(len(services) == len(nodes_non_br))
for host in hosts:
verify(host['addresses'][0].startswith(br2_local_omr[:-4]))
# Check the history tracker `ailrouters` command
hist_table = br2.cli('history ailrouters')
verify(len(hist_table) == 10)
hist_list = br2.cli('history ailrouters list')
verify(len(hist_list) == 6)
verify(hist_list[0].strip().split(' -> ')[1].startswith('event:Changed '))
verify(hist_list[2].strip().split(' -> ')[1].startswith('event:Changed '))
verify(hist_list[4].strip().split(' -> ')[1].startswith('event:Added '))
# -----------------------------------------------------------------------------------------------------------------------
# Test finished