mirror of
https://github.com/espressif/openthread.git
synced 2026-10-05 07:17:39 +00:00
[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:
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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_
|
||||
Reference in New Issue
Block a user