[cli] move a few static util methods to Cli::Utils class (#10138)

This commit moves a few static util methods from the `Interpreter`
class to the `Cli::Utils` class. Since the `Interpreter` class and
other classes for cli components inherit the `Cli::Utils`, they can
still access these methods. Putting these methods in utils class is
more intuitive. This change also makes other cli classes less
dependent on the `Interpreter` class.
This commit is contained in:
Li Cao
2024-05-01 10:56:18 -07:00
committed by GitHub
parent 0c6c2fedad
commit 3bf281d32d
13 changed files with 397 additions and 362 deletions
-264
View File
@@ -207,35 +207,6 @@ exit:
return;
}
const char *Interpreter::LinkModeToString(const otLinkModeConfig &aLinkMode, char (&aStringBuffer)[kLinkModeStringSize])
{
char *flagsPtr = &aStringBuffer[0];
if (aLinkMode.mRxOnWhenIdle)
{
*flagsPtr++ = 'r';
}
if (aLinkMode.mDeviceType)
{
*flagsPtr++ = 'd';
}
if (aLinkMode.mNetworkData)
{
*flagsPtr++ = 'n';
}
if (flagsPtr == &aStringBuffer[0])
{
*flagsPtr++ = '-';
}
*flagsPtr = '\0';
return aStringBuffer;
}
#if OPENTHREAD_CONFIG_DIAG_ENABLE
template <> otError Interpreter::Process<Cmd("diag")>(Arg aArgs[])
{
@@ -416,101 +387,6 @@ otError Interpreter::SetUserCommands(const otCliCommand *aCommands, uint8_t aLen
#if OPENTHREAD_FTD || OPENTHREAD_MTD
otError Interpreter::ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscerner)
{
otError error;
char *separator;
VerifyOrExit(!aArg.IsEmpty(), error = OT_ERROR_INVALID_ARGS);
separator = strstr(aArg.GetCString(), "/");
VerifyOrExit(separator != nullptr, error = OT_ERROR_NOT_FOUND);
SuccessOrExit(error = ot::Utils::CmdLineParser::ParseAsUint8(separator + 1, aDiscerner.mLength));
VerifyOrExit(aDiscerner.mLength > 0 && aDiscerner.mLength <= 64, error = OT_ERROR_INVALID_ARGS);
*separator = '\0';
error = aArg.ParseAsUint64(aDiscerner.mValue);
exit:
return error;
}
otError Interpreter::ParsePreference(const Arg &aArg, otRoutePreference &aPreference)
{
otError error = OT_ERROR_NONE;
if (aArg == "high")
{
aPreference = OT_ROUTE_PREFERENCE_HIGH;
}
else if (aArg == "med")
{
aPreference = OT_ROUTE_PREFERENCE_MED;
}
else if (aArg == "low")
{
aPreference = OT_ROUTE_PREFERENCE_LOW;
}
else
{
error = OT_ERROR_INVALID_ARGS;
}
return error;
}
const char *Interpreter::PreferenceToString(signed int aPreference)
{
const char *str = "";
switch (aPreference)
{
case OT_ROUTE_PREFERENCE_LOW:
str = "low";
break;
case OT_ROUTE_PREFERENCE_MED:
str = "med";
break;
case OT_ROUTE_PREFERENCE_HIGH:
str = "high";
break;
default:
break;
}
return str;
}
otError Interpreter::ParseToIp6Address(otInstance *aInstance,
const Arg &aArg,
otIp6Address &aAddress,
bool &aSynthesized)
{
Error error = OT_ERROR_NONE;
VerifyOrExit(!aArg.IsEmpty(), error = OT_ERROR_INVALID_ARGS);
error = aArg.ParseAsIp6Address(aAddress);
aSynthesized = false;
if (error != OT_ERROR_NONE)
{
// It might be an IPv4 address, let's have a try.
otIp4Address ip4Address;
// Do not touch the error value if we failed to parse it as an IPv4 address.
SuccessOrExit(aArg.ParseAsIp4Address(ip4Address));
SuccessOrExit(error = otNat64SynthesizeIp6Address(aInstance, &ip4Address, &aAddress));
aSynthesized = true;
}
exit:
return error;
}
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
template <> otError Interpreter::Process<Cmd("history")>(Arg aArgs[]) { return mHistory.Process(aArgs); }
#endif
@@ -3277,23 +3153,6 @@ template <> otError Interpreter::Process<Cmd("instanceid")>(Arg aArgs[])
return error;
}
const char *Interpreter::AddressOriginToString(uint8_t aOrigin)
{
static const char *const kOriginStrings[4] = {
"thread", // 0, OT_ADDRESS_ORIGIN_THREAD
"slaac", // 1, OT_ADDRESS_ORIGIN_SLAAC
"dhcp6", // 2, OT_ADDRESS_ORIGIN_DHCPV6
"manual", // 3, OT_ADDRESS_ORIGIN_MANUAL
};
static_assert(0 == OT_ADDRESS_ORIGIN_THREAD, "OT_ADDRESS_ORIGIN_THREAD value is incorrect");
static_assert(1 == OT_ADDRESS_ORIGIN_SLAAC, "OT_ADDRESS_ORIGIN_SLAAC value is incorrect");
static_assert(2 == OT_ADDRESS_ORIGIN_DHCPV6, "OT_ADDRESS_ORIGIN_DHCPV6 value is incorrect");
static_assert(3 == OT_ADDRESS_ORIGIN_MANUAL, "OT_ADDRESS_ORIGIN_MANUAL value is incorrect");
return Stringify(aOrigin, kOriginStrings);
}
template <> otError Interpreter::Process<Cmd("ipaddr")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -5853,80 +5712,6 @@ void Interpreter::HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx)
}
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
otError Interpreter::ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig)
{
otError error = OT_ERROR_NONE;
ClearAllBytes(aConfig);
SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(aConfig.mPrefix));
aArgs++;
for (; !aArgs->IsEmpty(); aArgs++)
{
otRoutePreference preference;
if (ParsePreference(*aArgs, preference) == OT_ERROR_NONE)
{
aConfig.mPreference = preference;
}
else
{
for (char *arg = aArgs->GetCString(); *arg != '\0'; arg++)
{
switch (*arg)
{
case 'p':
aConfig.mPreferred = true;
break;
case 'a':
aConfig.mSlaac = true;
break;
case 'd':
aConfig.mDhcp = true;
break;
case 'c':
aConfig.mConfigure = true;
break;
case 'r':
aConfig.mDefaultRoute = true;
break;
case 'o':
aConfig.mOnMesh = true;
break;
case 's':
aConfig.mStable = true;
break;
case 'n':
aConfig.mNdDns = true;
break;
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
case 'D':
aConfig.mDp = true;
break;
#endif
case '-':
break;
default:
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}
}
}
exit:
return error;
}
template <> otError Interpreter::Process<Cmd("prefix")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -6280,55 +6065,6 @@ template <> otError Interpreter::Process<Cmd("rloc16")>(Arg aArgs[])
}
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
otError Interpreter::ParseRoute(Arg aArgs[], otExternalRouteConfig &aConfig)
{
otError error = OT_ERROR_NONE;
ClearAllBytes(aConfig);
SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(aConfig.mPrefix));
aArgs++;
for (; !aArgs->IsEmpty(); aArgs++)
{
otRoutePreference preference;
if (ParsePreference(*aArgs, preference) == OT_ERROR_NONE)
{
aConfig.mPreference = preference;
}
else
{
for (char *arg = aArgs->GetCString(); *arg != '\0'; arg++)
{
switch (*arg)
{
case 's':
aConfig.mStable = true;
break;
case 'n':
aConfig.mNat64 = true;
break;
case 'a':
aConfig.mAdvPio = true;
break;
case '-':
break;
default:
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}
}
}
exit:
return error;
}
template <> otError Interpreter::Process<Cmd("route")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
-75
View File
@@ -191,76 +191,6 @@ public:
*/
otError SetUserCommands(const otCliCommand *aCommands, uint8_t aLength, void *aContext);
static constexpr uint8_t kLinkModeStringSize = sizeof("rdn"); ///< Size of string buffer for a MLE Link Mode.
/**
* Converts a given MLE Link Mode to flag string.
*
* The characters 'r', 'd', and 'n' are respectively used for `mRxOnWhenIdle`, `mDeviceType` and `mNetworkData`
* flags. If all flags are `false`, then "-" is returned.
*
* @param[in] aLinkMode The MLE Link Mode to convert.
* @param[out] aStringBuffer A reference to an string array to place the string.
*
* @returns A pointer @p aStringBuffer which contains the converted string.
*
*/
static const char *LinkModeToString(const otLinkModeConfig &aLinkMode, char (&aStringBuffer)[kLinkModeStringSize]);
/**
* Converts an IPv6 address origin `OT_ADDRESS_ORIGIN_*` value to human-readable string.
*
* @param[in] aOrigin The IPv6 address origin to convert.
*
* @returns A human-readable string representation of @p aOrigin.
*
*/
static const char *AddressOriginToString(uint8_t aOrigin);
/**
* Parses a given argument string as a route preference comparing it against "high", "med", or
* "low".
*
* @param[in] aArg The argument string to parse.
* @param[out] aPreference Reference to a `otRoutePreference` to return the parsed preference.
*
* @retval OT_ERROR_NONE Successfully parsed @p aArg and updated @p aPreference.
* @retval OT_ERROR_INVALID_ARG @p aArg is not a valid preference string "high", "med", or "low".
*
*/
static otError ParsePreference(const Arg &aArg, otRoutePreference &aPreference);
/**
* Converts a route preference value to human-readable string.
*
* @param[in] aPreference The preference value to convert (`OT_ROUTE_PREFERENCE_*` values).
*
* @returns A string representation @p aPreference.
*
*/
static const char *PreferenceToString(signed int aPreference);
/**
* Parses the argument as an IP address.
*
* If the argument string is an IPv4 address, this method will try to synthesize an IPv6 address using preferred
* NAT64 prefix in the network data.
*
* @param[in] aInstance A pointer to OpenThread instance.
* @param[in] aArg The argument string to parse.
* @param[out] aAddress A reference to an `otIp6Address` to output the parsed IPv6 address.
* @param[out] aSynthesized Whether @p aAddress is synthesized from an IPv4 address.
*
* @retval OT_ERROR_NONE The argument was parsed successfully.
* @retval OT_ERROR_INVALID_ARGS The argument is empty or does not contain a valid IP address.
* @retval OT_ERROR_INVALID_STATE No valid NAT64 prefix in the network data.
*
*/
static otError ParseToIp6Address(otInstance *aInstance,
const Arg &aArg,
otIp6Address &aAddress,
bool &aSynthesized);
protected:
static Interpreter *sInterpreter;
@@ -280,11 +210,6 @@ private:
void OutputPrompt(void);
void OutputResult(otError aError);
static otError ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscerner);
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
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
+5 -6
View File
@@ -233,7 +233,7 @@ template <> otError Br::Process<Cmd("omrprefix")>(Arg aArgs[])
OutputFormat("%s", outputPrefixTypes == kPrefixTypeFavored ? "" : "Favored: ");
OutputIp6Prefix(favored);
OutputLine(" prf:%s", Interpreter::PreferenceToString(preference));
OutputLine(" prf:%s", PreferenceToString(preference));
}
exit:
@@ -365,7 +365,7 @@ template <> otError Br::Process<Cmd("nat64prefix")>(Arg aArgs[])
OutputFormat("%s", outputPrefixTypes == kPrefixTypeFavored ? "" : "Favored: ");
OutputIp6Prefix(favored);
OutputLine(" prf:%s", Interpreter::PreferenceToString(preference));
OutputLine(" prf:%s", PreferenceToString(preference));
}
exit:
@@ -424,7 +424,7 @@ template <> otError Br::Process<Cmd("prefixtable")>(Arg aArgs[])
}
else
{
OutputFormat("route-prf:%s, ", Interpreter::PreferenceToString(entry.mRoutePreference));
OutputFormat("route-prf:%s, ", PreferenceToString(entry.mRoutePreference));
}
OutputFormat("router:");
@@ -594,8 +594,7 @@ template <> otError Br::Process<Cmd("rioprf")>(Arg aArgs[])
*/
if (aArgs[0].IsEmpty())
{
OutputLine("%s",
Interpreter::PreferenceToString(otBorderRoutingGetRouteInfoOptionPreference(GetInstancePtr())));
OutputLine("%s", PreferenceToString(otBorderRoutingGetRouteInfoOptionPreference(GetInstancePtr())));
}
/**
* @cli br rioprf clear
@@ -648,7 +647,7 @@ template <> otError Br::Process<Cmd("routeprf")>(Arg aArgs[])
*/
if (aArgs[0].IsEmpty())
{
OutputLine("%s", Interpreter::PreferenceToString(otBorderRoutingGetRoutePreference(GetInstancePtr())));
OutputLine("%s", PreferenceToString(otBorderRoutingGetRoutePreference(GetInstancePtr())));
}
/**
* @cli br routeprf clear
+1 -1
View File
@@ -194,7 +194,7 @@ template <> otError Commissioner::Process<Cmd("joiner")>(Arg aArgs[])
}
else
{
error = Interpreter::ParseJoinerDiscerner(aArgs[1], discerner);
error = ParseJoinerDiscerner(aArgs[1], discerner);
if (error == OT_ERROR_NOT_FOUND)
{
+1 -2
View File
@@ -422,8 +422,7 @@ otError Dns::GetDnsConfig(Arg aArgs[], otDnsQueryConfig *&aConfig)
VerifyOrExit(!aArgs[0].IsEmpty(), aConfig = nullptr);
SuccessOrExit(error = Interpreter::ParseToIp6Address(GetInstancePtr(), aArgs[0], aConfig->mServerSockAddr.mAddress,
nat64Synth));
SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], aConfig->mServerSockAddr.mAddress, nat64Synth));
if (nat64Synth)
{
OutputFormat("Synthesized IPv6 DNS server address: ");
+2 -2
View File
@@ -1341,7 +1341,7 @@ template <> otError History::Process<Cmd("prefix")>(Arg aArgs[])
OutputLine(isList ? "%s -> event:%s prefix:%s flags:%s pref:%s rloc16:0x%04x"
: "| %20s | %-7s | %-43s | %-9s | %-4s | 0x%04x |",
ageString, Stringify(info->mEvent, kSimpleEventStrings), prefixString, flagsString,
Interpreter::PreferenceToString(info->mPrefix.mPreference), info->mPrefix.mRloc16);
PreferenceToString(info->mPrefix.mPreference), info->mPrefix.mRloc16);
}
exit:
@@ -1430,7 +1430,7 @@ template <> otError History::Process<Cmd("route")>(Arg aArgs[])
OutputLine(isList ? "%s -> event:%s route:%s flags:%s pref:%s rloc16:0x%04x"
: "| %20s | %-7s | %-43s | %-9s | %-4s | 0x%04x |",
ageString, Stringify(info->mEvent, kSimpleEventStrings), prefixString, flagsString,
Interpreter::PreferenceToString(info->mRoute.mPreference), info->mRoute.mRloc16);
PreferenceToString(info->mRoute.mPreference), info->mRoute.mRloc16);
}
exit:
+1 -1
View File
@@ -108,7 +108,7 @@ template <> otError Joiner::Process<Cmd("discerner")>(Arg aArgs[])
else
{
VerifyOrExit(aArgs[1].IsEmpty());
SuccessOrExit(Interpreter::ParseJoinerDiscerner(aArgs[0], discerner));
SuccessOrExit(ParseJoinerDiscerner(aArgs[0], discerner));
error = otJoinerSetDiscerner(GetInstancePtr(), &discerner);
}
}
+6 -6
View File
@@ -117,7 +117,7 @@ void NetworkData::OutputPrefix(const otBorderRouterConfig &aConfig)
OutputFormat(" %s", flagsString);
}
OutputLine(" %s %04x", Interpreter::PreferenceToString(aConfig.mPreference), aConfig.mRloc16);
OutputLine(" %s %04x", PreferenceToString(aConfig.mPreference), aConfig.mRloc16);
}
void NetworkData::RouteFlagsToString(const otExternalRouteConfig &aConfig, FlagsString &aString)
@@ -155,7 +155,7 @@ void NetworkData::OutputRoute(const otExternalRouteConfig &aConfig)
OutputFormat(" %s", flagsString);
}
OutputLine(" %s %04x", Interpreter::PreferenceToString(aConfig.mPreference), aConfig.mRloc16);
OutputLine(" %s %04x", PreferenceToString(aConfig.mPreference), aConfig.mRloc16);
}
void NetworkData::OutputService(const otServiceConfig &aConfig)
@@ -343,7 +343,7 @@ template <> otError NetworkData::Process<Cmd("publish")>(Arg aArgs[])
{
otBorderRouterConfig config;
SuccessOrExit(error = Interpreter::ParsePrefix(aArgs + 1, config));
SuccessOrExit(error = ParsePrefix(aArgs + 1, config));
error = otNetDataPublishOnMeshPrefix(GetInstancePtr(), &config);
ExitNow();
}
@@ -364,7 +364,7 @@ template <> otError NetworkData::Process<Cmd("publish")>(Arg aArgs[])
{
otExternalRouteConfig config;
SuccessOrExit(error = Interpreter::ParseRoute(aArgs + 1, config));
SuccessOrExit(error = ParseRoute(aArgs + 1, config));
error = otNetDataPublishExternalRoute(GetInstancePtr(), &config);
ExitNow();
}
@@ -387,7 +387,7 @@ template <> otError NetworkData::Process<Cmd("publish")>(Arg aArgs[])
otExternalRouteConfig config;
SuccessOrExit(error = aArgs[1].ParseAsIp6Prefix(prefix));
SuccessOrExit(error = Interpreter::ParseRoute(aArgs + 2, config));
SuccessOrExit(error = ParseRoute(aArgs + 2, config));
error = otNetDataReplacePublishedExternalRoute(GetInstancePtr(), &prefix, &config);
ExitNow();
}
@@ -493,7 +493,7 @@ template <> otError NetworkData::Process<Cmd("steeringdata")>(Arg aArgs[])
VerifyOrExit(aArgs[0] == "check", error = OT_ERROR_INVALID_ARGS);
error = Interpreter::ParseJoinerDiscerner(aArgs[1], discerner);
error = ParseJoinerDiscerner(aArgs[1], discerner);
if (error == OT_ERROR_NOT_FOUND)
{
+1 -1
View File
@@ -96,7 +96,7 @@ otError PingSender::Process(Arg aArgs[])
aArgs++;
}
SuccessOrExit(error = Interpreter::ParseToIp6Address(GetInstancePtr(), aArgs[0], config.mDestination, nat64Synth));
SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], config.mDestination, nat64Synth));
if (nat64Synth)
{
+1 -1
View File
@@ -383,7 +383,7 @@ template <> otError TcpExample::Process<Cmd("connect")>(Arg aArgs[])
VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
SuccessOrExit(error = Interpreter::ParseToIp6Address(GetInstancePtr(), aArgs[0], sockaddr.mAddress, nat64Synth));
SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], sockaddr.mAddress, nat64Synth));
if (nat64Synth)
{
+2 -3
View File
@@ -134,7 +134,7 @@ template <> otError UdpExample::Process<Cmd("connect")>(Arg aArgs[])
otSockAddr sockaddr;
bool nat64Synth;
SuccessOrExit(error = Interpreter::ParseToIp6Address(GetInstancePtr(), aArgs[0], sockaddr.mAddress, nat64Synth));
SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], sockaddr.mAddress, nat64Synth));
if (nat64Synth)
{
@@ -269,8 +269,7 @@ template <> otError UdpExample::Process<Cmd("send")>(Arg aArgs[])
{
bool nat64Synth;
SuccessOrExit(
error = Interpreter::ParseToIp6Address(GetInstancePtr(), aArgs[0], messageInfo.mPeerAddr, nat64Synth));
SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], messageInfo.mPeerAddr, nat64Synth));
if (nat64Synth)
{
+265
View File
@@ -517,5 +517,270 @@ otError Utils::ProcessEnableDisable(Arg aArgs[],
return error;
}
otError Utils::ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscerner)
{
otError error;
char *separator;
VerifyOrExit(!aArg.IsEmpty(), error = OT_ERROR_INVALID_ARGS);
separator = strstr(aArg.GetCString(), "/");
VerifyOrExit(separator != nullptr, error = OT_ERROR_NOT_FOUND);
SuccessOrExit(error = ot::Utils::CmdLineParser::ParseAsUint8(separator + 1, aDiscerner.mLength));
VerifyOrExit(aDiscerner.mLength > 0 && aDiscerner.mLength <= 64, error = OT_ERROR_INVALID_ARGS);
*separator = '\0';
error = aArg.ParseAsUint64(aDiscerner.mValue);
exit:
return error;
}
otError Utils::ParsePreference(const Arg &aArg, otRoutePreference &aPreference)
{
otError error = OT_ERROR_NONE;
if (aArg == "high")
{
aPreference = OT_ROUTE_PREFERENCE_HIGH;
}
else if (aArg == "med")
{
aPreference = OT_ROUTE_PREFERENCE_MED;
}
else if (aArg == "low")
{
aPreference = OT_ROUTE_PREFERENCE_LOW;
}
else
{
error = OT_ERROR_INVALID_ARGS;
}
return error;
}
const char *Utils::PreferenceToString(signed int aPreference)
{
const char *str = "";
switch (aPreference)
{
case OT_ROUTE_PREFERENCE_LOW:
str = "low";
break;
case OT_ROUTE_PREFERENCE_MED:
str = "med";
break;
case OT_ROUTE_PREFERENCE_HIGH:
str = "high";
break;
default:
break;
}
return str;
}
#if OPENTHREAD_FTD || OPENTHREAD_MTD
otError Utils::ParseToIp6Address(otInstance *aInstance, const Arg &aArg, otIp6Address &aAddress, bool &aSynthesized)
{
Error error = OT_ERROR_NONE;
VerifyOrExit(!aArg.IsEmpty(), error = OT_ERROR_INVALID_ARGS);
error = aArg.ParseAsIp6Address(aAddress);
aSynthesized = false;
if (error != OT_ERROR_NONE)
{
// It might be an IPv4 address, let's have a try.
otIp4Address ip4Address;
// Do not touch the error value if we failed to parse it as an IPv4 address.
SuccessOrExit(aArg.ParseAsIp4Address(ip4Address));
SuccessOrExit(error = otNat64SynthesizeIp6Address(aInstance, &ip4Address, &aAddress));
aSynthesized = true;
}
exit:
return error;
}
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
otError Utils::ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig)
{
otError error = OT_ERROR_NONE;
ClearAllBytes(aConfig);
SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(aConfig.mPrefix));
aArgs++;
for (; !aArgs->IsEmpty(); aArgs++)
{
otRoutePreference preference;
if (ParsePreference(*aArgs, preference) == OT_ERROR_NONE)
{
aConfig.mPreference = preference;
}
else
{
for (char *arg = aArgs->GetCString(); *arg != '\0'; arg++)
{
switch (*arg)
{
case 'p':
aConfig.mPreferred = true;
break;
case 'a':
aConfig.mSlaac = true;
break;
case 'd':
aConfig.mDhcp = true;
break;
case 'c':
aConfig.mConfigure = true;
break;
case 'r':
aConfig.mDefaultRoute = true;
break;
case 'o':
aConfig.mOnMesh = true;
break;
case 's':
aConfig.mStable = true;
break;
case 'n':
aConfig.mNdDns = true;
break;
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
case 'D':
aConfig.mDp = true;
break;
#endif
case '-':
break;
default:
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}
}
}
exit:
return error;
}
otError Utils::ParseRoute(Arg aArgs[], otExternalRouteConfig &aConfig)
{
otError error = OT_ERROR_NONE;
ClearAllBytes(aConfig);
SuccessOrExit(error = aArgs[0].ParseAsIp6Prefix(aConfig.mPrefix));
aArgs++;
for (; !aArgs->IsEmpty(); aArgs++)
{
otRoutePreference preference;
if (ParsePreference(*aArgs, preference) == OT_ERROR_NONE)
{
aConfig.mPreference = preference;
}
else
{
for (char *arg = aArgs->GetCString(); *arg != '\0'; arg++)
{
switch (*arg)
{
case 's':
aConfig.mStable = true;
break;
case 'n':
aConfig.mNat64 = true;
break;
case 'a':
aConfig.mAdvPio = true;
break;
case '-':
break;
default:
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}
}
}
exit:
return error;
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
#endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD
const char *Utils::LinkModeToString(const otLinkModeConfig &aLinkMode, char (&aStringBuffer)[kLinkModeStringSize])
{
char *flagsPtr = &aStringBuffer[0];
if (aLinkMode.mRxOnWhenIdle)
{
*flagsPtr++ = 'r';
}
if (aLinkMode.mDeviceType)
{
*flagsPtr++ = 'd';
}
if (aLinkMode.mNetworkData)
{
*flagsPtr++ = 'n';
}
if (flagsPtr == &aStringBuffer[0])
{
*flagsPtr++ = '-';
}
*flagsPtr = '\0';
return aStringBuffer;
}
const char *Utils::AddressOriginToString(uint8_t aOrigin)
{
static const char *const kOriginStrings[4] = {
"thread", // 0, OT_ADDRESS_ORIGIN_THREAD
"slaac", // 1, OT_ADDRESS_ORIGIN_SLAAC
"dhcp6", // 2, OT_ADDRESS_ORIGIN_DHCPV6
"manual", // 3, OT_ADDRESS_ORIGIN_MANUAL
};
static_assert(0 == OT_ADDRESS_ORIGIN_THREAD, "OT_ADDRESS_ORIGIN_THREAD value is incorrect");
static_assert(1 == OT_ADDRESS_ORIGIN_SLAAC, "OT_ADDRESS_ORIGIN_SLAAC value is incorrect");
static_assert(2 == OT_ADDRESS_ORIGIN_DHCPV6, "OT_ADDRESS_ORIGIN_DHCPV6 value is incorrect");
static_assert(3 == OT_ADDRESS_ORIGIN_MANUAL, "OT_ADDRESS_ORIGIN_MANUAL value is incorrect");
return Stringify(aOrigin, kOriginStrings);
}
} // namespace Cli
} // namespace ot
+112
View File
@@ -38,7 +38,11 @@
#include <stdarg.h>
#include <openthread/border_router.h>
#include <openthread/border_routing.h>
#include <openthread/cli.h>
#include <openthread/joiner.h>
#include <openthread/thread.h>
#include "cli_config.h"
@@ -645,6 +649,114 @@ public:
IsEnabledHandler aIsEnabledHandler,
SetEnabledHandlerFailable aSetEnabledHandler);
/**
* Parses a given argument string as a route preference comparing it against "high", "med", or
* "low".
*
* @param[in] aArg The argument string to parse.
* @param[out] aPreference Reference to a `otRoutePreference` to return the parsed preference.
*
* @retval OT_ERROR_NONE Successfully parsed @p aArg and updated @p aPreference.
* @retval OT_ERROR_INVALID_ARG @p aArg is not a valid preference string "high", "med", or "low".
*
*/
static otError ParsePreference(const Arg &aArg, otRoutePreference &aPreference);
/**
* Converts a route preference value to human-readable string.
*
* @param[in] aPreference The preference value to convert (`OT_ROUTE_PREFERENCE_*` values).
*
* @returns A string representation @p aPreference.
*
*/
static const char *PreferenceToString(signed int aPreference);
/**
* Parses the argument as an IP address.
*
* If the argument string is an IPv4 address, this method will try to synthesize an IPv6 address using preferred
* NAT64 prefix in the network data.
*
* @param[in] aInstance A pointer to OpenThread instance.
* @param[in] aArg The argument string to parse.
* @param[out] aAddress A reference to an `otIp6Address` to output the parsed IPv6 address.
* @param[out] aSynthesized Whether @p aAddress is synthesized from an IPv4 address.
*
* @retval OT_ERROR_NONE The argument was parsed successfully.
* @retval OT_ERROR_INVALID_ARGS The argument is empty or does not contain a valid IP address.
* @retval OT_ERROR_INVALID_STATE No valid NAT64 prefix in the network data.
*
*/
static otError ParseToIp6Address(otInstance *aInstance,
const Arg &aArg,
otIp6Address &aAddress,
bool &aSynthesized);
/**
* Parses the argument as a Joiner Discerner.
*
* @param[in] aArg The argument string to parse.
* @param[out] aDiscerner A reference to an `otJoinerDiscerner` to output the parsed discerner
*
* @retval OT_ERROR_NONE The argument was parsed successfully.
* @retval OT_ERROR_INVALID_ARGS The argument is empty or does not contain a valid joiner discerner.
*
*/
static otError ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscerner);
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
/**
* Parses the argument as a Border Router configuration.
*
* @param[in] aArg The argument string to parse.
* @param[out] aConfig A reference to an `otBorderRouterConfig` to output the configuration.
*
* @retval OT_ERROR_NONE The argument was parsed successfully.
* @retval OT_ERROR_INVALID_ARGS The argument is empty or does not contain a valid configuration.
*
*/
static otError ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig);
/**
* Parses the argument as a External Route configuration.
*
* @param[in] aArg The argument string to parse.
* @param[out] aConfig A reference to an `otExternalRouteConfig` to output the configuration.
*
* @retval OT_ERROR_NONE The argument was parsed successfully.
* @retval OT_ERROR_INVALID_ARGS The argument is empty or does not contain a valid configuration.
*
*/
static otError ParseRoute(Arg aArgs[], otExternalRouteConfig &aConfig);
#endif
static constexpr uint8_t kLinkModeStringSize = sizeof("rdn"); ///< Size of string buffer for a MLE Link Mode.
/**
* Converts a given MLE Link Mode to flag string.
*
* The characters 'r', 'd', and 'n' are respectively used for `mRxOnWhenIdle`, `mDeviceType` and `mNetworkData`
* flags. If all flags are `false`, then "-" is returned.
*
* @param[in] aLinkMode The MLE Link Mode to convert.
* @param[out] aStringBuffer A reference to an string array to place the string.
*
* @returns A pointer @p aStringBuffer which contains the converted string.
*
*/
static const char *LinkModeToString(const otLinkModeConfig &aLinkMode, char (&aStringBuffer)[kLinkModeStringSize]);
/**
* Converts an IPv6 address origin `OT_ADDRESS_ORIGIN_*` value to human-readable string.
*
* @param[in] aOrigin The IPv6 address origin to convert.
*
* @returns A human-readable string representation of @p aOrigin.
*
*/
static const char *AddressOriginToString(uint8_t aOrigin);
protected:
void OutputFormatV(const char *aFormat, va_list aArguments);