From b01b262a5c6a8343fda5cd5c8baa48f584c031a1 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 21 May 2024 13:26:40 -0700 Subject: [PATCH] [routing-manager] track and report last update time of routers (#10244) This commit enhances the `DiscoveredPrefixTable::Router` class to track the last time an ND6 message (RA or NS) was received from each discovered router. This information is now available through the `otBorderRoutingRouterEntry` and can be viewed using the `br routers` CLI command. --- include/openthread/border_routing.h | 1 + include/openthread/instance.h | 2 +- src/cli/README_BR.md | 3 ++- src/cli/cli_br.cpp | 24 ++++++++++++++++------ src/cli/cli_br.hpp | 8 +++++++- src/core/border_router/routing_manager.cpp | 12 ++++++----- src/core/border_router/routing_manager.hpp | 3 ++- 7 files changed, 38 insertions(+), 15 deletions(-) diff --git a/include/openthread/border_routing.h b/include/openthread/border_routing.h index 33ef275cf..e00c33f31 100644 --- a/include/openthread/border_routing.h +++ b/include/openthread/border_routing.h @@ -97,6 +97,7 @@ typedef struct otBorderRoutingPrefixTableIterator typedef struct otBorderRoutingRouterEntry { otIp6Address mAddress; ///< IPv6 address of the router. + uint32_t mMsecSinceLastUpdate; ///< Milliseconds since last update (any message rx) from this router. 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 8e912e66c..1964b22d0 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 (413) +#define OPENTHREAD_API_VERSION (414) /** * @addtogroup api-instance diff --git a/src/cli/README_BR.md b/src/cli/README_BR.md index d043a5718..e6eb264ea 100644 --- a/src/cli/README_BR.md +++ b/src/cli/README_BR.md @@ -351,9 +351,10 @@ Info per router: - M: Managed Address Config flag - O: Other Config flag - Stub: Stub Router flag (indicates whether the router is a stub router) +- Milliseconds since last received message from this router ```bash > br routers -ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1) +ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1) ms-since-rx:1505 Done ``` diff --git a/src/cli/cli_br.cpp b/src/cli/cli_br.cpp index c8e9115b9..b24cf76d5 100644 --- a/src/cli/cli_br.cpp +++ b/src/cli/cli_br.cpp @@ -428,7 +428,7 @@ template <> otError Br::Process(Arg aArgs[]) } OutputFormat("router:"); - OutputRouterInfo(entry.mRouter); + OutputRouterInfo(entry.mRouter, kShortVersion); } exit: @@ -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) + * ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1) ms-since-rx:1505 * Done * @endcode * @par @@ -529,6 +529,7 @@ exit: * - M: Managed Address Config flag * - O: Other Config flag * - Stub: Stub Router flag (indicates whether the router is a stub router) + * - Milliseconds since last received message from this router * @sa otBorderRoutingGetNextRouterEntry */ template <> otError Br::Process(Arg aArgs[]) @@ -543,18 +544,29 @@ template <> otError Br::Process(Arg aArgs[]) while (otBorderRoutingGetNextRouterEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE) { - OutputRouterInfo(entry); + OutputRouterInfo(entry, kLongVersion); } exit: return error; } -void Br::OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry) +void Br::OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry, RouterOutputMode aMode) { OutputIp6Address(aEntry.mAddress); - OutputLine(" (M:%u O:%u Stub:%u)", aEntry.mManagedAddressConfigFlag, aEntry.mOtherConfigFlag, - aEntry.mStubRouterFlag); + OutputFormat(" (M:%u O:%u Stub:%u)", aEntry.mManagedAddressConfigFlag, aEntry.mOtherConfigFlag, + aEntry.mStubRouterFlag); + + switch (aMode) + { + case kShortVersion: + OutputNewLine(); + break; + + case kLongVersion: + OutputLine(" ms-since-rx:%lu", ToUlong(aEntry.mMsecSinceLastUpdate)); + break; + } } template <> otError Br::Process(Arg aArgs[]) diff --git a/src/cli/cli_br.hpp b/src/cli/cli_br.hpp index 5a877a84d..650544419 100644 --- a/src/cli/cli_br.hpp +++ b/src/cli/cli_br.hpp @@ -89,10 +89,16 @@ private: kPrefixTypeFavored = 1u << 1, }; + enum RouterOutputMode : uint8_t + { + kShortVersion, + kLongVersion, + }; + template otError Process(Arg aArgs[]); otError ParsePrefixTypeArgs(Arg aArgs[], PrefixType &aFlags); - void OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry); + void OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry, RouterOutputMode aMode); }; } // namespace Cli diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 012d5ecaa..96bc225e7 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -1643,9 +1643,10 @@ exit: void RoutingManager::RxRaTracker::UpdateRouterOnRx(Router &aRouter) { - aRouter.mNsProbeCount = 0; - aRouter.mTimeout = TimerMilli::GetNow() + Random::NonCrypto::AddJitter(Router::kActiveTimeout, Router::kJitter); + aRouter.mNsProbeCount = 0; + aRouter.mLastUpdateTime = TimerMilli::GetNow(); + aRouter.mTimeout = aRouter.mLastUpdateTime + Random::NonCrypto::AddJitter(Router::kActiveTimeout, Router::kJitter); mRouterTimer.FireAtIfEarlier(aRouter.mTimeout); } @@ -1770,7 +1771,7 @@ Error RoutingManager::RxRaTracker::GetNextEntry(PrefixTableIterator &aIterator, SuccessOrExit(error = iterator.AdvanceToNextEntry()); - iterator.GetRouter()->CopyInfoTo(aEntry.mRouter); + iterator.GetRouter()->CopyInfoTo(aEntry.mRouter, iterator.GetInitTime()); switch (iterator.GetEntryType()) { @@ -1794,7 +1795,7 @@ Error RoutingManager::RxRaTracker::GetNextRouter(PrefixTableIterator &aIterator, ClearAllBytes(aEntry); SuccessOrExit(error = iterator.AdvanceToNextRouter(Iterator::kRouterIterator)); - iterator.GetRouter()->CopyInfoTo(aEntry); + iterator.GetRouter()->CopyInfoTo(aEntry, iterator.GetInitTime()); exit: return error; @@ -1917,9 +1918,10 @@ bool RoutingManager::RxRaTracker::Router::Matches(EmptyChecker aChecker) const return !hasFlags && mOnLinkPrefixes.IsEmpty() && mRoutePrefixes.IsEmpty(); } -void RoutingManager::RxRaTracker::Router::CopyInfoTo(RouterEntry &aEntry) const +void RoutingManager::RxRaTracker::Router::CopyInfoTo(RouterEntry &aEntry, TimeMilli aNow) const { aEntry.mAddress = mAddress; + aEntry.mMsecSinceLastUpdate = aNow - mLastUpdateTime; 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 3cc3b5923..ac97b23e0 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -817,7 +817,7 @@ private: bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; } bool Matches(EmptyChecker aChecker) const; - void CopyInfoTo(RouterEntry &aEntry) const; + void CopyInfoTo(RouterEntry &aEntry, TimeMilli aNow) const; using OnLinkPrefixList = OwningList>; using RoutePrefixList = OwningList>; @@ -825,6 +825,7 @@ private: Ip6::Address mAddress; OnLinkPrefixList mOnLinkPrefixes; RoutePrefixList mRoutePrefixes; + TimeMilli mLastUpdateTime; TimeMilli mTimeout; uint8_t mNsProbeCount; bool mManagedAddressConfigFlag : 1;