[history-tracker] support tracking netdata prefix and route entries (#7324)

This commit adds a mechanism in `HistoryTracker` to track changes in
Thread Network Data maintaining a history of on-mesh prefix and
external route entries as they are added or removed by different
nodes in Network Data. This commit also adds new `cli history`
commands to retrieve the Network Data prefix/route history list and
updates the documentation in `cli/README_HISTORY.md`.
This commit is contained in:
Abtin Keshavarzian
2022-01-19 16:35:40 -08:00
committed by GitHub
parent 556cee64d3
commit 314e945bb6
11 changed files with 528 additions and 76 deletions
+66
View File
@@ -29,6 +29,7 @@
#include <openthread/instance.h>
#include <openthread/ip6.h>
#include <openthread/netdata.h>
#include <openthread/thread.h>
#ifdef __cplusplus
@@ -191,6 +192,36 @@ typedef struct otHistoryTrackerNeighborInfo
bool mIsChild : 1; ///< Indicates whether or not the neighbor is a child.
} otHistoryTrackerNeighborInfo;
/**
* This enumeration defines the events for a Network Data entry (i.e., whether an entry is added or removed).
*
*/
typedef enum
{
OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED = 0, ///< Network data entry is added.
OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED = 1, ///< Network data entry is removed.
} otHistoryTrackerNetDataEvent;
/**
* This structure represent a Network Data on mesh prefix info.
*
*/
typedef struct otHistoryTrackerOnMeshPrefixInfo
{
otBorderRouterConfig mPrefix; ///< The on mesh prefix entry.
otHistoryTrackerNetDataEvent mEvent; ///< Indicates the event (added/removed).
} otHistoryTrackerOnMeshPrefixInfo;
/**
* This structure represent a Network Data extern route info.
*
*/
typedef struct otHistoryTrackerExternalRouteInfo
{
otExternalRouteConfig mRoute; ///< The external route entry.
otHistoryTrackerNetDataEvent mEvent; ///< Indicates the event (added/removed).
} otHistoryTrackerExternalRouteInfo;
/**
* This function initializes an `otHistoryTrackerIterator`.
*
@@ -311,6 +342,41 @@ const otHistoryTrackerNeighborInfo *otHistoryTrackerIterateNeighborHistory(otIns
otHistoryTrackerIterator *aIterator,
uint32_t * aEntryAge);
/**
* This function iterates over the entries in the Network Data on mesh prefix entry history list.
*
* @param[in] aInstance A pointer to the OpenThread instance.
* @param[inout] 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 `otHistoryTrackerOnMeshPrefixInfo` entry or `NULL` if no more entries in the list.
*
*/
const otHistoryTrackerOnMeshPrefixInfo *otHistoryTrackerIterateOnMeshPrefixHistory(otInstance * aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t * aEntryAge);
/**
* This function iterates over the entries in the Network Data external route entry history list.
*
* @param[in] aInstance A pointer to the OpenThread instance.
* @param[inout] 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 `otHistoryTrackerExternalRouteInfo` entry or `NULL` if no more entries in the list.
*
*/
const otHistoryTrackerExternalRouteInfo *otHistoryTrackerIterateExternalRouteHistory(
otInstance * aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t * aEntryAge);
/**
* This function converts a given entry age to a human-readable string.
*
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (185)
#define OPENTHREAD_API_VERSION (186)
/**
* @addtogroup api-instance
+94
View File
@@ -15,6 +15,8 @@ Usage : `history [command] ...`
- [ipmaddr](#ipmaddr)
- [neighbor](#neighbor)
- [netinfo](#netinfo)
- [prefix](#prefix)
- [route](#route)
- [rx](#rx)
- [rxtx](#rxtx)
- [tx](#tx)
@@ -52,6 +54,8 @@ ipaddr
ipmaddr
neighbor
netinfo
prefix
route
rx
rxtx
tx
@@ -243,6 +247,96 @@ Print only the latest 2 entries.
Done
```
### prefix
Usage `history prefix [list] [<num-entries>]`
Print the Network Data on mesh prefix history. Each item provides:
- Event (`Added` or `Removed`)
- Prefix
- Flags
- Preference (`high`, `med`, `low`)
- RLOC16
The flags are as follows:
- `p`: Preferred flag
- `a`: Stateless IPv6 Address Autoconfiguration flag
- `d`: DHCPv6 IPv6 Address Configuration flag
- `c`: DHCPv6 Other Configuration flag
- `r`: Default Route flag
- `o`: On Mesh flag
- `s`: Stable flag
- `n`: Nd Dns flag
- `D`: Domain Prefix flag
Print the history as a table.
```bash
> history prefix
| Age | Event | Prefix | Flags | Pref | RLOC16 |
+----------------------+---------+---------------------------------------------+-----------+------+--------+
| 00:00:10.663 | Added | fd00:1111:2222:3333::/64 | paro | med | 0x5400 |
| 00:01:02.054 | Removed | fd00:dead:beef:1::/64 | paros | high | 0x5400 |
| 00:01:21.136 | Added | fd00:abba:cddd:0::/64 | paos | med | 0x5400 |
| 00:01:45.144 | Added | fd00:dead:beef:1::/64 | paros | high | 0x3c00 |
| 00:01:50.944 | Added | fd00:dead:beef:1::/64 | paros | high | 0x5400 |
| 00:01:59.887 | Added | fd00:dead:beef:1::/64 | paros | med | 0x8800 |
Done
```
Print the history as a list.
```bash
> history prefix list
00:04:12.487 -> event:Added prefix:fd00:1111:2222:3333::/64 flags:paro pref:med rloc16:0x5400
00:05:03.878 -> event:Removed prefix:fd00:dead:beef:1::/64 flags:paros pref:high rloc16:0x5400
00:05:22.960 -> event:Added prefix:fd00:abba:cddd:0::/64 flags:paos pref:med rloc16:0x5400
00:05:46.968 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:high rloc16:0x3c00
00:05:52.768 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:high rloc16:0x5400
00:06:01.711 -> event:Added prefix:fd00:dead:beef:1::/64 flags:paros pref:med rloc16:0x8800
```
### prefix
Usage `history route [list] [<num-entries>]`
Print the Network Data external route history. Each item provides:
- Event (`Added` or `Removed`)
- Route
- Flags
- Preference (`high`, `med`, `low`)
- RLOC16
The flags are as follows:
- `s`: Stable flag
- `n`: NAT64 flag
Print the history as a table.
```bash
history route
| Age | Event | Route | Flags | Pref | RLOC16 |
+----------------------+---------+---------------------------------------------+-----------+------+--------+
| 00:00:05.456 | Removed | fd00:1111:0::/48 | s | med | 0x3c00 |
| 00:00:29.310 | Added | fd00:1111:0::/48 | s | med | 0x3c00 |
| 00:00:42.822 | Added | fd00:1111:0::/48 | s | med | 0x5400 |
| 00:01:27.688 | Added | fd00:aaaa:bbbb:cccc::/64 | s | med | 0x8800 |
Done
```
Print the history as a list (last two entries).
```bash
> history route list 2
00:00:48.704 -> event:Removed route:fd00:1111:0::/48 flags:s pref:med rloc16:0x3c00
00:01:12.558 -> event:Added route:fd00:1111:0::/48 flags:s pref:med rloc16:0x3c00
Done
```
### rx
Usage `history rx [list] [<num-entries>]`
+107 -7
View File
@@ -44,6 +44,11 @@ namespace Cli {
constexpr History::Command History::sCommands[];
static const char *const kSimpleEventStrings[] = {
"Added", // (0) OT_HISTORY_TRACKER_{NET_DATA_ENTRY/ADDRESSS_EVENT}_ADDED
"Removed" // (1) OT_HISTORY_TRACKER_{NET_DATA_ENTRY/ADDRESS_EVENT}_REMOVED
};
otError History::ProcessHelp(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
@@ -82,11 +87,6 @@ otError History::ParseArgs(Arg aArgs[], bool &aIsList, uint16_t &aNumEntries) co
otError History::ProcessIpAddr(Arg aArgs[])
{
static const char *const kEventStrings[] = {
"Added", // (0) OT_HISTORY_TRACKER_ADDRESS_EVENT_ADDED
"Removed" // (1) OT_HISTORY_TRACKER_ADDRESS_EVENT_REMOVED
};
otError error;
bool isList;
uint16_t numEntries;
@@ -129,14 +129,14 @@ otError History::ProcessIpAddr(Arg aArgs[])
sprintf(&addressString[strlen(addressString)], "/%d", info->mPrefixLength);
OutputLine("| %20s | %-7s | %-43s | %-6s | %3d | %c | %c | %c |", ageString,
Stringify(info->mEvent, kEventStrings), addressString,
Stringify(info->mEvent, kSimpleEventStrings), addressString,
Interpreter::AddressOriginToString(info->mAddressOrigin), info->mScope,
info->mPreferred ? 'Y' : 'N', info->mValid ? 'Y' : 'N', info->mRloc ? 'Y' : 'N');
}
else
{
OutputLine("%s -> event:%s address:%s prefixlen:%d origin:%s scope:%d preferred:%s valid:%s rloc:%s",
ageString, Stringify(info->mEvent, kEventStrings), addressString, info->mPrefixLength,
ageString, Stringify(info->mEvent, kSimpleEventStrings), addressString, info->mPrefixLength,
Interpreter::AddressOriginToString(info->mAddressOrigin), info->mScope,
info->mPreferred ? "yes" : "no", info->mValid ? "yes" : "no", info->mRloc ? "yes" : "no");
}
@@ -571,6 +571,106 @@ void History::OutputRxTxEntryTableFormat(const otHistoryTrackerMessageInfo &aInf
OutputLine("| %20s | dst: %-70s |", "", addrString);
}
otError History::ProcessPrefix(Arg aArgs[])
{
otError error;
bool isList;
uint16_t numEntries;
otHistoryTrackerIterator iterator;
const otHistoryTrackerOnMeshPrefixInfo *info;
uint32_t entryAge;
char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
char prefixString[OT_IP6_PREFIX_STRING_SIZE];
NetworkData::FlagsString flagsString;
static_assert(0 == OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED, "NET_DATA_ENTRY_ADDED value is incorrect");
static_assert(1 == OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED, "NET_DATA_ENTRY_REMOVED value is incorrect");
SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
if (!isList)
{
// | Age | Event | Prefix | Flags | Pref | RLOC16 |
// +----------------------+---------+---------------------------------------------+-----------+------+--------+
static const char *const kPrefixTitles[] = {"Age", "Event", "Prefix", "Flags", "Pref", "RLOC16"};
static const uint8_t kPrefixColumnWidths[] = {22, 9, 45, 11, 6, 8};
OutputTableHeader(kPrefixTitles, kPrefixColumnWidths);
}
otHistoryTrackerInitIterator(&iterator);
for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
{
info = otHistoryTrackerIterateOnMeshPrefixHistory(GetInstancePtr(), &iterator, &entryAge);
VerifyOrExit(info != nullptr);
otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
otIp6PrefixToString(&info->mPrefix.mPrefix, prefixString, sizeof(prefixString));
NetworkData::PrefixFlagsToString(info->mPrefix, flagsString);
OutputLine(isList ? "%s -> event:%s prefix:%s flags:%s pref:%s rloc16:0x%04x"
: "| %20s | %-7s | %-43s | %-9s | %-4s | 0x%04x |",
ageString, Stringify(info->mEvent, kSimpleEventStrings), prefixString, flagsString,
NetworkData::PreferenceToString(info->mPrefix.mPreference), info->mPrefix.mRloc16);
}
exit:
return error;
}
otError History::ProcessRoute(Arg aArgs[])
{
otError error;
bool isList;
uint16_t numEntries;
otHistoryTrackerIterator iterator;
const otHistoryTrackerExternalRouteInfo *info;
uint32_t entryAge;
char ageString[OT_HISTORY_TRACKER_ENTRY_AGE_STRING_SIZE];
char prefixString[OT_IP6_PREFIX_STRING_SIZE];
NetworkData::FlagsString flagsString;
static_assert(0 == OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED, "NET_DATA_ENTRY_ADDED value is incorrect");
static_assert(1 == OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED, "NET_DATA_ENTRY_REMOVED value is incorrect");
SuccessOrExit(error = ParseArgs(aArgs, isList, numEntries));
if (!isList)
{
// | Age | Event | Route | Flags | Pref | RLOC16 |
// +----------------------+---------+---------------------------------------------+-----------+------+--------+
static const char *const kRouteTitles[] = {"Age", "Event", "Route", "Flags", "Pref", "RLOC16"};
static const uint8_t kRouteColumnWidths[] = {22, 9, 45, 11, 6, 8};
OutputTableHeader(kRouteTitles, kRouteColumnWidths);
}
otHistoryTrackerInitIterator(&iterator);
for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
{
info = otHistoryTrackerIterateExternalRouteHistory(GetInstancePtr(), &iterator, &entryAge);
VerifyOrExit(info != nullptr);
otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
otIp6PrefixToString(&info->mRoute.mPrefix, prefixString, sizeof(prefixString));
NetworkData::RouteFlagsToString(info->mRoute, flagsString);
OutputLine(isList ? "%s -> event:%s route:%s flags:%s pref:%s rloc16:0x%04x"
: "| %20s | %-7s | %-43s | %-9s | %-4s | 0x%04x |",
ageString, Stringify(info->mEvent, kSimpleEventStrings), prefixString, flagsString,
NetworkData::PreferenceToString(info->mRoute.mPreference), info->mRoute.mRloc16);
}
exit:
return error;
}
otError History::Process(Arg aArgs[])
{
otError error = OT_ERROR_INVALID_COMMAND;
+4
View File
@@ -93,6 +93,8 @@ private:
otError ProcessIpMulticastAddr(Arg aArgs[]);
otError ProcessNetInfo(Arg aArgs[]);
otError ProcessNeighbor(Arg aArgs[]);
otError ProcessPrefix(Arg aArgs[]);
otError ProcessRoute(Arg aArgs[]);
otError ProcessRx(Arg aArgs[]);
otError ProcessRxTx(Arg aArgs[]);
otError ProcessTx(Arg aArgs[]);
@@ -112,6 +114,8 @@ private:
{"ipmaddr", &History::ProcessIpMulticastAddr},
{"neighbor", &History::ProcessNeighbor},
{"netinfo", &History::ProcessNetInfo},
{"prefix", &History::ProcessPrefix},
{"route", &History::ProcessRoute},
{"rx", &History::ProcessRx},
{"rxtx", &History::ProcessRxTx},
{"tx", &History::ProcessTx},
+34 -38
View File
@@ -45,20 +45,9 @@ namespace Cli {
constexpr NetworkData::Command NetworkData::sCommands[];
void NetworkData::OutputPrefix(const otBorderRouterConfig &aConfig)
void NetworkData::PrefixFlagsToString(const otBorderRouterConfig &aConfig, FlagsString &aString)
{
enum
{
// BorderRouter flag is `uint16_t` (though some of the bits are
// reserved for future use), so we use 17 chars string (16 flags
// plus null char at end of string).
kMaxFlagStringSize = 17,
};
char flagsString[kMaxFlagStringSize];
char *flagsPtr = &flagsString[0];
OutputIp6Prefix(aConfig.mPrefix);
char *flagsPtr = &aString[0];
if (aConfig.mPreferred)
{
@@ -106,31 +95,27 @@ void NetworkData::OutputPrefix(const otBorderRouterConfig &aConfig)
}
*flagsPtr = '\0';
}
if (flagsPtr != &flagsString[0])
void NetworkData::OutputPrefix(const otBorderRouterConfig &aConfig)
{
FlagsString flagsString;
OutputIp6Prefix(aConfig.mPrefix);
PrefixFlagsToString(aConfig, flagsString);
if (flagsString[0] != '\0')
{
OutputFormat(" %s", flagsString);
}
OutputPreference(aConfig.mPreference);
OutputLine(" %04x", aConfig.mRloc16);
OutputLine(" %s %04x", PreferenceToString(aConfig.mPreference), aConfig.mRloc16);
}
void NetworkData::OutputRoute(const otExternalRouteConfig &aConfig)
void NetworkData::RouteFlagsToString(const otExternalRouteConfig &aConfig, FlagsString &aString)
{
enum
{
// ExternalRoute flag is `uint8_t` (though some of the bits are
// reserved for future use), so we use 9 chars string (8 flags
// plus null char at end of string).
kMaxFlagStringSize = 9,
};
char flagsString[kMaxFlagStringSize];
char *flagsPtr = &flagsString[0];
OutputIp6Prefix(aConfig.mPrefix);
char *flagsPtr = &aString[0];
if (aConfig.mStable)
{
@@ -143,36 +128,47 @@ void NetworkData::OutputRoute(const otExternalRouteConfig &aConfig)
}
*flagsPtr = '\0';
}
if (flagsPtr != &flagsString[0])
void NetworkData::OutputRoute(const otExternalRouteConfig &aConfig)
{
FlagsString flagsString;
OutputIp6Prefix(aConfig.mPrefix);
RouteFlagsToString(aConfig, flagsString);
if (flagsString[0] != '\0')
{
OutputFormat(" %s", flagsString);
}
OutputPreference(aConfig.mPreference);
OutputLine(" %04x", aConfig.mRloc16);
OutputLine(" %s %04x", PreferenceToString(aConfig.mPreference), aConfig.mRloc16);
}
void NetworkData::OutputPreference(signed int aPreference)
const char *NetworkData::PreferenceToString(signed int aPreference)
{
const char *str = "";
switch (aPreference)
{
case OT_ROUTE_PREFERENCE_LOW:
OutputFormat(" low");
str = "low";
break;
case OT_ROUTE_PREFERENCE_MED:
OutputFormat(" med");
str = "med";
break;
case OT_ROUTE_PREFERENCE_HIGH:
OutputFormat(" high");
str = "high";
break;
default:
break;
}
return str;
}
void NetworkData::OutputService(const otServiceConfig &aConfig)
+40 -1
View File
@@ -52,6 +52,18 @@ class NetworkData : private OutputWrapper
public:
typedef Utils::CmdLineParser::Arg Arg;
/**
* This constant specifies the string size for representing Network Data prefix/route entry flags.
*
* BorderRouter (OnMeshPrefix) TLV uses `uint16_t` for its flags and ExternalRoute uses `uint8_t`, though some of
* the bits are not currently used and reserved for future, so 17 chars string (16 flags plus null char at end of
* string) covers current and future flags.
*
*/
static constexpr uint16_t kFlagsStringSize = 17;
typedef char FlagsString[kFlagsStringSize]; ///< Flags String type (char array of `kFlagsStringSize`).
/**
* Constructor
*
@@ -95,6 +107,34 @@ public:
*/
void OutputService(const otServiceConfig &aConfig);
/**
* This method converts the flags from a given prefix config to string.
*
* @param[in] aConfig The prefix config.
* @param[out] aString The string to populate from @a Config flags.
*
*/
static void PrefixFlagsToString(const otBorderRouterConfig &aConfig, FlagsString &aString);
/**
* This method converts the flags from a given route config to string.
*
* @param[in] aConfig The route config.
* @param[out] aString The string to populate from @a Config flags.
*
*/
static void RouteFlagsToString(const otExternalRouteConfig &aConfig, FlagsString &aString);
/**
* This static method converts a route preference value to human-readable string.
*
* @param[in] aPreference The preference value to convert (`OT_ROUTE_PREFERENCE_*` values).
*
* @returns A string representation @p aPreference.
*
*/
static const char *PreferenceToString(signed int aPreference);
private:
using Command = CommandEntry<NetworkData>;
@@ -117,7 +157,6 @@ private:
void OutputPrefixes(bool aLocal);
void OutputRoutes(bool aLocal);
void OutputServices(bool aLocal);
void OutputPreference(signed int aPreference);
static constexpr Command sCommands[] = {
{"help", &NetworkData::ProcessHelp},
+17
View File
@@ -94,6 +94,23 @@ const otHistoryTrackerNeighborInfo *otHistoryTrackerIterateNeighborHistory(otIns
return AsCoreType(aInstance).Get<Utils::HistoryTracker>().IterateNeighborHistory(AsCoreType(aIterator), *aEntryAge);
}
const otHistoryTrackerOnMeshPrefixInfo *otHistoryTrackerIterateOnMeshPrefixHistory(otInstance * aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t * aEntryAge)
{
return AsCoreType(aInstance).Get<Utils::HistoryTracker>().IterateOnMeshPrefixHistory(AsCoreType(aIterator),
*aEntryAge);
}
const otHistoryTrackerExternalRouteInfo *otHistoryTrackerIterateExternalRouteHistory(
otInstance * aInstance,
otHistoryTrackerIterator *aIterator,
uint32_t * aEntryAge)
{
return AsCoreType(aInstance).Get<Utils::HistoryTracker>().IterateExternalRouteHistory(AsCoreType(aIterator),
*aEntryAge);
}
void otHistoryTrackerEntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize)
{
Utils::HistoryTracker::EntryAgeToString(aEntryAge, aBuffer, aSize);
+24
View File
@@ -127,4 +127,28 @@
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_NEIGHBOR_LIST_SIZE 64
#endif
/**
* @def OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE
*
* Specifies the maximum number of entries in Network Data On Mesh Prefix history list.
*
* Can be set to zero to configure History Tracker module not to collect prefix info.
*
*/
#ifndef OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE 32
#endif
/**
* @def OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE
*
* Specifies the maximum number of entries in Network Data External Route history list.
*
* Can be set to zero to configure History Tracker module not to collect route info.
*
*/
#ifndef OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE 32
#endif
#endif // CONFIG_HISTORY_TRACKER_H_
+92
View File
@@ -52,6 +52,9 @@ namespace Utils {
HistoryTracker::HistoryTracker(Instance &aInstance)
: InstanceLocator(aInstance)
, mTimer(aInstance, HandleTimer)
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
, mPreviousNetworkData(aInstance, mNetworkDataTlvBuffer, 0, sizeof(mNetworkDataTlvBuffer))
#endif
{
mTimer.Start(kAgeCheckPeriod);
}
@@ -291,6 +294,86 @@ exit:
return;
}
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
void HistoryTracker::RecordNetworkDataChange(void)
{
NetworkData::Iterator iterator;
NetworkData::OnMeshPrefixConfig prefix;
NetworkData::ExternalRouteConfig route;
// On mesh prefix entries
iterator = NetworkData::kIteratorInit;
while (mPreviousNetworkData.GetNextOnMeshPrefix(iterator, prefix) == kErrorNone)
{
if (!Get<NetworkData::Leader>().ContainsOnMeshPrefix(prefix))
{
RecordOnMeshPrefixEvent(kNetDataEntryRemoved, prefix);
}
}
iterator = NetworkData::kIteratorInit;
while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, prefix) == kErrorNone)
{
if (!mPreviousNetworkData.ContainsOnMeshPrefix(prefix))
{
RecordOnMeshPrefixEvent(kNetDataEntryAdded, prefix);
}
}
// External route entries
iterator = NetworkData::kIteratorInit;
while (mPreviousNetworkData.GetNextExternalRoute(iterator, route) == kErrorNone)
{
if (!Get<NetworkData::Leader>().ContainsExternalRoute(route))
{
RecordExternalRouteEvent(kNetDataEntryRemoved, route);
}
}
iterator = NetworkData::kIteratorInit;
while (Get<NetworkData::Leader>().GetNextExternalRoute(iterator, route) == kErrorNone)
{
if (!mPreviousNetworkData.ContainsExternalRoute(route))
{
RecordExternalRouteEvent(kNetDataEntryAdded, route);
}
}
SuccessOrAssert(Get<NetworkData::Leader>().CopyNetworkData(/* aSatble */ false, mPreviousNetworkData));
}
void HistoryTracker::RecordOnMeshPrefixEvent(NetDataEvent aEvent, const NetworkData::OnMeshPrefixConfig &aPrefix)
{
OnMeshPrefixInfo *entry = mOnMeshPrefixHistory.AddNewEntry();
VerifyOrExit(entry != nullptr);
entry->mPrefix = aPrefix;
entry->mEvent = aEvent;
exit:
return;
}
void HistoryTracker::RecordExternalRouteEvent(NetDataEvent aEvent, const NetworkData::ExternalRouteConfig &aRoute)
{
ExternalRouteInfo *entry = mExternalRouteHistory.AddNewEntry();
VerifyOrExit(entry != nullptr);
entry->mRoute = aRoute;
entry->mEvent = aEvent;
exit:
return;
}
#endif // OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
void HistoryTracker::HandleNotifierEvents(Events aEvents)
{
if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadRlocAdded | kEventThreadRlocRemoved |
@@ -298,6 +381,13 @@ void HistoryTracker::HandleNotifierEvents(Events aEvents)
{
RecordNetworkInfo();
}
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
if (aEvents.Contains(kEventThreadNetdataChanged))
{
RecordNetworkDataChange();
}
#endif
}
void HistoryTracker::HandleTimer(Timer &aTimer)
@@ -313,6 +403,8 @@ void HistoryTracker::HandleTimer(void)
mRxHistory.UpdateAgedEntries();
mTxHistory.UpdateAgedEntries();
mNeighborHistory.UpdateAgedEntries();
mOnMeshPrefixHistory.UpdateAgedEntries();
mExternalRouteHistory.UpdateAgedEntries();
mTimer.Start(kAgeCheckPeriod);
}
+49 -29
View File
@@ -53,10 +53,20 @@
#include "thread/mle.hpp"
#include "thread/mle_types.hpp"
#include "thread/neighbor_table.hpp"
#include "thread/network_data.hpp"
namespace ot {
namespace Utils {
#ifdef OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
#error "OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA should not be defined directly." \
"It is derived from other configs: on-mesh prefix and external route history list sizes"
#endif
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA \
((OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE > 0) || \
(OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE > 0))
/**
* This class implements History Tracker.
*
@@ -110,35 +120,13 @@ public:
void SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); }
};
/**
* This type represents Thread network info.
*
*/
typedef otHistoryTrackerNetworkInfo NetworkInfo;
/**
* This structure represents a unicast IPv6 address info.
*
*/
typedef otHistoryTrackerUnicastAddressInfo UnicastAddressInfo;
/**
* This structure represent a multicast IPv6 address info.
*
*/
typedef otHistoryTrackerMulticastAddressInfo MulticastAddressInfo;
/**
* This type represents a RX/TX IPv6 message info.
*
*/
typedef otHistoryTrackerMessageInfo MessageInfo;
/**
* This type represents a neighbor info.
*
*/
typedef otHistoryTrackerNeighborInfo NeighborInfo;
typedef otHistoryTrackerNetworkInfo NetworkInfo; ///< Thread network info.
typedef otHistoryTrackerUnicastAddressInfo UnicastAddressInfo; ///< Unicast IPv6 address info.
typedef otHistoryTrackerMulticastAddressInfo MulticastAddressInfo; ///< Multicast IPv6 address info.
typedef otHistoryTrackerMessageInfo MessageInfo; ///< RX/TX IPv6 message info.
typedef otHistoryTrackerNeighborInfo NeighborInfo; ///< Neighbor info.
typedef otHistoryTrackerOnMeshPrefixInfo OnMeshPrefixInfo; ///< Network Data on mesh prefix info.
typedef otHistoryTrackerExternalRouteInfo ExternalRouteInfo; ///< Network Data external route info
/**
* This constructor initializes the `HistoryTracker`.
@@ -233,6 +221,16 @@ public:
return mNeighborHistory.Iterate(aIterator, aEntryAge);
}
const OnMeshPrefixInfo *IterateOnMeshPrefixHistory(Iterator &aIterator, uint32_t &aEntryAge) const
{
return mOnMeshPrefixHistory.Iterate(aIterator, aEntryAge);
}
const ExternalRouteInfo *IterateExternalRouteHistory(Iterator &aIterator, uint32_t &aEntryAge) const
{
return mExternalRouteHistory.Iterate(aIterator, aEntryAge);
}
/**
* This static method converts a given entry age to a human-readable string.
*
@@ -262,6 +260,8 @@ 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 kOnMeshPrefixListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_ON_MESH_PREFIX_LIST_SIZE;
static constexpr uint16_t kExternalRouteListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE;
typedef otHistoryTrackerAddressEvent AddressEvent;
@@ -278,6 +278,11 @@ private:
static constexpr NeighborEvent kNeighborChanged = OT_HISTORY_TRACKER_NEIGHBOR_EVENT_CHANGED;
static constexpr NeighborEvent kNeighborRestoring = OT_HISTORY_TRACKER_NEIGHBOR_EVENT_RESTORING;
typedef otHistoryTrackerNetDataEvent NetDataEvent;
static constexpr NetDataEvent kNetDataEntryAdded = OT_HISTORY_TRACKER_NET_DATA_ENTRY_ADDED;
static constexpr NetDataEvent kNetDataEntryRemoved = OT_HISTORY_TRACKER_NET_DATA_ENTRY_REMOVED;
class Timestamp
{
public:
@@ -379,6 +384,11 @@ private:
void HandleNotifierEvents(Events aEvents);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
void RecordNetworkDataChange(void);
void RecordOnMeshPrefixEvent(NetDataEvent aEvent, const NetworkData::OnMeshPrefixConfig &aPrefix);
void RecordExternalRouteEvent(NetDataEvent aEvent, const NetworkData::ExternalRouteConfig &aRoute);
#endif
EntryList<NetworkInfo, kNetInfoListSize> mNetInfoHistory;
EntryList<UnicastAddressInfo, kUnicastAddrListSize> mUnicastAddressHistory;
@@ -386,8 +396,16 @@ private:
EntryList<MessageInfo, kRxListSize> mRxHistory;
EntryList<MessageInfo, kTxListSize> mTxHistory;
EntryList<NeighborInfo, kNeighborListSize> mNeighborHistory;
EntryList<OnMeshPrefixInfo, kOnMeshPrefixListSize> mOnMeshPrefixHistory;
EntryList<ExternalRouteInfo, kExternalRouteListSize> mExternalRouteHistory;
TimerMilli mTimer;
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_DATA
NetworkData::MutableNetworkData mPreviousNetworkData;
uint8_t mNetworkDataTlvBuffer[NetworkData::NetworkData::kMaxSize];
#endif
};
} // namespace Utils
@@ -396,6 +414,8 @@ DefineCoreType(otHistoryTrackerIterator, Utils::HistoryTracker::Iterator);
DefineCoreType(otHistoryTrackerNetworkInfo, Utils::HistoryTracker::NetworkInfo);
DefineCoreType(otHistoryTrackerMessageInfo, Utils::HistoryTracker::MessageInfo);
DefineCoreType(otHistoryTrackerNeighborInfo, Utils::HistoryTracker::NeighborInfo);
DefineCoreType(otHistoryTrackerOnMeshPrefixInfo, Utils::HistoryTracker::OnMeshPrefixInfo);
DefineCoreType(otHistoryTrackerExternalRouteInfo, Utils::HistoryTracker::ExternalRouteInfo);
} // namespace ot