mirror of
https://github.com/espressif/openthread.git
synced 2026-06-19 11:44:35 +00:00
7f3ab64dce
This commit introduces a new helper method `Utils::ToYesNo()` in the CLI module to convert boolean values into "yes" or "no" strings. Previously, this conversion was performed using inline ternary operators (e.g., `val ? "yes" : "no"`) scattered throughout the CLI implementation. This change replaces these instances with the new helper method, improving code readability and consistency.
1264 lines
36 KiB
C++
1264 lines
36 KiB
C++
/*
|
|
* 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 <string.h>
|
|
|
|
#include "cli/cli.hpp"
|
|
|
|
namespace ot {
|
|
namespace Cli {
|
|
|
|
/**
|
|
* @cli br init
|
|
* @code
|
|
* br init 2 1
|
|
* Done
|
|
* @endcode
|
|
* @cparam br init @ca{infrastructure-network-index} @ca{is-running}
|
|
* @par
|
|
* Initializes the Border Routing Manager.
|
|
* @sa otBorderRoutingInit
|
|
*/
|
|
template <> otError Br::Process<Cmd("init")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
uint32_t ifIndex;
|
|
bool isRunning;
|
|
|
|
SuccessOrExit(error = aArgs[0].ParseAsUint32(ifIndex));
|
|
SuccessOrExit(error = aArgs[1].ParseAsBool(isRunning));
|
|
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
error = otBorderRoutingInit(GetInstancePtr(), ifIndex, isRunning);
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* @cli br infraif
|
|
* @code
|
|
* br infraif
|
|
* if-index:2, is-running:yes
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Gets the interface index and running state of the configured infrastructure interface.
|
|
*/
|
|
template <> otError Br::Process<Cmd("infraif")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
uint32_t ifIndex;
|
|
bool isRunning;
|
|
|
|
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
SuccessOrExit(error = otBorderRoutingGetInfraIfInfo(GetInstancePtr(), &ifIndex, &isRunning));
|
|
OutputLine("if-index:%lu, is-running:%s", ToUlong(ifIndex), ToYesNo(isRunning));
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* @cli br enable
|
|
* @code
|
|
* br enable
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Enables the Border Routing Manager.
|
|
* @sa otBorderRoutingSetEnabled
|
|
*/
|
|
template <> otError Br::Process<Cmd("enable")>(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<Cmd("disable")>(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<Cmd("state")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
OutputLine("%s", BorderRoutingStateToString(otBorderRoutingGetState(GetInstancePtr())));
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
|
|
|
template <> otError Br::Process<Cmd("multiail")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
/**
|
|
* @cli br multiail
|
|
* @code
|
|
* br multiail
|
|
* not detected
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingIsMultiAilDetected
|
|
*/
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
OutputLine("%sdetected", otBorderRoutingIsMultiAilDetected(GetInstancePtr()) ? "" : "not ");
|
|
}
|
|
/**
|
|
* @cli br multiail callback
|
|
* @code
|
|
* br multiail callback enable
|
|
* Done
|
|
* @endcode
|
|
* @cparam br multiail callback @ca{enable|disable}
|
|
* @par api_copy
|
|
* #otBorderRoutingSetMultiAilCallback
|
|
*/
|
|
else if (aArgs[0] == "callback")
|
|
{
|
|
bool enable;
|
|
otBorderRoutingMultiAilCallback callback = nullptr;
|
|
|
|
SuccessOrExit(error = ParseEnableOrDisable(aArgs[1], enable));
|
|
|
|
if (enable)
|
|
{
|
|
callback = &HandleMultiAilDetected;
|
|
}
|
|
|
|
otBorderRoutingSetMultiAilCallback(GetInstancePtr(), callback, this);
|
|
}
|
|
/**
|
|
* @cli br multiail state
|
|
* @code
|
|
* br multiail state
|
|
* Enabled: yes
|
|
* Running: yes
|
|
* Detected: no
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Outputs full state of multi-AIL detector:
|
|
* - Whether the detector is enabled.
|
|
* - Whether the detector is running (when it is enabled and the infra-if interface is also active).
|
|
* - Whether multi-AIL was detected.
|
|
*/
|
|
else if (aArgs[0] == "state")
|
|
{
|
|
OutputLine("Enabled: %s", ToYesNo(otBorderRoutingIsMultiAilDetectionEnabled(GetInstancePtr())));
|
|
OutputLine("Running: %s", ToYesNo(otBorderRoutingIsMultiAilDetectionRunning(GetInstancePtr())));
|
|
OutputLine("Detected: %s", ToYesNo(otBorderRoutingIsMultiAilDetected(GetInstancePtr())));
|
|
}
|
|
/**
|
|
* @cli br multiail (enable, disable)
|
|
* @code
|
|
* br multiail enable
|
|
* Done
|
|
* @endcode
|
|
* @cparam br multiail @ca{enable|disable}
|
|
* @par api_copy
|
|
* #otBorderRoutingSetMultiAilDetectionEnabled
|
|
*/
|
|
else if (ProcessEnableDisable(aArgs, otBorderRoutingSetMultiAilDetectionEnabled) == OT_ERROR_NONE)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
error = OT_ERROR_INVALID_ARGS;
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
void Br::HandleMultiAilDetected(bool aDetected, void *aContext)
|
|
{
|
|
static_cast<Br *>(aContext)->HandleMultiAilDetected(aDetected);
|
|
}
|
|
|
|
void Br::HandleMultiAilDetected(bool aDetected)
|
|
{
|
|
OutputLine("BR multi AIL callback: %s", aDetected ? "detected" : "cleared");
|
|
}
|
|
|
|
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
|
|
|
otError Br::ParsePrefixTypeArgs(Arg aArgs[], PrefixType &aFlags)
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
aFlags = 0;
|
|
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
aFlags = kPrefixTypeFavored | kPrefixTypeLocal;
|
|
ExitNow();
|
|
}
|
|
|
|
if (aArgs[0] == "local")
|
|
{
|
|
aFlags = kPrefixTypeLocal;
|
|
}
|
|
else if (aArgs[0] == "favored")
|
|
{
|
|
aFlags = kPrefixTypeFavored;
|
|
}
|
|
else
|
|
{
|
|
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
|
}
|
|
|
|
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
template <> otError Br::Process<Cmd("omrconfig")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
otIp6Prefix customPrefix;
|
|
otRoutePreference preference;
|
|
otBorderRoutingOmrConfig omrConfig;
|
|
|
|
/**
|
|
* @cli br omrconfig
|
|
* @code
|
|
* br omrconfig
|
|
* auto
|
|
* Done
|
|
* @endcode
|
|
* @code
|
|
* br omrconfig
|
|
* custom (fd00:0:0:0::/64, prf:med)
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Outputs current OMR prefix configuration mode.
|
|
* @sa otBorderRoutingGetOmrConfig
|
|
*/
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
omrConfig = otBorderRoutingGetOmrConfig(GetInstancePtr(), &customPrefix, &preference);
|
|
|
|
switch (omrConfig)
|
|
{
|
|
case OT_BORDER_ROUTING_OMR_CONFIG_AUTO:
|
|
OutputLine("auto");
|
|
break;
|
|
case OT_BORDER_ROUTING_OMR_CONFIG_CUSTOM:
|
|
OutputFormat("custom (");
|
|
OutputIp6Prefix(customPrefix);
|
|
OutputLine(", prf:%s)", PreferenceToString(preference));
|
|
break;
|
|
case OT_BORDER_ROUTING_OMR_CONFIG_DISABLED:
|
|
OutputLine("disabled");
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ClearAllBytes(customPrefix);
|
|
preference = OT_ROUTE_PREFERENCE_MED;
|
|
|
|
/**
|
|
* @cli br omrconfig auto
|
|
* @code
|
|
* br omrconfig auto
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Sets OMR prefix configuration mode to `auto` In this mode, the Border Routing Manager automatically
|
|
* selects and manages the OMR prefix.
|
|
*/
|
|
if (aArgs[0] == "auto")
|
|
{
|
|
omrConfig = OT_BORDER_ROUTING_OMR_CONFIG_AUTO;
|
|
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
}
|
|
/**
|
|
* @cli br omrconfig custom
|
|
* @code
|
|
* br omrconfig custom fd00::/64 med
|
|
* Done
|
|
* @endcode
|
|
* @cparam br omrconfig custom @ca{prefix} [@ca{high}|@ca{med}|@ca{low}]
|
|
* @par
|
|
* Sets OMR prefix configuration mode to `custom`. In this mode, a custom OMR prefix and its associated
|
|
* preference are used.
|
|
*/
|
|
else if (aArgs[0] == "custom")
|
|
{
|
|
omrConfig = OT_BORDER_ROUTING_OMR_CONFIG_CUSTOM;
|
|
|
|
SuccessOrExit(error = aArgs[1].ParseAsIp6Prefix(customPrefix));
|
|
SuccessOrExit(error = Interpreter::ParsePreference(aArgs[2], preference));
|
|
VerifyOrExit(aArgs[3].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
}
|
|
/**
|
|
* @cli br omrconfig disable
|
|
* @code
|
|
* br omrconfig disable
|
|
* Done
|
|
* @endcode
|
|
* @cparam br omrconfig disable
|
|
* @par
|
|
* Sets OMR prefix configuration mode to `disable` which prevents the Border Routing Manager from adding any
|
|
* local or DHCPv6 PD OMR prefixes to the Network Data.
|
|
*/
|
|
else if (aArgs[0] == "disable")
|
|
{
|
|
omrConfig = OT_BORDER_ROUTING_OMR_CONFIG_DISABLED;
|
|
}
|
|
else
|
|
{
|
|
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
|
}
|
|
|
|
error = otBorderRoutingSetOmrConfig(GetInstancePtr(), omrConfig, &customPrefix, preference);
|
|
}
|
|
|
|
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<Cmd("omrprefix")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
PrefixType outputPrefixTypes;
|
|
|
|
SuccessOrExit(error = ParsePrefixTypeArgs(aArgs, outputPrefixTypes));
|
|
|
|
/**
|
|
* @cli br omrprefix local
|
|
* @code
|
|
* br omrprefix local
|
|
* fdfc:1ff5:1512:5622::/64
|
|
* Done
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingGetOmrPrefix
|
|
*/
|
|
if (outputPrefixTypes & kPrefixTypeLocal)
|
|
{
|
|
otIp6Prefix local;
|
|
|
|
SuccessOrExit(error = otBorderRoutingGetOmrPrefix(GetInstancePtr(), &local));
|
|
|
|
OutputFormat("%s", outputPrefixTypes == kPrefixTypeLocal ? "" : "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 (outputPrefixTypes & kPrefixTypeFavored)
|
|
{
|
|
otIp6Prefix favored;
|
|
otRoutePreference preference;
|
|
|
|
SuccessOrExit(error = otBorderRoutingGetFavoredOmrPrefix(GetInstancePtr(), &favored, &preference));
|
|
|
|
OutputFormat("%s", outputPrefixTypes == kPrefixTypeFavored ? "" : "Favored: ");
|
|
OutputIp6Prefix(favored);
|
|
OutputLine(" prf:%s", 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<Cmd("onlinkprefix")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
PrefixType outputPrefixTypes;
|
|
|
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_TESTING_API_ENABLE
|
|
if (aArgs[0] == "test")
|
|
{
|
|
otIp6Prefix prefix;
|
|
|
|
SuccessOrExit(error = aArgs[1].ParseAsIp6Prefix(prefix));
|
|
otBorderRoutingSetOnLinkPrefix(GetInstancePtr(), &prefix);
|
|
ExitNow();
|
|
}
|
|
#endif
|
|
|
|
error = ParsePrefixTypeArgs(aArgs, outputPrefixTypes);
|
|
|
|
SuccessOrExit(error);
|
|
|
|
/**
|
|
* @cli br onlinkprefix local
|
|
* @code
|
|
* br onlinkprefix local
|
|
* fd41:2650:a6f5:0::/64
|
|
* Done
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingGetOnLinkPrefix
|
|
*/
|
|
if (outputPrefixTypes & kPrefixTypeLocal)
|
|
{
|
|
otIp6Prefix local;
|
|
|
|
SuccessOrExit(error = otBorderRoutingGetOnLinkPrefix(GetInstancePtr(), &local));
|
|
|
|
OutputFormat("%s", outputPrefixTypes == kPrefixTypeLocal ? "" : "Local: ");
|
|
OutputIp6PrefixLine(local);
|
|
}
|
|
|
|
/**
|
|
* @cli br onlinkprefix favored
|
|
* @code
|
|
* br onlinkprefix favored
|
|
* 2600::0:1234:da12::/64
|
|
* Done
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingGetFavoredOnLinkPrefix
|
|
*/
|
|
if (outputPrefixTypes & kPrefixTypeFavored)
|
|
{
|
|
otIp6Prefix favored;
|
|
|
|
SuccessOrExit(error = otBorderRoutingGetFavoredOnLinkPrefix(GetInstancePtr(), &favored));
|
|
|
|
OutputFormat("%s", outputPrefixTypes == kPrefixTypeFavored ? "" : "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<Cmd("nat64prefix")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
PrefixType outputPrefixTypes;
|
|
|
|
SuccessOrExit(error = ParsePrefixTypeArgs(aArgs, outputPrefixTypes));
|
|
|
|
/**
|
|
* @cli br nat64prefix local
|
|
* @code
|
|
* br nat64prefix local
|
|
* fd14:1078:b3d5:b0b0:0:0::/96
|
|
* Done
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingGetNat64Prefix
|
|
*/
|
|
if (outputPrefixTypes & kPrefixTypeLocal)
|
|
{
|
|
otIp6Prefix local;
|
|
|
|
SuccessOrExit(error = otBorderRoutingGetNat64Prefix(GetInstancePtr(), &local));
|
|
|
|
OutputFormat("%s", outputPrefixTypes == kPrefixTypeLocal ? "" : "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 (outputPrefixTypes & kPrefixTypeFavored)
|
|
{
|
|
otIp6Prefix favored;
|
|
otRoutePreference preference;
|
|
|
|
SuccessOrExit(error = otBorderRoutingGetFavoredNat64Prefix(GetInstancePtr(), &favored, &preference));
|
|
|
|
OutputFormat("%s", outputPrefixTypes == kPrefixTypeFavored ? "" : "Favored: ");
|
|
OutputIp6Prefix(favored);
|
|
OutputLine(" prf:%s", PreferenceToString(preference));
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* @cli br nat64prefixtable
|
|
* @code
|
|
* br nat64prefixtable
|
|
* prefix:fd00:1234:5678:0:0:0::/96, ms-since-rx:29526, lifetime:1800, router:fe80:0:0:0:0:0:0:1 (M:0 O:0 S:1)
|
|
* prefix:fd11:2233:4455:0:0:0::/96, ms-since-rx:29527, lifetime:1800, router:fe80:0:0:0:0:0:0:1 (M:0 O:0 S:1)
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Get the RA-discovered NAT64 prefixes by Border Routing Manager on the infrastructure link.
|
|
* Info per prefix entry:
|
|
* - The prefix
|
|
* - Milliseconds since last received Router Advertisement containing this prefix
|
|
* - Prefix lifetime in seconds
|
|
* - The router IPv6 address which advertises this prefix
|
|
* - Flags in received Router Advertisement header:
|
|
* - M: Managed Address Config flag
|
|
* - O: Other Config flag
|
|
* - S: SNAC Router flag
|
|
* @sa otBorderRoutingGetNextNat64PrefixEntry
|
|
*/
|
|
template <> otError Br::Process<Cmd("nat64prefixtable")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
otBorderRoutingPrefixTableIterator iterator;
|
|
otBorderRoutingNat64PrefixEntry entry;
|
|
|
|
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
|
|
|
|
while (otBorderRoutingGetNextNat64PrefixEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
|
|
{
|
|
char string[OT_IP6_PREFIX_STRING_SIZE];
|
|
|
|
otIp6PrefixToString(&entry.mPrefix, string, sizeof(string));
|
|
OutputFormat("prefix:%s, ms-since-rx:%lu, lifetime:%lu, router:", string, ToUlong(entry.mMsecSinceLastUpdate),
|
|
ToUlong(entry.mLifetime));
|
|
OutputRouterInfo(entry.mRouter, kShortVersion);
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
|
|
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
|
|
|
|
template <> otError Br::Process<Cmd("peers")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
/**
|
|
* @cli br peers
|
|
* @code
|
|
* br peers
|
|
* rloc16:0x5c00 age:00:00:49
|
|
* rloc16:0xf800 age:00:01:51
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Get the list of peer BRs found in Network Data entries.
|
|
* `OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE` is required.
|
|
* Peer BRs are other devices within the Thread mesh that provide external IP connectivity. A device is considered
|
|
* to provide external IP connectivity if at least one of the following conditions is met regarding its Network
|
|
* Data entries:
|
|
* - It has added at least one external route entry.
|
|
* - It has added at least one prefix entry with both the default-route and on-mesh flags set.
|
|
* - It has added at least one domain prefix (with both the domain and on-mesh flags set).
|
|
* The list of peer BRs specifically excludes the current device, even if its is itself acting as a BR.
|
|
* Info per BR entry:
|
|
* - RLOC16 of the BR
|
|
* - Age as the duration interval since this BR appeared in Network Data. 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.
|
|
* @sa otBorderRoutingGetNextPrefixTableEntry
|
|
*/
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
otBorderRoutingPrefixTableIterator iterator;
|
|
otBorderRoutingPeerBorderRouterEntry peerBrEntry;
|
|
char ageString[OT_DURATION_STRING_SIZE];
|
|
|
|
otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
|
|
|
|
while (otBorderRoutingGetNextPeerBrEntry(GetInstancePtr(), &iterator, &peerBrEntry) == OT_ERROR_NONE)
|
|
{
|
|
otConvertDurationInSecondsToString(peerBrEntry.mAge, ageString, sizeof(ageString));
|
|
OutputLine("rloc16:0x%04x age:%s", peerBrEntry.mRloc16, ageString);
|
|
}
|
|
}
|
|
/**
|
|
* @cli br peers count
|
|
* @code
|
|
* br peers count
|
|
* 2 min-age:00:00:47
|
|
* Done
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingCountPeerBrs
|
|
*/
|
|
else if (aArgs[0] == "count")
|
|
{
|
|
uint32_t minAge;
|
|
uint16_t count;
|
|
char ageString[OT_DURATION_STRING_SIZE];
|
|
|
|
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
count = otBorderRoutingCountPeerBrs(GetInstancePtr(), &minAge);
|
|
otConvertDurationInSecondsToString(minAge, ageString, sizeof(ageString));
|
|
OutputLine("%u min-age:%s", count, ageString);
|
|
}
|
|
else
|
|
{
|
|
error = OT_ERROR_INVALID_ARGS;
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_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 (M:0 O:0 S: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 (M:0 O:0 S:1)
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Get the discovered prefixes by Border Routing Manager on the infrastructure link.
|
|
* Info per prefix entry:
|
|
* - The prefix
|
|
* - Whether the prefix is on-link or route
|
|
* - Milliseconds since last received Router Advertisement containing this prefix
|
|
* - Prefix lifetime in seconds
|
|
* - Preferred lifetime in seconds only if prefix is on-link
|
|
* - Route preference (low, med, high) only if prefix is route (not on-link)
|
|
* - The router IPv6 address which advertises this prefix
|
|
* - Flags in received Router Advertisement header:
|
|
* - M: Managed Address Config flag
|
|
* - O: Other Config flag
|
|
* - S: SNAC Router flag
|
|
* @sa otBorderRoutingGetNextPrefixTableEntry
|
|
*/
|
|
template <> otError Br::Process<Cmd("prefixtable")>(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, ToYesNo(entry.mIsOnLink),
|
|
ToUlong(entry.mMsecSinceLastUpdate), ToUlong(entry.mValidLifetime));
|
|
|
|
if (entry.mIsOnLink)
|
|
{
|
|
OutputFormat("preferred:%lu, ", ToUlong(entry.mPreferredLifetime));
|
|
}
|
|
else
|
|
{
|
|
OutputFormat("route-prf:%s, ", PreferenceToString(entry.mRoutePreference));
|
|
}
|
|
|
|
OutputFormat("router:");
|
|
OutputRouterInfo(entry.mRouter, kShortVersion);
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* @cli br rdnsstable
|
|
* @code
|
|
* br rdnsstable
|
|
* fd00:1234:5678::1, lifetime:500, ms-since-rx:29526, router:ff02:0:0:0:0:0:0:1 (M:0 O:0 S:1)
|
|
* fd00:aaaa::2, lifetime:500, ms-since-rx:107, router:ff02:0:0:0:0:0:0:1 (M:0 O:0 S:1)
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Get the discovered Recursive DNS Server (RDNSS) address table by Border Routing Manager on the infrastructure link.
|
|
* Info per entry:
|
|
* - IPv6 address
|
|
* - Lifetime in seconds
|
|
* - Milliseconds since last received Router Advertisement containing this address
|
|
* - The router IPv6 address which advertised this prefix
|
|
* - Flags in received Router Advertisement header:
|
|
* - M: Managed Address Config flag
|
|
* - O: Other Config flag
|
|
* - S: SNAC Router flag
|
|
* @sa otBorderRoutingGetNextRdnssAddrEntry
|
|
*/
|
|
template <> otError Br::Process<Cmd("rdnsstable")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
otBorderRoutingPrefixTableIterator iterator;
|
|
otBorderRoutingRdnssAddrEntry entry;
|
|
|
|
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
|
|
|
|
while (otBorderRoutingGetNextRdnssAddrEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
|
|
{
|
|
char string[OT_IP6_ADDRESS_STRING_SIZE];
|
|
|
|
otIp6AddressToString(&entry.mAddress, string, sizeof(string));
|
|
OutputFormat("%s, lifetime:%lu, ms-since-rx:%lu, router:", string, ToUlong(entry.mLifetime),
|
|
ToUlong(entry.mMsecSinceLastUpdate));
|
|
OutputRouterInfo(entry.mRouter, kShortVersion);
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
/**
|
|
* @cli br ifaddrs
|
|
* @code
|
|
* br ifaddrs
|
|
* fe80::896:228b:4ae0:8609, sec-since-use:15
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Get the infrastructure interface addresses. These are addresses used by the BR itself, for example, when sending
|
|
* Router Advertisements.
|
|
* Info per entry:
|
|
* - IPv6 address
|
|
* - Seconds since the last RA was sent from this BR using this address.
|
|
* @sa otBorderRoutingGetNextIfAddrEntry
|
|
*/
|
|
template <> otError Br::Process<Cmd("ifaddrs")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
otBorderRoutingPrefixTableIterator iterator;
|
|
otBorderRoutingIfAddrEntry entry;
|
|
|
|
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
|
|
|
|
while (otBorderRoutingGetNextIfAddrEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
|
|
{
|
|
char string[OT_IP6_ADDRESS_STRING_SIZE];
|
|
|
|
otIp6AddressToString(&entry.mAddress, string, sizeof(string));
|
|
OutputLine("%s, sec-since-use:%lu", string, ToUlong(entry.mSecSinceLastUse));
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
|
|
|
|
const char *Br::Dhcp6PdStateToString(otBorderRoutingDhcp6PdState aState)
|
|
{
|
|
static const char *const kDhcpv6PdStateStrings[] = {
|
|
"disabled", // (0) OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED
|
|
"stopped", // (1) OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED
|
|
"running", // (2) OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING
|
|
"idle", // (3) OT_BORDER_ROUTING_DHCP6_PD_STATE_IDLE
|
|
};
|
|
|
|
static_assert(0 == OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED, "DHCP6_PD_STATE_DISABLED value is incorrect");
|
|
static_assert(1 == OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED, "DHCP6_PD_STATE_STOPPED value is incorrect");
|
|
static_assert(2 == OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING, "DHCP6_PD_STATE_RUNNING value is incorrect");
|
|
static_assert(3 == OT_BORDER_ROUTING_DHCP6_PD_STATE_IDLE, "DHCP6_PD_STATE_IDLE value is incorrect");
|
|
|
|
return Stringify(aState, kDhcpv6PdStateStrings);
|
|
}
|
|
|
|
template <> otError Br::Process<Cmd("pd")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
/**
|
|
* @cli br pd (enable,disable)
|
|
* @code
|
|
* br pd enable
|
|
* Done
|
|
* @endcode
|
|
* @code
|
|
* br pd disable
|
|
* Done
|
|
* @endcode
|
|
* @cparam br pd @ca{enable|disable}
|
|
* @par api_copy
|
|
* #otBorderRoutingDhcp6PdSetEnabled
|
|
*/
|
|
if (ProcessEnableDisable(aArgs, otBorderRoutingDhcp6PdSetEnabled) == OT_ERROR_NONE)
|
|
{
|
|
}
|
|
/**
|
|
* @cli br pd state
|
|
* @code
|
|
* br pd state
|
|
* running
|
|
* Done
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingDhcp6PdGetState
|
|
*/
|
|
else if (aArgs[0] == "state")
|
|
{
|
|
OutputLine("%s", Dhcp6PdStateToString(otBorderRoutingDhcp6PdGetState(GetInstancePtr())));
|
|
}
|
|
/**
|
|
* @cli br pd omrprefix
|
|
* @code
|
|
* br pd omrprefix
|
|
* 2001:db8:cafe:0:0/64 lifetime:1800 preferred:1800
|
|
* Done
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingGetPdOmrPrefix
|
|
*/
|
|
else if (aArgs[0] == "omrprefix")
|
|
{
|
|
otBorderRoutingPrefixTableEntry entry;
|
|
|
|
SuccessOrExit(error = otBorderRoutingGetPdOmrPrefix(GetInstancePtr(), &entry));
|
|
|
|
OutputIp6Prefix(entry.mPrefix);
|
|
OutputLine(" lifetime:%lu preferred:%lu", ToUlong(entry.mValidLifetime), ToUlong(entry.mPreferredLifetime));
|
|
}
|
|
else
|
|
{
|
|
ExitNow(error = OT_ERROR_INVALID_COMMAND);
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
|
|
|
|
/**
|
|
* @cli br routers
|
|
* @code
|
|
* br routers
|
|
* ff02:0:0:0:0:0:0:1 (M:0 O:0 S:1) ms-since-rx:1505 reachable:yes age:00:18:13
|
|
* Done
|
|
* @endcode
|
|
* @par
|
|
* Get the list of discovered routers by Border Routing Manager on the infrastructure link.
|
|
* Info per router:
|
|
* - The router IPv6 address
|
|
* - Flags in received Router Advertisement header:
|
|
* - M: Managed Address Config flag
|
|
* - O: Other Config flag
|
|
* - S: SNAC 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.
|
|
* - `(peer BR)` is appended when the router is likely a peer BR connected to the same Thread mesh. This requires
|
|
* `OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE`.
|
|
* @sa otBorderRoutingGetNextRouterEntry
|
|
*/
|
|
template <> otError Br::Process<Cmd("routers")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
otBorderRoutingPrefixTableIterator iterator;
|
|
otBorderRoutingRouterEntry entry;
|
|
|
|
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
|
|
|
|
while (otBorderRoutingGetNextRouterEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
|
|
{
|
|
OutputRouterInfo(entry, kLongVersion);
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
void Br::OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry, RouterOutputMode aMode)
|
|
{
|
|
OutputIp6Address(aEntry.mAddress);
|
|
OutputFormat(" (M:%u O:%u S:%u)", aEntry.mManagedAddressConfigFlag, aEntry.mOtherConfigFlag,
|
|
aEntry.mSnacRouterFlag);
|
|
|
|
if (aMode == kLongVersion)
|
|
{
|
|
char ageString[OT_DURATION_STRING_SIZE];
|
|
|
|
otConvertDurationInSecondsToString(aEntry.mAge, ageString, sizeof(ageString));
|
|
|
|
OutputFormat(" ms-since-rx:%lu reachable:%s age:%s", ToUlong(aEntry.mMsecSinceLastUpdate),
|
|
ToYesNo(aEntry.mIsReachable), ageString);
|
|
|
|
if (aEntry.mIsLocalDevice)
|
|
{
|
|
OutputFormat(" (this BR)");
|
|
}
|
|
|
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
|
|
if (aEntry.mIsPeerBr)
|
|
{
|
|
OutputFormat(" (peer BR)");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
OutputNewLine();
|
|
}
|
|
|
|
template <> otError Br::Process<Cmd("raoptions")>(Arg aArgs[])
|
|
{
|
|
static constexpr uint16_t kMaxExtraOptions = 800;
|
|
|
|
otError error = OT_ERROR_NONE;
|
|
uint8_t options[kMaxExtraOptions];
|
|
uint16_t length;
|
|
|
|
/**
|
|
* @cli br raoptions (set,clear)
|
|
* @code
|
|
* br raoptions 0400ff00020001
|
|
* Done
|
|
* @endcode
|
|
* @code
|
|
* br raoptions clear
|
|
* Done
|
|
* @endcode
|
|
* @cparam br raoptions @ca{options|clear}
|
|
* `br raoptions clear` passes a `nullptr` to #otBorderRoutingSetExtraRouterAdvertOptions.
|
|
* Otherwise, you can pass the `options` byte as hex data.
|
|
* @par api_copy
|
|
* #otBorderRoutingSetExtraRouterAdvertOptions
|
|
*/
|
|
if (aArgs[0] == "clear")
|
|
{
|
|
length = 0;
|
|
}
|
|
else
|
|
{
|
|
length = sizeof(options);
|
|
SuccessOrExit(error = aArgs[0].ParseAsHexString(length, options));
|
|
}
|
|
|
|
error = otBorderRoutingSetExtraRouterAdvertOptions(GetInstancePtr(), length > 0 ? options : nullptr, length);
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
template <> otError Br::Process<Cmd("rioprf")>(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", 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;
|
|
}
|
|
|
|
template <> otError Br::Process<Cmd("routeprf")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
/**
|
|
* @cli br routeprf
|
|
* @code
|
|
* br routeprf
|
|
* med
|
|
* Done
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingGetRoutePreference
|
|
*/
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
OutputLine("%s", PreferenceToString(otBorderRoutingGetRoutePreference(GetInstancePtr())));
|
|
}
|
|
/**
|
|
* @cli br routeprf clear
|
|
* @code
|
|
* br routeprf clear
|
|
* Done
|
|
* @endcode
|
|
* @par api_copy
|
|
* #otBorderRoutingClearRoutePreference
|
|
*/
|
|
else if (aArgs[0] == "clear")
|
|
{
|
|
otBorderRoutingClearRoutePreference(GetInstancePtr());
|
|
}
|
|
/**
|
|
* @cli br routeprf (high,med,low)
|
|
* @code
|
|
* br routeprf low
|
|
* Done
|
|
* @endcode
|
|
* @cparam br routeprf [@ca{high}|@ca{med}|@ca{low}]
|
|
* @par api_copy
|
|
* #otBorderRoutingSetRoutePreference
|
|
*/
|
|
else
|
|
{
|
|
otRoutePreference preference;
|
|
|
|
SuccessOrExit(error = Interpreter::ParsePreference(aArgs[0], preference));
|
|
otBorderRoutingSetRoutePreference(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<Cmd("counters")>(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<Cmd(aCommandString)>}
|
|
|
|
static constexpr Command kCommands[] = {
|
|
#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
|
|
CmdEntry("counters"),
|
|
#endif
|
|
CmdEntry("disable"), CmdEntry("enable"), CmdEntry("ifaddrs"), CmdEntry("infraif"),
|
|
CmdEntry("init"),
|
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_MULTI_AIL_DETECTION_ENABLE
|
|
CmdEntry("multiail"),
|
|
#endif
|
|
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
|
|
CmdEntry("nat64prefix"), CmdEntry("nat64prefixtable"),
|
|
#endif
|
|
CmdEntry("omrconfig"), CmdEntry("omrprefix"), CmdEntry("onlinkprefix"),
|
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
|
|
CmdEntry("pd"),
|
|
#endif
|
|
#if OPENTHREAD_CONFIG_BORDER_ROUTING_TRACK_PEER_BR_INFO_ENABLE
|
|
CmdEntry("peers"),
|
|
#endif
|
|
CmdEntry("prefixtable"), CmdEntry("raoptions"), CmdEntry("rdnsstable"), CmdEntry("rioprf"),
|
|
CmdEntry("routeprf"), CmdEntry("routers"), 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
|