Skip to content

Commit 2cf0bda

Browse files
authored
[vendor-info] add vendor OUI support (openthread#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.
1 parent d37e9df commit 2cf0bda

12 files changed

Lines changed: 207 additions & 6 deletions

File tree

etc/cmake/options.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ ot_int_option(OT_MLE_MAX_CHILDREN OPENTHREAD_CONFIG_MLE_MAX_CHILDREN "set maximu
362362
ot_int_option(OT_RCP_RESTORATION_MAX_COUNT OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT "set max RCP restoration count")
363363
ot_int_option(OT_RCP_TIME_SYNC_INTERVAL OPENTHREAD_SPINEL_CONFIG_RCP_TIME_SYNC_INTERVAL "set host-RCP time sync interval in microseconds")
364364
ot_int_option(OT_RCP_TX_WAIT_TIME_SECS OPENTHREAD_SPINEL_CONFIG_RCP_TX_WAIT_TIME_SECS "set RCP TX wait TIME in seconds")
365+
ot_int_option(OT_VENDOR_OUI OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI "set the vendor OUI")
365366

366367
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
367368

include/openthread/instance.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ extern "C" {
5252
*
5353
* @note This number versions both OpenThread platform and user APIs.
5454
*/
55-
#define OPENTHREAD_API_VERSION (592)
55+
#define OPENTHREAD_API_VERSION (593)
5656

5757
/**
5858
* @addtogroup api-instance

include/openthread/netdiag.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,20 @@ const char *otThreadGetVendorSwVersion(otInstance *aInstance);
425425
*/
426426
const char *otThreadGetVendorAppUrl(otInstance *aInstance);
427427

428+
/**
429+
* Represents an unspecified Vendor OUI.
430+
*/
431+
#define OT_THREAD_UNSPECIFIED_VENDOR_OUI (0xffffffff)
432+
433+
/**
434+
* Get the vendor OUI-24
435+
*
436+
* @param[in] aInstance A pointer to an OpenThread instance.
437+
*
438+
* @returns The vendor OUI-24 value in hex format, or `OT_THREAD_UNSPECIFIED_VENDOR_OUI` is not specified.
439+
*/
440+
uint32_t otThreadGetVendorOui(otInstance *aInstance);
441+
428442
/**
429443
* Set the vendor name string.
430444
*
@@ -494,6 +508,20 @@ otError otThreadSetVendorSwVersion(otInstance *aInstance, const char *aVendorSwV
494508
*/
495509
otError otThreadSetVendorAppUrl(otInstance *aInstance, const char *aVendorAppUrl);
496510

511+
/**
512+
* Set the vendor OUI-24.
513+
*
514+
* Requires `OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE`.
515+
*
516+
* @param[in] aInstance A pointer to an OpenThread instance.
517+
* @param[in] aVendorOui The vendor OUI-24 value in Hexadecimal representation (e.g., OUI 64-16-66 is represented as
518+
* `0x641666`). Must be a 24-bit value.
519+
*
520+
* @retval OT_ERROR_NONE Successfully set the vendor OUI.
521+
* @retval OT_ERROR_INVALID_ARGS @p aVendorOui is not a valid 24-bit value.
522+
*/
523+
otError otThreadSetVendorOui(otInstance *aInstance, uint32_t aVendorOui);
524+
497525
/**
498526
* Callback function pointer to notify when a Network Diagnostic Reset request message is received for the
499527
* `OT_NETWORK_DIAGNOSTIC_TLV_NON_PREFERRED_CHANNELS` TLV.

src/cli/cli.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7627,6 +7627,53 @@ template <> otError Interpreter::Process<Cmd("vendor")>(Arg aArgs[])
76277627
error = ProcessGetSet(aArgs, otThreadGetVendorAppUrl, otThreadSetVendorAppUrl);
76287628
#endif
76297629
}
7630+
/**
7631+
* @cli vendor oui
7632+
* @code
7633+
* vendor oui
7634+
* B4-A6-61
7635+
* Done
7636+
* @endcode
7637+
* @par api_copy
7638+
* #otThreadGetVendorOui
7639+
*/
7640+
else if (aArgs[0] == "oui")
7641+
{
7642+
if (aArgs[1].IsEmpty())
7643+
{
7644+
uint32_t oui = otThreadGetVendorOui(GetInstancePtr());
7645+
7646+
if (oui == OT_THREAD_UNSPECIFIED_VENDOR_OUI)
7647+
{
7648+
OutputLine("unspecified");
7649+
}
7650+
else
7651+
{
7652+
OutputLine("%02X-%02X-%02X", static_cast<uint8_t>((oui >> 16) & 0xff),
7653+
static_cast<uint8_t>((oui >> 8) & 0xff), static_cast<uint8_t>(oui & 0xff));
7654+
}
7655+
7656+
error = OT_ERROR_NONE;
7657+
}
7658+
else
7659+
{
7660+
#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
7661+
/**
7662+
* @cli vendor oui (set)
7663+
* @code
7664+
* vendor oui 0xb4a661
7665+
* Done
7666+
* @endcode
7667+
* @par api_copy
7668+
* #otThreadSetVendorOui
7669+
* @cparam vendor oui @ca{oui}
7670+
*/
7671+
error = ProcessSet(aArgs + 1, otThreadSetVendorOui);
7672+
#else
7673+
error = OT_ERROR_INVALID_ARGS;
7674+
#endif
7675+
}
7676+
}
76307677

76317678
return error;
76327679
}

src/core/api/netdiag_api.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ const char *otThreadGetVendorAppUrl(otInstance *aInstance)
8585
return AsCoreType(aInstance).Get<VendorInfo>().GetAppUrl();
8686
}
8787

88+
uint32_t otThreadGetVendorOui(otInstance *aInstance) { return AsCoreType(aInstance).Get<VendorInfo>().GetOui(); }
89+
8890
#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
91+
8992
otError otThreadSetVendorName(otInstance *aInstance, const char *aVendorName)
9093
{
9194
return AsCoreType(aInstance).Get<VendorInfo>().SetName(aVendorName);
@@ -105,7 +108,13 @@ otError otThreadSetVendorAppUrl(otInstance *aInstance, const char *aVendorAppUrl
105108
{
106109
return AsCoreType(aInstance).Get<VendorInfo>().SetAppUrl(aVendorAppUrl);
107110
}
108-
#endif
111+
112+
otError otThreadSetVendorOui(otInstance *aInstance, uint32_t aVendorOui)
113+
{
114+
return AsCoreType(aInstance).Get<VendorInfo>().SetOui(aVendorOui);
115+
}
116+
117+
#endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
109118

110119
void otThreadSetNonPreferredChannels(otInstance *aInstance, otChannelMask aChannelMask)
111120
{

src/core/config/network_diagnostic.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,18 @@
8888
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_APP_URL ""
8989
#endif
9090

91+
/**
92+
* @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI
93+
*
94+
* Specifies the default Vendor OUI-24 value in Hexadecimal representation (e.g., OUI 64-16-66 is represented as
95+
* `0x641666`).
96+
*
97+
* The value of `0xffffffff` (UINT32_MAX) is used to indicate OUI is not specified.
98+
*/
99+
#ifndef OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI
100+
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_OUI (0xffffffff)
101+
#endif
102+
91103
/**
92104
* @def OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
93105
*

src/core/meshcop/border_agent_txt_data.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ TxtData::TxtData(Instance &aInstance)
6969
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
7070
, mShouldAddVendorName(true)
7171
, mShouldAddVendorModel(true)
72+
, mShouldAddVendorOui(true)
7273
#endif
7374
{
7475
}
@@ -79,7 +80,8 @@ Error TxtData::Prepare(uint8_t *aBuffer,
7980
uint16_t aBufferSize,
8081
uint16_t &aLength,
8182
bool aAddVendorName,
82-
bool aAddVendorModel)
83+
bool aAddVendorModel,
84+
bool aAddVendorOui)
8385
{
8486
Error error = kErrorNone;
8587
Dns::TxtDataEncoder encoder(aBuffer, aBufferSize);
@@ -169,6 +171,14 @@ Error TxtData::Prepare(uint8_t *aBuffer,
169171
SuccessOrExit(error = encoder.AppendStringEntry(Key::kModelName, Get<VendorInfo>().GetModel()));
170172
}
171173

174+
if (aAddVendorOui && Get<VendorInfo>().IsOuiSpecified())
175+
{
176+
uint8_t ouiData[kVendorOuiSize];
177+
178+
BigEndian::WriteUint24(Get<VendorInfo>().GetOui(), ouiData);
179+
SuccessOrExit(error = encoder.AppendEntry(Key::kVendorOui, ouiData));
180+
}
181+
172182
aLength = encoder.GetLength();
173183

174184
exit:
@@ -178,7 +188,7 @@ Error TxtData::Prepare(uint8_t *aBuffer,
178188
Error TxtData::Prepare(ServiceTxtData &aTxtData)
179189
{
180190
return Prepare(aTxtData.mData, sizeof(aTxtData.mData), aTxtData.mLength, /* aAddVendorName */ false,
181-
/* aAddVendorModel */ false);
191+
/* aAddVendorModel */ false, /* aAddVendorOui */ false);
182192
}
183193

184194
void TxtData::SetChangedCallback(ChangedCallback aCallback, void *aContext)
@@ -236,11 +246,16 @@ void TxtData::PrepareWithVendorData(Heap::Data &aTxtData)
236246
size += Tlv::kMaxVendorModelLength + sizeof(Key::kModelName) + sizeof('=');
237247
}
238248

