From 8d4119c9140ca188748f4dec2907d2748593b050 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 9 Jul 2024 09:57:57 -0700 Subject: [PATCH] [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. --- include/openthread/border_routing.h | 2 ++ include/openthread/instance.h | 2 +- script/check-scan-build | 1 + src/cli/README_BR.md | 3 ++- src/cli/cli_br.cpp | 13 ++++++++++--- src/core/border_router/routing_manager.cpp | 15 +++++++++------ src/core/border_router/routing_manager.hpp | 21 +++++++++++++++++++-- 7 files changed, 44 insertions(+), 13 deletions(-) diff --git a/include/openthread/border_routing.h b/include/openthread/border_routing.h index 55af0131a..95e50a116 100644 --- a/include/openthread/border_routing.h +++ b/include/openthread/border_routing.h @@ -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. diff --git a/include/openthread/instance.h b/include/openthread/instance.h index b1079aab7..f533e4c11 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -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 diff --git a/script/check-scan-build b/script/check-scan-build index 2d855fb16..142468f9c 100755 --- a/script/check-scan-build +++ b/script/check-scan-build @@ -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" diff --git a/src/cli/README_BR.md b/src/cli/README_BR.md index ed704ee32..cd7783fd9 100644 --- a/src/cli/README_BR.md +++ b/src/cli/README_BR.md @@ -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 ``` diff --git a/src/cli/cli_br.cpp b/src/cli/cli_br.cpp index cee063d01..7839823bb 100644 --- a/src/cli/cli_br.cpp +++ b/src/cli/cli_br.cpp @@ -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) { diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index f0cb6a24c..86fc96d3d 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -1032,7 +1032,8 @@ void RoutingManager::RxRaTracker::ProcessRouterAdvertMessage(const RouterAdvert: router = newEntry; router->Clear(); - router->mAddress = aSrcAddress; + router->mDiscoverTime = Uptime::MsecToSec(Get().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(aIterator).Init(mRouters.GetHead()); + static_cast(aIterator).Init(mRouters.GetHead(), Uptime::MsecToSec(Get().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 *aRoutersHead) +void RoutingManager::RxRaTracker::Iterator::Init(const Entry *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; diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index 17bcbd4b2..058974ba0 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -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 #include #include @@ -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>; using RoutePrefixList = OwningList>; + // `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 *aRoutersHead); + void Init(const Entry *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(mData2); } const Entry *GetRouter(void) const { return static_cast *>(mPtr1); } @@ -888,6 +904,7 @@ private: private: void SetRouter(const Entry *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; }