mirror of
https://github.com/espressif/openthread.git
synced 2026-10-12 02:37:37 +00:00
[history-tracker] track favored OMR prefix on a border router (#11775)
This commit adds support for tracking the history of the favored OMR prefix on a border router. A new public API and the corresponding `history omrprefix` CLI command are added to retrieve the recorded history. A new `otHistoryTrackerFavoredOmrPrefix` type is introduced to represent an entry in the history. Each entry includes the OMR prefix, its preference, and a boolean flag `mIsLocal` indicating whether the prefix is the same as the one maintained locally by the border router. The local OMR prefix can be based on either a randomly generated ULA or a prefix delegated via DHCPv6-PD.
This commit is contained in:
@@ -289,6 +289,19 @@ typedef enum
|
||||
OT_HISTORY_TRACKER_BORDER_AGENT_EPSKC_EVENT_DEACTIVATED_UNKNOWN, ///< Deactivated for an unknown reason.
|
||||
} otHistoryTrackerBorderAgentEpskcEvent;
|
||||
|
||||
/**
|
||||
* Represents a favored OMR prefix tracked by a device acting as a Border Router (BR).
|
||||
*
|
||||
* The `mIsLocal` field indicates whether the favored OMR prefix is the same as the local one maintained by this BR.
|
||||
* The local OMR prefix can be either based on (random) ULA or a prefix delegated via DHCPv6-PD.
|
||||
*/
|
||||
typedef struct otHistoryTrackerFavoredOmrPrefix
|
||||
{
|
||||
otIp6Prefix mOmrPrefix; ///< The OMR prefix.
|
||||
signed int mPreference : 2; ///< The 2-bit signed preference (`OT_ROUTE_PREFERENCE_*` values).
|
||||
bool mIsLocal : 1; ///< `true` if the prefix is the local OMR prefix; `false` otherwise.
|
||||
} otHistoryTrackerFavoredOmrPrefix;
|
||||
|
||||
/**
|
||||
* Initializes an `otHistoryTrackerIterator`.
|
||||
*
|
||||
@@ -484,6 +497,25 @@ const otHistoryTrackerBorderAgentEpskcEvent *otHistoryTrackerIterateBorderAgentE
|
||||
otHistoryTrackerIterator *aIterator,
|
||||
uint32_t *aEntryAge);
|
||||
|
||||
/**
|
||||
* Iterates over the entries in the favored OMR 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 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 `otHistoryTrackerFavoredOmrPrefix` entry or `NULL` if no more entries in the list.
|
||||
*/
|
||||
const otHistoryTrackerFavoredOmrPrefix *otHistoryTrackerIterateFavoredOmrPrefixHistory(
|
||||
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 (523)
|
||||
#define OPENTHREAD_API_VERSION (524)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -16,6 +16,7 @@ Usage : `history [command] ...`
|
||||
- [ipmaddr](#ipmaddr)
|
||||
- [neighbor](#neighbor)
|
||||
- [netinfo](#netinfo)
|
||||
- [omrprefix](#omrprefix)
|
||||
- [prefix](#prefix)
|
||||
- [route](#route)
|
||||
- [router](#router)
|
||||
@@ -292,6 +293,40 @@ Print only the latest 2 entries.
|
||||
Done
|
||||
```
|
||||
|
||||
### omrprefix
|
||||
|
||||
Usage `history omrprefix [list] [<num-entries>]`
|
||||
|
||||
Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE`.
|
||||
|
||||
Print the favored OMR prefix history. Each entry provides:
|
||||
|
||||
- The favored OMR prefix.
|
||||
- Preference (`high`, `med`, `low`).
|
||||
- IsLocal as boolean `yes`/`no` indicating whether the favored OMR prefix is the same as the local one maintained by this BR.
|
||||
|
||||
Print the OMR prefix history as a table.
|
||||
|
||||
```bash
|
||||
> history omrprefix
|
||||
| Age | OMR Prefix | Pref |IsLocal |
|
||||
+----------------------+--------------------------------------------------+--------+--------+
|
||||
| 00:00:10.110 | fd44:dc78:510b:1::/64 | low | yes |
|
||||
| 00:06:17.604 | 2001:1a:12d5:23ae::/64 | med | no |
|
||||
| 00:13:11.235 | fd44:dc78:510b:1::/64 | low | yes |
|
||||
Done
|
||||
```
|
||||
|
||||
Print the OMR prefix history as a list
|
||||
|
||||
```bash
|
||||
> history omrprefix list
|
||||
00:03:20.379 -> omr-prefix:fd44:dc78:510b:1::/64 prf:low is-local:yes
|
||||
00:09:27.873 -> omr-prefix:2001:1a:12d5:23ae::/64 prf:med is-local:no
|
||||
00:16:21.504 -> omr-prefix:fd44:dc78:510b:1::/64 prf:low is-local:yes
|
||||
Done
|
||||
```
|
||||
|
||||
### prefix
|
||||
|
||||
Usage `history prefix [list] [<num-entries>]`
|
||||
|
||||
+83
-3
@@ -1539,6 +1539,83 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
/**
|
||||
* @cli history omrprefix
|
||||
* @code
|
||||
* history omrprefix
|
||||
* | Age | OMR Prefix | Pref |IsLocal |
|
||||
* +----------------------+--------------------------------------------------+--------+--------+
|
||||
* | 00:00:10.110 | fd44:dc78:510b:1::/64 | low | yes |
|
||||
* | 00:06:17.604 | 2001:1a:12d5:23ae::/64 | med | no |
|
||||
* | 00:13:11.235 | fd44:dc78:510b:1::/64 | low | yes |
|
||||
* Done
|
||||
* @endcode
|
||||
* @code
|
||||
* history omrprefix list
|
||||
* 00:03:20.379 -> omr-prefix:fd44:dc78:510b:1::/64 prf:low is-local:yes
|
||||
* 00:09:27.873 -> omr-prefix:2001:1a:12d5:23ae::/64 prf:med is-local:no
|
||||
* 00:16:21.504 -> omr-prefix:fd44:dc78:510b:1::/64 prf:low is-local:yes
|
||||
* Done
|
||||
* @endcode
|
||||
* @cparam history omrprefix [@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 OMR 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`
|
||||
* * OMR Prefix: The favored OMR prefix.
|
||||
* * Preference: The prefix preference associated with the OMR prefix (`low`, `med`, `high`).
|
||||
* * IsLocal: Indicates whether the favored OMR prefix is the same as the local one maintained by this BR.
|
||||
* @sa otHistoryTrackerIterateFavoredOmrPrefixHistory
|
||||
*/
|
||||
template <> otError History::Process<Cmd("omrprefix")>(Arg aArgs[])
|
||||
{
|
||||
otError error;
|
||||
bool isList;
|
||||
uint16_t numEntries;
|
||||
otHistoryTrackerIterator iterator;
|
||||
const otHistoryTrackerFavoredOmrPrefix *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", "OMR Prefix", "Pref", "IsLocal"};
|
||||
static const uint8_t kColumnWidths[] = {22, 50, 8, 8};
|
||||
|
||||
OutputTableHeader(kTitles, kColumnWidths);
|
||||
}
|
||||
|
||||
otHistoryTrackerInitIterator(&iterator);
|
||||
|
||||
for (uint16_t index = 0; (numEntries == 0) || (index < numEntries); index++)
|
||||
{
|
||||
info = otHistoryTrackerIterateFavoredOmrPrefixHistory(GetInstancePtr(), &iterator, &entryAge);
|
||||
VerifyOrExit(info != nullptr);
|
||||
|
||||
otHistoryTrackerEntryAgeToString(entryAge, ageString, sizeof(ageString));
|
||||
|
||||
otIp6PrefixToString(&info->mOmrPrefix, prefixString, sizeof(prefixString));
|
||||
|
||||
OutputLine(isList ? "%s -> omr-prefix:%s prf:%s is-local:%s" : "| %20s | %-48s | %-6s | %-6s |", ageString,
|
||||
prefixString, PreferenceToString(info->mPreference), info->mIsLocal ? "yes" : "no");
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
const char *History::DnsSrpAddrTypeToString(otHistoryTrackerDnsSrpAddrType aType)
|
||||
{
|
||||
static const char *const kAddrTypeStrings[] = {
|
||||
@@ -1559,9 +1636,12 @@ 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("prefix"), CmdEntry("route"), CmdEntry("router"),
|
||||
CmdEntry("rx"), CmdEntry("rxtx"), CmdEntry("tx"),
|
||||
CmdEntry("dnssrpaddr"), CmdEntry("ipaddr"), CmdEntry("ipmaddr"), CmdEntry("neighbor"), CmdEntry("netinfo"),
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
CmdEntry("omrprefix"),
|
||||
#endif
|
||||
CmdEntry("prefix"), CmdEntry("route"), CmdEntry("router"), CmdEntry("rx"), CmdEntry("rxtx"),
|
||||
CmdEntry("tx"),
|
||||
};
|
||||
|
||||
#undef CmdEntry
|
||||
|
||||
@@ -152,6 +152,19 @@ const otHistoryTrackerBorderAgentEpskcEvent *otHistoryTrackerIterateBorderAgentE
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
const otHistoryTrackerFavoredOmrPrefix *otHistoryTrackerIterateFavoredOmrPrefixHistory(
|
||||
otInstance *aInstance,
|
||||
otHistoryTrackerIterator *aIterator,
|
||||
uint32_t *aEntryAge)
|
||||
{
|
||||
AssertPointerIsNotNull(aEntryAge);
|
||||
|
||||
return AsCoreType(aInstance).Get<HistoryTracker::Local>().IterateFavoredOmrPrefixHistory(AsCoreType(aIterator),
|
||||
*aEntryAge);
|
||||
}
|
||||
#endif
|
||||
|
||||
void otHistoryTrackerEntryAgeToString(uint32_t aEntryAge, char *aBuffer, uint16_t aSize)
|
||||
{
|
||||
HistoryTracker::Local::EntryAgeToString(aEntryAge, aBuffer, aSize);
|
||||
|
||||
@@ -2649,6 +2649,11 @@ void RoutingManager::OmrPrefixManager::SetFavoredPrefix(const OmrPrefix &aOmrPre
|
||||
#endif
|
||||
LogInfo("Favored OMR prefix: %s -> %s", FavoredToString(oldFavoredPrefix).AsCString(),
|
||||
FavoredToString(mFavoredPrefix).AsCString());
|
||||
|
||||
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
|
||||
Get<HistoryTracker::Local>().RecordFavoredOmrPrefix(mFavoredPrefix.GetPrefix(), mFavoredPrefix.GetPreference(),
|
||||
mFavoredPrefix.GetPrefix() == mLocalPrefix.GetPrefix());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -182,6 +182,17 @@
|
||||
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_EPSKC_EVENT_SIZE 64
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_HISTORY_TRACKER_OMR_PREFIX_LIST_SIZE
|
||||
*
|
||||
* Specifies the maximum number of entries in OMR Prefix history.
|
||||
*
|
||||
* Can be set to zero to configure History Tracker module not to collect any OMR prefix info.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_HISTORY_TRACKER_OMR_PREFIX_LIST_SIZE
|
||||
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_OMR_PREFIX_LIST_SIZE 16
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -577,6 +577,26 @@ exit:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
void Local::RecordFavoredOmrPrefix(const Ip6::Prefix &aPrefix,
|
||||
BorderRouter::RoutingManager::RoutePreference aPreference,
|
||||
bool aIsLocal)
|
||||
{
|
||||
FavoredOmrPrefix *entry = mFavoredOmrPrefixHistory.AddNewEntry();
|
||||
|
||||
VerifyOrExit(entry != nullptr);
|
||||
|
||||
entry->mOmrPrefix = aPrefix;
|
||||
entry->mPreference = NetworkData::RoutePreferenceToValue(aPreference);
|
||||
entry->mIsLocal = aIsLocal;
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
void Local::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadRlocAdded | kEventThreadRlocRemoved |
|
||||
@@ -606,6 +626,9 @@ void Local::HandleTimer(void)
|
||||
mDnsSrpAddrHistory.UpdateAgedEntries();
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
|
||||
mEpskcEventHistory.UpdateAgedEntries();
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
mFavoredOmrPrefixHistory.UpdateAgedEntries();
|
||||
#endif
|
||||
mTimer.Start(kAgeCheckPeriod);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <openthread/history_tracker.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#include "border_router/routing_manager.hpp"
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/clearable.hpp"
|
||||
#include "common/locator.hpp"
|
||||
@@ -109,6 +110,9 @@ typedef otHistoryTrackerDnsSrpAddrInfo DnsSrpAddrInfo; ///< Network
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
|
||||
typedef otHistoryTrackerBorderAgentEpskcEvent EpskcEvent; ///< Border Agent ePSKc Event.
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
typedef otHistoryTrackerFavoredOmrPrefix FavoredOmrPrefix; ///< Favored OMR Prefix
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This constant specifies the maximum age of entries which is 49 days (value in msec).
|
||||
@@ -146,6 +150,9 @@ class Local : public InstanceLocator, private NonCopyable
|
||||
friend class ot::MeshCoP::BorderAgent;
|
||||
friend class ot::MeshCoP::BorderAgent::EphemeralKeyManager;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
friend class ot::BorderRouter::RoutingManager;
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -267,6 +274,13 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
const FavoredOmrPrefix *IterateFavoredOmrPrefixHistory(Iterator &aIterator, uint32_t &aEntryAge) const
|
||||
{
|
||||
return mFavoredOmrPrefixHistory.Iterate(aIterator, aEntryAge);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Converts a given entry age to a human-readable string.
|
||||
*
|
||||
@@ -300,6 +314,7 @@ private:
|
||||
static constexpr uint16_t kExternalRouteListSize = OPENTHREAD_CONFIG_HISTORY_TRACKER_EXTERNAL_ROUTE_LIST_SIZE;
|
||||
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;
|
||||
|
||||
typedef otHistoryTrackerAddressEvent AddressEvent;
|
||||
|
||||
@@ -477,6 +492,11 @@ private:
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
|
||||
void RecordEpskcEvent(EpskcEvent aEvent);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
void RecordFavoredOmrPrefix(const Ip6::Prefix &aPrefix,
|
||||
BorderRouter::RoutingManager::RoutePreference aPreference,
|
||||
bool aIsLocal);
|
||||
#endif
|
||||
|
||||
using TrackerTimer = TimerMilliIn<Local, &Local::HandleTimer>;
|
||||
|
||||
@@ -493,6 +513,9 @@ private:
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
|
||||
EntryList<EpskcEvent, kEpskcEventListSize> mEpskcEventHistory;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
EntryList<FavoredOmrPrefix, kOmrPrefixListSize> mFavoredOmrPrefixHistory;
|
||||
#endif
|
||||
|
||||
TrackerTimer mTimer;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user