[history-tracker] track changes to router table (next hop, cost) (#8734)

This commit adds anew feature in `HistoryTracker` to track the history
of changes to routers. In particular we track when a new router is
added or removed, or when next hop and/or path cost towards a router
is changed. On a cost change the recorded entry, provides the old
cost value along with the new path cost. This helps to track the cost
changes more easily (no need to look back at history to find the old
cost value).

This commit also adds CLI command `history router` for the new
feature.
This commit is contained in:
Abtin Keshavarzian
2023-02-13 08:41:42 -08:00
committed by GitHub
parent 3d7626f560
commit a4223001f2
10 changed files with 356 additions and 5 deletions
+46
View File
@@ -192,6 +192,35 @@ typedef struct otHistoryTrackerNeighborInfo
bool mIsChild : 1; ///< Indicates whether or not the neighbor is a child.
} otHistoryTrackerNeighborInfo;
/**
* This enumeration defines the events in a router info (i.e. whether router is added, removed, or changed).
*
*/
typedef enum
{
OT_HISTORY_TRACKER_ROUTER_EVENT_ADDED = 0, ///< Router is added (router ID allocated).
OT_HISTORY_TRACKER_ROUTER_EVENT_REMOVED = 1, ///< Router entry is removed (router ID released).
OT_HISTORY_TRACKER_ROUTER_EVENT_NEXT_HOP_CHANGED = 2, ///< Router entry next hop and cost changed.
OT_HISTORY_TRACKER_ROUTER_EVENT_COST_CHANGED = 3, ///< Router entry path cost changed (next hop as before).
} otHistoryTrackerRouterEvent;
#define OT_HISTORY_TRACKER_NO_NEXT_HOP 63 ///< No next hop - For `mNextHop` in `otHistoryTrackerRouterInfo`.
#define OT_HISTORY_TRACKER_INFINITE_PATH_COST 0 ///< Infinite path cost - used in `otHistoryTrackerRouterInfo`.
/**
* This structure represents a router table entry event.
*
*/
typedef struct otHistoryTrackerRouterInfo
{
uint8_t mEvent : 2; ///< Router entry event (`OT_HISTORY_TRACKER_ROUTER_EVENT_*` enumeration).
uint8_t mRouterId : 6; ///< Router ID.
uint8_t mNextHop; ///< Next Hop Router ID - `OT_HISTORY_TRACKER_NO_NEXT_HOP` if no next hop.
uint8_t mOldPathCost : 4; ///< Old path cost - `OT_HISTORY_TRACKER_INFINITE_PATH_COST` if infinite or unknown.
uint8_t mPathCost : 4; ///< New path cost - `OT_HISTORY_TRACKER_INFINITE_PATH_COST` if infinite or unknown.
} otHistoryTrackerRouterInfo;
/**
* This enumeration defines the events for a Network Data entry (i.e., whether an entry is added or removed).
*
@@ -342,6 +371,23 @@ const otHistoryTrackerNeighborInfo *otHistoryTrackerIterateNeighborHistory(otIns
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge);
/**
* This function iterates over the entries in the router history list.
*
* @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 entry was recorded to
* @p aIterator initialization time. It is set to `OT_HISTORY_TRACKER_MAX_AGE` for entries
* older than max age.
*
* @returns The `otHistoryTrackerRouterInfo` entry or `NULL` if no more entries in the list.
*
*/
const otHistoryTrackerRouterInfo *otHistoryTrackerIterateRouterHistory(otInstance *aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge);
/**
* This function iterates over the entries in the Network Data on mesh prefix entry history list.
*
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (284)
#define OPENTHREAD_API_VERSION (285)
/**
* @addtogroup api-instance
+79 -1
View File
@@ -17,6 +17,7 @@ Usage : `history [command] ...`
- [netinfo](#netinfo)
- [prefix](#prefix)
- [route](#route)
- [router](#router)
- [rx](#rx)
- [rxtx](#rxtx)
- [tx](#tx)
@@ -56,6 +57,7 @@ neighbor
netinfo
prefix
route
router
rx
rxtx
tx
@@ -298,7 +300,7 @@ Print the history as a list.
00:06:01.711 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:med rloc16:0x8800
```
### prefix
### route
Usage `history route [list] [<num-entries>]`
@@ -337,6 +339,82 @@ Print the history as a list (last two entries).
Done
```
### router
Usage `history router [list] [<num-entries>]`
Print the route table history. Each item provides:
- Event (`Added`, `Removed`, `NextHopChnaged`, `CostChanged`)
- Router ID and RLOC16 of router
- Next Hop (Router ID and RLOC16) - `none` if no next hop.
- Path cost (old `->` new) - `inf` to indicate infinite path cost.
Print the history as a table.
```bash
> history router
| Age | Event | ID (RLOC16) | Next Hop | Path Cost |
+----------------------+----------------+-------------+-------------+------------+
| 00:00:05.258 | NextHopChanged | 7 (0x1c00) | 34 (0x8800) | inf -> 3 |
| 00:00:08.604 | NextHopChanged | 34 (0x8800) | 34 (0x8800) | inf -> 2 |
| 00:00:08.604 | Added | 7 (0x1c00) | none | inf -> inf |
| 00:00:11.931 | Added | 34 (0x8800) | none | inf -> inf |
| 00:00:14.948 | Removed | 59 (0xec00) | none | inf -> inf |
| 00:00:14.948 | Removed | 54 (0xd800) | none | inf -> inf |
| 00:00:14.948 | Removed | 34 (0x8800) | none | inf -> inf |
| 00:00:14.948 | Removed | 7 (0x1c00) | none | inf -> inf |
| 00:00:54.795 | NextHopChanged | 59 (0xec00) | 34 (0x8800) | 1 -> 5 |
| 00:02:33.735 | NextHopChanged | 54 (0xd800) | none | 15 -> inf |
| 00:03:10.915 | CostChanged | 54 (0xd800) | 34 (0x8800) | 13 -> 15 |
| 00:03:45.716 | NextHopChanged | 54 (0xd800) | 34 (0x8800) | 15 -> 13 |
| 00:03:46.188 | CostChanged | 54 (0xd800) | 59 (0xec00) | 13 -> 15 |
| 00:04:19.124 | CostChanged | 54 (0xd800) | 59 (0xec00) | 11 -> 13 |
| 00:04:52.008 | CostChanged | 54 (0xd800) | 59 (0xec00) | 9 -> 11 |
| 00:05:23.176 | CostChanged | 54 (0xd800) | 59 (0xec00) | 7 -> 9 |
| 00:05:51.081 | CostChanged | 54 (0xd800) | 59 (0xec00) | 5 -> 7 |
| 00:06:48.721 | CostChanged | 54 (0xd800) | 59 (0xec00) | 3 -> 5 |
| 00:07:13.792 | NextHopChanged | 54 (0xd800) | 59 (0xec00) | 1 -> 3 |
| 00:09:28.681 | NextHopChanged | 7 (0x1c00) | 34 (0x8800) | inf -> 3 |
| 00:09:31.882 | Added | 7 (0x1c00) | none | inf -> inf |
| 00:09:51.240 | NextHopChanged | 54 (0xd800) | 54 (0xd800) | inf -> 1 |
| 00:09:54.204 | Added | 54 (0xd800) | none | inf -> inf |
| 00:10:20.645 | NextHopChanged | 34 (0x8800) | 34 (0x8800) | inf -> 2 |
| 00:10:24.242 | NextHopChanged | 59 (0xec00) | 59 (0xec00) | inf -> 1 |
| 00:10:24.242 | Added | 34 (0x8800) | none | inf -> inf |
| 00:10:41.900 | NextHopChanged | 59 (0xec00) | none | 1 -> inf |
| 00:10:42.480 | Added | 3 (0x0c00) | 3 (0x0c00) | inf -> inf |
| 00:10:43.614 | Added | 59 (0xec00) | 59 (0xec00) | inf -> 1 |
Done
```
Print the history as a list (last 20 entries).
```bash
> history router list 20
00:00:06.959 -> event:NextHopChanged router:7(0x1c00) nexthop:34(0x8800) old-cost:inf new-cost:3
00:00:10.305 -> event:NextHopChanged router:34(0x8800) nexthop:34(0x8800) old-cost:inf new-cost:2
00:00:10.305 -> event:Added router:7(0x1c00) nexthop:none old-cost:inf new-cost:inf
00:00:13.632 -> event:Added router:34(0x8800) nexthop:none old-cost:inf new-cost:inf
00:00:16.649 -> event:Removed router:59(0xec00) nexthop:none old-cost:inf new-cost:inf
00:00:16.649 -> event:Removed router:54(0xd800) nexthop:none old-cost:inf new-cost:inf
00:00:16.649 -> event:Removed router:34(0x8800) nexthop:none old-cost:inf new-cost:inf
00:00:16.649 -> event:Removed router:7(0x1c00) nexthop:none old-cost:inf new-cost:inf
00:00:56.496 -> event:NextHopChanged router:59(0xec00) nexthop:34(0x8800) old-cost:1 new-cost:5
00:02:35.436 -> event:NextHopChanged router:54(0xd800) nexthop:none old-cost:15 new-cost:inf
00:03:12.616 -> event:CostChanged router:54(0xd800) nexthop:34(0x8800) old-cost:13 new-cost:15
00:03:47.417 -> event:NextHopChanged router:54(0xd800) nexthop:34(0x8800) old-cost:15 new-cost:13
00:03:47.889 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:13 new-cost:15
00:04:20.825 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:11 new-cost:13
00:04:53.709 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:9 new-cost:11
00:05:24.877 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:7 new-cost:9
00:05:52.782 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:5 new-cost:7
00:06:50.422 -> event:CostChanged router:54(0xd800) nexthop:59(0xec00) old-cost:3 new-cost:5
00:07:15.493 -> event:NextHopChanged router:54(0xd800) nexthop:59(0xec00) old-cost:1 new-cost:3
00:09:30.382 -> event:NextHopChanged router:7(0x1c00) nexthop:34(0x8800) old-cost:inf new-cost:3
Done
```
### rx
Usage `history rx [list] [<num-entries>]`
+87 -1
View File
@@ -256,6 +256,92 @@ exit:
return error;
}
template <> otError History::Process<Cmd("router")>(Arg aArgs[])
{
static const char *const kEventString[] = {
/* (0) OT_HISTORY_TRACKER_ROUTER_EVENT_ADDED -> */ "Added",
/* (1) OT_HISTORY_TRACKER_ROUTER_EVENT_REMOVED -> */ "Removed",
/* (2) OT_HISTORY_TRACKER_ROUTER_EVENT_NEXT_HOP_CHANGED -> */ "NextHopChanged",
/* (3) OT_HISTORY_TRACKER_ROUTER_EVENT_COST_CHANGED -> */ "CostChanged",
};
constexpr uint8_t kRouterIdOffset = 10; // Bit offset of Router ID in RLOC16
otError error;
bool isList;
uint16_t numEntries;
otHistoryTrackerIterator iterator;
const otHistoryTrackerRouterInfo *info;
uint32_t entryAge;
char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
static_assert(0 == OT_HISTORY_TRACKER_ROUTER_EVENT_ADDED, "EVENT_ADDED is incorrect");
static_assert(1 == OT_HISTORY_TRACKER_ROUTER_EVENT_REMOVED, "EVENT_REMOVED is incorrect");
static_assert(2 == OT_HISTORY_TRACKER_ROUTER_EVENT_NEXT_HOP_CHANGED, "EVENT_NEXT_HOP_CHANGED is incorrect");
static_assert(3 == OT_HISTORY_TRACKER_ROUTER_EVENT_COST_CHANGED, "EVENT_COST_CHANGED is incorrect");
SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
if (!isList)
{
// | Age | Event | ID (RlOC16) | Next Hop | Path Cost |
// +----------------------+----------------+-------------+------------+-------------+
static const char *const kRouterInfoTitles[] = {
"Age", "Event", "ID (RLOC16)", "Next Hop", "Path Cost",
};
static const uint8_t kRouterInfoColumnWidths[] = {22, 16, 13, 13, 12};
OutputTableHeader(kRouterInfoTitles, kRouterInfoColumnWidths);
}
otHistoryTrackerInitIterator(&iterator);
for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
{
info = otHistoryTrackerIterateRouterHistory(GetInstancePtr(), &iterator, &entryAge);
VerifyOrExit(info != nullptr);
otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
OutputFormat(isList ? "%s -> event:%s router:%u(0x%04x) nexthop:" : "| %20s | %-14s | %2u (0x%04x) | ",
ageString, kEventString[info->mEvent], info->mRouterId,
static_cast<uint16_t>(info->mRouterId) << kRouterIdOffset);
if (info->mNextHop != OT_HISTORY_TRACKER_NO_NEXT_HOP)
{
OutputFormat(isList ? "%u(0x%04x)" : "%2u (0x%04x)", info->mNextHop,
static_cast<uint16_t>(info->mNextHop) << kRouterIdOffset);
}
else
{
OutputFormat(isList ? "%s" : "%11s", "none");
}
if (info->mOldPathCost != OT_HISTORY_TRACKER_INFINITE_PATH_COST)
{
OutputFormat(isList ? " old-cost:%u" : " | %3u ->", info->mOldPathCost);
}
else
{
OutputFormat(isList ? " old-cost:inf" : " | inf ->");
}
if (info->mPathCost != OT_HISTORY_TRACKER_INFINITE_PATH_COST)
{
OutputLine(isList ? " new-cost:%u" : " %3u |", info->mPathCost);
}
else
{
OutputLine(isList ? " new-cost:inf" : " inf |");
}
}
exit:
return error;
}
template <> otError History::Process<Cmd("netinfo")>(Arg aArgs[])
{
otError error;
@@ -659,7 +745,7 @@ otError History::Process(Arg aArgs[])
static constexpr Command kCommands[] = {
CmdEntry("ipaddr"), CmdEntry("ipmaddr"), CmdEntry("neighbor"), CmdEntry("netinfo"), CmdEntry("prefix"),
CmdEntry("route"), CmdEntry("rx"), CmdEntry("rxtx"), CmdEntry("tx"),
CmdEntry("route"), CmdEntry("router"), CmdEntry("rx"), CmdEntry("rxtx"), CmdEntry("tx"),
};
#undef CmdEntry
+9
View File
@@ -103,6 +103,15 @@ const otHistoryTrackerNeighborInfo *otHistoryTrackerIterateNeighborHistory(otIns
return AsCoreType(aInstance).Get<Utils::HistoryTracker>().IterateNeighborHistory(AsCoreType(aIterator), *aEntryAge);
}
const otHistoryTrackerRouterInfo *otHistoryTrackerIterateRouterHistory(otInstance *aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge)
{
AssertPointerIsNotNull(aEntryAge);
return AsCoreType(aInstance).Get<Utils::HistoryTracker>().IterateRouterHistory(AsCoreType(aIterator), *aEntryAge);
}
const otHistoryTrackerOnMeshPrefixInfo *otHistoryTrackerIterateOnMeshPrefixHistory(otInstance *aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t *aEntryAge)
+12
View File
@@ -127,6 +127,18 @@
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_NEIGHBOR_LIST_SIZE 64
#endif
/**
* @def OPENTHREAD_CONFIG_HISTORY_TRACKER_ROUTER_LIST_SIZE
*
* Specifies the maximum number of entries in router table history list.
*
* Can be set to zero to configure History Tracker module not to collect any router table history.
*
*/
#ifndef OPENTHREAD_CONFIG_HISTORY_TRACKER_ROUTER_LIST_SIZE
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ROUTER_LIST_SIZE 256
#endif
/**
* @def OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE
*
+5 -1
View File
@@ -871,10 +871,14 @@ void RouterTable::HandleTableChanged(void)
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
LogRouteTable();
#endif
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
Get<Utils::HistoryTracker>().RecordRouterTableChange();
#endif
}
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
void RouterTable::LogRouteTable(void)
void RouterTable::LogRouteTable(void) const
{
static constexpr uint16_t kStringSize = 128;
+1 -1
View File
@@ -440,7 +440,7 @@ private:
void SignalTableChanged(void);
void HandleTableChanged(void);
void LogRouteTable(void);
void LogRouteTable(void) const;
class RouterIdMap
{
+74
View File
@@ -59,6 +59,10 @@ HistoryTracker::HistoryTracker(Instance &aInstance)
#endif
{
mTimer.Start(kAgeCheckPeriod);
#if OPENTHREAD_FTD && (OPENTHREAD_CONFIG_HISTORY_TRACKER_ROUTER_LIST_SIZE > 0)
memset(mRouterEntries, 0, sizeof(mRouterEntries));
#endif
}
void HistoryTracker::RecordNetworkInfo(void)
@@ -279,6 +283,76 @@ exit:
return;
}
#if OPENTHREAD_FTD
void HistoryTracker::RecordRouterTableChange(void)
{
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ROUTER_LIST_SIZE > 0
for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++)
{
RouterInfo entry;
RouterEntry &oldEntry = mRouterEntries[routerId];
entry.mRouterId = routerId;
if (Get<RouterTable>().IsAllocated(routerId))
{
uint16_t nextHopRloc;
uint8_t pathCost;
Get<RouterTable>().GetNextHopAndPathCost(Mle::Rloc16FromRouterId(routerId), nextHopRloc, pathCost);
entry.mNextHop = (nextHopRloc == Mle::kInvalidRloc16) ? kNoNextHop : Mle::RouterIdFromRloc16(nextHopRloc);
entry.mPathCost = (pathCost < Mle::kMaxRouteCost) ? pathCost : 0;
if (!oldEntry.mIsAllocated)
{
entry.mEvent = kRouterAdded;
entry.mOldPathCost = 0;
}
else if (oldEntry.mNextHop != entry.mNextHop)
{
entry.mEvent = kRouterNextHopChanged;
entry.mOldPathCost = oldEntry.mPathCost;
}
else if ((entry.mNextHop != kNoNextHop) && (oldEntry.mPathCost != entry.mPathCost))
{
entry.mEvent = kRouterCostChanged;
entry.mOldPathCost = oldEntry.mPathCost;
}
else
{
continue;
}
mRouterHistory.AddNewEntry(entry);
oldEntry.mIsAllocated = true;
oldEntry.mNextHop = entry.mNextHop;
oldEntry.mPathCost = entry.mPathCost;
}
else
{
// `routerId` is not allocated.
if (oldEntry.mIsAllocated)
{
entry.mEvent = kRouterRemoved;
entry.mNextHop = Mle::kInvalidRouterId;
entry.mOldPathCost = 0;
entry.mPathCost = 0;
mRouterHistory.AddNewEntry(entry);
oldEntry.mIsAllocated = false;
}
}
}
#endif // (OPENTHREAD_CONFIG_HISTORY_TRACKER_ROUTER_LIST_SIZE > 0)
}
#endif // OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
void HistoryTracker::RecordNetworkDataChange(void)
{
+42
View File
@@ -54,6 +54,7 @@
#include "thread/mle_types.hpp"
#include "thread/neighbor_table.hpp"
#include "thread/network_data.hpp"
#include "thread/router_table.hpp"
namespace ot {
namespace Utils {
@@ -78,6 +79,9 @@ class HistoryTracker : public InstanceLocator, private NonCopyable
friend class ot::Mle::Mle;
friend class ot::NeighborTable;
friend class ot::Ip6::Netif;
#if OPENTHREAD_FTD
friend class ot::RouterTable;
#endif
public:
/**
@@ -94,6 +98,14 @@ public:
*/
static constexpr uint16_t kEntryAgeStringSize = OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE;
/**
* This constants specifid no next hop.
*
* Used for `mNextHop` in `RouteInfo` struture.
*
*/
static constexpr uint8_t kNoNextHop = OT_HISTORY_TRACKER_NO_NEXT_HOP;
/**
* This type represents an iterator to iterate through a history list.
*
@@ -125,6 +137,7 @@ public:
typedef otHistoryTrackerMulticastAddressInfo MulticastAddressInfo; ///< Multicast IPv6 address info.
typedef otHistoryTrackerMessageInfo MessageInfo; ///< RX/TX IPv6 message info.
typedef otHistoryTrackerNeighborInfo NeighborInfo; ///< Neighbor info.
typedef otHistoryTrackerRouterInfo RouterInfo; ///< Router info.
typedef otHistoryTrackerOnMeshPrefixInfo OnMeshPrefixInfo; ///< Network Data on mesh prefix info.
typedef otHistoryTrackerExternalRouteInfo ExternalRouteInfo; ///< Network Data external route info
@@ -226,6 +239,11 @@ public:
return mNeighborHistory.Iterate(aIterator, aEntryAge);
}
const RouterInfo *IterateRouterHistory(Iterator &aIterator, uint32_t &aEntryAge) const
{
return mRouterHistory.Iterate(aIterator, aEntryAge);
}
const OnMeshPrefixInfo *IterateOnMeshPrefixHistory(Iterator &aIterator, uint32_t &aEntryAge) const
{
return mOnMeshPrefixHistory.Iterate(aIterator, aEntryAge);
@@ -265,6 +283,7 @@ private:
static constexpr uint16_t kRxListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_RX_LIST_SIZE;
static constexpr uint16_t kTxListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_TX_LIST_SIZE;
static constexpr uint16_t kNeighborListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_NEIGHBOR_LIST_SIZE;
static constexpr uint16_t kRouterListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_ROUTER_LIST_SIZE;
static constexpr uint16_t kOnMeshPrefixListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE;
static constexpr uint16_t kExternalRouteListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE;
@@ -282,6 +301,13 @@ private:
static constexpr NeighborEvent kNeighborChanged = OT_HISTORY_TRACKER_NEIGHBOR_EVENT_CHANGED;
static constexpr NeighborEvent kNeighborRestoring = OT_HISTORY_TRACKER_NEIGHBOR_EVENT_RESTORING;
typedef otHistoryTrackerRouterEvent RouterEvent;
static constexpr RouterEvent kRouterAdded = OT_HISTORY_TRACKER_ROUTER_EVENT_ADDED;
static constexpr RouterEvent kRouterRemoved = OT_HISTORY_TRACKER_ROUTER_EVENT_REMOVED;
static constexpr RouterEvent kRouterNextHopChanged = OT_HISTORY_TRACKER_ROUTER_EVENT_NEXT_HOP_CHANGED;
static constexpr RouterEvent kRouterCostChanged = OT_HISTORY_TRACKER_ROUTER_EVENT_COST_CHANGED;
typedef otHistoryTrackerNetDataEvent NetDataEvent;
static constexpr NetDataEvent kNetDataEntryAdded = OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED;
@@ -387,6 +413,9 @@ private:
Ip6::Netif::AddressOrigin aAddressOrigin);
void HandleNotifierEvents(Events aEvents);
void HandleTimer(void);
#if OPENTHREAD_FTD
void RecordRouterTableChange(void);
#endif
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
void RecordNetworkDataChange(void);
void RecordOnMeshPrefixEvent(NetDataEvent aEvent, const NetworkData::OnMeshPrefixConfig &aPrefix);
@@ -401,11 +430,23 @@ private:
EntryList<MessageInfo, kRxListSize> mRxHistory;
EntryList<MessageInfo, kTxListSize> mTxHistory;
EntryList<NeighborInfo, kNeighborListSize> mNeighborHistory;
EntryList<RouterInfo, kRouterListSize> mRouterHistory;
EntryList<OnMeshPrefixInfo, kOnMeshPrefixListSize> mOnMeshPrefixHistory;
EntryList<ExternalRouteInfo, kExternalRouteListSize> mExternalRouteHistory;
TrackerTimer mTimer;
#if OPENTHREAD_FTD && (OPENTHREAD_CONFIG_HISTORY_TRACKER_ROUTER_LIST_SIZE > 0)
struct RouterEntry
{
bool mIsAllocated : 1;
uint8_t mNextHop : 6;
uint8_t mPathCost : 4;
};
RouterEntry mRouterEntries[Mle::kMaxRouterId + 1];
#endif
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
NetworkData::MutableNetworkData mPreviousNetworkData;
@@ -419,6 +460,7 @@ DefineCoreType(otHistoryTrackerIterator, Utils::HistoryTracker::Iterator);
DefineCoreType(otHistoryTrackerNetworkInfo, Utils::HistoryTracker::NetworkInfo);
DefineCoreType(otHistoryTrackerMessageInfo, Utils::HistoryTracker::MessageInfo);
DefineCoreType(otHistoryTrackerNeighborInfo, Utils::HistoryTracker::NeighborInfo);
DefineCoreType(otHistoryTrackerRouterInfo, Utils::HistoryTracker::RouterInfo);
DefineCoreType(otHistoryTrackerOnMeshPrefixInfo, Utils::HistoryTracker::OnMeshPrefixInfo);
DefineCoreType(otHistoryTrackerExternalRouteInfo, Utils::HistoryTracker::ExternalRouteInfo);