[cli] add CLI Backbone Router (Bbr) sub-module (#9128)

This commit adds `Bbr` CLI sub-module that implements all
"bbr" sub-commands.
This commit is contained in:
Abtin Keshavarzian
2023-06-05 12:32:25 -07:00
committed by GitHub
parent 977ac21743
commit 41d6fc861c
7 changed files with 612 additions and 398 deletions
+2
View File
@@ -30,6 +30,8 @@ import("../../etc/gn/openthread.gni")
openthread_cli_sources = [
"cli.cpp",
"cli.hpp",
"cli_bbr.cpp",
"cli_bbr.hpp",
"cli_br.cpp",
"cli_br.hpp",
"cli_coap.cpp",
+1
View File
@@ -33,6 +33,7 @@ set(COMMON_INCLUDES
set(COMMON_SOURCES
cli.cpp
cli_bbr.cpp
cli_br.cpp
cli_coap.cpp
cli_coap_secure.cpp
+2
View File
@@ -153,6 +153,7 @@ libopenthread_cli_radio_a_CPPFLAGS = \
SOURCES_COMMON = \
cli.cpp \
cli_bbr.cpp \
cli_br.cpp \
cli_coap.cpp \
cli_coap_secure.cpp \
@@ -185,6 +186,7 @@ libopenthread_cli_radio_a_SOURCES = \
noinst_HEADERS = \
cli.hpp \
cli_bbr.hpp \
cli_br.hpp \
cli_coap.hpp \
cli_coap_secure.hpp \
+4 -398
View File
@@ -115,6 +115,9 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
#if OPENTHREAD_CLI_DNS_ENABLE
, mDns(aInstance, *this)
#endif
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
, mBbr(aInstance, *this)
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
, mBr(aInstance, *this)
#endif
@@ -902,405 +905,8 @@ void Interpreter::OutputNat64Counters(const otNat64Counters &aCounters)
#endif // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE || OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
template <> otError Interpreter::Process<Cmd("bbr")>(Arg aArgs[])
{
otError error = OT_ERROR_INVALID_COMMAND;
otBackboneRouterConfig config;
/**
* @cli bbr
* @code
* bbr
* BBR Primary:
* server16: 0xE400
* seqno: 10
* delay: 120 secs
* timeout: 300 secs
* Done
* @endcode
* @code
* bbr
* BBR Primary: None
* Done
* @endcode
* @par
* Returns the current Primary Backbone Router information for the Thread device.
*/
if (aArgs[0].IsEmpty())
{
if (otBackboneRouterGetPrimary(GetInstancePtr(), &config) == OT_ERROR_NONE)
{
OutputLine("BBR Primary:");
OutputLine("server16: 0x%04X", config.mServer16);
OutputLine("seqno: %u", config.mSequenceNumber);
OutputLine("delay: %u secs", config.mReregistrationDelay);
OutputLine("timeout: %lu secs", ToUlong(config.mMlrTimeout));
}
else
{
OutputLine("BBR Primary: None");
}
error = OT_ERROR_NONE;
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
else
{
if (aArgs[0] == "mgmt")
{
if (aArgs[1].IsEmpty())
{
ExitNow(error = OT_ERROR_INVALID_COMMAND);
}
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
/**
* @cli bbr mgmt dua
* @code
* bbr mgmt dua 1 2f7c235e5025a2fd
* Done
* @endcode
* @code
* bbr mgmt dua 160
* Done
* @endcode
* @cparam bbr mgmt dua @ca{status|coap-code} [@ca{meshLocalIid}]
* For `status` or `coap-code`, use:
* * 0: ST_DUA_SUCCESS
* * 1: ST_DUA_REREGISTER
* * 2: ST_DUA_INVALID
* * 3: ST_DUA_DUPLICATE
* * 4: ST_DUA_NO_RESOURCES
* * 5: ST_DUA_BBR_NOT_PRIMARY
* * 6: ST_DUA_GENERAL_FAILURE
* * 160: COAP code 5.00
* @par
* With the `meshLocalIid` included, this command configures the response status
* for the next DUA registration. Without `meshLocalIid`, respond to the next
* DUA.req with the specified `status` or `coap-code`.
* @par
* Available when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
* @sa otBackboneRouterConfigNextDuaRegistrationResponse
*/
else if (aArgs[1] == "dua")
{
uint8_t status;
otIp6InterfaceIdentifier *mlIid = nullptr;
otIp6InterfaceIdentifier iid;
SuccessOrExit(error = aArgs[2].ParseAsUint8(status));
if (!aArgs[3].IsEmpty())
{
SuccessOrExit(error = aArgs[3].ParseAsHexString(iid.mFields.m8));
mlIid = &iid;
VerifyOrExit(aArgs[4].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
}
otBackboneRouterConfigNextDuaRegistrationResponse(GetInstancePtr(), mlIid, status);
ExitNow();
}
#endif
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
else if (aArgs[1] == "mlr")
{
error = ProcessBackboneRouterMgmtMlr(aArgs + 2);
ExitNow();
}
#endif
}
SuccessOrExit(error = ProcessBackboneRouterLocal(aArgs));
}
exit:
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
return error;
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
otError Interpreter::ProcessBackboneRouterMgmtMlr(Arg aArgs[])
{
otError error = OT_ERROR_INVALID_COMMAND;
/**
* @cli bbr mgmt mlr listener
* @code
* bbr mgmt mlr listener
* ff04:0:0:0:0:0:0:abcd 3534000
* ff04:0:0:0:0:0:0:eeee 3537610
* Done
* @endcode
* @par
* Returns the Multicast Listeners with the #otBackboneRouterMulticastListenerInfo
* `mTimeout` in seconds.
* @par
* Available when `OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` and
* `OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE` are enabled.
* @sa otBackboneRouterMulticastListenerGetNext
*/
if (aArgs[0] == "listener")
{
if (aArgs[1].IsEmpty())
{
PrintMulticastListenersTable();
ExitNow(error = OT_ERROR_NONE);
}
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
/**
* @cli bbr mgmt mlr listener clear
* @code
* bbr mgmt mlr listener clear
* Done
* @endcode
* @par api_copy
* #otBackboneRouterMulticastListenerClear
*/
if (aArgs[1] == "clear")
{
otBackboneRouterMulticastListenerClear(GetInstancePtr());
error = OT_ERROR_NONE;
}
/**
* @cli bbr mgmt mlr listener add
* @code
* bbr mgmt mlr listener add ff04::1
* Done
* @endcode
* @code
* bbr mgmt mlr listener add ff04::2 300
* Done
* @endcode
* @cparam bbr mgmt mlr listener add @ca{ipaddress} [@ca{timeout-seconds}]
* @par api_copy
* #otBackboneRouterMulticastListenerAdd
*/
else if (aArgs[1] == "add")
{
otIp6Address address;
uint32_t timeout = 0;
SuccessOrExit(error = aArgs[2].ParseAsIp6Address(address));
if (!aArgs[3].IsEmpty())
{
SuccessOrExit(error = aArgs[3].ParseAsUint32(timeout));
VerifyOrExit(aArgs[4].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
}
error = otBackboneRouterMulticastListenerAdd(GetInstancePtr(), &address, timeout);
}
}
/**
* @cli bbr mgmt mlr response
* @code
* bbr mgmt mlr response 2
* Done
* @endcode
* @cparam bbr mgmt mlr response @ca{status-code}
* For `status-code`, use:
* * 0: ST_MLR_SUCCESS
* * 2: ST_MLR_INVALID
* * 3: ST_MLR_NO_PERSISTENT
* * 4: ST_MLR_NO_RESOURCES
* * 5: ST_MLR_BBR_NOT_PRIMARY
* * 6: ST_MLR_GENERAL_FAILURE
* @par api_copy
* #otBackboneRouterConfigNextMulticastListenerRegistrationResponse
*/
else if (aArgs[0] == "response")
{
error = ProcessSet(aArgs + 1, otBackboneRouterConfigNextMulticastListenerRegistrationResponse);
#endif
}
exit:
return error;
}
void Interpreter::PrintMulticastListenersTable(void)
{
otBackboneRouterMulticastListenerIterator iter = OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT;
otBackboneRouterMulticastListenerInfo listenerInfo;
while (otBackboneRouterMulticastListenerGetNext(GetInstancePtr(), &iter, &listenerInfo) == OT_ERROR_NONE)
{
OutputIp6Address(listenerInfo.mAddress);
OutputLine(" %lu", ToUlong(listenerInfo.mTimeout));
}
}
#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
otError Interpreter::ProcessBackboneRouterLocal(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otBackboneRouterConfig config;
bool enable;
/**
* @cli bbr (enable,disable)
* @code
* bbr enable
* Done
* @endcode
* @code
* bbr disable
* Done
* @endcode
* @par api_copy
* #otBackboneRouterSetEnabled
*/
if (ParseEnableOrDisable(aArgs[0], enable) == OT_ERROR_NONE)
{
otBackboneRouterSetEnabled(GetInstancePtr(), enable);
}
/**
* @cli bbr jitter (get,set)
* @code
* bbr jitter
* 20
* Done
* @endcode
* @code
* bbr jitter 10
* Done
* @endcode
* @cparam bbr jitter [@ca{jitter}]
* @par
* Gets or sets jitter (in seconds) for Backbone Router registration.
* @par
* Available when `OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is enabled.
* @sa otBackboneRouterGetRegistrationJitter
* @sa otBackboneRouterSetRegistrationJitter
*/
else if (aArgs[0] == "jitter")
{
error = ProcessGetSet(aArgs + 1, otBackboneRouterGetRegistrationJitter, otBackboneRouterSetRegistrationJitter);
}
/**
* @cli bbr register
* @code
* bbr register
* Done
* @endcode
* @par api_copy
* #otBackboneRouterRegister
*/
else if (aArgs[0] == "register")
{
SuccessOrExit(error = otBackboneRouterRegister(GetInstancePtr()));
}
/**
* @cli bbr state
* @code
* bbr state
* Disabled
* Done
* @endcode
* @code
* bbr state
* Primary
* Done
* @endcode
* @code
* bbr state
* Secondary
* Done
* @endcode
* @par
* Available when `OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is enabled.
* @par api_copy
* #otBackboneRouterGetState
*/
else if (aArgs[0] == "state")
{
static const char *const kStateStrings[] = {
"Disabled", // (0) OT_BACKBONE_ROUTER_STATE_DISABLED
"Secondary", // (1) OT_BACKBONE_ROUTER_STATE_SECONDARY
"Primary", // (2) OT_BACKBONE_ROUTER_STATE_PRIMARY
};
static_assert(0 == OT_BACKBONE_ROUTER_STATE_DISABLED, "OT_BACKBONE_ROUTER_STATE_DISABLED value is incorrect");
static_assert(1 == OT_BACKBONE_ROUTER_STATE_SECONDARY, "OT_BACKBONE_ROUTER_STATE_SECONDARY value is incorrect");
static_assert(2 == OT_BACKBONE_ROUTER_STATE_PRIMARY, "OT_BACKBONE_ROUTER_STATE_PRIMARY value is incorrect");
OutputLine("%s", Stringify(otBackboneRouterGetState(GetInstancePtr()), kStateStrings));
}
/**
* @cli bbr config
* @code
* bbr config
* seqno: 10
* delay: 120 secs
* timeout: 300 secs
* Done
* @endcode
* @par api_copy
* #otBackboneRouterGetConfig
*/
else if (aArgs[0] == "config")
{
otBackboneRouterGetConfig(GetInstancePtr(), &config);
if (aArgs[1].IsEmpty())
{
OutputLine("seqno: %u", config.mSequenceNumber);
OutputLine("delay: %u secs", config.mReregistrationDelay);
OutputLine("timeout: %lu secs", ToUlong(config.mMlrTimeout));
}
else
{
// Set local Backbone Router configuration.
/**
* @cli bbr config (set)
* @code
* bbr config seqno 20 delay 30
* Done
* @endcode
* @cparam bbr config [seqno @ca{seqno}] [delay @ca{delay}] [timeout @ca{timeout}]
* @par
* `bbr register` should be issued explicitly to register Backbone Router service to Leader
* for Secondary Backbone Router.
* @par api_copy
* #otBackboneRouterSetConfig
*/
for (Arg *arg = &aArgs[1]; !arg->IsEmpty(); arg++)
{
if (*arg == "seqno")
{
arg++;
SuccessOrExit(error = arg->ParseAsUint8(config.mSequenceNumber));
}
else if (*arg == "delay")
{
arg++;
SuccessOrExit(error = arg->ParseAsUint16(config.mReregistrationDelay));
}
else if (*arg == "timeout")
{
arg++;
SuccessOrExit(error = arg->ParseAsUint32(config.mMlrTimeout));
}
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}
SuccessOrExit(error = otBackboneRouterSetConfig(GetInstancePtr(), &config));
}
}
else
{
error = OT_ERROR_INVALID_COMMAND;
}
exit:
return error;
}
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
template <> otError Interpreter::Process<Cmd("bbr")>(Arg aArgs[]) { return mBbr.Process(aArgs); }
/**
* @cli domainname
+6
View File
@@ -58,6 +58,7 @@
#include <openthread/thread_ftd.h>
#include <openthread/udp.h>
#include "cli/cli_bbr.hpp"
#include "cli/cli_br.hpp"
#include "cli/cli_commissioner.hpp"
#include "cli/cli_dataset.hpp"
@@ -108,6 +109,7 @@ class Interpreter : public OutputImplementer, public Output
{
#if OPENTHREAD_FTD || OPENTHREAD_MTD
friend class Br;
friend class Bbr;
friend class Commissioner;
friend class Dns;
friend class Joiner;
@@ -549,6 +551,10 @@ private:
Dns mDns;
#endif
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
Bbr mBbr;
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
Br mBr;
#endif
+499
View File
@@ -0,0 +1,499 @@
/*
* 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 Backbone Router.
*/
#include "cli_bbr.hpp"
#include "cli/cli.hpp"
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
namespace ot {
namespace Cli {
void Bbr::OutputConfig(const otBackboneRouterConfig &aConfig)
{
OutputLine("seqno: %u", aConfig.mSequenceNumber);
OutputLine("delay: %u secs", aConfig.mReregistrationDelay);
OutputLine("timeout: %lu secs", ToUlong(aConfig.mMlrTimeout));
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
template <> otError Bbr::Process<Cmd("mlr")>(Arg aArgs[])
{
otError error = OT_ERROR_INVALID_COMMAND;
/**
* @cli bbr mgmt mlr listener
* @code
* bbr mgmt mlr listener
* ff04:0:0:0:0:0:0:abcd 3534000
* ff04:0:0:0:0:0:0:eeee 3537610
* Done
* @endcode
* @par
* Returns the Multicast Listeners with the #otBackboneRouterMulticastListenerInfo
* `mTimeout` in seconds.
* @par
* Available when `OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` and
* `OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE` are enabled.
* @sa otBackboneRouterMulticastListenerGetNext
*/
if (aArgs[0] == "listener")
{
if (aArgs[1].IsEmpty())
{
otBackboneRouterMulticastListenerIterator iter = OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT;
otBackboneRouterMulticastListenerInfo listenerInfo;
while (otBackboneRouterMulticastListenerGetNext(GetInstancePtr(), &iter, &listenerInfo) == OT_ERROR_NONE)
{
OutputIp6Address(listenerInfo.mAddress);
OutputLine(" %lu", ToUlong(listenerInfo.mTimeout));
}
ExitNow(error = OT_ERROR_NONE);
}
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
/**
* @cli bbr mgmt mlr listener clear
* @code
* bbr mgmt mlr listener clear
* Done
* @endcode
* @par api_copy
* #otBackboneRouterMulticastListenerClear
*/
if (aArgs[1] == "clear")
{
otBackboneRouterMulticastListenerClear(GetInstancePtr());
error = OT_ERROR_NONE;
}
/**
* @cli bbr mgmt mlr listener add
* @code
* bbr mgmt mlr listener add ff04::1
* Done
* @endcode
* @code
* bbr mgmt mlr listener add ff04::2 300
* Done
* @endcode
* @cparam bbr mgmt mlr listener add @ca{ipaddress} [@ca{timeout-seconds}]
* @par api_copy
* #otBackboneRouterMulticastListenerAdd
*/
else if (aArgs[1] == "add")
{
otIp6Address address;
uint32_t timeout = 0;
SuccessOrExit(error = aArgs[2].ParseAsIp6Address(address));
if (!aArgs[3].IsEmpty())
{
SuccessOrExit(error = aArgs[3].ParseAsUint32(timeout));
}
error = otBackboneRouterMulticastListenerAdd(GetInstancePtr(), &address, timeout);
}
}
/**
* @cli bbr mgmt mlr response
* @code
* bbr mgmt mlr response 2
* Done
* @endcode
* @cparam bbr mgmt mlr response @ca{status-code}
* For `status-code`, use:
* * 0: ST_MLR_SUCCESS
* * 2: ST_MLR_INVALID
* * 3: ST_MLR_NO_PERSISTENT
* * 4: ST_MLR_NO_RESOURCES
* * 5: ST_MLR_BBR_NOT_PRIMARY
* * 6: ST_MLR_GENERAL_FAILURE
* @par api_copy
* #otBackboneRouterConfigNextMulticastListenerRegistrationResponse
*/
else if (aArgs[0] == "response")
{
uint8_t status;
SuccessOrExit(error = aArgs[1].ParseAsUint8(status));
otBackboneRouterConfigNextMulticastListenerRegistrationResponse(GetInstancePtr(), status);
error = OT_ERROR_NONE;
#endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
}
exit:
return error;
}
#endif // #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
template <> otError Bbr::Process<Cmd("mgmt")>(Arg aArgs[])
{
otError error = OT_ERROR_INVALID_COMMAND;
if (aArgs[0].IsEmpty())
{
ExitNow(error = OT_ERROR_INVALID_COMMAND);
}
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
/**
* @cli bbr mgmt dua
* @code
* bbr mgmt dua 1 2f7c235e5025a2fd
* Done
* @endcode
* @code
* bbr mgmt dua 160
* Done
* @endcode
* @cparam bbr mgmt dua @ca{status|coap-code} [@ca{meshLocalIid}]
* For `status` or `coap-code`, use:
* * 0: ST_DUA_SUCCESS
* * 1: ST_DUA_REREGISTER
* * 2: ST_DUA_INVALID
* * 3: ST_DUA_DUPLICATE
* * 4: ST_DUA_NO_RESOURCES
* * 5: ST_DUA_BBR_NOT_PRIMARY
* * 6: ST_DUA_GENERAL_FAILURE
* * 160: COAP code 5.00
* @par
* With the `meshLocalIid` included, this command configures the response status
* for the next DUA registration. Without `meshLocalIid`, respond to the next
* DUA.req with the specified `status` or `coap-code`.
* @par
* Available when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
* @sa otBackboneRouterConfigNextDuaRegistrationResponse
*/
if (aArgs[0] == "dua")
{
uint8_t status;
otIp6InterfaceIdentifier *mlIid = nullptr;
otIp6InterfaceIdentifier iid;
SuccessOrExit(error = aArgs[1].ParseAsUint8(status));
if (!aArgs[2].IsEmpty())
{
SuccessOrExit(error = aArgs[2].ParseAsHexString(iid.mFields.m8));
mlIid = &iid;
VerifyOrExit(aArgs[3].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
}
otBackboneRouterConfigNextDuaRegistrationResponse(GetInstancePtr(), mlIid, status);
ExitNow();
}
#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
if (aArgs[0] == "mlr")
{
error = Process<Cmd("mlr")>(aArgs + 1);
ExitNow();
}
#endif
exit:
return error;
}
/**
* @cli bbr enable
* @code
* bbr enable
* Done
* @endcode
* @par api_copy
* #otBackboneRouterSetEnabled
*/
template <> otError Bbr::Process<Cmd("enable")>(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
otBackboneRouterSetEnabled(GetInstancePtr(), true);
return OT_ERROR_NONE;
}
/**
* @cli bbr disable
* @code
* bbr disable
* Done
* @endcode
* @par api_copy
* #otBackboneRouterSetEnabled
*/
template <> otError Bbr::Process<Cmd("disable")>(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
otBackboneRouterSetEnabled(GetInstancePtr(), false);
return OT_ERROR_NONE;
}
/**
* @cli bbr jitter (get,set)
* @code
* bbr jitter
* 20
* Done
* @endcode
* @code
* bbr jitter 10
* Done
* @endcode
* @cparam bbr jitter [@ca{jitter}]
* @par
* Gets or sets jitter (in seconds) for Backbone Router registration.
* @par
* Available when `OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is enabled.
* @sa otBackboneRouterGetRegistrationJitter
* @sa otBackboneRouterSetRegistrationJitter
*/
template <> otError Bbr::Process<Cmd("jitter")>(Arg aArgs[])
{
return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otBackboneRouterGetRegistrationJitter,
otBackboneRouterSetRegistrationJitter);
}
/**
* @cli bbr register
* @code
* bbr register
* Done
* @endcode
* @par api_copy
* #otBackboneRouterRegister
*/
template <> otError Bbr::Process<Cmd("register")>(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
return otBackboneRouterRegister(GetInstancePtr());
}
/**
* @cli bbr state
* @code
* bbr state
* Disabled
* Done
* @endcode
* @code
* bbr state
* Primary
* Done
* @endcode
* @code
* bbr state
* Secondary
* Done
* @endcode
* @par
* Available when `OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE` is enabled.
* @par api_copy
* #otBackboneRouterGetState
*/
template <> otError Bbr::Process<Cmd("state")>(Arg aArgs[])
{
static const char *const kStateStrings[] = {
"Disabled", // (0) OT_BACKBONE_ROUTER_STATE_DISABLED
"Secondary", // (1) OT_BACKBONE_ROUTER_STATE_SECONDARY
"Primary", // (2) OT_BACKBONE_ROUTER_STATE_PRIMARY
};
static_assert(0 == OT_BACKBONE_ROUTER_STATE_DISABLED, "OT_BACKBONE_ROUTER_STATE_DISABLED value is incorrect");
static_assert(1 == OT_BACKBONE_ROUTER_STATE_SECONDARY, "OT_BACKBONE_ROUTER_STATE_SECONDARY value is incorrect");
static_assert(2 == OT_BACKBONE_ROUTER_STATE_PRIMARY, "OT_BACKBONE_ROUTER_STATE_PRIMARY value is incorrect");
OT_UNUSED_VARIABLE(aArgs);
OutputLine("%s", Stringify(otBackboneRouterGetState(GetInstancePtr()), kStateStrings));
return OT_ERROR_NONE;
}
/**
* @cli bbr config
* @code
* bbr config
* seqno: 10
* delay: 120 secs
* timeout: 300 secs
* Done
* @endcode
* @par api_copy
* #otBackboneRouterGetConfig
*/
template <> otError Bbr::Process<Cmd("config")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otBackboneRouterConfig config;
otBackboneRouterGetConfig(GetInstancePtr(), &config);
if (aArgs[0].IsEmpty())
{
OutputConfig(config);
}
else
{
// Set local Backbone Router configuration.
/**
* @cli bbr config (set)
* @code
* bbr config seqno 20 delay 30
* Done
* @endcode
* @cparam bbr config [seqno @ca{seqno}] [delay @ca{delay}] [timeout @ca{timeout}]
* @par
* `bbr register` should be issued explicitly to register Backbone Router service to Leader
* for Secondary Backbone Router.
* @par api_copy
* #otBackboneRouterSetConfig
*/
for (Arg *arg = &aArgs[0]; !arg->IsEmpty(); arg++)
{
if (*arg == "seqno")
{
arg++;
SuccessOrExit(error = arg->ParseAsUint8(config.mSequenceNumber));
}
else if (*arg == "delay")
{
arg++;
SuccessOrExit(error = arg->ParseAsUint16(config.mReregistrationDelay));
}
else if (*arg == "timeout")
{
arg++;
SuccessOrExit(error = arg->ParseAsUint32(config.mMlrTimeout));
}
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}
error = otBackboneRouterSetConfig(GetInstancePtr(), &config);
}
exit:
return error;
}
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
otError Bbr::Process(Arg aArgs[])
{
#define CmdEntry(aCommandString) {aCommandString, &Bbr::Process<Cmd(aCommandString)>}
otError error = OT_ERROR_INVALID_COMMAND;
/**
* @cli bbr
* @code
* bbr
* BBR Primary:
* server16: 0xE400
* seqno: 10
* delay: 120 secs
* timeout: 300 secs
* Done
* @endcode
* @code
* bbr
* BBR Primary: None
* Done
* @endcode
* @par
* Returns the current Primary Backbone Router information for the Thread device.
*/
if (aArgs[0].IsEmpty())
{
otBackboneRouterConfig config;
OutputFormat("BBR Primary:");
if (otBackboneRouterGetPrimary(GetInstancePtr(), &config) == OT_ERROR_NONE)
{
OutputNewLine();
OutputLine("server16: 0x%04X", config.mServer16);
OutputConfig(config);
}
else
{
OutputLine(" None");
}
error = OT_ERROR_NONE;
ExitNow();
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
{
static constexpr Command kCommands[] = {
CmdEntry("config"), CmdEntry("disable"), CmdEntry("enable"), CmdEntry("jitter"),
CmdEntry("mgmt"), CmdEntry("register"), CmdEntry("state"),
};
#undef CmdEntry
static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
const Command *command;
command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
VerifyOrExit(command != nullptr);
error = (this->*command->mHandler)(aArgs + 1);
}
#endif // #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
exit:
return error;
}
} // namespace Cli
} // namespace ot
#endif // #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+98
View File
@@ -0,0 +1,98 @@
/*
* 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 backbone router.
*/
#ifndef CLI_BBR_HPP_
#define CLI_BBR_HPP_
#include "openthread-core-config.h"
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
#include <openthread/backbone_router.h>
#include <openthread/backbone_router_ftd.h>
#include "cli/cli_config.h"
#include "cli/cli_output.hpp"
namespace ot {
namespace Cli {
/**
* Implements the BBR CLI interpreter.
*
*/
class Bbr : private Output
{
public:
typedef Utils::CmdLineParser::Arg Arg;
/**
* Constructor.
*
* @param[in] aInstance The OpenThread Instance.
* @param[in] aOutputImplementer An `OutputImplementer`.
*
*/
Bbr(otInstance *aInstance, OutputImplementer &aOutputImplementer)
: Output(aInstance, aOutputImplementer)
{
}
/**
* Processes a CLI sub-command.
*
* @param[in] aArgs An array of command line arguments.
*
* @retval OT_ERROR_NONE Successfully executed the CLI command.
* @retval OT_ERROR_PENDING The CLI command was successfully started but final result is pending.
* @retval OT_ERROR_INVALID_COMMAND Invalid or unknown CLI command.
* @retval OT_ERROR_INVALID_ARGS Invalid arguments.
* @retval ... Error during execution of the CLI command.
*
*/
otError Process(Arg aArgs[]);
private:
using Command = CommandEntry<Bbr>;
template <CommandId kCommandId> otError Process(Arg aArgs[]);
void OutputConfig(const otBackboneRouterConfig &aConfig);
};
} // namespace Cli
} // namespace ot
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
#endif // CLI_BBR_HPP_