From 96819f934ac715a2cc45cc5ae4c963ad2f4951b2 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Thu, 21 Jul 2022 21:32:52 -0700 Subject: [PATCH] [routing-manager] new API to get currently favored OMR prefix (#7913) This commit updates `RoutingManager` to remember the currently favored OMR prefix (which can be an OMR prefix discovered from Network Data or device's local OMR prefix). It adds a new public API to retrieve this prefix and adds a related CLI sub-command. --- include/openthread/border_routing.h | 17 +++++++++- include/openthread/instance.h | 2 +- src/cli/cli.cpp | 19 ++++++++++++ src/core/api/border_routing_api.cpp | 13 ++++++++ src/core/border_router/routing_manager.cpp | 36 +++++++++++++++++----- src/core/border_router/routing_manager.hpp | 28 +++++++++++++++-- 6 files changed, 103 insertions(+), 12 deletions(-) diff --git a/include/openthread/border_routing.h b/include/openthread/border_routing.h index f4c4d777b..8cfec1bdb 100644 --- a/include/openthread/border_routing.h +++ b/include/openthread/border_routing.h @@ -166,7 +166,7 @@ otRoutePreference otBorderRoutingGetRouteInfoOptionPreference(otInstance *aInsta void otBorderRoutingSetRouteInfoOptionPreference(otInstance *aInstance, otRoutePreference aPreference); /** - * Gets the Off-Mesh-Routable (OMR) Prefix, for example `fdfc:1ff5:1512:5622::/64`. + * Gets the local Off-Mesh-Routable (OMR) Prefix, for example `fdfc:1ff5:1512:5622::/64`. * * An OMR Prefix is a randomly generated 64-bit prefix that's published in the * Thread network if there isn't already an OMR prefix. This prefix can be reached @@ -181,6 +181,21 @@ void otBorderRoutingSetRouteInfoOptionPreference(otInstance *aInstance, otRouteP */ otError otBorderRoutingGetOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix); +/** + * Gets the currently favored Off-Mesh-Routable (OMR) Prefix. + * + * The favored OMR prefix can be discovered from Network Data or can be this device's local OMR prefix. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[out] aPrefix A pointer to output the favored OMR prefix. + * @param[out] aPreference A pointer to output the preference associated the favored prefix. + * + * @retval OT_ERROR_INVALID_STATE The Border Routing Manager is not initialized yet. + * @retval OT_ERROR_NONE Successfully retrieved the favored OMR prefix. + * + */ +otError otBorderRoutingGetFavoredOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix, otRoutePreference *aPreference); + /** * Gets the On-Link Prefix for the adjacent infrastructure link, for example `fd41:2650:a6f5:0::/64`. * diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 2ba2889e7..87cea53cd 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 (228) +#define OPENTHREAD_API_VERSION (229) /** * @addtogroup api-instance diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index b90ed3764..71785276b 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -549,6 +549,25 @@ template <> otError Interpreter::Process(Arg aArgs[]) SuccessOrExit(error = otBorderRoutingGetOmrPrefix(GetInstancePtr(), &omrPrefix)); OutputIp6PrefixLine(omrPrefix); } + /** + * @cli br favoredomrprefix + * @code + * br favoredomrprefix + * fdfc:1ff5:1512:5622::/64 prf:low + * Done + * @endcode + * @par api_copy + * #otBorderRoutingGetFavoredOmrPrefix + */ + else if (aArgs[0] == "favoredomrprefix") + { + otIp6Prefix prefix; + otRoutePreference preference; + + SuccessOrExit(error = otBorderRoutingGetFavoredOmrPrefix(GetInstancePtr(), &prefix, &preference)); + OutputIp6Prefix(prefix); + OutputLine(" prf:%s", PreferenceToString(preference)); + } /** * @cli br onlinkprefix * @code diff --git a/src/core/api/border_routing_api.cpp b/src/core/api/border_routing_api.cpp index 38160401d..1d942c5b8 100644 --- a/src/core/api/border_routing_api.cpp +++ b/src/core/api/border_routing_api.cpp @@ -69,6 +69,19 @@ otError otBorderRoutingGetOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix) return AsCoreType(aInstance).Get().GetOmrPrefix(AsCoreType(aPrefix)); } +otError otBorderRoutingGetFavoredOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix, otRoutePreference *aPreference) +{ + otError error; + BorderRouter::RoutingManager::RoutePreference preference; + + SuccessOrExit(error = AsCoreType(aInstance).Get().GetFavoredOmrPrefix( + AsCoreType(aPrefix), preference)); + *aPreference = static_cast(preference); + +exit: + return error; +} + otError otBorderRoutingGetOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPrefix) { return AsCoreType(aInstance).Get().GetOnLinkPrefix(AsCoreType(aPrefix)); diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 01202ce55..901945b20 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -151,6 +151,18 @@ exit: return error; } +Error RoutingManager::GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference) +{ + Error error = kErrorNone; + + VerifyOrExit(IsInitialized(), error = kErrorInvalidState); + aPrefix = mFavoredOmrPrefix.GetPrefix(); + aPreference = mFavoredOmrPrefix.GetPreference(); + +exit: + return error; +} + Error RoutingManager::GetOnLinkPrefix(Ip6::Prefix &aPrefix) { Error error = kErrorNone; @@ -263,6 +275,7 @@ void RoutingManager::Stop(void) VerifyOrExit(mIsRunning); mLocalOmrPrefix.RemoveFromNetData(); + mFavoredOmrPrefix.Clear(); mFavoredDiscoveredOnLinkPrefix.Clear(); @@ -410,10 +423,11 @@ void RoutingManager::EvaluateOmrPrefix(OnMeshPrefixArray &aNewPrefixes) { NetworkData::Iterator iterator = NetworkData::kIteratorInit; NetworkData::OnMeshPrefixConfig onMeshPrefixConfig; - OmrPrefix favoredOmrPrefix; OT_ASSERT(mIsRunning); + mFavoredOmrPrefix.Clear(); + while (Get().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == kErrorNone) { if (!onMeshPrefixConfig.mOnMesh || onMeshPrefixConfig.mDp) @@ -437,15 +451,15 @@ void RoutingManager::EvaluateOmrPrefix(OnMeshPrefixArray &aNewPrefixes) continue; } - if (favoredOmrPrefix.IsEmpty() || !favoredOmrPrefix.IsFavoredOver(onMeshPrefixConfig)) + if (mFavoredOmrPrefix.IsEmpty() || !mFavoredOmrPrefix.IsFavoredOver(onMeshPrefixConfig)) { - favoredOmrPrefix.SetFrom(onMeshPrefixConfig); + mFavoredOmrPrefix.SetFrom(onMeshPrefixConfig); } } // Decide if we need to add or remove our local OMR prefix. - if (favoredOmrPrefix.IsEmpty()) + if (mFavoredOmrPrefix.IsEmpty()) { LogInfo("EvaluateOmrPrefix: No preferred OMR prefix found in Thread network"); @@ -453,12 +467,14 @@ void RoutingManager::EvaluateOmrPrefix(OnMeshPrefixArray &aNewPrefixes) // the local OMR prefix. SuccessOrExit(mLocalOmrPrefix.AddToNetData()); + mFavoredOmrPrefix.SetFrom(mLocalOmrPrefix); + if (!aNewPrefixes.Contains(mLocalOmrPrefix.GetPrefix())) { SuccessOrExit(aNewPrefixes.PushBack(mLocalOmrPrefix.GetPrefix())); } } - else if (favoredOmrPrefix.GetPrefix() == mLocalOmrPrefix.GetPrefix()) + else if (mFavoredOmrPrefix.GetPrefix() == mLocalOmrPrefix.GetPrefix()) { IgnoreError(mLocalOmrPrefix.AddToNetData()); } @@ -467,7 +483,7 @@ void RoutingManager::EvaluateOmrPrefix(OnMeshPrefixArray &aNewPrefixes) OnMeshPrefix *entry; LogInfo("EvaluateOmrPrefix: There is already a preferred OMR prefix %s in the Thread network", - favoredOmrPrefix.GetPrefix().ToString().AsCString()); + mFavoredOmrPrefix.GetPrefix().ToString().AsCString()); mLocalOmrPrefix.RemoveFromNetData(); @@ -1967,6 +1983,12 @@ void RoutingManager::OmrPrefix::SetFrom(const NetworkData::OnMeshPrefixConfig &a mPreference = aOnMeshPrefixConfig.GetPreference(); } +void RoutingManager::OmrPrefix::SetFrom(const LocalOmrPrefix &aLocalOmrPrefix) +{ + mPrefix = aLocalOmrPrefix.GetPrefix(); + mPreference = aLocalOmrPrefix.GetPreference(); +} + bool RoutingManager::OmrPrefix::IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const { // This method determines whether this OMR prefix is favored @@ -2018,7 +2040,7 @@ Error RoutingManager::LocalOmrPrefix::AddToNetData(void) config.mPreferred = true; config.mOnMesh = true; config.mDefaultRoute = false; - config.mPreference = NetworkData::kRoutePreferenceLow; + config.mPreference = GetPreference(); error = Get().AddOnMeshPrefix(config); diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index 31c24b975..4895ba0e3 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -141,10 +141,10 @@ public: void SetRouteInfoOptionPreference(RoutePreference aPreference); /** - * This method returns the off-mesh-routable (OMR) prefix. + * This method returns the local off-mesh-routable (OMR) prefix. * - * The randomly generated 64-bit prefix will be published - * in the Thread network if there isn't already an OMR prefix. + * The randomly generated 64-bit prefix will be added to the Thread Network Data if there isn't already an OMR + * prefix. * * @param[out] aPrefix A reference to where the prefix will be output to. * @@ -154,6 +154,23 @@ public: */ Error GetOmrPrefix(Ip6::Prefix &aPrefix); + /** + * This method returns the currently favored off-mesh-routable (OMR) prefix. + * + * The favored OMR prefix can be discovered from Network Data or can be our local OMR prefix. + * + * An OMR prefix with higher preference is favored. If the preference is the same, then the smaller prefix (in the + * sense defined by `Ip6::Prefix`) is favored. + * + * @param[out] aPrefix A reference to output the favored prefix. + * @param[out] aPreference A reference to output the preference associated with the favored OMR prefix. + * + * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. + * @retval kErrorNone Successfully retrieved the OMR prefix. + * + */ + Error GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference); + /** * This method returns the on-link prefix for the adjacent infrastructure link. * @@ -473,6 +490,8 @@ private: bool mAllowDefaultRouteInNetData; }; + class LocalOmrPrefix; + class OmrPrefix : public Clearable { public: @@ -480,6 +499,7 @@ private: bool IsEmpty(void) const { return (mPrefix.GetLength() == 0); } void SetFrom(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig); + void SetFrom(const LocalOmrPrefix &aLocalOmrPrefix); const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } RoutePreference GetPreference(void) const { return mPreference; } bool IsFavoredOver(const NetworkData::OnMeshPrefixConfig &aOmrPrefixConfig) const; @@ -499,6 +519,7 @@ private: explicit LocalOmrPrefix(Instance &aInstance); void GenerateFrom(const Ip6::Prefix &aBrUlaPrefix); const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } + RoutePreference GetPreference(void) const { return NetworkData::kRoutePreferenceLow; } Error AddToNetData(void); void RemoveFromNetData(void); bool IsAddedInNetData(void) const { return mIsAddedInNetData; } @@ -575,6 +596,7 @@ private: Ip6::Prefix mBrUlaPrefix; LocalOmrPrefix mLocalOmrPrefix; + OmrPrefix mFavoredOmrPrefix; // List of on-mesh prefixes (discovered from Network Data) which // were advertised as RIO in the last sent RA message.