249+
if (mShouldAddVendorOui)
250+
{
251+
size += kVendorOuiSize + sizeof(Key::kVendorOui) + sizeof('=');
252+
}
253+
239254
buffer = reinterpret_cast<uint8_t *>(Heap::CAlloc(size, sizeof(uint8_t)));
240255

241256
OT_ASSERT(buffer != nullptr);
242257

243-
SuccessOrAssert(Prepare(buffer, size, length, mShouldAddVendorName, mShouldAddVendorModel));
258+
SuccessOrAssert(Prepare(buffer, size, length, mShouldAddVendorName, mShouldAddVendorModel, mShouldAddVendorOui));
244259

245260
if (mVendorData.GetLength() != 0)
246261
{
@@ -266,6 +281,7 @@ void TxtData::SetVendorData(const uint8_t *aVendorData, uint16_t aVendorDataLeng
266281

267282
mShouldAddVendorName = true;
268283
mShouldAddVendorModel = true;
284+
mShouldAddVendorOui = true;
269285

270286
iterator.Init(mVendorData.GetBytes(), mVendorData.GetLength());
271287

@@ -279,6 +295,10 @@ void TxtData::SetVendorData(const uint8_t *aVendorData, uint16_t aVendorDataLeng
279295
{
280296
mShouldAddVendorModel = false;
281297
}
298+
else if (entry.MatchesKey(Key::kVendorOui))
299+
{
300+
mShouldAddVendorOui = false;
301+
}
282302
}
283303

284304
Refresh();
@@ -303,6 +323,14 @@ void TxtData::HandleVendorModelChange(void)
303323
}
304324
}
305325

