From acd16029a72431c85ed9af4edfef2fa82f63b3ce Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 8 Dec 2023 15:56:13 -0800 Subject: [PATCH] [cli] add `debug` command (#9587) This commit adds cli `debug` command. This command is specifically designed for testing and debugging purposes. It executes a series of CLI commands to gather information about the device and thread network. --- src/cli/README.md | 47 +++++++++ src/cli/cli.cpp | 156 +++++++++++++++++++++++++++-- src/cli/cli.hpp | 1 + tests/scripts/expect/cli-debug.exp | 35 +++++++ 4 files changed, 229 insertions(+), 10 deletions(-) create mode 100644 tests/scripts/expect/cli-debug.exp diff --git a/src/cli/README.md b/src/cli/README.md index 20df53e0de0..262b9f567dc 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -40,6 +40,7 @@ Done - [counters](#counters) - [csl](#csl) - [dataset](README_DATASET.md) +- [debug](#debug) - [delaytimermin](#delaytimermin) - [detach](#detach) - [deviceprops](#deviceprops) @@ -1049,6 +1050,52 @@ Set time sync parameters Done ``` +### debug + +Executes a series of CLI commands to gather information about the device and thread network. This is intended for debugging. + +The output will display each executed CLI command preceded by "\$", followed by the corresponding command's generated output. + +The generated output encompasses the following information: + +- Version +- Current state +- RLOC16, extended MAC address +- Unicast and multicast IPv6 address list +- Channel +- PAN ID and extended PAN ID +- Network Data +- Partition ID +- Leader Data + +If the device is operating as FTD: + +- Child and neighbor table +- Router table and next hop Info +- Address cache table +- Registered MTD child IPv6 address +- Device properties + +If the device supports and acts as an SRP client: + +- SRP client state +- SRP client services and host info + +If the device supports and acts as an SRP sever: + +- SRP server state and address mode +- SRP server registered hosts and services + +If the device supports TREL: + +- TREL status and peer table + +If the device supports and acts as a border router: + +- BR state +- BR prefixes (OMR, on-link, NAT64) +- Discovered prefix table + ### delaytimermin Get the minimal delay timer (in seconds). diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index c1443aec76c..fb6de4cf422 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -101,6 +101,7 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi : OutputImplementer(aCallback, aContext) , Output(aInstance, *this) , mCommandIsPending(false) + , mInternalDebugCommand(false) , mTimer(*aInstance, HandleTimer, this) #if OPENTHREAD_FTD || OPENTHREAD_MTD #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE @@ -166,6 +167,16 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi void Interpreter::OutputResult(otError aError) { + if (mInternalDebugCommand) + { + if (aError != OT_ERROR_NONE) + { + OutputLine("Error %u: %s", aError, otThreadErrorToString(aError)); + } + + ExitNow(); + } + OT_ASSERT(mCommandIsPending); VerifyOrExit(aError != OT_ERROR_PENDING); @@ -314,24 +325,30 @@ void Interpreter::ProcessLine(char *aBuf) OT_ASSERT(aBuf != nullptr); - // Ignore the command if another command is pending. - VerifyOrExit(!mCommandIsPending, args[0].Clear()); - mCommandIsPending = true; + if (!mInternalDebugCommand) + { + // Ignore the command if another command is pending. + VerifyOrExit(!mCommandIsPending, args[0].Clear()); + mCommandIsPending = true; - VerifyOrExit(StringLength(aBuf, kMaxLineLength) <= kMaxLineLength - 1, error = OT_ERROR_PARSE); + VerifyOrExit(StringLength(aBuf, kMaxLineLength) <= kMaxLineLength - 1, error = OT_ERROR_PARSE); + } SuccessOrExit(error = Utils::CmdLineParser::ParseCmd(aBuf, args, kMaxArgs)); VerifyOrExit(!args[0].IsEmpty(), mCommandIsPending = false); - LogInput(args); + if (!mInternalDebugCommand) + { + LogInput(args); #if OPENTHREAD_CONFIG_DIAG_ENABLE - if (otDiagIsEnabled(GetInstancePtr()) && (args[0] != "diag") && (args[0] != "factoryreset")) - { - OutputLine("under diagnostics mode, execute 'diag stop' before running any other commands."); - ExitNow(error = OT_ERROR_INVALID_STATE); - } + if (otDiagIsEnabled(GetInstancePtr()) && (args[0] != "diag") && (args[0] != "factoryreset")) + { + OutputLine("under diagnostics mode, execute 'diag stop' before running any other commands."); + ExitNow(error = OT_ERROR_INVALID_STATE); + } #endif + } error = ProcessCommand(args); @@ -7243,6 +7260,124 @@ template <> otError Interpreter::Process(Arg aArgs[]) return error; } +/** + * @cli debug + * @par + * Executes a series of CLI commands to gather information about the device and thread network. This is intended for + * debugging. + * The output will display each executed CLI command preceded by `$`, followed by the corresponding command's + * generated output. + * The generated output encompasses the following information: + * - Version + * - Current state + * - RLOC16, extended MAC address + * - Unicast and multicast IPv6 address list + * - Channel + * - PAN ID and extended PAN ID + * - Network Data + * - Partition ID + * - Leader Data + * @par + * If the device is operating as FTD: + * - Child and neighbor table + * - Router table and next hop info + * - Address cache table + * - Registered MTD child IPv6 address + * - Device properties + * @par + * If the device supports and acts as an SRP client: + * - SRP client state + * - SRP client services and host info + * @par + * If the device supports and acts as an SRP sever: + * - SRP server state and address mode + * - SRP server registered hosts and services + * @par + * If the device supports TREL: + * - TREL status and peer table + * @par + * If the device supports and acts as a border router: + * - BR state + * - BR prefixes (OMR, on-link, NAT64) + * - Discovered prefix table + */ +template <> otError Interpreter::Process(Arg aArgs[]) +{ + static constexpr uint16_t kMaxDebugCommandSize = 30; + + static const char *const kDebugCommands[] = { + "version", + "state", + "rloc16", + "extaddr", + "ipaddrs", + "ipmaddrs", + "channel", + "panid", + "extpanid", + "netdata show", + "netdata show -x", + "partitionid", + "leaderdata", +#if OPENTHREAD_FTD + "child table", + "childip", + "neighbor table", + "router table", + "nexthop", + "eidcache", +#if OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE + "deviceprops", +#endif +#endif // OPENTHREAD_FTD +#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE + "srp client state", + "srp client host", + "srp client service", + "srp client server", +#endif +#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE + "srp server state", + "srp server addrmode", + "srp server host", + "srp server service", +#endif +#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE + "trel", + "trel peers", +#endif +#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE + "br state", + "br omrprefix", + "br onlinkprefix", + "br prefixtable", +#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE + "br nat64prefix", +#endif +#endif + "bufferinfo", + }; + + char commandString[kMaxDebugCommandSize]; + + OT_UNUSED_VARIABLE(aArgs); + + mInternalDebugCommand = true; + + for (const char *debugCommand : kDebugCommands) + { + strncpy(commandString, debugCommand, sizeof(commandString) - 1); + commandString[sizeof(commandString) - 1] = '\0'; + + OutputLine("$ %s", commandString); + ProcessLine(commandString); + } + + mInternalDebugCommand = false; + + return OT_ERROR_NONE; +} + #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE template <> otError Interpreter::Process(Arg aArgs[]) { return mTcat.Process(aArgs); } #endif @@ -8345,6 +8480,7 @@ otError Interpreter::ProcessCommand(Arg aArgs[]) CmdEntry("csl"), #endif CmdEntry("dataset"), + CmdEntry("debug"), #if OPENTHREAD_FTD CmdEntry("delaytimermin"), #endif diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index f95759e718a..6fb727607b0 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -533,6 +533,7 @@ class Interpreter : public OutputImplementer, public Output UserCommandsEntry mUserCommands[kMaxUserCommandEntries]; bool mCommandIsPending; + bool mInternalDebugCommand; TimerMilliContext mTimer; diff --git a/tests/scripts/expect/cli-debug.exp b/tests/scripts/expect/cli-debug.exp new file mode 100644 index 00000000000..6c5ced74a15 --- /dev/null +++ b/tests/scripts/expect/cli-debug.exp @@ -0,0 +1,35 @@ +#!/usr/bin/expect -f +# +# 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. +# + +source "tests/scripts/expect/_common.exp" + +spawn_node 1 + +send "debug\n" +expect_line "Done"