diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake index b1a124ab1..7853d6679 100644 --- a/etc/cmake/options.cmake +++ b/etc/cmake/options.cmake @@ -159,6 +159,36 @@ if(OT_FULL_LOGS) target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1") endif() +set(OT_VENDOR_NAME "" CACHE STRING "set the vendor name config") +set_property(CACHE OT_VENDOR_NAME PROPERTY STRINGS ${OT_VENDOR_NAME_VALUES}) +string(COMPARE EQUAL "${OT_VENDOR_NAME}" "" is_empty) +if (is_empty) + message(STATUS "OT_VENDOR_NAME=\"\"") +else() + message(STATUS "OT_VENDOR_NAME=\"${OT_VENDOR_NAME}\" --> OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME=\"${OT_VENDOR_NAME}\"") + target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME=\"${OT_VENDOR_NAME}\"") +endif() + +set(OT_VENDOR_MODEL "" CACHE STRING "set the vendor model config") +set_property(CACHE OT_VENDOR_MODEL PROPERTY STRINGS ${OT_VENDOR_MODEL_VALUES}) +string(COMPARE EQUAL "${OT_VENDOR_MODEL}" "" is_empty) +if (is_empty) + message(STATUS "OT_VENDOR_MODEL=\"\"") +else() + message(STATUS "OT_VENDOR_MODEL=\"${OT_VENDOR_MODEL}\" --> OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL=\"${OT_VENDOR_MODEL}\"") + target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL=\"${OT_VENDOR_MODEL}\"") +endif() + +set(OT_VENDOR_SW_VERSION "" CACHE STRING "set the vendor sw version config") +set_property(CACHE OT_VENDOR_SW_VERSION PROPERTY STRINGS ${OT_VENDOR_SW_VERSION_VALUES}) +string(COMPARE EQUAL "${OT_VENDOR_SW_VERSION}" "" is_empty) +if (is_empty) + message(STATUS "OT_VENDOR_SW_VERSION=\"\"") +else() + message(STATUS "OT_VENDOR_SW_VERSION=\"${OT_VENDOR_SW_VERSION}\" --> OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION=\"${OT_VENDOR_SW_VERSION}\"") + target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION=\"${OT_VENDOR_SW_VERSION}\"") +endif() + set(OT_POWER_SUPPLY "" CACHE STRING "set the device power supply config") set(OT_POWER_SUPPLY_VALUES "" diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 9440c7bc7..a5f01c0db 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (315) +#define OPENTHREAD_API_VERSION (316) /** * @addtogroup api-instance diff --git a/include/openthread/netdiag.h b/include/openthread/netdiag.h index ce8ab36ac..76e523bcd 100644 --- a/include/openthread/netdiag.h +++ b/include/openthread/netdiag.h @@ -47,8 +47,6 @@ extern "C" { * * @{ * - * - * Network Dianostics APIs require OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE. */ /** @@ -68,25 +66,34 @@ extern "C" { enum { - OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS = 0, ///< MAC Extended Address TLV - OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS = 1, ///< Address16 TLV - OT_NETWORK_DIAGNOSTIC_TLV_MODE = 2, ///< Mode TLV - OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT = 3, ///< Timeout TLV (the maximum polling time period for SEDs) - OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY = 4, ///< Connectivity TLV - OT_NETWORK_DIAGNOSTIC_TLV_ROUTE = 5, ///< Route64 TLV - OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA = 6, ///< Leader Data TLV - OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA = 7, ///< Network Data TLV - OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST = 8, ///< IPv6 Address List TLV - OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS = 9, ///< MAC Counters TLV - OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL = 14, ///< Battery Level TLV - OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE = 15, ///< Supply Voltage TLV - OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE = 16, ///< Child Table TLV - OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES = 17, ///< Channel Pages TLV - OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST = 18, ///< Type List TLV - OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT = 19, ///< Max Child Timeout TLV - OT_NETWORK_DIAGNOSTIC_TLV_VERSION = 24, ///< Version TLV + OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS = 0, ///< MAC Extended Address TLV + OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS = 1, ///< Address16 TLV + OT_NETWORK_DIAGNOSTIC_TLV_MODE = 2, ///< Mode TLV + OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT = 3, ///< Timeout TLV (the maximum polling time period for SEDs) + OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY = 4, ///< Connectivity TLV + OT_NETWORK_DIAGNOSTIC_TLV_ROUTE = 5, ///< Route64 TLV + OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA = 6, ///< Leader Data TLV + OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA = 7, ///< Network Data TLV + OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST = 8, ///< IPv6 Address List TLV + OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS = 9, ///< MAC Counters TLV + OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL = 14, ///< Battery Level TLV + OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE = 15, ///< Supply Voltage TLV + OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE = 16, ///< Child Table TLV + OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES = 17, ///< Channel Pages TLV + OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST = 18, ///< Type List TLV + OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT = 19, ///< Max Child Timeout TLV + OT_NETWORK_DIAGNOSTIC_TLV_VERSION = 24, ///< Version TLV + OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME = 25, ///< Vendor Name TLV + OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL = 26, ///< Vendor Model TLV + OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION = 27, ///< Vendor SW Version TLV + OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION = 28, ///< Thread Stack Version TLV }; +#define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_NAME_TLV_LENGTH 32 ///< Max length of Vendor Name TLV. +#define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_MODEL_TLV_LENGTH 32 ///< Max length of Vendor Model TLV. +#define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_SW_VERSION_TLV_LENGTH 16 ///< Max length of Vendor SW Version TLV. +#define OT_NETWORK_DIAGNOSTIC_MAX_THREAD_STACK_VERSION_TLV_LENGTH 64 ///< Max length of Thread Stack Version TLV. + typedef uint16_t otNetworkDiagIterator; ///< Used to iterate through Network Diagnostic TLV. /** @@ -249,6 +256,10 @@ typedef struct otNetworkDiagTlv uint16_t mSupplyVoltage; uint32_t mMaxChildTimeout; uint16_t mVersion; + char mVendorName[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_NAME_TLV_LENGTH + 1]; + char mVendorModel[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_MODEL_TLV_LENGTH + 1]; + char mVendorSwVersion[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_SW_VERSION_TLV_LENGTH + 1]; + char mThreadStackVersion[OT_NETWORK_DIAGNOSTIC_MAX_THREAD_STACK_VERSION_TLV_LENGTH + 1]; struct { uint8_t mCount; @@ -276,6 +287,8 @@ typedef struct otNetworkDiagTlv /** * This function gets the next Network Diagnostic TLV in the message. * + * Requires `OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE`. + * * @param[in] aMessage A pointer to a message. * @param[in,out] aIterator A pointer to the Network Diagnostic iterator context. To get the first * Network Diagnostic TLV it should be set to OT_NETWORK_DIAGNOSTIC_ITERATOR_INIT. @@ -311,6 +324,8 @@ typedef void (*otReceiveDiagnosticGetCallback)(otError aError, /** * Send a Network Diagnostic Get request. * + * Requires `OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE`. + * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aDestination A pointer to destination address. * @param[in] aTlvTypes An array of Network Diagnostic TLV types. @@ -333,6 +348,8 @@ otError otThreadSendDiagnosticGet(otInstance *aInstance, /** * Send a Network Diagnostic Reset request. * + * Requires `OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE`. + * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aDestination A pointer to destination address. * @param[in] aTlvTypes An array of Network Diagnostic TLV types. Currently only Type 9 is allowed. @@ -347,6 +364,87 @@ otError otThreadSendDiagnosticReset(otInstance *aInstance, const uint8_t aTlvTypes[], uint8_t aCount); +/** + * Get the vendor name string. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns The vendor name string. + * + */ +const char *otThreadGetVendorName(otInstance *aInstance); + +/** + * Get the vendor model string. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns The vendor model string. + * + */ +const char *otThreadGetVendorModel(otInstance *aInstance); + +/** + * Get the vendor sw version string. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns The vendor sw version string. + * + */ +const char *otThreadGetVendorSwVersion(otInstance *aInstance); + +/** + * Set the vendor name string. + * + * Requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`. + * + * @p aVendorName should be UTF8 with max length of 32 chars (`MAX_VENDOR_NAME_TLV_LENGTH`). Maximum length does not + * include the null `\0` character. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aVendorName The vendor name string. + * + * @retval OT_ERROR_NONE Successfully set the vendor name. + * @retval OT_ERROR_INVALID_ARGS @p aVendorName is not valid (too long or not UTF8). + * + */ +otError otThreadSetVendorName(otInstance *aInstance, const char *aVendorName); + +/** + * Set the vendor model string. + * + * Requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`. + * + * @p aVendorModel should be UTF8 with max length of 32 chars (`MAX_VENDOR_MODEL_TLV_LENGTH`). Maximum length does not + * include the null `\0` character. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aVendorModel The vendor model string. + * + * @retval OT_ERROR_NONE Successfully set the vendor model. + * @retval OT_ERROR_INVALID_ARGS @p aVendorModel is not valid (too long or not UTF8). + * + */ +otError otThreadSetVendorModel(otInstance *aInstance, const char *aVendorModel); + +/** + * Set the vendor software version string. + * + * Requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`. + * + * @p aVendorSwVersion should be UTF8 with max length of 16 chars(`MAX_VENDOR_SW_VERSION_TLV_LENGTH`). Maximum length + * does not include the null `\0` character. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aVendorSwVersion The vendor software version string. + * + * @retval OT_ERROR_NONE Successfully set the vendor software version. + * @retval OT_ERROR_INVALID_ARGS @p aVendorSwVersion is not valid (too long or not UTF8). + * + */ +otError otThreadSetVendorSwVersion(otInstance *aInstance, const char *aVendorSwVersion); + /** * @} * diff --git a/script/check-scan-build b/script/check-scan-build index edd86d7ca..ef723faad 100755 --- a/script/check-scan-build +++ b/script/check-scan-build @@ -75,6 +75,9 @@ OT_BUILD_OPTIONS=( "-DOT_SNTP_CLIENT=ON" "-DOT_SRP_CLIENT=ON" "-DOT_SRP_SERVER=ON" + "-DOT_VENDOR_NAME=OpenThread" + "-DOT_VENDOR_MODEL=Scan-build" + "-DOT_VENDOR_SW_VERSION=OT" ) readonly OT_BUILD_OPTIONS diff --git a/src/cli/README.md b/src/cli/README.md index f6006955f..a1326d4d2 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -121,6 +121,7 @@ Done - [udp](README_UDP.md) - [unsecureport](#unsecureport-add-port) - [uptime](#uptime) +- [vendor](#vendor-name) - [version](#version) ## OpenThread Command Details @@ -3360,6 +3361,63 @@ Done > ``` +### vendor name + +This command requires `OPENTHREAD_FTD` or `OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE`. + +Get the vendor name. + +```bash +> vendor name +nest +Done +``` + +Set the vendor name (requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`). + +```bash +> vendor name nest +Done +``` + +### vendor model + +This command requires `OPENTHREAD_FTD` or `OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE`. + +Get the vendor model. + +```bash +> vendor model +Hub Max +Done +``` + +Set the vendor model (requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`). + +```bash +> vendor model Hub\ Max +Done +``` + +### vendor swversion + +This command requires `OPENTHREAD_FTD` or `OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE`. + +Get the vendor SW version. + +```bash +> vendor swversion +Marble3.5.1 +Done +``` + +Set the vendor SW version (requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`). + +```bash +> vendor swversion Marble3.5.1 +Done +``` + ### version Print the build version information. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 4ab4b36a4..1143d7921 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -1255,24 +1255,18 @@ exit: } #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE +/** + * @cli domainname + * @code + * domainname + * Thread + * Done + * @endcode + * @par api_copy + * #otThreadGetDomainName + */ template <> otError Interpreter::Process(Arg aArgs[]) { - otError error = OT_ERROR_NONE; - - /** - * @cli domainname - * @code - * domainname - * Thread - * Done - * @endcode - * @par api_copy - * #otThreadGetDomainName - */ - if (aArgs[0].IsEmpty()) - { - OutputLine("%s", otThreadGetDomainName(GetInstancePtr())); - } /** * @cli domainname (set) * @code @@ -1284,13 +1278,7 @@ template <> otError Interpreter::Process(Arg aArgs[]) * @par api_copy * #otThreadSetDomainName */ - else - { - SuccessOrExit(error = otThreadSetDomainName(GetInstancePtr(), aArgs[0].GetCString())); - } - -exit: - return error; + return ProcessGetSet(aArgs, otThreadGetDomainName, otThreadSetDomainName); } #if OPENTHREAD_CONFIG_DUA_ENABLE @@ -5521,24 +5509,18 @@ exit: } #endif +/** + * @cli networkname + * @code + * networkname + * OpenThread + * Done + * @endcode + * @par api_copy + * #otThreadGetNetworkName + */ template <> otError Interpreter::Process(Arg aArgs[]) { - otError error = OT_ERROR_NONE; - - /** - * @cli networkname - * @code - * networkname - * OpenThread - * Done - * @endcode - * @par api_copy - * #otThreadGetNetworkName - */ - if (aArgs[0].IsEmpty()) - { - OutputLine("%s", otThreadGetNetworkName(GetInstancePtr())); - } /** * @cli networkname (name) * @code @@ -5551,13 +5533,7 @@ template <> otError Interpreter::Process(Arg aArgs[]) * @par * Note: The current commissioning credential becomes stale after changing this value. Use `pskc` to reset. */ - else - { - SuccessOrExit(error = otThreadSetNetworkName(GetInstancePtr(), aArgs[0].GetCString())); - } - -exit: - return error; + return ProcessGetSet(aArgs, otThreadGetNetworkName, otThreadSetNetworkName); } #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE @@ -7965,7 +7941,106 @@ exit: } #endif +template <> otError Interpreter::Process(Arg aArgs[]) +{ + Error error = OT_ERROR_INVALID_ARGS; + + /** + * @cli vendor name + * @code + * vendor name + * nest + * Done + * @endcode + * @par api_copy + * #otThreadGetVendorName + */ + if (aArgs[0] == "name") + { + aArgs++; + +#if !OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + error = ProcessGet(aArgs, otThreadGetVendorName); +#else + /** + * @cli vendor name (name) + * @code + * vendor name nest + * Done + * @endcode + * @par api_copy + * #otThreadSetVendorName + * @cparam vendor name @ca{name} + */ + error = ProcessGetSet(aArgs, otThreadGetVendorName, otThreadSetVendorName); +#endif + } + /** + * @cli vendor model + * @code + * vendor model + * Hub Max + * Done + * @endcode + * @par api_copy + * #otThreadGetVendorModel + */ + else if (aArgs[0] == "model") + { + aArgs++; + +#if !OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + error = ProcessGet(aArgs, otThreadGetVendorModel); +#else + /** + * @cli vendor model (name) + * @code + * vendor model Hub\ Max + * Done + * @endcode + * @par api_copy + * #otThreadSetVendorModel + * @cparam vendor model @ca{name} + */ + error = ProcessGetSet(aArgs, otThreadGetVendorModel, otThreadSetVendorModel); +#endif + } + /** + * @cli vendor swversion + * @code + * vendor swversion + * Marble3.5.1 + * Done + * @endcode + * @par api_copy + * #otThreadGetVendorSwVersion + */ + else if (aArgs[0] == "swversion") + { + aArgs++; + +#if !OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + error = ProcessGet(aArgs, otThreadGetVendorSwVersion); +#else + /** + * @cli vendor swversion (version) + * @code + * vendor swversion Marble3.5.1 + * Done + * @endcode + * @par api_copy + * #otThreadSetVendorSwVersion + * @cparam vendor swversion @ca{version} + */ + error = ProcessGetSet(aArgs, otThreadGetVendorSwVersion, otThreadSetVendorSwVersion); +#endif + } + + return error; +} + #if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE + template <> otError Interpreter::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -8111,6 +8186,20 @@ void Interpreter::HandleDiagnosticGetResponse(otError aError, case OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT: OutputLine("Max Child Timeout: %lu", ToUlong(diagTlv.mData.mMaxChildTimeout)); break; + case OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME: + OutputLine("Vendor Name: %s", diagTlv.mData.mVendorName); + break; + case OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL: + OutputLine("Vendor Model: %s", diagTlv.mData.mVendorModel); + break; + case OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION: + OutputLine("Vendor SW Version: %s", diagTlv.mData.mVendorSwVersion); + break; + case OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION: + OutputLine("Thread Stack Version: %s", diagTlv.mData.mThreadStackVersion); + break; + default: + break; } } @@ -8503,6 +8592,9 @@ otError Interpreter::ProcessCommand(Arg aArgs[]) #if OPENTHREAD_CONFIG_UPTIME_ENABLE CmdEntry("uptime"), #endif +#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE + CmdEntry("vendor"), +#endif #endif // OPENTHREAD_FTD || OPENTHREAD_MTD CmdEntry("version"), }; diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 6f880ad3f..6c6cbbd8a 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -295,8 +295,9 @@ private: { static_assert( TypeTraits::IsSame::kValue || TypeTraits::IsSame::kValue || - TypeTraits::IsSame::kValue || TypeTraits::IsSame::kValue, - "ValueType must be an 8, 16 `int` or `uint` type"); + TypeTraits::IsSame::kValue || TypeTraits::IsSame::kValue || + TypeTraits::IsSame::kValue, + "ValueType must be an 8, 16 `int` or `uint` type, or a `const char *`"); otError error = OT_ERROR_NONE; @@ -619,6 +620,8 @@ template <> inline constexpr const char *Interpreter::FormatStringFor(v template <> inline constexpr const char *Interpreter::FormatStringFor(void) { return "%ld"; } +template <> inline constexpr const char *Interpreter::FormatStringFor(void) { return "%s"; } + // Specialization of ProcessGet<> for `uint32_t` and `int32_t` template <> inline otError Interpreter::ProcessGet(Arg aArgs[], GetHandler aGetHandler) diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 5212041b4..d7f9f63a5 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -795,6 +795,7 @@ source_set("libopenthread_core_config") { "config/mle.h", "config/nat64.h", "config/netdata_publisher.h", + "config/network_diagnostic.h", "config/openthread-core-config-check.h", "config/parent_search.h", "config/ping_sender.h", diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 169902e73..92c2bf634 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -520,6 +520,7 @@ HEADERS_COMMON = \ config/mle.h \ config/nat64.h \ config/netdata_publisher.h \ + config/network_diagnostic.h \ config/openthread-core-config-check.h \ config/parent_search.h \ config/ping_sender.h \ diff --git a/src/core/api/netdiag_api.cpp b/src/core/api/netdiag_api.cpp index 68cf91c62..ffcc4c121 100644 --- a/src/core/api/netdiag_api.cpp +++ b/src/core/api/netdiag_api.cpp @@ -33,8 +33,6 @@ #include "openthread-core-config.h" -#if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE - #include #include "common/as_core_type.hpp" @@ -42,6 +40,8 @@ using namespace ot; +#if OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE + otError otThreadGetNextDiagnosticTlv(const otMessage *aMessage, otNetworkDiagIterator *aIterator, otNetworkDiagTlv *aNetworkDiagTlv) @@ -73,3 +73,35 @@ otError otThreadSendDiagnosticReset(otInstance *aInstance, } #endif // OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE + +const char *otThreadGetVendorName(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().GetVendorName(); +} + +const char *otThreadGetVendorModel(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().GetVendorModel(); +} + +const char *otThreadGetVendorSwVersion(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().GetVendorSwVersion(); +} + +#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE +otError otThreadSetVendorName(otInstance *aInstance, const char *aVendorName) +{ + return AsCoreType(aInstance).Get().SetVendorName(aVendorName); +} + +otError otThreadSetVendorModel(otInstance *aInstance, const char *aVendorModel) +{ + return AsCoreType(aInstance).Get().SetVendorModel(aVendorModel); +} + +otError otThreadSetVendorSwVersion(otInstance *aInstance, const char *aVendorSwVersion) +{ + return AsCoreType(aInstance).Get().SetVendorSwVersion(aVendorSwVersion); +} +#endif diff --git a/src/core/config/network_diagnostic.h b/src/core/config/network_diagnostic.h new file mode 100644 index 000000000..2aaf26018 --- /dev/null +++ b/src/core/config/network_diagnostic.h @@ -0,0 +1,85 @@ +/* + * 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 includes compile-time configurations for the Network Diagnostics. + * + */ + +#ifndef CONFIG_NETWORK_DIAGNOSTIC_H_ +#define CONFIG_NETWORK_DIAGNOSTIC_H_ + +/** + * @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME + * + * Specifies the default Vendor Name string. + * + */ +#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME +#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME "" +#endif + +/** + * @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL + * + * Specifies the default Vendor Model string. + * + */ +#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL +#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL "" +#endif + +/** + * @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION + * + * Specifies the default Vendor SW Version string. + * + */ +#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION +#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION "" +#endif + +/** + * @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + * + * Define as 1 to add APIs to allow Vendor Name, Model, SW Version to change at run-time. + * + * It is recommended that Vendor Name, Model, and SW Version are set at build time using the OpenThread configurations + * `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_*`. This way they are treated as constants and won't consume RAM. + * + * However, for situations where the OpenThread stack is integrated as a library into different projects/products, this + * config can be used to add API to change Vendor Name, Model, and SW Version at run-time. In this case, the strings in + * `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_*` are treated as the default values (used when OT stack is initialized). + * + */ +#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE +#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE 0 +#endif + +#endif // CONFIG_NETWORK_DIAGNOSTIC_H_ diff --git a/src/core/openthread-core-config.h b/src/core/openthread-core-config.h index b0362433f..2b4127dcc 100644 --- a/src/core/openthread-core-config.h +++ b/src/core/openthread-core-config.h @@ -88,6 +88,7 @@ #include "config/mle.h" #include "config/nat64.h" #include "config/netdata_publisher.h" +#include "config/network_diagnostic.h" #include "config/parent_search.h" #include "config/ping_sender.h" #include "config/platform.h" diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp index 14703c6df..dfa8570e7 100644 --- a/src/core/thread/network_diagnostic.cpp +++ b/src/core/thread/network_diagnostic.cpp @@ -56,14 +56,65 @@ RegisterLogModule("NetDiag"); namespace NetworkDiagnostic { +const char Server::kVendorName[] = OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME; +const char Server::kVendorModel[] = OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL; +const char Server::kVendorSwVersion[] = OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION; + //--------------------------------------------------------------------------------------------------------------------- // Server Server::Server(Instance &aInstance) : InstanceLocator(aInstance) { + static_assert(sizeof(kVendorName) <= sizeof(VendorNameTlv::StringType), "VENDOR_NAME is too long"); + static_assert(sizeof(kVendorModel) <= sizeof(VendorModelTlv::StringType), "VENDOR_MODEL is too long"); + static_assert(sizeof(kVendorSwVersion) <= sizeof(VendorSwVersionTlv::StringType), "VENDOR_SW_VERSION is too long"); + +#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + memcpy(mVendorName, kVendorName, sizeof(kVendorName)); + memcpy(mVendorModel, kVendorModel, sizeof(kVendorModel)); + memcpy(mVendorSwVersion, kVendorSwVersion, sizeof(kVendorSwVersion)); +#endif } +#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + +Error Server::SetVendorName(const char *aVendorName) +{ + return SetVendorString(mVendorName, sizeof(mVendorName), aVendorName); +} + +Error Server::SetVendorModel(const char *aVendorModel) +{ + return SetVendorString(mVendorModel, sizeof(mVendorModel), aVendorModel); +} + +Error Server::SetVendorSwVersion(const char *aVendorSwVersion) +{ + return SetVendorString(mVendorSwVersion, sizeof(mVendorSwVersion), aVendorSwVersion); +} + +Error Server::SetVendorString(char *aDestString, uint16_t kMaxSize, const char *aSrcString) +{ + Error error = kErrorInvalidArgs; + uint16_t length; + + VerifyOrExit(aSrcString != nullptr); + + length = StringLength(aSrcString, kMaxSize); + VerifyOrExit(length < kMaxSize); + + VerifyOrExit(IsValidUtf8String(aSrcString)); + + memcpy(aDestString, aSrcString, length + 1); + error = kErrorNone; + +exit: + return error; +} + +#endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + void Server::PrepareMessageInfoForDest(const Ip6::Address &aDestination, Tmf::MessageInfo &aMessageInfo) const { if (aDestination.IsMulticast()) @@ -267,6 +318,22 @@ Error Server::AppendDiagTlv(uint8_t aTlvType, Message &aMessage) error = AppendMacCounters(aMessage); break; + case Tlv::kVendorName: + error = Tlv::Append(aMessage, GetVendorName()); + break; + + case Tlv::kVendorModel: + error = Tlv::Append(aMessage, GetVendorModel()); + break; + + case Tlv::kVendorSwVersion: + error = Tlv::Append(aMessage, GetVendorSwVersion()); + break; + + case Tlv::kThreadStackVersion: + error = Tlv::Append(aMessage, otGetVersionString()); + break; + case Tlv::kChannelPages: { ChannelPagesTlv tlv; @@ -761,6 +828,23 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, SuccessOrExit(error = Tlv::Read(aMessage, offset, aTlvInfo.mData.mVersion)); break; + case Tlv::kVendorName: + SuccessOrExit(error = Tlv::Read(aMessage, offset, aTlvInfo.mData.mVendorName)); + break; + + case Tlv::kVendorModel: + SuccessOrExit(error = Tlv::Read(aMessage, offset, aTlvInfo.mData.mVendorModel)); + break; + + case Tlv::kVendorSwVersion: + SuccessOrExit(error = Tlv::Read(aMessage, offset, aTlvInfo.mData.mVendorSwVersion)); + break; + + case Tlv::kThreadStackVersion: + SuccessOrExit(error = + Tlv::Read(aMessage, offset, aTlvInfo.mData.mThreadStackVersion)); + break; + default: // Skip unrecognized TLVs. skipTlv = true; diff --git a/src/core/thread/network_diagnostic.hpp b/src/core/thread/network_diagnostic.hpp index 2521418e4..4026aa32c 100644 --- a/src/core/thread/network_diagnostic.hpp +++ b/src/core/thread/network_diagnostic.hpp @@ -79,9 +79,77 @@ public: */ explicit Server(Instance &aInstance); +#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + /** + * This method returns the vendor name string. + * + * @returns The vendor name string. + * + */ + const char *GetVendorName(void) const { return mVendorName; } + + /** + * This method sets the vendor name string. + * + * @param[in] aVendorName The vendor name string. + * + * @retval kErrorNone Successfully set the vendor name. + * @retval kErrorInvalidArgs @p aVendorName is not valid (too long or not UTF8). + * + */ + Error SetVendorName(const char *aVendorName); + + /** + * This method returns the vendor model string. + * + * @returns The vendor model string. + * + */ + const char *GetVendorModel(void) const { return mVendorModel; } + + /** + * This method sets the vendor model string. + * + * @param[in] aVendorModel The vendor model string. + * + * @retval kErrorNone Successfully set the vendor model. + * @retval kErrorInvalidArgs @p aVendorModel is not valid (too long or not UTF8). + * + */ + Error SetVendorModel(const char *aVendorModel); + + /** + * This method returns the vendor software version string. + * + * @returns The vendor software version string. + * + */ + const char *GetVendorSwVersion(void) const { return mVendorSwVersion; } + + /** + * This method sets the vendor sw version string + * + * @param[in] aVendorSwVersion The vendor sw version string. + * + * @retval kErrorNone Successfully set the vendor sw version. + * @retval kErrorInvalidArgs @p aVendorSwVersion is not valid (too long or not UTF8). + * + */ + Error SetVendorSwVersion(const char *aVendorSwVersion); + +#else + const char *GetVendorName(void) const { return kVendorName; } + const char *GetVendorModel(void) const { return kVendorModel; } + const char *GetVendorSwVersion(void) const { return kVendorSwVersion; } +#endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + private: static constexpr uint16_t kMaxChildEntries = 398; + static const char kVendorName[]; + static const char kVendorModel[]; + static const char kVendorSwVersion[]; + Error AppendDiagTlv(uint8_t aTlvType, Message &aMessage); Error AppendIp6AddressList(Message &aMessage); Error AppendMacCounters(Message &aMessage); @@ -90,6 +158,14 @@ private: void PrepareMessageInfoForDest(const Ip6::Address &aDestination, Tmf::MessageInfo &aMessageInfo) const; template void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + +#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + Error SetVendorString(char *aDestString, uint16_t kMaxSize, const char *aSrcString); + + VendorNameTlv::StringType mVendorName; + VendorModelTlv::StringType mVendorModel; + VendorSwVersionTlv::StringType mVendorSwVersion; +#endif }; DeclareTmfHandler(Server, kUriDiagnosticGetRequest); @@ -164,8 +240,6 @@ public: static Error GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, TlvInfo &aTlvInfo); private: - static constexpr uint16_t kMaxChildEntries = 398; - Error SendCommand(Uri aUri, const Ip6::Address &aDestination, const uint8_t aTlvTypes[], diff --git a/src/core/thread/network_diagnostic_tlvs.hpp b/src/core/thread/network_diagnostic_tlvs.hpp index 6d1fd6051..c46298cff 100644 --- a/src/core/thread/network_diagnostic_tlvs.hpp +++ b/src/core/thread/network_diagnostic_tlvs.hpp @@ -69,25 +69,53 @@ public: */ enum Type : uint8_t { - kExtMacAddress = OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS, - kAddress16 = OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS, - kMode = OT_NETWORK_DIAGNOSTIC_TLV_MODE, - kTimeout = OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT, - kConnectivity = OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY, - kRoute = OT_NETWORK_DIAGNOSTIC_TLV_ROUTE, - kLeaderData = OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA, - kNetworkData = OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA, - kIp6AddressList = OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST, - kMacCounters = OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS, - kBatteryLevel = OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL, - kSupplyVoltage = OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE, - kChildTable = OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE, - kChannelPages = OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES, - kTypeList = OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST, - kMaxChildTimeout = OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT, - kVersion = OT_NETWORK_DIAGNOSTIC_TLV_VERSION, + kExtMacAddress = OT_NETWORK_DIAGNOSTIC_TLV_EXT_ADDRESS, + kAddress16 = OT_NETWORK_DIAGNOSTIC_TLV_SHORT_ADDRESS, + kMode = OT_NETWORK_DIAGNOSTIC_TLV_MODE, + kTimeout = OT_NETWORK_DIAGNOSTIC_TLV_TIMEOUT, + kConnectivity = OT_NETWORK_DIAGNOSTIC_TLV_CONNECTIVITY, + kRoute = OT_NETWORK_DIAGNOSTIC_TLV_ROUTE, + kLeaderData = OT_NETWORK_DIAGNOSTIC_TLV_LEADER_DATA, + kNetworkData = OT_NETWORK_DIAGNOSTIC_TLV_NETWORK_DATA, + kIp6AddressList = OT_NETWORK_DIAGNOSTIC_TLV_IP6_ADDR_LIST, + kMacCounters = OT_NETWORK_DIAGNOSTIC_TLV_MAC_COUNTERS, + kBatteryLevel = OT_NETWORK_DIAGNOSTIC_TLV_BATTERY_LEVEL, + kSupplyVoltage = OT_NETWORK_DIAGNOSTIC_TLV_SUPPLY_VOLTAGE, + kChildTable = OT_NETWORK_DIAGNOSTIC_TLV_CHILD_TABLE, + kChannelPages = OT_NETWORK_DIAGNOSTIC_TLV_CHANNEL_PAGES, + kTypeList = OT_NETWORK_DIAGNOSTIC_TLV_TYPE_LIST, + kMaxChildTimeout = OT_NETWORK_DIAGNOSTIC_TLV_MAX_CHILD_TIMEOUT, + kVersion = OT_NETWORK_DIAGNOSTIC_TLV_VERSION, + kVendorName = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_NAME, + kVendorModel = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_MODEL, + kVendorSwVersion = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION, + kThreadStackVersion = OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION, }; + /** + * Maximum length of Vendor Name TLV. + * + */ + static constexpr uint8_t kMaxVendorNameLength = OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_NAME_TLV_LENGTH; + + /** + * Maximum length of Vendor Model TLV. + * + */ + static constexpr uint8_t kMaxVendorModelLength = OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_MODEL_TLV_LENGTH; + + /** + * Maximum length of Vendor SW Version TLV. + * + */ + static constexpr uint8_t kMaxVendorSwVersionLength = OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_SW_VERSION_TLV_LENGTH; + + /** + * Maximum length of Vendor SW Version TLV. + * + */ + static constexpr uint8_t kMaxThreadStackVersionLength = OT_NETWORK_DIAGNOSTIC_MAX_THREAD_STACK_VERSION_TLV_LENGTH; + /** * This method returns the Type value. * @@ -172,6 +200,30 @@ typedef UintTlvInfo MaxChildTimeoutTlv; */ typedef UintTlvInfo VersionTlv; +/** + * This class defines Vendor Name TLV constants and types. + * + */ +typedef StringTlvInfo VendorNameTlv; + +/** + * This class defines Vendor Model TLV constants and types. + * + */ +typedef StringTlvInfo VendorModelTlv; + +/** + * This class defines Vendor SW Version TLV constants and types. + * + */ +typedef StringTlvInfo VendorSwVersionTlv; + +/** + * This class defines Thread Stack Version TLV constants and types. + * + */ +typedef StringTlvInfo ThreadStackVersionTlv; + typedef otNetworkDiagConnectivity Connectivity; ///< Network Diagnostic Connectivity value. /** diff --git a/src/core/utils/parse_cmdline.hpp b/src/core/utils/parse_cmdline.hpp index e36506556..777a50aae 100644 --- a/src/core/utils/parse_cmdline.hpp +++ b/src/core/utils/parse_cmdline.hpp @@ -673,6 +673,11 @@ template <> inline otError Arg::ParseAs(int16_t &aValue) const { return ParseAsI template <> inline otError Arg::ParseAs(int32_t &aValue) const { return ParseAsInt32(aValue); } +template <> inline otError Arg::ParseAs(const char *&aValue) const +{ + return IsEmpty() ? OT_ERROR_INVALID_ARGS : (aValue = GetCString(), OT_ERROR_NONE); +} + #if OPENTHREAD_FTD || OPENTHREAD_MTD template <> inline otError Arg::ParseAs(otIp6Address &aValue) const { return ParseAsIp6Address(aValue); } diff --git a/tests/toranj/cli/cli.py b/tests/toranj/cli/cli.py index b8a8b02c4..fd24205b8 100644 --- a/tests/toranj/cli/cli.py +++ b/tests/toranj/cli/cli.py @@ -214,6 +214,9 @@ class Node(object): def get_state(self): return self._cli_single_output('state', expected_outputs=['detached', 'child', 'router', 'leader', 'disabled']) + def get_version(self): + return self._cli_single_output('version') + def get_channel(self): return self._cli_single_output('channel') @@ -357,6 +360,24 @@ class Node(object): def get_eidcache(self): return self.cli('eidcache') + def get_vendor_name(self): + return self._cli_single_output('vendor name') + + def set_vendor_name(self, name): + self._cli_no_output('vendor name', name) + + def get_vendor_model(self): + return self._cli_single_output('vendor model') + + def set_vendor_model(self, model): + self._cli_no_output('vendor model', model) + + def get_vendor_sw_version(self): + return self._cli_single_output('vendor swversion') + + def set_vendor_sw_version(self, version): + return self._cli_no_output('vendor swversion', version) + #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # netdata diff --git a/tests/toranj/cli/test-020-net-diag-vendor-info.py b/tests/toranj/cli/test-020-net-diag-vendor-info.py new file mode 100755 index 000000000..6f205cd25 --- /dev/null +++ b/tests/toranj/cli/test-020-net-diag-vendor-info.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 +# +# 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. + +from cli import verify +from cli import verify_within +import cli +import time + +# ----------------------------------------------------------------------------------------------------------------------- +# Test description: Network Diagnostics Vendor Name, Vendor Model, Vendor SW Version TLVs. +# +# Network topology +# +# r1 ---- r2 +# + +test_name = __file__[:-3] if __file__.endswith('.py') else __file__ +print('-' * 120) +print('Starting \'{}\''.format(test_name)) + +# ----------------------------------------------------------------------------------------------------------------------- +# Creating `cli.Node` instances + +speedup = 40 +cli.Node.set_time_speedup_factor(speedup) + +r1 = cli.Node() +r2 = cli.Node() + +# ----------------------------------------------------------------------------------------------------------------------- +# Form topology + +r1.form('netdiag-vendor') +r2.join(r1) + +verify(r1.get_state() == 'leader') +verify(r2.get_state() == 'router') + +# ----------------------------------------------------------------------------------------------------------------------- +# Test Implementation + +VENDOR_NAME_TLV = 25 +VENDOR_MODEL_TLV = 26 +VENDOR_SW_VERSION_TLV = 27 +THREAD_STACK_VERSION_TLV = 28 + +#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# Check setting vendor name, model, ans sw version + +r1.set_vendor_name('nest') +r1.set_vendor_model('marble') +r1.set_vendor_sw_version('ot-1.3.1') + +verify(r1.get_vendor_name() == 'nest') +verify(r1.get_vendor_model() == 'marble') +verify(r1.get_vendor_sw_version() == 'ot-1.3.1') + +#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# Check invalid names (too long) + +# Vendor name should accept up to 32 chars + +r2.set_vendor_name('01234567890123456789012345678901') # 32 chars + +errored = False + +try: + r2.set_vendor_name('012345678901234567890123456789012') # 33 chars +except cli.CliError as e: + verify(e.message == 'InvalidArgs') + errored = True + +verify(errored) + +# Vendor model should accept up to 32 chars + +r2.set_vendor_model('01234567890123456789012345678901') # 32 chars + +errored = False + +try: + r2.set_vendor_model('012345678901234567890123456789012') # 33 chars +except cli.CliError as e: + verify(e.message == 'InvalidArgs') + errored = True + +verify(errored) + +# Vendor SW version should accept up to 16 chars + +r2.set_vendor_sw_version('0123456789012345') # 16 chars + +errored = False + +try: + r2.set_vendor_sw_version('01234567890123456') # 17 chars +except cli.CliError as e: + verify(e.message == 'InvalidArgs') + errored = True + +verify(errored) + +#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# Perform net diag query + +r1_rloc = r1.get_rloc_ip_addr() +r2_rloc = r2.get_rloc_ip_addr() + +# Get vendor name (TLV 27) + +result = r2.cli('networkdiagnostic get', r1_rloc, VENDOR_NAME_TLV) +verify(len(result) == 2) +verify(result[1].startswith("Vendor Name:")) +verify(result[1].split(':')[1].strip() == r1.get_vendor_name()) + +# Get vendor model (TLV 28) + +result = r2.cli('networkdiagnostic get', r1_rloc, VENDOR_MODEL_TLV) +verify(len(result) == 2) +verify(result[1].startswith("Vendor Model:")) +verify(result[1].split(':')[1].strip() == r1.get_vendor_model()) + +# Get vendor sw version (TLV 29) + +result = r2.cli('networkdiagnostic get', r1_rloc, VENDOR_SW_VERSION_TLV) +verify(len(result) == 2) +verify(result[1].startswith("Vendor SW Version:")) +verify(result[1].split(':')[1].strip() == r1.get_vendor_sw_version()) + +# Get thread stack version (TLV 30) + +result = r2.cli('networkdiagnostic get', r1_rloc, THREAD_STACK_VERSION_TLV) +verify(len(result) == 2) +verify(result[1].startswith("Thread Stack Version:")) +verify(r1.get_version().startswith(result[1].split(':', 1)[1].strip())) + +# Get all three TLVs (now from `r1`) + +result = r1.cli('networkdiagnostic get', r2_rloc, VENDOR_NAME_TLV, VENDOR_MODEL_TLV, VENDOR_SW_VERSION_TLV, + THREAD_STACK_VERSION_TLV) +verify(len(result) == 5) +for line in result[1:]: + if line.startswith("Vendor Name:"): + verify(line.split(':')[1].strip() == r2.get_vendor_name()) + elif line.startswith("Vendor Model:"): + verify(line.split(':')[1].strip() == r2.get_vendor_model()) + elif line.startswith("Vendor SW Version:"): + verify(line.split(':')[1].strip() == r2.get_vendor_sw_version()) + elif line.startswith("Thread Stack Version:"): + verify(r2.get_version().startswith(line.split(':', 1)[1].strip())) + else: + verify(False) + +# ----------------------------------------------------------------------------------------------------------------------- +# Test finished + +cli.Node.finalize_all_nodes() + +print('\'{}\' passed.'.format(test_name)) diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h index 20d351210..1812c81a4 100644 --- a/tests/toranj/openthread-core-toranj-config.h +++ b/tests/toranj/openthread-core-toranj-config.h @@ -566,6 +566,43 @@ */ #define OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE 1 +/** + * @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME + * + * Specifies the default Vendor Name string. + * + */ +#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME +#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME "OpenThread by Google Nest" +#endif + +/** + * @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL + * + * Specifies the default Vendor Model string. + * + */ +#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL +#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL "Toranj Simulation" +#endif + +/** + * @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION + * + * Specifies the default Vendor SW Version string. + * + */ +#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION +#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION "OT-simul-toranj" +#endif + +/** + * @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE + * + * Define as 1 to add APIs to allow Vendor Name, Model, SW Version to change at run-time. + */ +#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE OPENTHREAD_FTD + #if OPENTHREAD_RADIO /** * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE diff --git a/tests/toranj/start.sh b/tests/toranj/start.sh index d2f019786..2bc8fa996 100755 --- a/tests/toranj/start.sh +++ b/tests/toranj/start.sh @@ -184,6 +184,7 @@ if [ "$TORANJ_CLI" = 1 ]; then run cli/test-017-network-data-versions.py run cli/test-018-next-hop-and-path-cost.py run cli/test-019-netdata-context-id.py + run cli/test-020-net-diag-vendor-info.py run cli/test-400-srp-client-server.py run cli/test-601-channel-manager-channel-change.py # Skip the "channel-select" test on a TREL only radio link, since it