mirror of
https://github.com/espressif/openthread.git
synced 2026-09-01 14:59:54 +00:00
[vendor-info] add vendor OUI support (#12991)
This commit introduces support for configuring and retrieving a vendor OUI-24 (Organizationally Unique Identifier). It defines the new `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI` configuration option and adds the `otThreadGetVendorOui()` and `otThreadSetVendorOui()` APIs. When specified, the vendor OUI is included in the `BorderAgent` mDNS/DNS-SD TXT data under the `vo` key. The `VendorInfo` class is updated to manage the OUI value. This commit also adds the `vendor oui` CLI command to get or set this property. Finally, it updates the tests to validate the presence and correctness of the new `vo` key in the TXT data.
This commit is contained in:
@@ -362,6 +362,7 @@ ot_int_option(OT_MLE_MAX_CHILDREN OPENTHREAD_CONFIG_MLE_MAX_CHILDREN "set maximu
|
||||
ot_int_option(OT_RCP_RESTORATION_MAX_COUNT OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT "set max RCP restoration count")
|
||||
ot_int_option(OT_RCP_TIME_SYNC_INTERVAL OPENTHREAD_SPINEL_CONFIG_RCP_TIME_SYNC_INTERVAL "set host-RCP time sync interval in microseconds")
|
||||
ot_int_option(OT_RCP_TX_WAIT_TIME_SECS OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS "set RCP TX wait TIME in seconds")
|
||||
ot_int_option(OT_VENDOR_OUI OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI "set the vendor OUI")
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (592)
|
||||
#define OPENTHREAD_API_VERSION (593)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -425,6 +425,20 @@ const char *otThreadGetVendorSwVersion(otInstance *aInstance);
|
||||
*/
|
||||
const char *otThreadGetVendorAppUrl(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Represents an unspecified Vendor OUI.
|
||||
*/
|
||||
#define OT_THREAD_UNSPECIFIED_VENDOR_OUI (0xffffffff)
|
||||
|
||||
/**
|
||||
* Get the vendor OUI-24
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @returns The vendor OUI-24 value in hex format, or `OT_THREAD_UNSPECIFIED_VENDOR_OUI` is not specified.
|
||||
*/
|
||||
uint32_t otThreadGetVendorOui(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Set the vendor name string.
|
||||
*
|
||||
@@ -494,6 +508,20 @@ otError otThreadSetVendorSwVersion(otInstance *aInstance, const char *aVendorSwV
|
||||
*/
|
||||
otError otThreadSetVendorAppUrl(otInstance *aInstance, const char *aVendorAppUrl);
|
||||
|
||||
/**
|
||||
* Set the vendor OUI-24.
|
||||
*
|
||||
* Requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aVendorOui The vendor OUI-24 value in Hexadecimal representation (e.g., OUI 64-16-66 is represented as
|
||||
* `0x641666`). Must be a 24-bit value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set the vendor OUI.
|
||||
* @retval OT_ERROR_INVALID_ARGS @p aVendorOui is not a valid 24-bit value.
|
||||
*/
|
||||
otError otThreadSetVendorOui(otInstance *aInstance, uint32_t aVendorOui);
|
||||
|
||||
/**
|
||||
* Callback function pointer to notify when a Network Diagnostic Reset request message is received for the
|
||||
* `OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS` TLV.
|
||||
|
||||
@@ -7627,6 +7627,53 @@ template <> otError Interpreter::Process<Cmd("vendor")>(Arg aArgs[])
|
||||
error = ProcessGetSet(aArgs, otThreadGetVendorAppUrl, otThreadSetVendorAppUrl);
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* @cli vendor oui
|
||||
* @code
|
||||
* vendor oui
|
||||
* B4-A6-61
|
||||
* Done
|
||||
* @endcode
|
||||
* @par api_copy
|
||||
* #otThreadGetVendorOui
|
||||
*/
|
||||
else if (aArgs[0] == "oui")
|
||||
{
|
||||
if (aArgs[1].IsEmpty())
|
||||
{
|
||||
uint32_t oui = otThreadGetVendorOui(GetInstancePtr());
|
||||
|
||||
if (oui == OT_THREAD_UNSPECIFIED_VENDOR_OUI)
|
||||
{
|
||||
OutputLine("unspecified");
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputLine("%02X-%02X-%02X", static_cast<uint8_t>((oui >> 16) & 0xff),
|
||||
static_cast<uint8_t>((oui >> 8) & 0xff), static_cast<uint8_t>(oui & 0xff));
|
||||
}
|
||||
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
|
||||
/**
|
||||
* @cli vendor oui (set)
|
||||
* @code
|
||||
* vendor oui 0xb4a661
|
||||
* Done
|
||||
* @endcode
|
||||
* @par api_copy
|
||||
* #otThreadSetVendorOui
|
||||
* @cparam vendor oui @ca{oui}
|
||||
*/
|
||||
error = ProcessSet(aArgs + 1, otThreadSetVendorOui);
|
||||
#else
|
||||
error = OT_ERROR_INVALID_ARGS;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,10 @@ const char *otThreadGetVendorAppUrl(otInstance *aInstance)
|
||||
return AsCoreType(aInstance).Get<VendorInfo>().GetAppUrl();
|
||||
}
|
||||
|
||||
uint32_t otThreadGetVendorOui(otInstance *aInstance) { return AsCoreType(aInstance).Get<VendorInfo>().GetOui(); }
|
||||
|
||||
#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
|
||||
|
||||
otError otThreadSetVendorName(otInstance *aInstance, const char *aVendorName)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<VendorInfo>().SetName(aVendorName);
|
||||
@@ -105,7 +108,13 @@ otError otThreadSetVendorAppUrl(otInstance *aInstance, const char *aVendorAppUrl
|
||||
{
|
||||
return AsCoreType(aInstance).Get<VendorInfo>().SetAppUrl(aVendorAppUrl);
|
||||
}
|
||||
#endif
|
||||
|
||||
otError otThreadSetVendorOui(otInstance *aInstance, uint32_t aVendorOui)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<VendorInfo>().SetOui(aVendorOui);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
|
||||
|
||||
void otThreadSetNonPreferredChannels(otInstance *aInstance, otChannelMask aChannelMask)
|
||||
{
|
||||
|
||||
@@ -88,6 +88,18 @@
|
||||
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_APP_URL ""
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI
|
||||
*
|
||||
* Specifies the default Vendor OUI-24 value in Hexadecimal representation (e.g., OUI 64-16-66 is represented as
|
||||
* `0x641666`).
|
||||
*
|
||||
* The value of `0xffffffff` (UINT32_MAX) is used to indicate OUI is not specified.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI
|
||||
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI (0xffffffff)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
|
||||
*
|
||||
|
||||
@@ -69,6 +69,7 @@ TxtData::TxtData(Instance &aInstance)
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
|
||||
, mShouldAddVendorName(true)
|
||||
, mShouldAddVendorModel(true)
|
||||
, mShouldAddVendorOui(true)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -79,7 +80,8 @@ Error TxtData::Prepare(uint8_t *aBuffer,
|
||||
uint16_t aBufferSize,
|
||||
uint16_t &aLength,
|
||||
bool aAddVendorName,
|
||||
bool aAddVendorModel)
|
||||
bool aAddVendorModel,
|
||||
bool aAddVendorOui)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Dns::TxtDataEncoder encoder(aBuffer, aBufferSize);
|
||||
@@ -169,6 +171,14 @@ Error TxtData::Prepare(uint8_t *aBuffer,
|
||||
SuccessOrExit(error = encoder.AppendStringEntry(Key::kModelName, Get<VendorInfo>().GetModel()));
|
||||
}
|
||||
|
||||
if (aAddVendorOui && Get<VendorInfo>().IsOuiSpecified())
|
||||
{
|
||||
uint8_t ouiData[kVendorOuiSize];
|
||||
|
||||
BigEndian::WriteUint24(Get<VendorInfo>().GetOui(), ouiData);
|
||||
SuccessOrExit(error = encoder.AppendEntry(Key::kVendorOui, ouiData));
|
||||
}
|
||||
|
||||
aLength = encoder.GetLength();
|
||||
|
||||
exit:
|
||||
@@ -178,7 +188,7 @@ exit:
|
||||
Error TxtData::Prepare(ServiceTxtData &aTxtData)
|
||||
{
|
||||
return Prepare(aTxtData.mData, sizeof(aTxtData.mData), aTxtData.mLength, /* aAddVendorName */ false,
|
||||
/* aAddVendorModel */ false);
|
||||
/* aAddVendorModel */ false, /* aAddVendorOui */ false);
|
||||
}
|
||||
|
||||
void TxtData::SetChangedCallback(ChangedCallback aCallback, void *aContext)
|
||||
@@ -236,11 +246,16 @@ void TxtData::PrepareWithVendorData(Heap::Data &aTxtData)
|
||||
size += Tlv::kMaxVendorModelLength + sizeof(Key::kModelName) + sizeof('=');
|
||||
}
|
||||
|
||||
if (mShouldAddVendorOui)
|
||||
{
|
||||
size += kVendorOuiSize + sizeof(Key::kVendorOui) + sizeof('=');
|
||||
}
|
||||
|
||||
buffer = reinterpret_cast<uint8_t *>(Heap::CAlloc(size, sizeof(uint8_t)));
|
||||
|
||||
OT_ASSERT(buffer != nullptr);
|
||||
|
||||
SuccessOrAssert(Prepare(buffer, size, length, mShouldAddVendorName, mShouldAddVendorModel));
|
||||
SuccessOrAssert(Prepare(buffer, size, length, mShouldAddVendorName, mShouldAddVendorModel, mShouldAddVendorOui));
|
||||
|
||||
if (mVendorData.GetLength() != 0)
|
||||
{
|
||||
@@ -266,6 +281,7 @@ void TxtData::SetVendorData(const uint8_t *aVendorData, uint16_t aVendorDataLeng
|
||||
|
||||
mShouldAddVendorName = true;
|
||||
mShouldAddVendorModel = true;
|
||||
mShouldAddVendorOui = true;
|
||||
|
||||
iterator.Init(mVendorData.GetBytes(), mVendorData.GetLength());
|
||||
|
||||
@@ -279,6 +295,10 @@ void TxtData::SetVendorData(const uint8_t *aVendorData, uint16_t aVendorDataLeng
|
||||
{
|
||||
mShouldAddVendorModel = false;
|
||||
}
|
||||
else if (entry.MatchesKey(Key::kVendorOui))
|
||||
{
|
||||
mShouldAddVendorOui = false;
|
||||
}
|
||||
}
|
||||
|
||||
Refresh();
|
||||
@@ -303,6 +323,14 @@ void TxtData::HandleVendorModelChange(void)
|
||||
}
|
||||
}
|
||||
|
||||
void TxtData::HandleVendorOuiChange(void)
|
||||
{
|
||||
if (mShouldAddVendorOui)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
|
||||
|
||||
uint32_t TxtData::StateBitmap::Determine(Instance &aInstance)
|
||||
|
||||
@@ -279,6 +279,7 @@ public:
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kVendorOuiSize = OT_BORDER_AGENT_VENDOR_OUI_SIZE;
|
||||
static constexpr uint16_t kMaxSizeNoVendorData = OT_BORDER_AGENT_MESHCOP_SERVICE_TXT_DATA_MAX_LENGTH;
|
||||
|
||||
static const char kRecordVersion[];
|
||||
@@ -358,7 +359,12 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
Error Prepare(uint8_t *aBuffer, uint16_t aBufferSize, uint16_t &aLength, bool aAddVendorName, bool aAddVendorModel);
|
||||
Error Prepare(uint8_t *aBuffer,
|
||||
uint16_t aBufferSize,
|
||||
uint16_t &aLength,
|
||||
bool aAddVendorName,
|
||||
bool aAddVendorModel,
|
||||
bool aAddVendorOui);
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
|
||||
// Callback from Notifier
|
||||
@@ -366,6 +372,7 @@ private:
|
||||
// Callbacks from VendorInfo
|
||||
void HandleVendorNameChange(void);
|
||||
void HandleVendorModelChange(void);
|
||||
void HandleVendorOuiChange(void);
|
||||
|
||||
void HandleChangedTask(void);
|
||||
|
||||
@@ -377,6 +384,7 @@ private:
|
||||
Heap::Data mVendorData;
|
||||
bool mShouldAddVendorName;
|
||||
bool mShouldAddVendorModel;
|
||||
bool mShouldAddVendorOui;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -57,11 +57,14 @@ VendorInfo::VendorInfo(Instance &aInstance)
|
||||
static_assert(sizeof(kSwVersion) <= sizeof(SwVersionStringType), "VENDOR_SW_VERSION is too long");
|
||||
static_assert(sizeof(kAppUrl) <= sizeof(AppUrlStringType), "VENDOR_APP_URL is too long");
|
||||
|
||||
static_assert((kOui == kUnspecifiedOui) || ((kOui & ~kOuiMask) == 0), "VENDOR_OUI is invalid, MUST be 24-bit");
|
||||
|
||||
#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
|
||||
memcpy(mName, kName, sizeof(kName));
|
||||
memcpy(mModel, kModel, sizeof(kModel));
|
||||
memcpy(mSwVersion, kSwVersion, sizeof(kSwVersion));
|
||||
memcpy(mAppUrl, kAppUrl, sizeof(kAppUrl));
|
||||
mOui = kOui;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -110,6 +113,23 @@ Error VendorInfo::SetSwVersion(const char *aSwVersion)
|
||||
|
||||
Error VendorInfo::SetAppUrl(const char *aAppUrl) { return StringCopy(mAppUrl, aAppUrl, kStringCheckUtf8Encoding); }
|
||||
|
||||
Error VendorInfo::SetOui(uint32_t aOui)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit((aOui & ~kOuiMask) == 0, error = kErrorInvalidArgs);
|
||||
|
||||
VerifyOrExit(aOui != mOui);
|
||||
mOui = aOui;
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
|
||||
Get<MeshCoP::BorderAgent::TxtData>().HandleVendorOuiChange();
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/netdiag.h>
|
||||
|
||||
#include "common/error.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/non_copyable.hpp"
|
||||
@@ -49,6 +51,11 @@ namespace ot {
|
||||
class VendorInfo : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Unspecified Vendor OUI value.
|
||||
*/
|
||||
static constexpr uint32_t kUnspecifiedOui = OT_THREAD_UNSPECIFIED_VENDOR_OUI;
|
||||
|
||||
/**
|
||||
* Initializes the `VendorInfo`.
|
||||
*
|
||||
@@ -130,14 +137,45 @@ public:
|
||||
*/
|
||||
Error SetAppUrl(const char *aAppUrl);
|
||||
|
||||
/**
|
||||
* Indicates whether the Vendor OUI is specified.
|
||||
*
|
||||
* @retval TRUE The Vendor OUI is specified.
|
||||
* @retval FALSE The Vendor OUI is not specified.
|
||||
*/
|
||||
bool IsOuiSpecified(void) const { return mOui != kUnspecifiedOui; }
|
||||
|
||||
/**
|
||||
* Returns the Vendor OUI-24.
|
||||
*
|
||||
* @returns The Vendor OUI-24 value. Returns `kUnspecifiedOui` if it is not set.
|
||||
*/
|
||||
uint32_t GetOui(void) const { return mOui; }
|
||||
|
||||
/**
|
||||
* Sets the Vendor OUI-24.
|
||||
*
|
||||
* @param[in] aOui The Vendor OUI-24 value in Hexadecimal representation (e.g., OUI 64-16-66 is represented as
|
||||
* `0x641666`). Must be a 24-bit value.
|
||||
*
|
||||
* @retval kErrorNone Successfully set the Vendor OUI.
|
||||
* @retval kErrorInvalidArgs @p aOui is not a valid 24-bit value.
|
||||
*/
|
||||
Error SetOui(uint32_t aOui);
|
||||
|
||||
#else
|
||||
const char *GetName(void) const { return kName; }
|
||||
const char *GetModel(void) const { return kModel; }
|
||||
const char *GetSwVersion(void) const { return kSwVersion; }
|
||||
const char *GetAppUrl(void) const { return kAppUrl; }
|
||||
uint32_t GetOui(void) const { return kOui; }
|
||||
bool IsOuiSpecified(void) const { return kOui != kUnspecifiedOui; }
|
||||
#endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
|
||||
|
||||
private:
|
||||
static constexpr uint32_t kOui = OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI;
|
||||
static constexpr uint32_t kOuiMask = 0xffffff;
|
||||
|
||||
// String buffer types (max size specified by corresponding TLV)
|
||||
typedef NetworkDiagnostic::VendorNameTlv::StringType NameStringType;
|
||||
typedef NetworkDiagnostic::VendorModelTlv::StringType ModelStringType;
|
||||
@@ -154,6 +192,7 @@ private:
|
||||
ModelStringType mModel;
|
||||
SwVersionStringType mSwVersion;
|
||||
AppUrlStringType mAppUrl;
|
||||
uint32_t mOui;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL "Nexus Simulation"
|
||||
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME "RD:OpenThread by Google Nest"
|
||||
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_SW_VERSION "OT-simul-nexus"
|
||||
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI 0x020100
|
||||
#define OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 256
|
||||
#define OPENTHREAD_CONFIG_PARENT_SEARCH_BACKOFF_INTERVAL (10 * 60)
|
||||
|
||||
@@ -1461,6 +1461,14 @@ void ValidateMeshCoPTxtData(TxtData &aTxtData, Node &aNode, bool aExpectVendorIn
|
||||
aTxtData.ValidateKey("mn", expectedModelName);
|
||||
VerifyOrQuit(info.mHasModelName);
|
||||
VerifyOrQuit(StringMatch(info.mModelName, expectedModelName));
|
||||
|
||||
if (aNode.Get<VendorInfo>().IsOuiSpecified())
|
||||
{
|
||||
uint8_t ouiData[3];
|
||||
|
||||
BigEndian::WriteUint24(aNode.Get<VendorInfo>().GetOui(), ouiData);
|
||||
aTxtData.ValidateKey("vo", ouiData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user