From 2caa934410939301f8889e079095307346e48dd7 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 27 Feb 2023 19:03:29 -0800 Subject: [PATCH] [routing-manager] new APIs to get state and new CLI commands (#8784) This commit adds new public OT APIs in `border_routing.h` to get the current state of `RoutingManager` and to get the current favored on-link prefix. This commit also updates CLI `br` commands: - It moves the CLI `br` implementation into own `cli_br` module. - It adds `br state` to get the current state - It changes `br omrprefix`, `br onlinkprefix`, and `br nat64prefix` to output both local and favored prefixes when no additional arg is provided and allow the use of `local` or `favored` extra arg to specify the type. - It updates the documentation of `br` related commands in the source code and also adding `cli/README_BR.md`. --- include/openthread/border_routing.h | 44 +- include/openthread/instance.h | 2 +- src/cli/BUILD.gn | 2 + src/cli/CMakeLists.txt | 1 + src/cli/Makefile.am | 2 + src/cli/README.md | 67 +-- src/cli/README_BR.md | 208 ++++++++ src/cli/cli.cpp | 289 ++--------- src/cli/cli.hpp | 9 + src/cli/cli_br.cpp | 542 +++++++++++++++++++++ src/cli/cli_br.hpp | 89 ++++ src/core/api/border_routing_api.cpp | 10 + src/core/border_router/routing_manager.cpp | 35 +- src/core/border_router/routing_manager.hpp | 66 ++- tests/scripts/thread-cert/node.py | 8 +- tools/harness-thci/OpenThread.py | 2 +- 16 files changed, 1037 insertions(+), 339 deletions(-) create mode 100644 src/cli/README_BR.md create mode 100644 src/cli/cli_br.cpp create mode 100644 src/cli/cli_br.hpp diff --git a/include/openthread/border_routing.h b/include/openthread/border_routing.h index 79be8e167..961554ea5 100644 --- a/include/openthread/border_routing.h +++ b/include/openthread/border_routing.h @@ -106,6 +106,18 @@ typedef struct otBorderRoutingPrefixTableEntry uint32_t mPreferredLifetime; ///< Preferred lifetime of the on-link prefix when `mIsOnLink` is true. } otBorderRoutingPrefixTableEntry; +/** + * This enumeration represents the state of Border Routing Manager. + * + */ +typedef enum +{ + OT_BORDER_ROUTING_STATE_UNINITIALIZED, ///< Routing Manager is uninitialized. + OT_BORDER_ROUTING_STATE_DISABLED, ///< Routing Manager is initialized but disabled. + OT_BORDER_ROUTING_STATE_STOPPED, ///< Routing Manager in initialized and enabled but currently stopped. + OT_BORDER_ROUTING_STATE_RUNNING, ///< Routing Manager is initialized, enabled, and running. +} otBorderRoutingState; + /** * This method initializes the Border Routing Manager on given infrastructure interface. * @@ -140,6 +152,16 @@ otError otBorderRoutingInit(otInstance *aInstance, uint32_t aInfraIfIndex, bool */ otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled); +/** + * Gets the current state of Border Routing Manager. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns The current state of Border Routing Manager. + * + */ +otBorderRoutingState otBorderRoutingGetState(otInstance *aInstance); + /** * This function gets the current preference used when advertising Route Info Options (RIO) in Router Advertisement * messages sent over the infrastructure link. @@ -212,20 +234,34 @@ otError otBorderRoutingGetOmrPrefix(otInstance *aInstance, otIp6Prefix *aPrefix) 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`. + * Gets the local On-Link Prefix for the adjacent infrastructure link. * - * An On-Link Prefix is a 64-bit prefix that's advertised on the infrastructure link if there isn't already a usable - * on-link prefix being advertised on the link. + * The local On-Link Prefix is a 64-bit prefix that's advertised on the infrastructure link if there isn't already a + * usable on-link prefix being advertised on the link. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[out] aPrefix A pointer to where the prefix will be output to. * * @retval OT_ERROR_INVALID_STATE The Border Routing Manager is not initialized yet. - * @retval OT_ERROR_NONE Successfully retrieved the on-link prefix. + * @retval OT_ERROR_NONE Successfully retrieved the local on-link prefix. * */ otError otBorderRoutingGetOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPrefix); +/** + * Gets the currently favored On-Link Prefix. + * + * The favored prefix is either a discovered on-link prefix on the infrastructure link or the local on-link prefix. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[out] aPrefix A pointer to where the prefix will be output to. + * + * @retval OT_ERROR_INVALID_STATE The Border Routing Manager is not initialized yet. + * @retval OT_ERROR_NONE Successfully retrieved the favored on-link prefix. + * + */ +otError otBorderRoutingGetFavoredOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPrefix); + /** * Gets the local NAT64 Prefix of the Border Router. * diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 2ab91ec4e..302665967 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 (289) +#define OPENTHREAD_API_VERSION (290) /** * @addtogroup api-instance diff --git a/src/cli/BUILD.gn b/src/cli/BUILD.gn index 2d4e8f6a0..86e06af76 100644 --- a/src/cli/BUILD.gn +++ b/src/cli/BUILD.gn @@ -30,6 +30,8 @@ import("../../etc/gn/openthread.gni") openthread_cli_sources = [ "cli.cpp", "cli.hpp", + "cli_br.cpp", + "cli_br.hpp", "cli_coap.cpp", "cli_coap.hpp", "cli_coap_secure.cpp", diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt index 67c8b01b8..32c9d7b34 100644 --- a/src/cli/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -33,6 +33,7 @@ set(COMMON_INCLUDES set(COMMON_SOURCES cli.cpp + cli_br.cpp cli_coap.cpp cli_coap_secure.cpp cli_commissioner.cpp diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am index f6e32d02d..43d1b4750 100644 --- a/src/cli/Makefile.am +++ b/src/cli/Makefile.am @@ -153,6 +153,7 @@ libopenthread_cli_radio_a_CPPFLAGS = \ SOURCES_COMMON = \ cli.cpp \ + cli_br.cpp \ cli_coap.cpp \ cli_coap_secure.cpp \ cli_commissioner.cpp \ @@ -182,6 +183,7 @@ libopenthread_cli_radio_a_SOURCES = \ noinst_HEADERS = \ cli.hpp \ + cli_br.hpp \ cli_coap.hpp \ cli_coap_secure.hpp \ cli_commissioner.hpp \ diff --git a/src/cli/README.md b/src/cli/README.md index badb9edbe..94f08e4a8 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -23,7 +23,7 @@ Done - [ba](#ba) - [bbr](#bbr) -- [br](#br) +- [br](README_BR.md) - [bufferinfo](#bufferinfo) - [ccathreshold](#ccathreshold) - [channel](#channel) @@ -353,71 +353,6 @@ Started Done ``` -### br - -Enbale/disable the Border Routing functionality. - -```bash -> br enable -Done -``` - -```bash -> br disable -Done -``` - -### br omrprefix - -Get the randomly generated off-mesh-routable prefix of the Border Router. - -```bash -> br omrprefix -fdfc:1ff5:1512:5622::/64 -Done -``` - -### br onlinkprefix - -Get the randomly generated on-link prefix of the Border Router. - -```bash -> br onlinkprefix -fd41:2650:a6f5:0::/64 -Done -``` - -### br nat64prefix - -Get the local NAT64 prefix of the Border Router. - -`OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is required. - -```bash -> br nat64prefix -fd14:1078:b3d5:b0b0:0:0::/96 -Done -``` - -### br rioprf - -Get the preference used when advertising Route Info Options (e.g., for discovered OMR prefixes) in emitted Router Advertisement message. - -```bash -> br rioprf -med -Done -``` - -### br rioprf \ - -Set the preference (which may be 'high', 'med', or 'low') to use when advertising Route Info Options (e.g., for discovered OMR prefixes) in emitted Router Advertisement message. - -```bash -> br rioprf low -Done -``` - ### bufferinfo Show the current message buffer information. diff --git a/src/cli/README_BR.md b/src/cli/README_BR.md new file mode 100644 index 000000000..90a50b619 --- /dev/null +++ b/src/cli/README_BR.md @@ -0,0 +1,208 @@ +# OpenThread CLI - Border Router (BR) + +## Command List + +Usage : `br [command] ...` + +- [counters](#counters) +- [disable](#disable) +- [enable](#enable) +- [help](#help) +- [nat64prefix](#nat64prefix) +- [omrprefix](#omrprefix) +- [onlinkprefix](#onlinkprefix) +- [prefixtable](#prefixtable) +- [rioprf](#rioprf) +- [state](#state) + +## Command Details + +### help + +Usage: `br help` + +Print BR command help menu. + +```bash +> br help +counters +disable +enable +omrprefix +onlinkprefix +prefixtable +rioprf +state +Done +``` + +### enable + +Usage: `br enable` + +Enable the Border Routing functionality. + +```bash +> br enable +Done +``` + +### disable + +Usage: `br disable` + +Disable the Border Routing functionality. + +```bash +> br disable +Done +``` + +### state + +Usage: `br state` + +Get the Border Routing state: + +- `uninitialized`: Routing Manager is uninitialized. +- `disabled`: Routing Manager is initialized but disabled. +- `stopped`: Routing Manager in initialized and enabled but currently stopped. +- `running`: Routing Manager is initialized, enabled, and running. + +```bash +> br state +running +``` + +### counters + +Usage : `br counters` + +Get the Border Router counter. + +```bash +> br counters +Inbound Unicast: Packets 4 Bytes 320 +Inbound Multicast: Packets 0 Bytes 0 +Outbound Unicast: Packets 2 Bytes 160 +Outbound Multicast: Packets 0 Bytes 0 +RA Rx: 4 +RA TxSuccess: 2 +RA TxFailed: 0 +RS Rx: 0 +RS TxSuccess: 2 +RS TxFailed: 0 +Done +``` + +### omrprefix + +Usage: `br omrprefix [local|favored]` + +Get local or favored or both off-mesh-routable prefixes of the Border Router. + +```bash +> br omrprefix +Local: fdfc:1ff5:1512:5622::/64 +Favored: fdfc:1ff5:1512:5622::/64 prf:low +Done + +> br omrprefix favored +fdfc:1ff5:1512:5622::/64 prf:low +Done + +> br omrprefix local +fdfc:1ff5:1512:5622::/64 +Done +``` + +### onlinkprefix + +Usage: `br onlinkprefix [local|favored]` + +Get local or favored or both on-link prefixes of the Border Router. + +```bash +> br onlinkprefix +Local: fd41:2650:a6f5:0::/64 +Favored: 2600::0:1234:da12::/64 +Done + +> br onlinkprefix favored +2600::0:1234:da12::/64 +Done + +> br onlinkprefix local +fd41:2650:a6f5:0::/64 +Done +``` + +### nat64prefix + +Usage: `br nat64prefix [local|favored]` + +Get local or favored or both NAT64 prefixes of the Border Router. + +`OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE` is required. + +```bash +> br nat64prefix +Local: fd14:1078:b3d5:b0b0:0:0::/96 +Favored: fd14:1078:b3d5:b0b0:0:0::/96 prf:low +Done + +> br nat64prefix favored +fd14:1078:b3d5:b0b0:0:0::/96 prf:low +Done + +> br nat64prefix +fd14:1078:b3d5:b0b0:0:0::/96 +Done +``` + +### prefixtable + +Usage: `br prefixtable` + +Get the discovered prefixes by Border Routing Manager on the infrastructure link. + +```bash +> br prefixtable +prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med, router:ff02:0:0:0:0:0:0:1 +prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800, router:ff02:0:0:0:0:0:0:1 +Done +``` + +### rioprf + +Usage: `br rioprf` + +Get the preference used when advertising Route Info Options (e.g., for discovered OMR prefixes) in emitted Router Advertisement message. + +```bash +> br rioprf +med +Done +``` + +### rioprf \ + +Usage: `br rioprf high|med|low` + +Set the preference (which may be 'high', 'med', or 'low') to use when advertising Route Info Options (e.g., for discovered OMR prefixes) in emitted Router Advertisement message. + +```bash +> br rioprf low +Done +``` + +### rioprf clear + +Usage: `br rioprf clear` + +Clear a previously set preference value for advertising Route Info Options (e.g., for discovered OMR prefixes) in emitted Router Advertisement message. When cleared BR will use device's role to determine the RIO preference: Medium preference when in router/leader role and low preference when in child role. + +```bash +> br rioprf clear +Done +``` diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 14a3e8c37..0b8752bef 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -113,6 +113,9 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi , mDataset(aInstance, *this) , mNetworkData(aInstance, *this) , mUdp(aInstance, *this) +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + , mBr(aInstance, *this) +#endif #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE , mTcp(aInstance, *this) #endif @@ -539,221 +542,8 @@ template <> otError Interpreter::Process(Arg aArgs[]) #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE -template <> otError Interpreter::Process(Arg aArgs[]) -{ - otError error = OT_ERROR_NONE; - bool enable; - - /** - * @cli br (enable,disable) - * @code - * br enable - * Done - * @endcode - * @code - * br disable - * Done - * @endcode - * @par api_copy - * #otBorderRoutingSetEnabled - */ - if (ParseEnableOrDisable(aArgs[0], enable) == OT_ERROR_NONE) - { - SuccessOrExit(error = otBorderRoutingSetEnabled(GetInstancePtr(), enable)); - } - /** - * @cli br omrprefix - * @code - * br omrprefix - * fdfc:1ff5:1512:5622::/64 - * Done - * @endcode - * @par api_copy - * #otBorderRoutingGetOmrPrefix - */ - else if (aArgs[0] == "omrprefix") - { - otIp6Prefix omrPrefix; - - 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 - * br onlinkprefix - * fd41:2650:a6f5:0::/64 - * Done - * @endcode - * @par api_copy - * #otBorderRoutingGetOnLinkPrefix - */ - else if (aArgs[0] == "onlinkprefix") - { - otIp6Prefix onLinkPrefix; - - SuccessOrExit(error = otBorderRoutingGetOnLinkPrefix(GetInstancePtr(), &onLinkPrefix)); - OutputIp6PrefixLine(onLinkPrefix); - } -#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE - /** - * @cli br nat64prefix - * @code - * br nat64prefix - * fd14:1078:b3d5:b0b0:0:0::/96 - * Done - * @endcode - * @par api_copy - * #otBorderRoutingGetNat64Prefix - */ - else if (aArgs[0] == "nat64prefix") - { - otIp6Prefix nat64Prefix; - - SuccessOrExit(error = otBorderRoutingGetNat64Prefix(GetInstancePtr(), &nat64Prefix)); - OutputIp6PrefixLine(nat64Prefix); - } - /** - * @cli br favorednat64prefix - * @code - * br favorednat64prefix - * fd14:1078:b3d5:b0b0:0:0::/96 prf:low - * Done - * @endcode - * @par api_copy - * #otBorderRoutingGetFavoredNat64Prefix - */ - else if (aArgs[0] == "favorednat64prefix") - { - otIp6Prefix prefix; - otRoutePreference preference; - - SuccessOrExit(error = otBorderRoutingGetFavoredNat64Prefix(GetInstancePtr(), &prefix, &preference)); - OutputIp6Prefix(prefix); - OutputLine(" prf:%s", PreferenceToString(preference)); - } -#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE - else if (aArgs[0] == "rioprf") - { - /** - * @cli br rioprf - * @code - * br rioprf - * med - * Done - * @endcode - * @par api_copy - * #otBorderRoutingGetRouteInfoOptionPreference - * - */ - if (aArgs[1].IsEmpty()) - { - OutputLine("%s", PreferenceToString(otBorderRoutingGetRouteInfoOptionPreference(GetInstancePtr()))); - } - /** - * @cli br rioprf clear - * @code - * br rioprf clear - * Done - * @endcode - * @par api_copy - * #otBorderRoutingClearRouteInfoOptionPreference - * - */ - else if (aArgs[1] == "clear") - { - otBorderRoutingClearRouteInfoOptionPreference(GetInstancePtr()); - } - /** - * @cli br rioprf (high,med,low) - * @code - * br rioprf low - * Done - * @endcode - * @cparam br rioprf [@ca{high}|@ca{med}|@ca{low}] - * @par api_copy - * #otBorderRoutingSetRouteInfoOptionPreference - * - */ - else - { - otRoutePreference preference; - - SuccessOrExit(error = ParsePreference(aArgs[1], preference)); - otBorderRoutingSetRouteInfoOptionPreference(GetInstancePtr(), preference); - } - } - /** - * @cli br prefixtable - * @code - * br prefixtable - * prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med, - * router:ff02:0:0:0:0:0:0:1 - * prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800, - * router:ff02:0:0:0:0:0:0:1 - * Done - * @endcode - * @par api_copy - * #otBorderRoutingGetNextPrefixTableEntry - * - */ - else if (aArgs[0] == "prefixtable") - { - otBorderRoutingPrefixTableIterator iterator; - otBorderRoutingPrefixTableEntry entry; - - otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator); - - while (otBorderRoutingGetNextPrefixTableEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE) - { - char string[OT_IP6_PREFIX_STRING_SIZE]; - - otIp6PrefixToString(&entry.mPrefix, string, sizeof(string)); - OutputFormat("prefix:%s, on-link:%s, ms-since-rx:%lu, lifetime:%lu, ", string, - entry.mIsOnLink ? "yes" : "no", ToUlong(entry.mMsecSinceLastUpdate), - ToUlong(entry.mValidLifetime)); - - if (entry.mIsOnLink) - { - OutputFormat("preferred:%lu, ", ToUlong(entry.mPreferredLifetime)); - } - else - { - OutputFormat("route-prf:%s, ", PreferenceToString(entry.mRoutePreference)); - } - - otIp6AddressToString(&entry.mRouterAddress, string, sizeof(string)); - OutputLine("router:%s", string); - } - } - else - { - error = OT_ERROR_INVALID_COMMAND; - } - -exit: - return error; -} -#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +template <> otError Interpreter::Process(Arg aArgs[]) { return mBr.Process(aArgs); } +#endif #if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE || OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE template <> otError Interpreter::Process(Arg aArgs[]) @@ -2479,6 +2269,42 @@ template <> otError Interpreter::Process(Arg aArgs[]) } #endif +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE +void Interpreter::OutputBorderRouterCounters(void) +{ + struct BrCounterName + { + const otPacketsAndBytes otBorderRoutingCounters::*mPacketsAndBytes; + const char *mName; + }; + + static const BrCounterName kCounterNames[] = { + {&otBorderRoutingCounters::mInboundUnicast, "Inbound Unicast"}, + {&otBorderRoutingCounters::mInboundMulticast, "Inbound Multicast"}, + {&otBorderRoutingCounters::mOutboundUnicast, "Outbound Unicast"}, + {&otBorderRoutingCounters::mOutboundMulticast, "Outbound Multicast"}, + }; + + const otBorderRoutingCounters *brCounters = otIp6GetBorderRoutingCounters(GetInstancePtr()); + Uint64StringBuffer uint64StringBuffer; + + for (const BrCounterName &counter : kCounterNames) + { + OutputFormat("%s:", counter.mName); + OutputFormat(" Packets %s", + Uint64ToString((brCounters->*counter.mPacketsAndBytes).mPackets, uint64StringBuffer)); + OutputLine(" Bytes %s", Uint64ToString((brCounters->*counter.mPacketsAndBytes).mBytes, uint64StringBuffer)); + } + + OutputLine("RA Rx: %lu", ToUlong(brCounters->mRaRx)); + OutputLine("RA TxSuccess: %lu", ToUlong(brCounters->mRaTxSuccess)); + OutputLine("RA TxFailed: %lu", ToUlong(brCounters->mRaTxFailure)); + OutputLine("RS Rx: %lu", ToUlong(brCounters->mRsRx)); + OutputLine("RS TxSuccess: %lu", ToUlong(brCounters->mRsTxSuccess)); + OutputLine("RS TxFailed: %lu", ToUlong(brCounters->mRsTxFailure)); +} +#endif // OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + template <> otError Interpreter::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -2528,38 +2354,7 @@ template <> otError Interpreter::Process(Arg aArgs[]) { if (aArgs[1].IsEmpty()) { - struct BrCounterName - { - const otPacketsAndBytes otBorderRoutingCounters::*mPacketsAndBytes; - const char *mName; - }; - - static const BrCounterName kCounterNames[] = { - {&otBorderRoutingCounters::mInboundUnicast, "Inbound Unicast"}, - {&otBorderRoutingCounters::mInboundMulticast, "Inbound Multicast"}, - {&otBorderRoutingCounters::mOutboundUnicast, "Outbound Unicast"}, - {&otBorderRoutingCounters::mOutboundMulticast, "Outbound Multicast"}, - }; - - const otBorderRoutingCounters *brCounters = otIp6GetBorderRoutingCounters(GetInstancePtr()); - Uint64StringBuffer uint64StringBuffer; - - for (const BrCounterName &counter : kCounterNames) - { - OutputFormat("%s:", counter.mName); - OutputFormat(" Packets %s", - Uint64ToString((brCounters->*counter.mPacketsAndBytes).mPackets, uint64StringBuffer)); - OutputFormat(" Bytes %s", - Uint64ToString((brCounters->*counter.mPacketsAndBytes).mBytes, uint64StringBuffer)); - OutputNewLine(); - } - - OutputLine("RA Rx: %lu", ToUlong(brCounters->mRaRx)); - OutputLine("RA TxSuccess: %lu", ToUlong(brCounters->mRaTxSuccess)); - OutputLine("RA TxFailed: %lu", ToUlong(brCounters->mRaTxFailure)); - OutputLine("RS Rx: %lu", ToUlong(brCounters->mRsRx)); - OutputLine("RS TxSuccess: %lu", ToUlong(brCounters->mRsTxSuccess)); - OutputLine("RS TxFailed: %lu", ToUlong(brCounters->mRsTxFailure)); + OutputBorderRouterCounters(); } /** * @cli counters br reset diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index a3aaea2e1..de01fd7e6 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -57,6 +57,7 @@ #include #include +#include "cli/cli_br.hpp" #include "cli/cli_commissioner.hpp" #include "cli/cli_dataset.hpp" #include "cli/cli_history.hpp" @@ -102,6 +103,7 @@ extern "C" void otCliOutputFormat(const char *aFmt, ...); class Interpreter : public OutputImplementer, public Output { #if OPENTHREAD_FTD || OPENTHREAD_MTD + friend class Br; friend class Commissioner; friend class Joiner; friend class NetworkData; @@ -363,6 +365,9 @@ private: static otError ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig); static otError ParseRoute(Arg aArgs[], otExternalRouteConfig &aConfig); #endif +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + void OutputBorderRouterCounters(void); +#endif otError ProcessCommand(Arg aArgs[]); @@ -535,6 +540,10 @@ private: NetworkData mNetworkData; UdpExample mUdp; +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + Br mBr; +#endif + #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE TcpExample mTcp; #endif diff --git a/src/cli/cli_br.cpp b/src/cli/cli_br.cpp new file mode 100644 index 000000000..643b43528 --- /dev/null +++ b/src/cli/cli_br.cpp @@ -0,0 +1,542 @@ +/* + * Copyright (c) 2023, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements CLI for Border Router. + */ + +#include "cli_br.hpp" + +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + +#include + +#include + +#include "cli/cli.hpp" + +namespace ot { +namespace Cli { + +/** + * @cli br enable + * @code + * br enable + * Done + * @endcode + * @par + * Enables the Border Routing Manager. + * @sa otBorderRoutingSetEnabled + */ +template <> otError Br::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS); + error = otBorderRoutingSetEnabled(GetInstancePtr(), true); + +exit: + return error; +} + +/** + * @cli br disable + * @code + * br disable + * Done + * @endcode + * @par + * Disables the Border Routing Manager. + * @sa otBorderRoutingSetEnabled + */ +template <> otError Br::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS); + error = otBorderRoutingSetEnabled(GetInstancePtr(), false); + +exit: + return error; +} + +/** + * @cli br state + * @code + * br state + * running + * @endcode + * @par api_copy + * #otBorderRoutingGetState + */ +template <> otError Br::Process(Arg aArgs[]) +{ + static const char *const kStateStrings[] = { + + "uninitialized", // (0) OT_BORDER_ROUTING_STATE_UNINITIALIZED + "disabled", // (1) OT_BORDER_ROUTING_STATE_DISABLED + "stopped", // (2) OT_BORDER_ROUTING_STATE_STOPPED + "running", // (3) OT_BORDER_ROUTING_STATE_RUNNING + }; + + otError error = OT_ERROR_NONE; + + static_assert(0 == OT_BORDER_ROUTING_STATE_UNINITIALIZED, "STATE_UNINITIALIZED value is incorrect"); + static_assert(1 == OT_BORDER_ROUTING_STATE_DISABLED, "STATE_DISABLED value is incorrect"); + static_assert(2 == OT_BORDER_ROUTING_STATE_STOPPED, "STATE_STOPPED value is incorrect"); + static_assert(3 == OT_BORDER_ROUTING_STATE_RUNNING, "STATE_RUNNING value is incorrect"); + + VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS); + OutputLine("%s", Stringify(otBorderRoutingGetState(GetInstancePtr()), kStateStrings)); + +exit: + return error; +} + +otError Br::ParsePrefixTypeArgs(Arg aArgs[], bool &aOutputLocal, bool &aOutputFavored) +{ + otError error = OT_ERROR_NONE; + + aOutputLocal = false; + aOutputFavored = false; + + if (aArgs[0].IsEmpty()) + { + aOutputLocal = true; + aOutputFavored = true; + ExitNow(); + } + + if (aArgs[0] == "local") + { + aOutputLocal = true; + } + else if (aArgs[0] == "favored") + { + aOutputFavored = true; + } + else + { + ExitNow(error = OT_ERROR_INVALID_ARGS); + } + + VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS); + +exit: + return error; +} + +/** + * @cli br omrprefix + * @code + * br omrprefix + * Local: fdfc:1ff5:1512:5622::/64 + * Favored: fdfc:1ff5:1512:5622::/64 prf:low + * Done + * @endcode + * @par + * Outputs both local and favored OMR prefix. + * @sa otBorderRoutingGetOmrPrefix + * @sa otBorderRoutingGetFavoredOmrPrefix + */ +template <> otError Br::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + bool outputLocal; + bool outputFavored; + + SuccessOrExit(error = ParsePrefixTypeArgs(aArgs, outputLocal, outputFavored)); + + /** + * @cli br omrprefix local + * @code + * br omrprefix local + * fdfc:1ff5:1512:5622::/64 + * Done + * @endcode + * @par api_copy + * #otBorderRoutingGetOmrPrefix + */ + if (outputLocal) + { + otIp6Prefix local; + + SuccessOrExit(error = otBorderRoutingGetOmrPrefix(GetInstancePtr(), &local)); + + OutputFormat("%s", outputFavored ? "Local: " : ""); + OutputIp6PrefixLine(local); + } + + /** + * @cli br omrprefix favored + * @code + * br omrprefix favored + * fdfc:1ff5:1512:5622::/64 prf:low + * Done + * @endcode + * @par api_copy + * #otBorderRoutingGetFavoredOmrPrefix + */ + if (outputFavored) + { + otIp6Prefix favored; + otRoutePreference preference; + + SuccessOrExit(error = otBorderRoutingGetFavoredOmrPrefix(GetInstancePtr(), &favored, &preference)); + + OutputFormat("%s", outputLocal ? "Favored: " : ""); + OutputIp6Prefix(favored); + OutputLine(" prf:%s", Interpreter::PreferenceToString(preference)); + } + +exit: + return error; +} + +/** + * @cli br onlinkprefix + * @code + * br onlinkprefix + * Local: fd41:2650:a6f5:0::/64 + * Favored: 2600::0:1234:da12::/64 + * Done + * @endcode + * @par + * Outputs both local and favored on-link prefixes. + * @sa otBorderRoutingGetOnLinkPrefix + * @sa otBorderRoutingGetFavoredOnLinkPrefix + */ +template <> otError Br::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + bool outputLocal; + bool outputFavored; + + SuccessOrExit(error = ParsePrefixTypeArgs(aArgs, outputLocal, outputFavored)); + + /** + * @cli br onlinkprefix local + * @code + * br onlinkprefix local + * fd41:2650:a6f5:0::/64 + * Done + * @endcode + * @par api_copy + * #otBorderRoutingGetOnLinkPrefix + */ + if (outputLocal) + { + otIp6Prefix local; + + SuccessOrExit(error = otBorderRoutingGetOnLinkPrefix(GetInstancePtr(), &local)); + + OutputFormat("%s", outputFavored ? "Local: " : ""); + OutputIp6PrefixLine(local); + } + + /** + * @cli br onlinkprefix favored + * @code + * br onlinkprefix favored + * 2600::0:1234:da12::/64 + * Done + * @endcode + * @par api_copy + * #otBorderRoutingGetFavoredOnLinkPrefix + */ + if (outputFavored) + { + otIp6Prefix favored; + + SuccessOrExit(error = otBorderRoutingGetFavoredOnLinkPrefix(GetInstancePtr(), &favored)); + + OutputFormat("%s", outputLocal ? "Favored: " : ""); + OutputIp6PrefixLine(favored); + } + +exit: + return error; +} + +#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE + +/** + * @cli br nat64prefix + * @code + * br nat64prefix + * Local: fd14:1078:b3d5:b0b0:0:0::/96 + * Favored: fd14:1078:b3d5:b0b0:0:0::/96 prf:low + * Done + * @endcode + * @par + * Outputs both local and favored NAT64 prefixes. + * @sa otBorderRoutingGetNat64Prefix + * @sa otBorderRoutingGetFavoredNat64Prefix + */ +template <> otError Br::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + bool outputLocal; + bool outputFavored; + + SuccessOrExit(error = ParsePrefixTypeArgs(aArgs, outputLocal, outputFavored)); + + /** + * @cli br nat64prefix local + * @code + * br nat64prefix local + * fd14:1078:b3d5:b0b0:0:0::/96 + * Done + * @endcode + * @par api_copy + * #otBorderRoutingGetNat64Prefix + */ + if (outputLocal) + { + otIp6Prefix local; + + SuccessOrExit(error = otBorderRoutingGetNat64Prefix(GetInstancePtr(), &local)); + + OutputFormat("%s", outputFavored ? "Local: " : ""); + OutputIp6PrefixLine(local); + } + + /** + * @cli br nat64prefix favored + * @code + * br nat64prefix favored + * fd14:1078:b3d5:b0b0:0:0::/96 prf:low + * Done + * @endcode + * @par api_copy + * #otBorderRoutingGetFavoredNat64Prefix + */ + if (outputFavored) + { + otIp6Prefix favored; + otRoutePreference preference; + + SuccessOrExit(error = otBorderRoutingGetFavoredNat64Prefix(GetInstancePtr(), &favored, &preference)); + + OutputFormat("%s", outputLocal ? "Favored: " : ""); + OutputIp6Prefix(favored); + OutputLine(" prf:%s", Interpreter::PreferenceToString(preference)); + } + +exit: + return error; +} + +#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE + +/** + * @cli br prefixtable + * @code + * br prefixtable + * prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med, + * router:ff02:0:0:0:0:0:0:1 + * prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800, + * router:ff02:0:0:0:0:0:0:1 + * Done + * @endcode + * @par api_copy + * #otBorderRoutingGetNextPrefixTableEntry + */ +template <> otError Br::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + otBorderRoutingPrefixTableIterator iterator; + otBorderRoutingPrefixTableEntry entry; + + VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS); + + otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator); + + while (otBorderRoutingGetNextPrefixTableEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE) + { + char string[OT_IP6_PREFIX_STRING_SIZE]; + + otIp6PrefixToString(&entry.mPrefix, string, sizeof(string)); + OutputFormat("prefix:%s, on-link:%s, ms-since-rx:%lu, lifetime:%lu, ", string, entry.mIsOnLink ? "yes" : "no", + ToUlong(entry.mMsecSinceLastUpdate), ToUlong(entry.mValidLifetime)); + + if (entry.mIsOnLink) + { + OutputFormat("preferred:%lu, ", ToUlong(entry.mPreferredLifetime)); + } + else + { + OutputFormat("route-prf:%s, ", Interpreter::PreferenceToString(entry.mRoutePreference)); + } + + otIp6AddressToString(&entry.mRouterAddress, string, sizeof(string)); + OutputLine("router:%s", string); + } + +exit: + return error; +} + +template <> otError Br::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + + /** + * @cli br rioprf + * @code + * br rioprf + * med + * Done + * @endcode + * @par api_copy + * #otBorderRoutingGetRouteInfoOptionPreference + */ + if (aArgs[0].IsEmpty()) + { + OutputLine("%s", + Interpreter::PreferenceToString(otBorderRoutingGetRouteInfoOptionPreference(GetInstancePtr()))); + } + /** + * @cli br rioprf clear + * @code + * br rioprf clear + * Done + * @endcode + * @par api_copy + * #otBorderRoutingClearRouteInfoOptionPreference + */ + else if (aArgs[0] == "clear") + { + otBorderRoutingClearRouteInfoOptionPreference(GetInstancePtr()); + } + /** + * @cli br rioprf (high,med,low) + * @code + * br rioprf low + * Done + * @endcode + * @cparam br rioprf [@ca{high}|@ca{med}|@ca{low}] + * @par api_copy + * #otBorderRoutingSetRouteInfoOptionPreference + */ + else + { + otRoutePreference preference; + + SuccessOrExit(error = Interpreter::ParsePreference(aArgs[0], preference)); + otBorderRoutingSetRouteInfoOptionPreference(GetInstancePtr(), preference); + } + +exit: + return error; +} + +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + +/** + * @cli br counters + * @code + * br counters + * Inbound Unicast: Packets 4 Bytes 320 + * Inbound Multicast: Packets 0 Bytes 0 + * Outbound Unicast: Packets 2 Bytes 160 + * Outbound Multicast: Packets 0 Bytes 0 + * RA Rx: 4 + * RA TxSuccess: 2 + * RA TxFailed: 0 + * RS Rx: 0 + * RS TxSuccess: 2 + * RS TxFailed: 0 + * Done + * @endcode + * @par api_copy + * #otIp6GetBorderRoutingCounters + */ +template <> otError Br::Process(Arg aArgs[]) +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS); + Interpreter::GetInterpreter().OutputBorderRouterCounters(); + +exit: + return error; +} + +#endif // OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + +otError Br::Process(Arg aArgs[]) +{ +#define CmdEntry(aCommandString) \ + { \ + aCommandString, &Br::Process \ + } + + static constexpr Command kCommands[] = { +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + CmdEntry("counters"), +#endif + CmdEntry("disable"), + CmdEntry("enable"), +#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE + CmdEntry("nat64prefix"), +#endif + CmdEntry("omrprefix"), + CmdEntry("onlinkprefix"), + CmdEntry("prefixtable"), + CmdEntry("rioprf"), + CmdEntry("state"), + }; + +#undef CmdEntry + + static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted"); + + otError error = OT_ERROR_INVALID_COMMAND; + const Command *command; + + if (aArgs[0].IsEmpty() || (aArgs[0] == "help")) + { + OutputCommandTable(kCommands); + ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE); + } + + command = BinarySearch::Find(aArgs[0].GetCString(), kCommands); + VerifyOrExit(command != nullptr); + + error = (this->*command->mHandler)(aArgs + 1); + +exit: + return error; +} + +} // namespace Cli +} // namespace ot + +#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE diff --git a/src/cli/cli_br.hpp b/src/cli/cli_br.hpp new file mode 100644 index 000000000..5a30977a5 --- /dev/null +++ b/src/cli/cli_br.hpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file contains definitions for CLI to Border Router. + */ + +#ifndef CLI_BR_HPP_ +#define CLI_BR_HPP_ + +#include "openthread-core-config.h" + +#include "cli/cli_config.h" +#include "cli/cli_output.hpp" + +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + +namespace ot { +namespace Cli { + +/** + * This class implements the Border Router CLI interpreter. + * + */ +class Br : private Output +{ +public: + typedef Utils::CmdLineParser::Arg Arg; + + /** + * Constructor + * + * @param[in] aInstance The OpenThread Instance. + * @param[in] aOutputImplementer An `OutputImplementer`. + * + */ + Br(otInstance *aInstance, OutputImplementer &aOutputImplementer) + : Output(aInstance, aOutputImplementer) + { + } + + /** + * This method interprets a list of CLI arguments. + * + * @param[in] aArgs A pointer an array of command line arguments. + * + */ + otError Process(Arg aArgs[]); + +private: + using Command = CommandEntry
; + + template otError Process(Arg aArgs[]); + + otError ParsePrefixTypeArgs(Arg aArgs[], bool &aOutputLocal, bool &aOutputFavored); +}; + +} // namespace Cli +} // namespace ot + +#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + +#endif // CLI_BR_HPP_ diff --git a/src/core/api/border_routing_api.cpp b/src/core/api/border_routing_api.cpp index baa29c71b..2731e02c0 100644 --- a/src/core/api/border_routing_api.cpp +++ b/src/core/api/border_routing_api.cpp @@ -52,6 +52,11 @@ otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled) return AsCoreType(aInstance).Get().SetEnabled(aEnabled); } +otBorderRoutingState otBorderRoutingGetState(otInstance *aInstance) +{ + return MapEnum(AsCoreType(aInstance).Get().GetState()); +} + otRoutePreference otBorderRoutingGetRouteInfoOptionPreference(otInstance *aInstance) { return static_cast( @@ -94,6 +99,11 @@ otError otBorderRoutingGetOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPref return AsCoreType(aInstance).Get().GetOnLinkPrefix(AsCoreType(aPrefix)); } +otError otBorderRoutingGetFavoredOnLinkPrefix(otInstance *aInstance, otIp6Prefix *aPrefix) +{ + return AsCoreType(aInstance).Get().GetFavoredOnLinkPrefix(AsCoreType(aPrefix)); +} + #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE otError otBorderRoutingGetNat64Prefix(otInstance *aInstance, otIp6Prefix *aPrefix) { diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index f8e3d16e1..8cae2141a 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -121,6 +121,19 @@ exit: return error; } +RoutingManager::State RoutingManager::GetState(void) const +{ + State state = kStateUninitialized; + + VerifyOrExit(IsInitialized()); + VerifyOrExit(IsEnabled(), state = kStateDisabled); + + state = IsRunning() ? kStateRunning : kStateStopped; + +exit: + return state; +} + void RoutingManager::SetRouteInfoOptionPreference(RoutePreference aPreference) { LogInfo("User explicitly set RIO Preference to %s", RoutePreferenceToString(aPreference)); @@ -161,7 +174,7 @@ exit: return; } -Error RoutingManager::GetOmrPrefix(Ip6::Prefix &aPrefix) +Error RoutingManager::GetOmrPrefix(Ip6::Prefix &aPrefix) const { Error error = kErrorNone; @@ -172,7 +185,7 @@ exit: return error; } -Error RoutingManager::GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference) +Error RoutingManager::GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference) const { Error error = kErrorNone; @@ -184,7 +197,7 @@ exit: return error; } -Error RoutingManager::GetOnLinkPrefix(Ip6::Prefix &aPrefix) +Error RoutingManager::GetOnLinkPrefix(Ip6::Prefix &aPrefix) const { Error error = kErrorNone; @@ -195,6 +208,22 @@ exit: return error; } +Error RoutingManager::GetFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const +{ + Error error = kErrorNone; + + VerifyOrExit(IsInitialized(), error = kErrorInvalidState); + aPrefix = mOnLinkPrefixManager.GetFavoredDiscoveredPrefix(); + + if (aPrefix.GetLength() == 0) + { + aPrefix = mOnLinkPrefixManager.GetLocalPrefix(); + } + +exit: + return error; +} + #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE void RoutingManager::SetNat64PrefixManagerEnabled(bool aEnabled) { diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index 19e057d75..5ed94e2c8 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -100,6 +100,19 @@ public: */ static constexpr uint16_t kMaxPublishedPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_DISCOVERED_PREFIXES + 1 + OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_OLD_ON_LINK_PREFIXES + 1; + + /** + * This enumeration represents the states of `RoutingManager`. + * + */ + enum State : uint8_t + { + kStateUninitialized = OT_BORDER_ROUTING_STATE_UNINITIALIZED, ///< Uninitialized. + kStateDisabled = OT_BORDER_ROUTING_STATE_DISABLED, ///< Initialized but disabled. + kStateStopped = OT_BORDER_ROUTING_STATE_STOPPED, ///< Initialized & enabled, but currently stopped. + kStateRunning = OT_BORDER_ROUTING_STATE_RUNNING, ///< Initialized, enabled, and running. + }; + /** * This constructor initializes the routing manager. * @@ -134,6 +147,26 @@ public: */ Error SetEnabled(bool aEnabled); + /** + * This method indicates whether or not it is currently running. + * + * In order for the `RoutingManager` to be running it needs to be initialized and enabled, and device being + * attached. + * + * @retval TRUE The RoutingManager is currently running. + * @retval FALSE The RoutingManager is not running. + * + */ + bool IsRunning(void) const { return mIsRunning; } + + /** + * This method gets the state of `RoutingManager`. + * + * @returns The current state of `RoutingManager`. + * + */ + State GetState(void) const; + /** * This method requests the Border Routing Manager to stop. * @@ -197,7 +230,7 @@ public: * @retval kErrorNone Successfully retrieved the OMR prefix. * */ - Error GetOmrPrefix(Ip6::Prefix &aPrefix); + Error GetOmrPrefix(Ip6::Prefix &aPrefix) const; /** * This method returns the currently favored off-mesh-routable (OMR) prefix. @@ -214,7 +247,7 @@ public: * @retval kErrorNone Successfully retrieved the OMR prefix. * */ - Error GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference); + Error GetFavoredOmrPrefix(Ip6::Prefix &aPrefix, RoutePreference &aPreference) const; /** * This method returns the on-link prefix for the adjacent infrastructure link. @@ -226,10 +259,23 @@ public: * @param[out] aPrefix A reference to where the prefix will be output to. * * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. - * @retval kErrorNone Successfully retrieved the on-link prefix. + * @retval kErrorNone Successfully retrieved the local on-link prefix. * */ - Error GetOnLinkPrefix(Ip6::Prefix &aPrefix); + Error GetOnLinkPrefix(Ip6::Prefix &aPrefix) const; + + /** + * This method returns the favored on-link prefix for the adjacent infrastructure link. + * + * The favored prefix is either a discovered prefix on the infrastructure link or the local on-link prefix. + * + * @param[out] aPrefix A reference to where the prefix will be output to. + * + * @retval kErrorInvalidState The Border Routing Manager is not initialized yet. + * @retval kErrorNone Successfully retrieved the favored on-link prefix. + * + */ + Error GetFavoredOnLinkPrefix(Ip6::Prefix &aPrefix) const; #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE /** @@ -369,15 +415,6 @@ public: void HandleSrpServerAutoEnableMode(void); #endif - /** - * Gets the state of RoutingManager. - * - * @retval TRUE The RoutingManager is currently running. - * @retval FALSE The RoutingManager is not running. - * - */ - bool IsRunning(void) const { return mIsRunning; } - private: static constexpr uint8_t kMaxOnMeshPrefixes = OPENTHREAD_CONFIG_BORDER_ROUTING_MAX_ON_MESH_PREFIXES; @@ -683,6 +720,7 @@ private: void Stop(void); void Evaluate(void); const Ip6::Prefix &GetLocalPrefix(void) const { return mLocalPrefix; } + const Ip6::Prefix &GetFavoredDiscoveredPrefix(void) const { return mFavoredDiscoveredPrefix; } bool IsInitalEvaluationDone(void) const; void HandleDiscoveredPrefixTableChanged(void); bool ShouldPublish(NetworkData::ExternalRouteConfig &aRouteConfig) const; @@ -924,6 +962,8 @@ private: } // namespace BorderRouter +DefineMapEnum(otBorderRoutingState, BorderRouter::RoutingManager::State); + } // namespace ot #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py index b4c5f7746..fe581e4c4 100755 --- a/tests/scripts/thread-cert/node.py +++ b/tests/scripts/thread-cert/node.py @@ -2110,7 +2110,7 @@ class NodeImpl: self._expect_done() def get_br_omr_prefix(self): - cmd = 'br omrprefix' + cmd = 'br omrprefix local' self.send_command(cmd) return self._expect_command_output()[0] @@ -2124,7 +2124,7 @@ class NodeImpl: return omr_prefixes def get_br_on_link_prefix(self): - cmd = 'br onlinkprefix' + cmd = 'br onlinkprefix local' self.send_command(cmd) return self._expect_command_output()[0] @@ -2137,12 +2137,12 @@ class NodeImpl: return prefixes def get_br_nat64_prefix(self): - cmd = 'br nat64prefix' + cmd = 'br nat64prefix local' self.send_command(cmd) return self._expect_command_output()[0] def get_br_favored_nat64_prefix(self): - cmd = 'br favorednat64prefix' + cmd = 'br nat64prefix favored' self.send_command(cmd) return self._expect_command_output()[0].split(' ')[0] diff --git a/tools/harness-thci/OpenThread.py b/tools/harness-thci/OpenThread.py index 3b1a99415..5942aeec4 100644 --- a/tools/harness-thci/OpenThread.py +++ b/tools/harness-thci/OpenThread.py @@ -3214,7 +3214,7 @@ class OpenThreadTHCI(object): @watched def isBorderRoutingEnabled(self): try: - self.__executeCommand('br omrprefix') + self.__executeCommand('br omrprefix local') return True except CommandError: return False