326+
void TxtData::HandleVendorOuiChange(void)
327+
{
328+
if (mShouldAddVendorOui)
329+
{
330+
Refresh();
331+
}
332+
}
333+
306334
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
307335

308336
uint32_t TxtData::StateBitmap::Determine(Instance &aInstance)

src/core/meshcop/border_agent_txt_data.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ class TxtData : public InstanceLocator
279279
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
280280

281281
private:
282+
static constexpr uint8_t kVendorOuiSize = OT_BORDER_AGENT_VENDOR_OUI_SIZE;
282283
static constexpr uint16_t kMaxSizeNoVendorData = OT_BORDER_AGENT_MESHCOP_SERVICE_TXT_DATA_MAX_LENGTH;
283284

284285
static const char kRecordVersion[];
@@ -358,14 +359,20 @@ class TxtData : public InstanceLocator
358359
#endif
359360
};
360361

361-
Error Prepare(uint8_t *aBuffer, uint16_t aBufferSize, uint16_t &aLength, bool aAddVendorName, bool aAddVendorModel);
362+
Error Prepare(uint8_t *aBuffer,
363+
uint16_t aBufferSize,
364+
uint16_t &aLength,
365+
bool aAddVendorName,
366+
bool aAddVendorModel,
367+
bool aAddVendorOui);
362368

363369
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
364370
// Callback from Notifier
365371
void HandleNotifierEvents(Events aEvents);
366372
// Callbacks from VendorInfo
367373
void HandleVendorNameChange(void);
368374
void HandleVendorModelChange(void);
375+
void HandleVendorOuiChange(void);
369376

370377
void HandleChangedTask(void);
371378

@@ -377,6 +384,7 @@ class TxtData : public InstanceLocator
377384
Heap::Data mVendorData;
378385
bool mShouldAddVendorName;
379386
bool mShouldAddVendorModel;
387+
bool mShouldAddVendorOui;
380388
#endif
381389
#endif
382390
};

src/core/thread/vendor_info.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,14 @@ VendorInfo::VendorInfo(Instance &aInstance)
5757
static_assert(sizeof(kSwVersion) <= sizeof(SwVersionStringType), "VENDOR_SW_VERSION is too long");
5858
static_assert(sizeof(kAppUrl) <= sizeof(AppUrlStringType), "VENDOR_APP_URL is too long");
5959

60+
static_assert((kOui == kUnspecifiedOui) || ((kOui & ~kOuiMask) == 0), "VENDOR_OUI is invalid, MUST be 24-bit");
61+
6062
#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
6163
memcpy(mName, kName, sizeof(kName));
6264
memcpy(mModel, kModel, sizeof(kModel));
6365
memcpy(mSwVersion, kSwVersion, sizeof(kSwVersion));
6466
memcpy(mAppUrl, kAppUrl, sizeof(kAppUrl));
67+
mOui = kOui;
6568
#endif
6669
}
6770

@@ -110,6 +113,23 @@ Error VendorInfo::SetSwVersion(const char *aSwVersion)
110113

111114
Error VendorInfo::SetAppUrl(const char *aAppUrl) { return StringCopy(mAppUrl, aAppUrl, kStringCheckUtf8Encoding); }
112115

116+
Error VendorInfo::SetOui(uint32_t aOui)
117+
{
118+
Error error = kErrorNone;
119+
120+
VerifyOrExit((aOui & ~kOuiMask) == 0, error = kErrorInvalidArgs);
121+
122+
VerifyOrExit(aOui != mOui);
123+
mOui = aOui;
124+
125+
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
126+
Get<MeshCoP::BorderAgent::TxtData>().HandleVendorOuiChange();
127+
#endif
128+
129+
exit:
130+
return error;
131+
}
132+
113133
#endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
114134

115135
} // namespace ot

0 commit comments

Comments
 (0)