diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h index 6dbd9e68b..8bb7e574b 100644 --- a/include/openthread/dataset.h +++ b/include/openthread/dataset.h @@ -306,7 +306,7 @@ typedef enum otMeshcopTlvType OT_MESHCOP_TLV_WAKEUP_CHANNEL = 74, ///< meshcop Wake-up Channel TLV OT_MESHCOP_TLV_DISCOVERYREQUEST = 128, ///< meshcop Discovery Request TLV OT_MESHCOP_TLV_DISCOVERYRESPONSE = 129, ///< meshcop Discovery Response TLV - OT_MESHCOP_TLV_JOINERADVERTISEMENT = 241, ///< meshcop Joiner Advertisement TLV + OT_MESHCOP_TLV_JOINERADVERTISEMENT = 241, ///< meshcop Joiner Advertisement TLV (experimental) } otMeshcopTlvType; /** diff --git a/include/openthread/instance.h b/include/openthread/instance.h index b52977f01..0043a27d8 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -52,7 +52,7 @@ extern "C" { * * @note This number versions both OpenThread platform and user APIs. */ -#define OPENTHREAD_API_VERSION (569) +#define OPENTHREAD_API_VERSION (570) /** * @addtogroup api-instance diff --git a/include/openthread/thread.h b/include/openthread/thread.h index 5cbbad805..ba6f6e909 100644 --- a/include/openthread/thread.h +++ b/include/openthread/thread.h @@ -303,17 +303,24 @@ otError otThreadDiscover(otInstance *aInstance, bool otThreadIsDiscoverInProgress(otInstance *aInstance); /** - * Sets the Thread Joiner Advertisement when discovering Thread network. + * Sets the Thread Joiner Advertisement used when discovering a Thread network. * - * Thread Joiner Advertisement is used to allow a Joiner to advertise its own application-specific information - * (such as Vendor ID, Product ID, Discriminator, etc.) via a newly-proposed Joiner Advertisement TLV, - * and to make this information available to Commissioners or Commissioner Candidates without human interaction. + * Requires `OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE`. + * + * @note This is an experimental feature and is not part of the Thread specification. OpenThread's implementation is + * partial: it provides the mechanism for a Joiner to include a new Joiner Adv TLV in its emitted Discovery Scan + * Request messages, but does not include the corresponding logic for the receiver of Scan Request to read or + * parse this TLV. + * + * A Joiner can use this to advertise its own application-specific information (such as Vendor ID, Product ID, + * Discriminator, etc.) using a newly proposed Joiner Advertisement TLV (`OT_MESHCOP_TLV_JOINERADVERTISEMENT`). + * This TLV is appended as a sub-TLV within the MLE Discovery TLV in an MLE Discovery Scan Request message. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aOui The Vendor IEEE OUI value that will be included in the Joiner Advertisement. Only the * least significant 3 bytes will be used, and the most significant byte will be ignored. * @param[in] aAdvData A pointer to the AdvData that will be included in the Joiner Advertisement. - * @param[in] aAdvDataLength The length of AdvData in bytes. + * @param[in] aAdvDataLength The length of AdvData in bytes. Must not exceed `OT_JOINER_ADVDATA_MAX_LENGTH`. * * @retval OT_ERROR_NONE Successfully set Joiner Advertisement. * @retval OT_ERROR_INVALID_ARGS Invalid AdvData. diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp index 568b7e390..20052eae3 100644 --- a/src/core/api/thread_api.cpp +++ b/src/core/api/thread_api.cpp @@ -419,6 +419,7 @@ otError otThreadDiscover(otInstance *aInstance, /* aFilterIndexes (use hash of factory EUI64) */ nullptr, aCallback, aCallbackContext); } +#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE otError otThreadSetJoinerAdvertisement(otInstance *aInstance, uint32_t aOui, const uint8_t *aAdvData, @@ -426,6 +427,7 @@ otError otThreadSetJoinerAdvertisement(otInstance *aInstance, { return AsCoreType(aInstance).Get().SetJoinerAdvertisement(aOui, aAdvData, aAdvDataLength); } +#endif bool otThreadIsDiscoverInProgress(otInstance *aInstance) { diff --git a/src/core/config/joiner.h b/src/core/config/joiner.h index b428d2930..3ce4d4f08 100644 --- a/src/core/config/joiner.h +++ b/src/core/config/joiner.h @@ -61,6 +61,18 @@ #define OPENTHREAD_CONFIG_JOINER_MAX_CANDIDATES 2 #endif +/** + * @def OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE + * + * Define as 1 to enable including Joiner Advertisement TLV during discovery scan by the Joiner. + * + * This is an experimental feature. It is not part of the Thread specification. See `otThreadSetJoinerAdvertisement` + * for more details. + */ +#ifndef OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE +#define OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE 0 +#endif + /** * @} */ diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp index d422a8c77..edff0b87c 100644 --- a/src/core/meshcop/meshcop_tlvs.hpp +++ b/src/core/meshcop/meshcop_tlvs.hpp @@ -1120,6 +1120,8 @@ private: uint8_t mReserved; } OT_TOOL_PACKED_END; +#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE + /** * Implements Joiner Advertisement TLV generation and parsing. */ @@ -1193,6 +1195,8 @@ private: uint8_t mAdvData[kAdvDataMaxLength]; } OT_TOOL_PACKED_END; +#endif // OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE + } // namespace MeshCoP } // namespace ot diff --git a/src/core/thread/discover_scanner.cpp b/src/core/thread/discover_scanner.cpp index 5fe360f09..1c21ec089 100644 --- a/src/core/thread/discover_scanner.cpp +++ b/src/core/thread/discover_scanner.cpp @@ -45,9 +45,11 @@ DiscoverScanner::DiscoverScanner(Instance &aInstance) , mFilterIndexes() , mState(kStateIdle) , mScanChannel(0) - , mAdvDataLength(0) , mEnableFiltering(false) , mShouldRestorePanId(false) +#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE + , mAdvDataLength(0) +#endif { } @@ -59,12 +61,11 @@ Error DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels, Handler aCallback, void *aContext) { - Error error = kErrorNone; - Mle::TxMessage *message = nullptr; - Tlv::Bookmark tlvBookmark; - Ip6::Address destination; - MeshCoP::DiscoveryRequestTlv discoveryRequest; - MeshCoP::JoinerAdvertisementTlv joinerAdvertisement; + Error error = kErrorNone; + Mle::TxMessage *message = nullptr; + Tlv::Bookmark tlvBookmark; + Ip6::Address destination; + MeshCoP::DiscoveryRequestTlv discoveryRequest; VerifyOrExit(Get().IsUp(), error = kErrorInvalidState); @@ -109,13 +110,17 @@ Error DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels, discoveryRequest.SetJoiner(aJoiner); SuccessOrExit(error = discoveryRequest.AppendTo(*message)); +#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE if (mAdvDataLength != 0) { - joinerAdvertisement.Init(); - joinerAdvertisement.SetOui(mOui); - joinerAdvertisement.SetAdvData(mAdvData, mAdvDataLength); - SuccessOrExit(error = joinerAdvertisement.AppendTo(*message)); + MeshCoP::JoinerAdvertisementTlv joinerAdvTlv; + + joinerAdvTlv.Init(); + joinerAdvTlv.SetOui(mOui); + joinerAdvTlv.SetAdvData(mAdvData, mAdvDataLength); + SuccessOrExit(error = joinerAdvTlv.AppendTo(*message)); } +#endif SuccessOrExit(error = Tlv::EndTlv(*message, tlvBookmark)); @@ -153,22 +158,23 @@ exit: return error; } +#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE Error DiscoverScanner::SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength) { Error error = kErrorNone; - VerifyOrExit((aAdvData != nullptr) && (aAdvDataLength != 0) && - (aAdvDataLength <= MeshCoP::JoinerAdvertisementTlv::kAdvDataMaxLength) && (aOui <= kMaxOui), - error = kErrorInvalidArgs); + VerifyOrExit(aAdvData != nullptr, error = kErrorInvalidArgs); + VerifyOrExit(IsValueInRange(aAdvDataLength, kMinAdvDataLength, kMaxAdvDataLength), error = kErrorInvalidArgs); + VerifyOrExit(aOui <= kMaxOui, error = kErrorInvalidArgs); mOui = aOui; mAdvDataLength = aAdvDataLength; - memcpy(mAdvData, aAdvData, aAdvDataLength); exit: return error; } +#endif Mac::TxFrame *DiscoverScanner::PrepareDiscoveryRequestFrame(Mac::TxFrame &aFrame) { diff --git a/src/core/thread/discover_scanner.hpp b/src/core/thread/discover_scanner.hpp index 9baf27102..43cf017e8 100644 --- a/src/core/thread/discover_scanner.hpp +++ b/src/core/thread/discover_scanner.hpp @@ -132,6 +132,7 @@ public: */ bool IsInProgress(void) const { return (mState != kStateIdle); } +#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE /** * Sets Joiner Advertisement. * @@ -143,8 +144,15 @@ public: * @retval kErrorInvalidArgs Invalid AdvData. */ Error SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength); +#endif private: +#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE + static constexpr uint32_t kMaxOui = 0xffffff; + static constexpr uint8_t kMinAdvDataLength = 1; + static constexpr uint8_t kMaxAdvDataLength = MeshCoP::JoinerAdvertisementTlv::kAdvDataMaxLength; +#endif + enum State : uint8_t { kStateIdle, @@ -152,8 +160,6 @@ private: kStateScanDone, }; - static constexpr uint32_t kMaxOui = 0xffffff; - // Methods used by `MeshForwarder` Mac::TxFrame *PrepareDiscoveryRequestFrame(Mac::TxFrame &aFrame); void Stop(void) { HandleDiscoverComplete(); } @@ -176,12 +182,14 @@ private: FilterIndexes mFilterIndexes; Mac::ChannelMask mScanChannels; State mState; - uint32_t mOui; uint8_t mScanChannel; - uint8_t mAdvDataLength; - uint8_t mAdvData[MeshCoP::JoinerAdvertisementTlv::kAdvDataMaxLength]; bool mEnableFiltering : 1; bool mShouldRestorePanId : 1; +#if OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE + uint8_t mAdvDataLength; + uint8_t mAdvData[kMaxAdvDataLength]; + uint32_t mOui; +#endif }; } // namespace Mle diff --git a/tests/toranj/openthread-core-toranj-config-posix.h b/tests/toranj/openthread-core-toranj-config-posix.h index f66f1e725..e203aad02 100644 --- a/tests/toranj/openthread-core-toranj-config-posix.h +++ b/tests/toranj/openthread-core-toranj-config-posix.h @@ -60,6 +60,8 @@ #define OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE 1 +#define OPENTHREAD_CONFIG_JOINER_ADV_EXPERIMENTAL_ENABLE 1 + #define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED #define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 1