mirror of
https://github.com/espressif/openthread.git
synced 2026-10-13 03:07:41 +00:00
[joiner-adv] initial implementation of Joiner Advertisement (#5299)
This commit implements Thread based Joiner Advertisement from Joiner side, including: - A new MeshCop TLV: Joiner Advertisement TLV which includes IEEE OUI and the Advertisement Data. - New APIs to set Joiner Advertisement which will be sent along with Discovery Request messages.
This commit is contained in:
@@ -287,6 +287,7 @@ typedef enum otMeshcopTlvType
|
||||
OT_MESHCOP_TLV_ENERGY_LIST = 57, ///< meshcop Energy List 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
|
||||
} otMeshcopTlvType;
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (20)
|
||||
#define OPENTHREAD_API_VERSION (21)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -264,6 +264,30 @@ otError otThreadDiscover(otInstance * aInstance,
|
||||
*/
|
||||
bool otThreadIsDiscoverInProgress(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This method sets the Thread Joiner Advertisement when discovering 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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set Joiner Advertisement.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid AdvData.
|
||||
*
|
||||
*/
|
||||
otError otThreadSetJoinerAdvertisement(otInstance * aInstance,
|
||||
uint32_t aOui,
|
||||
const uint8_t *aAdvData,
|
||||
uint8_t aAdvDataLength);
|
||||
|
||||
#define OT_JOINER_ADVDATA_MAX_LENGTH 64 ///< Maximum AdvData Length of Joiner Advertisement
|
||||
|
||||
/**
|
||||
* Get the Thread Child Timeout used when operating in the Child role.
|
||||
*
|
||||
|
||||
@@ -462,6 +462,16 @@ otError otThreadDiscover(otInstance * aInstance,
|
||||
/* aFilterIndexes (use hash of factory EUI64) */ nullptr, aCallback, aCallbackContext);
|
||||
}
|
||||
|
||||
otError otThreadSetJoinerAdvertisement(otInstance * aInstance,
|
||||
uint32_t aOui,
|
||||
const uint8_t *aAdvData,
|
||||
uint8_t aAdvDataLength)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<Mle::DiscoverScanner>().SetJoinerAdvertisement(aOui, aAdvData, aAdvDataLength);
|
||||
}
|
||||
|
||||
bool otThreadIsDiscoverInProgress(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
@@ -111,6 +111,7 @@ public:
|
||||
kEnergyList = OT_MESHCOP_TLV_ENERGY_LIST, ///< Energy List TLV
|
||||
kDiscoveryRequest = OT_MESHCOP_TLV_DISCOVERYREQUEST, ///< Discovery Request TLV
|
||||
kDiscoveryResponse = OT_MESHCOP_TLV_DISCOVERYRESPONSE, ///< Discovery Response TLV
|
||||
kJoinerAdvertisement = OT_MESHCOP_TLV_JOINERADVERTISEMENT, ///< Joiner Advertisement TLV
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2354,6 +2355,100 @@ private:
|
||||
uint8_t mReserved;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Joiner Advertisement TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class JoinerAdvertisementTlv : public Tlv
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kType = kJoinerAdvertisement, ///< The TLV Type.
|
||||
kAdvDataMaxLength = OT_JOINER_ADVDATA_MAX_LENGTH, ///< The Max Length of AdvData
|
||||
};
|
||||
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
SetType(kJoinerAdvertisement);
|
||||
SetLength(sizeof(*this) - sizeof(Tlv));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return GetLength() >= sizeof(mOui) && GetLength() <= sizeof(mOui) + sizeof(mAdvData); }
|
||||
|
||||
/**
|
||||
* This method returns the Vendor OUI value.
|
||||
*
|
||||
* @returns The Vendor OUI value.
|
||||
*
|
||||
*/
|
||||
uint32_t GetOui(void) const
|
||||
{
|
||||
return (static_cast<uint32_t>(mOui[0]) << 16) | (static_cast<uint32_t>(mOui[1]) << 8) |
|
||||
static_cast<uint32_t>(mOui[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the Vendor OUI value.
|
||||
*
|
||||
* @param[in] aOui The Vendor OUI value.
|
||||
*
|
||||
*/
|
||||
void SetOui(uint32_t aOui)
|
||||
{
|
||||
mOui[0] = (aOui >> 16) & 0xff;
|
||||
mOui[1] = (aOui >> 8) & 0xff;
|
||||
mOui[2] = aOui & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Adv Data length.
|
||||
*
|
||||
* @returns The AdvData length.
|
||||
*
|
||||
*/
|
||||
uint8_t GetAdvDataLength(void) const { return GetLength() - sizeof(mOui); }
|
||||
|
||||
/**
|
||||
* This method returns the Adv Data value.
|
||||
*
|
||||
* @returns A pointer to the Adv Data value.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetAdvData(void) const { return mAdvData; }
|
||||
|
||||
/**
|
||||
* This method sets the Adv Data value.
|
||||
*
|
||||
* @param[in] aAdvData A pointer to the AdvData value.
|
||||
* @param[in] aAdvDataLength The length of AdvData in bytes.
|
||||
*
|
||||
*/
|
||||
void SetAdvData(const uint8_t *aAdvData, uint8_t aAdvDataLength)
|
||||
{
|
||||
OT_ASSERT((aAdvData != nullptr) && (aAdvDataLength > 0) && (aAdvDataLength <= kAdvDataMaxLength));
|
||||
|
||||
SetLength(aAdvDataLength + sizeof(mOui));
|
||||
memcpy(mAdvData, aAdvData, aAdvDataLength);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t mOui[3];
|
||||
uint8_t mAdvData[kAdvDataMaxLength];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
} // namespace MeshCoP
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -53,6 +53,7 @@ DiscoverScanner::DiscoverScanner(Instance &aInstance)
|
||||
, mScanChannels()
|
||||
, mState(kStateIdle)
|
||||
, mScanChannel(0)
|
||||
, mAdvDataLength(0)
|
||||
, mEnableFiltering(false)
|
||||
, mShouldRestorePanId(false)
|
||||
{
|
||||
@@ -66,10 +67,12 @@ otError DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
|
||||
Handler aCallback,
|
||||
void * aContext)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message * message = nullptr;
|
||||
Ip6::Address destination;
|
||||
MeshCoP::DiscoveryRequestTlv discoveryRequest;
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message * message = nullptr;
|
||||
Tlv tlv;
|
||||
Ip6::Address destination;
|
||||
MeshCoP::DiscoveryRequestTlv discoveryRequest;
|
||||
MeshCoP::JoinerAdvertisementTlv joinerAdvertisement;
|
||||
|
||||
VerifyOrExit(mState == kStateIdle, error = OT_ERROR_BUSY);
|
||||
|
||||
@@ -106,12 +109,31 @@ otError DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
|
||||
message->SetPanId(aPanId);
|
||||
SuccessOrExit(error = Get<Mle>().AppendHeader(*message, Header::kCommandDiscoveryRequest));
|
||||
|
||||
// Append MLE Discovery TLV with a single sub-TLV (MeshCoP Discovery Request).
|
||||
// Prepare sub-TLV MeshCoP Discovery Request.
|
||||
discoveryRequest.Init();
|
||||
discoveryRequest.SetVersion(kThreadVersion);
|
||||
discoveryRequest.SetJoiner(aJoiner);
|
||||
|
||||
SuccessOrExit(error = Tlv::AppendTlv(*message, Tlv::kDiscovery, &discoveryRequest, sizeof(discoveryRequest)));
|
||||
if (mAdvDataLength != 0)
|
||||
{
|
||||
// Prepare sub-TLV MeshCoP Joiner Advertisement.
|
||||
joinerAdvertisement.Init();
|
||||
joinerAdvertisement.SetOui(mOui);
|
||||
joinerAdvertisement.SetAdvData(mAdvData, mAdvDataLength);
|
||||
}
|
||||
|
||||
// Append Discovery TLV with one or two sub-TLVs.
|
||||
tlv.SetType(Tlv::kDiscovery);
|
||||
tlv.SetLength(
|
||||
static_cast<uint8_t>(discoveryRequest.GetSize() + ((mAdvDataLength != 0) ? joinerAdvertisement.GetSize() : 0)));
|
||||
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
SuccessOrExit(error = discoveryRequest.AppendTo(*message));
|
||||
|
||||
if (mAdvDataLength != 0)
|
||||
{
|
||||
SuccessOrExit(error = joinerAdvertisement.AppendTo(*message));
|
||||
}
|
||||
|
||||
destination.SetToLinkLocalAllRoutersMulticast();
|
||||
|
||||
@@ -144,6 +166,23 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError DiscoverScanner::SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit((aAdvData != nullptr) && (aAdvDataLength != 0) &&
|
||||
(aAdvDataLength <= MeshCoP::JoinerAdvertisementTlv::kAdvDataMaxLength),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
mOui = aOui;
|
||||
mAdvDataLength = aAdvDataLength;
|
||||
|
||||
memcpy(mAdvData, aAdvData, aAdvDataLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError DiscoverScanner::PrepareDiscoveryRequestFrame(Mac::TxFrame &aFrame)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
@@ -134,6 +134,19 @@ public:
|
||||
*/
|
||||
bool IsInProgress(void) const { return (mState != kStateIdle); }
|
||||
|
||||
/**
|
||||
* This method sets Joiner Advertisement.
|
||||
*
|
||||
* @param[in] aOui The Vendor OUI for Joiner Advertisement.
|
||||
* @param[in] aAdvData A pointer to AdvData for Joiner Advertisement.
|
||||
* @param[in] aAdvDataLength The length of AdvData.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set Joiner Advertisement.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid AdvData.
|
||||
*
|
||||
*/
|
||||
otError SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength);
|
||||
|
||||
private:
|
||||
enum State
|
||||
{
|
||||
@@ -160,7 +173,10 @@ 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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user