[netdiag] add support for Vendor App URL TLV (#9816)

This commit contains the following:

- Adds support for the Vendor App URL TLV.
- Includes new public OT APIs and configurations to get and set the
  TLV value.
- Enables use of the TLV in the CLI `networkdiagnostic` command.
- Updates `test-020-net-diag-vendor-info.py` to validate the new TLV.
This commit is contained in:
Abtin Keshavarzian
2024-02-20 12:49:42 -08:00
committed by GitHub
parent 33574ad417
commit 08d21f1f07
10 changed files with 161 additions and 7 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (395)
#define OPENTHREAD_API_VERSION (396)
/**
* @addtogroup api-instance
+30 -1
View File
@@ -95,13 +95,14 @@ enum
OT_NETWORK_DIAGNOSTIC_TLV_ANSWER = 32, ///< Answer TLV
OT_NETWORK_DIAGNOSTIC_TLV_QUERY_ID = 33, ///< Query ID TLV
OT_NETWORK_DIAGNOSTIC_TLV_MLE_COUNTERS = 34, ///< MLE Counters TLV
OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL = 35, ///< Vendor App URL 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.
#define OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_APP_URL_TLV_LENGTH 96 ///< Max length of Vendor App URL TLV.
typedef uint16_t otNetworkDiagIterator; ///< Used to iterate through Network Diagnostic TLV.
@@ -294,6 +295,7 @@ typedef struct otNetworkDiagTlv
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];
char mVendorAppUrl[OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_APP_URL_TLV_LENGTH + 1];
struct
{
uint8_t mCount;
@@ -428,6 +430,16 @@ const char *otThreadGetVendorModel(otInstance *aInstance);
*/
const char *otThreadGetVendorSwVersion(otInstance *aInstance);
/**
* Get the vendor app URL string.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns The vendor app URL string.
*
*/
const char *otThreadGetVendorAppUrl(otInstance *aInstance);
/**
* Set the vendor name string.
*
@@ -479,6 +491,23 @@ otError otThreadSetVendorModel(otInstance *aInstance, const char *aVendorModel);
*/
otError otThreadSetVendorSwVersion(otInstance *aInstance, const char *aVendorSwVersion);
/**
* Set the vendor app URL string.
*
* Requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`.
*
* @p aVendorAppUrl should be UTF8 with max length of 64 chars (`MAX_VENDOR_APPL_URL_TLV_LENGTH`). Maximum length
* does not include the null `\0` character.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aVendorAppUrl The vendor app URL string.
*
* @retval OT_ERROR_NONE Successfully set the vendor app URL string.
* @retval OT_ERROR_INVALID_ARGS @p aVendorAppUrl is not valid (too long or not UTF8).
*
*/
otError otThreadSetVendorAppUrl(otInstance *aInstance, const char *aVendorAppUrl);
/**
* @}
*
+37 -3
View File
@@ -7682,7 +7682,7 @@ template <> otError Interpreter::Process<Cmd("vendor")>(Arg aArgs[])
error = ProcessGet(aArgs, otThreadGetVendorName);
#else
/**
* @cli vendor name (name)
* @cli vendor name (set)
* @code
* vendor name nest
* Done
@@ -7712,7 +7712,7 @@ template <> otError Interpreter::Process<Cmd("vendor")>(Arg aArgs[])
error = ProcessGet(aArgs, otThreadGetVendorModel);
#else
/**
* @cli vendor model (name)
* @cli vendor model (set)
* @code
* vendor model Hub\ Max
* Done
@@ -7742,7 +7742,7 @@ template <> otError Interpreter::Process<Cmd("vendor")>(Arg aArgs[])
error = ProcessGet(aArgs, otThreadGetVendorSwVersion);
#else
/**
* @cli vendor swversion (version)
* @cli vendor swversion (set)
* @code
* vendor swversion Marble3.5.1
* Done
@@ -7754,6 +7754,36 @@ template <> otError Interpreter::Process<Cmd("vendor")>(Arg aArgs[])
error = ProcessGetSet(aArgs, otThreadGetVendorSwVersion, otThreadSetVendorSwVersion);
#endif
}
/**
* @cli vendor appurl
* @code
* vendor appurl
* http://www.example.com
* Done
* @endcode
* @par api_copy
* #otThreadGetVendorAppUrl
*/
else if (aArgs[0] == "appurl")
{
aArgs++;
#if !OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
error = ProcessGet(aArgs, otThreadGetVendorAppUrl);
#else
/**
* @cli vendor appurl (set)
* @code
* vendor appurl http://www.example.com
* Done
* @endcode
* @par api_copy
* #otThreadSetVendorAppUrl
* @cparam vendor appurl @ca{url}
*/
error = ProcessGetSet(aArgs, otThreadGetVendorAppUrl, otThreadSetVendorAppUrl);
#endif
}
return error;
}
@@ -7829,6 +7859,7 @@ template <> otError Interpreter::Process<Cmd("networkdiagnostic")>(Arg aArgs[])
* - `28`: Thread Stack Version TLV (version identifier as UTF-8 string for Thread stack codebase/commit/version)
* - `29`: Child TLV
* - `34`: MLE Counters TLV
* - `35`: Vendor App URL TLV
* @par
* Sends a network diagnostic request to retrieve specified Type Length Values (TLVs)
* for the specified addresses(es).
@@ -7996,6 +8027,9 @@ void Interpreter::HandleDiagnosticGetResponse(otError aError,
case OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_SW_VERSION:
OutputLine("Vendor SW Version: %s", diagTlv.mData.mVendorSwVersion);
break;
case OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL:
OutputLine("Vendor App URL: %s", diagTlv.mData.mVendorAppUrl);
break;
case OT_NETWORK_DIAGNOSTIC_TLV_THREAD_STACK_VERSION:
OutputLine("Thread Stack Version: %s", diagTlv.mData.mThreadStackVersion);
break;
+10
View File
@@ -89,6 +89,11 @@ const char *otThreadGetVendorSwVersion(otInstance *aInstance)
return AsCoreType(aInstance).Get<NetworkDiagnostic::Server>().GetVendorSwVersion();
}
const char *otThreadGetVendorAppUrl(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<NetworkDiagnostic::Server>().GetVendorAppUrl();
}
#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
otError otThreadSetVendorName(otInstance *aInstance, const char *aVendorName)
{
@@ -104,4 +109,9 @@ otError otThreadSetVendorSwVersion(otInstance *aInstance, const char *aVendorSwV
{
return AsCoreType(aInstance).Get<NetworkDiagnostic::Server>().SetVendorSwVersion(aVendorSwVersion);
}
otError otThreadSetVendorAppUrl(otInstance *aInstance, const char *aVendorAppUrl)
{
return AsCoreType(aInstance).Get<NetworkDiagnostic::Server>().SetVendorAppUrl(aVendorAppUrl);
}
#endif
+10
View File
@@ -75,6 +75,16 @@
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION ""
#endif
/**
* @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_APP_URL
*
* Specifies the default Vendor App URL string.
*
*/
#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_APP_URL
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_APP_URL ""
#endif
/**
* @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
*
+16
View File
@@ -61,6 +61,7 @@ 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;
const char Server::kVendorAppUrl[] = OPENTHREAD_CONFIG_NET_DIAG_VENDOR_APP_URL;
//---------------------------------------------------------------------------------------------------------------------
// Server
@@ -71,11 +72,13 @@ Server::Server(Instance &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");
static_assert(sizeof(kVendorAppUrl) <= sizeof(VendorAppUrlTlv::StringType), "VENDOR_APP_URL 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));
memcpy(mVendorAppUrl, kVendorAppUrl, sizeof(kVendorAppUrl));
#endif
}
@@ -96,6 +99,11 @@ Error Server::SetVendorSwVersion(const char *aVendorSwVersion)
return StringCopy(mVendorSwVersion, aVendorSwVersion, kStringCheckUtf8Encoding);
}
Error Server::SetVendorAppUrl(const char *aVendorAppUrl)
{
return StringCopy(mVendorAppUrl, aVendorAppUrl, kStringCheckUtf8Encoding);
}
#endif
void Server::PrepareMessageInfoForDest(const Ip6::Address &aDestination, Tmf::MessageInfo &aMessageInfo) const
@@ -329,6 +337,10 @@ Error Server::AppendDiagTlv(uint8_t aTlvType, Message &aMessage)
error = Tlv::Append<VendorSwVersionTlv>(aMessage, GetVendorSwVersion());
break;
case Tlv::kVendorAppUrl:
error = Tlv::Append<VendorAppUrlTlv>(aMessage, GetVendorAppUrl());
break;
case Tlv::kThreadStackVersion:
error = Tlv::Append<ThreadStackVersionTlv>(aMessage, otGetVersionString());
break;
@@ -1225,6 +1237,10 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator,
SuccessOrExit(error = Tlv::Read<VendorSwVersionTlv>(aMessage, offset, aTlvInfo.mData.mVendorSwVersion));
break;
case Tlv::kVendorAppUrl:
SuccessOrExit(error = Tlv::Read<VendorAppUrlTlv>(aMessage, offset, aTlvInfo.mData.mVendorAppUrl));
break;
case Tlv::kThreadStackVersion:
SuccessOrExit(error =
Tlv::Read<ThreadStackVersionTlv>(aMessage, offset, aTlvInfo.mData.mThreadStackVersion));
+22
View File
@@ -141,10 +141,30 @@ public:
*/
Error SetVendorSwVersion(const char *aVendorSwVersion);
/**
* Returns the vendor app URL string.
*
* @returns the vendor app URL string.
*
*/
const char *GetVendorAppUrl(void) const { return mVendorAppUrl; }
/**
* Sets the vendor app URL string.
*
* @param[in] aVendorAppUrl The vendor app URL string
*
* @retval kErrorNone Successfully set the vendor app URL.
* @retval kErrorInvalidArgs @p aVendorAppUrl is not valid (too long or not UTF8).
*
*/
Error SetVendorAppUrl(const char *aVendorAppUrl);
#else
const char *GetVendorName(void) const { return kVendorName; }
const char *GetVendorModel(void) const { return kVendorModel; }
const char *GetVendorSwVersion(void) const { return kVendorSwVersion; }
const char *GetVendorAppUrl(void) const { return kVendorAppUrl; }
#endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
private:
@@ -173,6 +193,7 @@ private:
static const char kVendorName[];
static const char kVendorModel[];
static const char kVendorSwVersion[];
static const char kVendorAppUrl[];
Error AppendDiagTlv(uint8_t aTlvType, Message &aMessage);
Error AppendIp6AddressList(Message &aMessage);
@@ -211,6 +232,7 @@ private:
VendorNameTlv::StringType mVendorName;
VendorModelTlv::StringType mVendorModel;
VendorSwVersionTlv::StringType mVendorSwVersion;
VendorAppUrlTlv::StringType mVendorAppUrl;
#endif
#if OPENTHREAD_FTD
@@ -96,6 +96,7 @@ public:
kAnswer = OT_NETWORK_DIAGNOSTIC_TLV_ANSWER,
kQueryId = OT_NETWORK_DIAGNOSTIC_TLV_QUERY_ID,
kMleCounters = OT_NETWORK_DIAGNOSTIC_TLV_MLE_COUNTERS,
kVendorAppUrl = OT_NETWORK_DIAGNOSTIC_TLV_VENDOR_APP_URL,
};
/**
@@ -122,6 +123,12 @@ public:
*/
static constexpr uint8_t kMaxThreadStackVersionLength = OT_NETWORK_DIAGNOSTIC_MAX_THREAD_STACK_VERSION_TLV_LENGTH;
/**
* Maximum length of Vendor SW Version TLV.
*
*/
static constexpr uint8_t kMaxVendorAppUrlLength = OT_NETWORK_DIAGNOSTIC_MAX_VENDOR_APP_URL_TLV_LENGTH;
/**
* Returns the Type value.
*
@@ -236,6 +243,12 @@ typedef StringTlvInfo<Tlv::kVendorSwVersion, Tlv::kMaxVendorSwVersionLength> Ven
*/
typedef StringTlvInfo<Tlv::kThreadStackVersion, Tlv::kMaxThreadStackVersionLength> ThreadStackVersionTlv;
/**
* Defines Vendor App URL TLV constants and types.
*
*/
typedef StringTlvInfo<Tlv::kVendorAppUrl, Tlv::kMaxVendorAppUrlLength> VendorAppUrlTlv;
/**
* Defines Child IPv6 Address List TLV constants and types.
*
+6
View File
@@ -378,6 +378,12 @@ class Node(object):
def set_vendor_sw_version(self, version):
return self._cli_no_output('vendor swversion', version)
def get_vendor_app_url(self):
return self._cli_single_output('vendor appurl')
def set_vendor_app_url(self, url):
return self._cli_no_output('vendor appurl', url)
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# netdata
@@ -69,6 +69,7 @@ VENDOR_MODEL_TLV = 26
VENDOR_SW_VERSION_TLV = 27
THREAD_STACK_VERSION_TLV = 28
MLE_COUNTERS_TLV = 34
VENDOR_APP_URL = 35
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Check setting vendor name, model, ans sw version
@@ -76,10 +77,12 @@ MLE_COUNTERS_TLV = 34
r1.set_vendor_name('nest')
r1.set_vendor_model('marble')
r1.set_vendor_sw_version('ot-1.3.1')
r1.set_vendor_app_url('https://example.com/vendor-app')
verify(r1.get_vendor_name() == 'nest')
verify(r1.get_vendor_model() == 'marble')
verify(r1.get_vendor_sw_version() == 'ot-1.3.1')
verify(r1.get_vendor_app_url() == 'https://example.com/vendor-app')
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Check invalid names (too long)
@@ -126,6 +129,8 @@ except cli.CliError as e:
verify(errored)
r2.set_vendor_app_url("https://example.com/vendor-app")
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Perform net diag query
@@ -153,6 +158,13 @@ verify(len(result) == 2)
verify(result[1].startswith("Vendor SW Version:"))
verify(result[1].split(':')[1].strip() == r1.get_vendor_sw_version())
# Get vendor app URL (TLV 35)
result = r2.cli('networkdiagnostic get', r1_rloc, VENDOR_APP_URL)
verify(len(result) == 2)
verify(result[1].startswith("Vendor App URL:"))
verify(result[1].split(':', 1)[1].strip() == r1.get_vendor_app_url())
# Get thread stack version (TLV 30)
result = r2.cli('networkdiagnostic get', r1_rloc, THREAD_STACK_VERSION_TLV)
@@ -163,8 +175,8 @@ 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)
THREAD_STACK_VERSION_TLV, VENDOR_APP_URL)
verify(len(result) == 6)
for line in result[1:]:
if line.startswith("Vendor Name:"):
verify(line.split(':')[1].strip() == r2.get_vendor_name())
@@ -172,6 +184,8 @@ for line in result[1:]:
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("Vendor App URL:"):
verify(line.split(':', 1)[1].strip() == r2.get_vendor_app_url())
elif line.startswith("Thread Stack Version:"):
verify(r2.get_version().startswith(line.split(':', 1)[1].strip()))
else: