[routing-manager] track router age (#10453)

This commit adds a new mechanism in `RoutingManager` to track the
duration since a router is first discovered. This information is now
provided in `otBorderRoutingRouterEntry`, and the CLI `br routers`
command is updated to include this information for each router.

To enable tracking of longer durations, `Uptime` is used, which tracks
milliseconds since the start of `ot::Instance` as a `uint64_t` value.
`TimerMilli::GetNow()` is not suitable for this purpose because it
utilizes `uint32_t` intervals, which would limit the maximum
trackable time to roughly 49 days due to potential overflow.
This commit is contained in:
Abtin Keshavarzian
2024-07-09 09:57:57 -07:00
committed by GitHub
parent 821f2415e0
commit 8d4119c914
7 changed files with 44 additions and 13 deletions
+2
View File
@@ -85,6 +85,7 @@ typedef struct otBorderRoutingPrefixTableIterator
{
const void *mPtr1;
const void *mPtr2;
uint32_t mData0;
uint32_t mData1;
uint8_t mData2;
uint8_t mData3;
@@ -98,6 +99,7 @@ typedef struct otBorderRoutingRouterEntry
{
otIp6Address mAddress; ///< IPv6 address of the router.
uint32_t mMsecSinceLastUpdate; ///< Milliseconds since last update (any message rx) from this router.
uint32_t mAge; ///< The router's age in seconds (duration since its first discovery).
bool mManagedAddressConfigFlag : 1; ///< The router's Managed Address Config flag (`M` flag).
bool mOtherConfigFlag : 1; ///< The router's Other Config flag (`O` flag).
bool mStubRouterFlag : 1; ///< The router's Stub Router flag.
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (424)
#define OPENTHREAD_API_VERSION (425)
/**
* @addtogroup api-instance
+1
View File
@@ -80,6 +80,7 @@ OT_BUILD_OPTIONS=(
"-DOT_SRP_ADV_PROXY=ON"
"-DOT_SRP_CLIENT=ON"
"-DOT_SRP_SERVER=ON"
"-DOT_UPTIME=ON"
"-DOT_VENDOR_NAME=OpenThread"
"-DOT_VENDOR_MODEL=Scan-build"
"-DOT_VENDOR_SW_VERSION=OT"
+2 -1
View File
@@ -353,10 +353,11 @@ Info per router:
- Stub: Stub Router flag (indicates whether the router is a stub router)
- Milliseconds since last received message from this router
- Reachability flag: A router is marked as unreachable if it fails to respond to multiple Neighbor Solicitation probes.
- Age: Duration interval since this router was first discovered. It is formatted as `{hh}:{mm}:{ss}` for hours, minutes, seconds, if the duration is less than 24 hours. If the duration is 24 hours or more, the format is `{dd}d.{hh}:{mm}:{ss}` for days, hours, minutes, seconds.
- `(this BR)` is appended when the router is the local device itself.
```bash
> br routers
ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1) ms-since-rx:1505 reachable:yes
ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1) ms-since-rx:1505 reachable:yes age:00:18:13
Done
```
+10 -3
View File
@@ -518,7 +518,7 @@ exit:
* @cli br routers
* @code
* br routers
* ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1) ms-since-rx:1505 reachable:yes
* ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1) ms-since-rx:1505 reachable:yes age:00:18:13
* Done
* @endcode
* @par
@@ -532,6 +532,9 @@ exit:
* - Milliseconds since last received message from this router
* - Reachability flag: A router is marked as unreachable if it fails to respond to multiple Neighbor Solicitation
* probes.
* - Age: Duration interval since this router was first discovered. It is formatted as `{hh}:{mm}:{ss}` for hours,
* minutes, seconds, if the duration is less than 24 hours. If the duration is 24 hours or more, the format is
* `{dd}d.{hh}:{mm}:{ss}` for days, hours, minutes, seconds.
* - `(this BR)` is appended when the router is the local device itself.
* @sa otBorderRoutingGetNextRouterEntry
*/
@@ -562,8 +565,12 @@ void Br::OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry, RouterOutput
if (aMode == kLongVersion)
{
OutputFormat(" ms-since-rx:%lu reachable:%s", ToUlong(aEntry.mMsecSinceLastUpdate),
aEntry.mIsReachable ? "yes" : "no");
char ageString[OT_DURATION_STRING_SIZE];
otConvertDurationInSecondsToString(aEntry.mAge, ageString, sizeof(ageString));
OutputFormat(" ms-since-rx:%lu reachable:%s age:%s", ToUlong(aEntry.mMsecSinceLastUpdate),
aEntry.mIsReachable ? "yes" : "no", ageString);
if (aEntry.mIsLocalDevice)
{
+9 -6
View File
@@ -1032,7 +1032,8 @@ void RoutingManager::RxRaTracker::ProcessRouterAdvertMessage(const RouterAdvert:
router = newEntry;
router->Clear();
router->mAddress = aSrcAddress;
router->mDiscoverTime = Uptime::MsecToSec(Get<Uptime>().GetUptime());
router->mAddress = aSrcAddress;
mRouters.Push(*newEntry);
}
@@ -1713,7 +1714,7 @@ void RoutingManager::RxRaTracker::SetHeaderFlagsOn(RouterAdvert::Header &aHeader
void RoutingManager::RxRaTracker::InitIterator(PrefixTableIterator &aIterator) const
{
static_cast<Iterator &>(aIterator).Init(mRouters.GetHead());
static_cast<Iterator &>(aIterator).Init(mRouters.GetHead(), Uptime::MsecToSec(Get<Uptime>().GetUptime()));
}
Error RoutingManager::RxRaTracker::GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const
@@ -1725,7 +1726,7 @@ Error RoutingManager::RxRaTracker::GetNextEntry(PrefixTableIterator &aIterator,
SuccessOrExit(error = iterator.AdvanceToNextEntry());
iterator.GetRouter()->CopyInfoTo(aEntry.mRouter, iterator.GetInitTime());
iterator.GetRouter()->CopyInfoTo(aEntry.mRouter, iterator.GetInitTime(), iterator.GetInitUptime());
switch (iterator.GetEntryType())
{
@@ -1749,7 +1750,7 @@ Error RoutingManager::RxRaTracker::GetNextRouter(PrefixTableIterator &aIterator,
ClearAllBytes(aEntry);
SuccessOrExit(error = iterator.AdvanceToNextRouter(Iterator::kRouterIterator));
iterator.GetRouter()->CopyInfoTo(aEntry, iterator.GetInitTime());
iterator.GetRouter()->CopyInfoTo(aEntry, iterator.GetInitTime(), iterator.GetInitUptime());
exit:
return error;
@@ -1758,8 +1759,9 @@ exit:
//---------------------------------------------------------------------------------------------------------------------
// RxRaTracker::Iterator
void RoutingManager::RxRaTracker::Iterator::Init(const Entry<Router> *aRoutersHead)
void RoutingManager::RxRaTracker::Iterator::Init(const Entry<Router> *aRoutersHead, uint32_t aUptime)
{
SetInitUptime(aUptime);
SetInitTime();
SetType(kUnspecified);
SetRouter(aRoutersHead);
@@ -1914,10 +1916,11 @@ bool RoutingManager::RxRaTracker::Router::Matches(const EmptyChecker &aChecker)
return !hasFlags && mOnLinkPrefixes.IsEmpty() && mRoutePrefixes.IsEmpty();
}
void RoutingManager::RxRaTracker::Router::CopyInfoTo(RouterEntry &aEntry, TimeMilli aNow) const
void RoutingManager::RxRaTracker::Router::CopyInfoTo(RouterEntry &aEntry, TimeMilli aNow, uint32_t aUptime) const
{
aEntry.mAddress = mAddress;
aEntry.mMsecSinceLastUpdate = aNow - mLastUpdateTime;
aEntry.mAge = aUptime - mDiscoverTime;
aEntry.mManagedAddressConfigFlag = mManagedAddressConfigFlag;
aEntry.mOtherConfigFlag = mOtherConfigFlag;
aEntry.mStubRouterFlag = mStubRouterFlag;
+19 -2
View File
@@ -47,6 +47,10 @@
#error "OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE."
#endif
#if !OPENTHREAD_CONFIG_UPTIME_ENABLE
#error "OPENTHREAD_CONFIG_UPTIME_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE"
#endif
#include <openthread/border_routing.h>
#include <openthread/nat64.h>
#include <openthread/netdata.h>
@@ -837,14 +841,25 @@ private:
void DetermineReachabilityTimeout(void);
bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
bool Matches(const EmptyChecker &aChecker);
void CopyInfoTo(RouterEntry &aEntry, TimeMilli aNow) const;
void CopyInfoTo(RouterEntry &aEntry, TimeMilli aNow, uint32_t aUptime) const;
using OnLinkPrefixList = OwningList<Entry<OnLinkPrefix>>;
using RoutePrefixList = OwningList<Entry<RoutePrefix>>;
// `mDiscoverTime` tracks the initial discovery time of
// this router. To accommodate longer durations, the
// `Uptime` is used, as `TimeMilli` (which uses `uint32_t`
// intervals) would be limited to tracking ~ 49 days.
//
// `mLastUpdateTime` tracks the most recent time an RA or
// NA was received from this router. It is bounded due to
// the frequency of reachability checks, so we can safely
// use `TimeMilli` for it.
Ip6::Address mAddress;
OnLinkPrefixList mOnLinkPrefixes;
RoutePrefixList mRoutePrefixes;
uint32_t mDiscoverTime;
TimeMilli mLastUpdateTime;
TimeMilli mTimeoutTime;
uint8_t mNsProbeCount;
@@ -873,9 +888,10 @@ private:
kRoutePrefix,
};
void Init(const Entry<Router> *aRoutersHead);
void Init(const Entry<Router> *aRoutersHead, uint32_t aUptime);
Error AdvanceToNextRouter(Type aType);
Error AdvanceToNextEntry(void);
uint32_t GetInitUptime(void) const { return mData0; }
TimeMilli GetInitTime(void) const { return TimeMilli(mData1); }
Type GetType(void) const { return static_cast<Type>(mData2); }
const Entry<Router> *GetRouter(void) const { return static_cast<const Entry<Router> *>(mPtr1); }
@@ -888,6 +904,7 @@ private:
private:
void SetRouter(const Entry<Router> *aRouter) { mPtr1 = aRouter; }
void SetInitUptime(uint32_t aUptime) { mData0 = aUptime; }
void SetInitTime(void) { mData1 = TimerMilli::GetNow().GetValue(); }
void SetEntry(const void *aEntry) { mPtr2 = aEntry; }
bool HasEntry(void) const { return mPtr2 != nullptr; }