mirror of
https://github.com/espressif/openthread.git
synced 2026-08-24 19:29:52 +00:00
[meshcop] adding SteeringData class (#5040)
This commit adds a new class `MeshCoP::SteeringData` which manages the Steering Data and bloom filter generating and filtering. This commit also adds a unit test `test-steering-data` for the newly added `SteeringData` class.
This commit is contained in:
@@ -226,20 +226,18 @@ otError Commissioner::SendCommissionerSet(void)
|
||||
{
|
||||
otError error;
|
||||
otCommissioningDataset dataset;
|
||||
SteeringDataTlv steeringData;
|
||||
SteeringData & steeringData = static_cast<SteeringData &>(dataset.mSteeringData);
|
||||
Mac::ExtAddress joinerId;
|
||||
|
||||
VerifyOrExit(mState == OT_COMMISSIONER_STATE_ACTIVE, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
memset(&dataset, 0, sizeof(dataset));
|
||||
|
||||
// session id
|
||||
dataset.mSessionId = mSessionId;
|
||||
dataset.mIsSessionIdSet = true;
|
||||
|
||||
// compute bloom filter
|
||||
// Compute bloom filter
|
||||
steeringData.Init();
|
||||
steeringData.Clear();
|
||||
|
||||
for (Joiner *joiner = &mJoiners[0]; joiner < OT_ARRAY_END(mJoiners); joiner++)
|
||||
{
|
||||
@@ -250,18 +248,14 @@ otError Commissioner::SendCommissionerSet(void)
|
||||
|
||||
if (joiner->mAny)
|
||||
{
|
||||
steeringData.SetLength(1);
|
||||
steeringData.Set();
|
||||
steeringData.SetToPermitAllJoiners();
|
||||
break;
|
||||
}
|
||||
|
||||
ComputeJoinerId(joiner->mEui64, joinerId);
|
||||
steeringData.ComputeBloomFilter(joinerId);
|
||||
steeringData.UpdateBloomFilter(joinerId);
|
||||
}
|
||||
|
||||
// set bloom filter
|
||||
dataset.mSteeringData.mLength = steeringData.GetSteeringDataLength();
|
||||
memcpy(dataset.mSteeringData.m8, steeringData.GetValue(), dataset.mSteeringData.mLength);
|
||||
dataset.mIsSteeringDataSet = true;
|
||||
|
||||
SuccessOrExit(error = SendMgmtCommissionerSetRequest(dataset, NULL, 0));
|
||||
@@ -615,11 +609,8 @@ otError Commissioner::SendMgmtCommissionerSetRequest(const otCommissioningDatase
|
||||
|
||||
if (aDataset.mIsSteeringDataSet)
|
||||
{
|
||||
MeshCoP::SteeringDataTlv steeringData;
|
||||
steeringData.Init();
|
||||
steeringData.SetLength(aDataset.mSteeringData.mLength);
|
||||
SuccessOrExit(error = message->Append(&steeringData, sizeof(MeshCoP::Tlv)));
|
||||
SuccessOrExit(error = message->Append(&aDataset.mSteeringData.m8, aDataset.mSteeringData.mLength));
|
||||
SuccessOrExit(error = Tlv::AppendTlv(*message, MeshCoP::Tlv::kSteeringData, aDataset.mSteeringData.m8,
|
||||
aDataset.mSteeringData.mLength));
|
||||
}
|
||||
|
||||
if (aDataset.mIsJoinerUdpPortSet)
|
||||
|
||||
@@ -275,19 +275,11 @@ exit:
|
||||
void Joiner::SaveDiscoveredJoinerRouter(const otActiveScanResult &aResult)
|
||||
{
|
||||
uint8_t priority;
|
||||
bool doesAllowAny = true;
|
||||
JoinerRouter *end = OT_ARRAY_END(mJoinerRouters);
|
||||
bool doesAllowAny;
|
||||
JoinerRouter *end = OT_ARRAY_END(mJoinerRouters);
|
||||
JoinerRouter *entry;
|
||||
|
||||
// Check whether Steering Data allows any joiner (it is all 0xff).
|
||||
for (uint8_t i = 0; i < aResult.mSteeringData.mLength; i++)
|
||||
{
|
||||
if (aResult.mSteeringData.m8[i] != 0xff)
|
||||
{
|
||||
doesAllowAny = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
doesAllowAny = static_cast<const SteeringData &>(aResult.mSteeringData).PermitsAllJoiners();
|
||||
|
||||
otLogInfoMeshCoP("Joiner discover network: %s, pan:0x%04x, port:%d, chan:%d, rssi:%d, allow-any:%s",
|
||||
static_cast<const Mac::ExtAddress &>(aResult.mExtAddress).ToString().AsCString(), aResult.mPanId,
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
* This file implements common MeshCoP utility functions.
|
||||
*/
|
||||
|
||||
#include "meshcop.hpp"
|
||||
|
||||
#include "common/crc16.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "common/locator-getters.hpp"
|
||||
#include "crypto/pbkdf2_cmac.h"
|
||||
#include "crypto/sha256.hpp"
|
||||
@@ -40,6 +44,76 @@
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
|
||||
void SteeringData::Init(uint8_t aLength)
|
||||
{
|
||||
OT_ASSERT(aLength <= kMaxLength);
|
||||
mLength = aLength;
|
||||
memset(m8, 0, sizeof(m8));
|
||||
}
|
||||
|
||||
void SteeringData::SetToPermitAllJoiners(void)
|
||||
{
|
||||
Init(1);
|
||||
m8[0] = kPermitAll;
|
||||
}
|
||||
|
||||
void SteeringData::UpdateBloomFilter(const Mac::ExtAddress &aJoinerId)
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
OT_ASSERT((mLength > 0) && (mLength <= kMaxLength));
|
||||
|
||||
CalculateHashBitIndexes(aJoinerId, indexes);
|
||||
|
||||
SetBit(indexes.mIndex[0] % GetNumBits());
|
||||
SetBit(indexes.mIndex[1] % GetNumBits());
|
||||
}
|
||||
|
||||
bool SteeringData::Contains(const Mac::ExtAddress &aJoinerId) const
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
CalculateHashBitIndexes(aJoinerId, indexes);
|
||||
|
||||
return Contains(indexes);
|
||||
}
|
||||
|
||||
bool SteeringData::Contains(const HashBitIndexes &aIndexes) const
|
||||
{
|
||||
return (mLength > 0) && GetBit(aIndexes.mIndex[0] % GetNumBits()) && GetBit(aIndexes.mIndex[1] % GetNumBits());
|
||||
}
|
||||
|
||||
void SteeringData::CalculateHashBitIndexes(const Mac::ExtAddress &aJoinerId, HashBitIndexes &aIndexes)
|
||||
{
|
||||
Crc16 ccitt(Crc16::kCcitt);
|
||||
Crc16 ansi(Crc16::kAnsi);
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(Mac::ExtAddress); i++)
|
||||
{
|
||||
ccitt.Update(aJoinerId.m8[i]);
|
||||
ansi.Update(aJoinerId.m8[i]);
|
||||
}
|
||||
|
||||
aIndexes.mIndex[0] = ccitt.Get();
|
||||
aIndexes.mIndex[1] = ansi.Get();
|
||||
}
|
||||
|
||||
bool SteeringData::DoesAllMatch(uint8_t aMatch) const
|
||||
{
|
||||
bool matches = true;
|
||||
|
||||
for (uint8_t i = 0; i < mLength; i++)
|
||||
{
|
||||
if (m8[i] != aMatch)
|
||||
{
|
||||
matches = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId)
|
||||
{
|
||||
Crypto::Sha256 sha256;
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <openthread/instance.h>
|
||||
|
||||
#include "coap/coap.hpp"
|
||||
@@ -55,6 +57,155 @@ enum
|
||||
kBorderAgentUdpPort = 49191, ///< UDP port of border agent service.
|
||||
};
|
||||
|
||||
/**
|
||||
* This type represents Steering Data (bloom filter).
|
||||
*
|
||||
*/
|
||||
class SteeringData : public otSteeringData
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kMaxLength = OT_STEERING_DATA_MAX_LENGTH, ///< Maximum Steering Data length (in bytes).
|
||||
};
|
||||
|
||||
/**
|
||||
* This structure represents the hash bit index values for the bloom filter calculated from a Joiner ID.
|
||||
*
|
||||
* The first hash bit index is derived using CRC16-CCITT and second one using CRC16-ANSI.
|
||||
*
|
||||
*/
|
||||
struct HashBitIndexes
|
||||
{
|
||||
enum
|
||||
{
|
||||
kNumIndexes = 2, ///< Number of hash bit indexes.
|
||||
};
|
||||
|
||||
uint16_t mIndex[kNumIndexes]; ///< The hash bit index array.
|
||||
};
|
||||
|
||||
/**
|
||||
* This method initializes the Steering Data and clears the bloom filter.
|
||||
*
|
||||
* @param[in] aLength The Steering Data length (in bytes) - MUST be smaller than or equal to `kMaxLength`.
|
||||
*
|
||||
*/
|
||||
void Init(uint8_t aLength = kMaxLength);
|
||||
|
||||
/**
|
||||
* This method clears the bloom filter (all bits are cleared and no Joiner Id is accepted)..
|
||||
*
|
||||
* The Steering Data length (bloom filter length) is set to one byte with all bits cleared.
|
||||
*
|
||||
*/
|
||||
void Clear(void) { Init(1); }
|
||||
|
||||
/**
|
||||
* This method sets the bloom filter to permit all Joiner IDs.
|
||||
*
|
||||
* To permit all Joiner IDs, The Steering Data length (bloom filter length) is set to one byte with all bits set.
|
||||
*
|
||||
*/
|
||||
void SetToPermitAllJoiners(void);
|
||||
|
||||
/**
|
||||
* This method returns the Steering Data length (in bytes).
|
||||
*
|
||||
* @returns The Steering Data length (in bytes).
|
||||
*
|
||||
*/
|
||||
uint8_t GetLength(void) const { return mLength; }
|
||||
|
||||
/**
|
||||
* This method gets the Steering Data buffer (bloom filter).
|
||||
*
|
||||
* @returns A pointer to the Steering Data buffer.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetData(void) const { return m8; }
|
||||
|
||||
/**
|
||||
* This method gets the Steering Data buffer (bloom filter).
|
||||
*
|
||||
* @returns A pointer to the Steering Data buffer.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetData(void) { return m8; }
|
||||
|
||||
/**
|
||||
* This method updates the bloom filter adding the given Joiner ID.
|
||||
*
|
||||
* @param[in] aJoinerId The Joiner ID to add to bloom filter.
|
||||
*
|
||||
*/
|
||||
void UpdateBloomFilter(const Mac::ExtAddress &aJoinerId);
|
||||
|
||||
/**
|
||||
* This method indicates whether the bloom filter is empty (all the bits are cleared).
|
||||
*
|
||||
* @returns TRUE if the bloom filter is empty, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool IsEmpty(void) const { return DoesAllMatch(0); }
|
||||
|
||||
/**
|
||||
* This method indicates whether the bloom filter permits all Joiner IDs (all the bits are set).
|
||||
*
|
||||
* @returns TRUE if the bloom filter permits all Joiners IDs, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool PermitsAllJoiners(void) const { return (mLength > 0) && DoesAllMatch(kPermitAll); }
|
||||
|
||||
/**
|
||||
* This method indicates whether the bloom filter contains a given Joiner ID.
|
||||
*
|
||||
* @param[in] aJoinderId A Joiner ID.
|
||||
*
|
||||
* @returns TRUE if the bloom filter contains @p aJoinerId, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool Contains(const Mac::ExtAddress &aJoinerId) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether the bloom filter contains the hash bit indexes (derived from a Joiner ID).
|
||||
*
|
||||
* @param[in] aIndexes A hash bit index structure (derived from a Joiner ID).
|
||||
*
|
||||
* @returns TRUE if the bloom filter contains the Joiner ID mapping to @p aIndexes, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool Contains(const HashBitIndexes &aIndexes) const;
|
||||
|
||||
/**
|
||||
* This static method calculates the bloom filter hash bit indexes from a given Joiner ID.
|
||||
*
|
||||
* The first hash bit index is derived using CRC16-CCITT and second one using CRC16-ANSI.
|
||||
*
|
||||
* @param[in] aJoinerId The Joiner ID to calculate the hash bit indexes.
|
||||
* @param[out] aIndexes A reference to a `HashBitIndexes` structure to output the calculated index values.
|
||||
*
|
||||
*/
|
||||
static void CalculateHashBitIndexes(const Mac::ExtAddress &aJoinerId, HashBitIndexes &aIndexes);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kPermitAll = 0xff,
|
||||
};
|
||||
|
||||
uint8_t GetNumBits(void) const { return (mLength * CHAR_BIT); }
|
||||
|
||||
uint8_t BitIndex(uint8_t aBit) const { return (mLength - 1 - (aBit / CHAR_BIT)); }
|
||||
uint8_t BitFlag(uint8_t aBit) const { return static_cast<uint8_t>(1U << (aBit % CHAR_BIT)); };
|
||||
|
||||
bool GetBit(uint8_t aBit) const { return (m8[BitIndex(aBit)] & BitFlag(aBit)) != 0; }
|
||||
void SetBit(uint8_t aBit) { m8[BitIndex(aBit)] |= BitFlag(aBit); }
|
||||
void ClearBit(uint8_t aBit) { m8[BitIndex(aBit)] &= ~BitFlag(aBit); }
|
||||
|
||||
bool DoesAllMatch(uint8_t aMatch) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function creates Message for MeshCoP.
|
||||
*
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "meshcop_tlvs.hpp"
|
||||
|
||||
#include "common/debug.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
@@ -128,36 +129,10 @@ void NetworkNameTlv::SetNetworkName(const Mac::NameData &aNameData)
|
||||
SetLength(len);
|
||||
}
|
||||
|
||||
bool SteeringDataTlv::IsCleared(void) const
|
||||
void SteeringDataTlv::CopyTo(SteeringData &aSteeringData)
|
||||
{
|
||||
bool rval = true;
|
||||
|
||||
for (uint8_t i = 0; i < GetLength(); i++)
|
||||
{
|
||||
if (mSteeringData[i] != 0)
|
||||
{
|
||||
rval = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
void SteeringDataTlv::ComputeBloomFilter(const otExtAddress &aJoinerId)
|
||||
{
|
||||
Crc16 ccitt(Crc16::kCcitt);
|
||||
Crc16 ansi(Crc16::kAnsi);
|
||||
|
||||
for (size_t j = 0; j < sizeof(otExtAddress); j++)
|
||||
{
|
||||
uint8_t byte = aJoinerId.m8[j];
|
||||
ccitt.Update(byte);
|
||||
ansi.Update(byte);
|
||||
}
|
||||
|
||||
SetBit(ccitt.Get() % GetNumBits());
|
||||
SetBit(ansi.Get() % GetNumBits());
|
||||
aSteeringData.Init(GetSteeringDataLength());
|
||||
memcpy(aSteeringData.GetData(), mSteeringData, GetSteeringDataLength());
|
||||
}
|
||||
|
||||
bool ChannelTlv::IsValid(void) const
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include <openthread/dataset.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#include "common/crc16.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/message.hpp"
|
||||
#include "common/string.hpp"
|
||||
@@ -724,6 +723,8 @@ private:
|
||||
Mle::MeshLocalPrefix mMeshLocalPrefix;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
class SteeringData;
|
||||
|
||||
/**
|
||||
* This class implements Steering Data TLV generation and parsing.
|
||||
*
|
||||
@@ -775,88 +776,12 @@ public:
|
||||
void Clear(void) { memset(mSteeringData, 0, GetSteeringDataLength()); }
|
||||
|
||||
/**
|
||||
* Ths method sets all bits in the Bloom Filter to one.
|
||||
* This method copies the Steering Data from the TLV into a given `SteeringData` variable.
|
||||
*
|
||||
* @param[out] aSteeringData A reference to a `SteeringData` to copy into.
|
||||
*
|
||||
*/
|
||||
void Set(void) { memset(mSteeringData, 0xff, GetSteeringDataLength()); }
|
||||
|
||||
/**
|
||||
* Ths method indicates whether or not the SteeringData allows all Joiners.
|
||||
*
|
||||
* @retval TRUE If the SteeringData allows all Joiners.
|
||||
* @retval FALSE If the SteeringData doesn't allow any Joiner.
|
||||
*
|
||||
*/
|
||||
bool DoesAllowAny(void)
|
||||
{
|
||||
bool rval = true;
|
||||
|
||||
for (uint8_t i = 0; i < GetSteeringDataLength(); i++)
|
||||
{
|
||||
if (mSteeringData[i] != 0xff)
|
||||
{
|
||||
rval = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the number of bits in the Bloom Filter.
|
||||
*
|
||||
* @returns The number of bits in the Bloom Filter.
|
||||
*
|
||||
*/
|
||||
uint8_t GetNumBits(void) const { return GetSteeringDataLength() * 8; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not bit @p aBit is set.
|
||||
*
|
||||
* @param[in] aBit The bit offset.
|
||||
*
|
||||
* @retval TRUE If bit @p aBit is set.
|
||||
* @retval FALSE If bit @p aBit is not set.
|
||||
*
|
||||
*/
|
||||
bool GetBit(uint8_t aBit) const
|
||||
{
|
||||
return (mSteeringData[GetSteeringDataLength() - 1 - (aBit / 8)] & (1 << (aBit % 8))) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method clears bit @p aBit.
|
||||
*
|
||||
* @param[in] aBit The bit offset.
|
||||
*
|
||||
*/
|
||||
void ClearBit(uint8_t aBit) { mSteeringData[GetSteeringDataLength() - 1 - (aBit / 8)] &= ~(1 << (aBit % 8)); }
|
||||
|
||||
/**
|
||||
* This method sets bit @p aBit.
|
||||
*
|
||||
* @param[in] aBit The bit offset.
|
||||
*
|
||||
*/
|
||||
void SetBit(uint8_t aBit) { mSteeringData[GetSteeringDataLength() - 1 - (aBit / 8)] |= 1 << (aBit % 8); }
|
||||
|
||||
/**
|
||||
* Ths method indicates whether or not the SteeringData is all zeros.
|
||||
*
|
||||
* @retval TRUE If the SteeringData is all zeros.
|
||||
* @retval FALSE If the SteeringData isn't all zeros.
|
||||
*
|
||||
*/
|
||||
bool IsCleared(void) const;
|
||||
|
||||
/**
|
||||
* This method computes the Bloom Filter.
|
||||
*
|
||||
* @param[in] aJoinerId The Joiner ID.
|
||||
*
|
||||
*/
|
||||
void ComputeBloomFilter(const otExtAddress &aJoinerId);
|
||||
void CopyTo(SteeringData &aSteeringData);
|
||||
|
||||
private:
|
||||
uint8_t mSteeringData[OT_STEERING_DATA_MAX_LENGTH];
|
||||
|
||||
+20
-26
@@ -92,8 +92,6 @@ Mle::Mle(Instance &aInstance)
|
||||
, mTimeout(kMleEndDeviceTimeout)
|
||||
, mDiscoverHandler(NULL)
|
||||
, mDiscoverContext(NULL)
|
||||
, mDiscoverCcittIndex(0)
|
||||
, mDiscoverAnsiIndex(0)
|
||||
, mDiscoverInProgress(false)
|
||||
, mDiscoverEnableFiltering(false)
|
||||
#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
|
||||
@@ -525,21 +523,11 @@ otError Mle::Discover(const Mac::ChannelMask &aScanChannels,
|
||||
if (mDiscoverEnableFiltering)
|
||||
{
|
||||
Mac::ExtAddress extAddress;
|
||||
Crc16 ccitt(Crc16::kCcitt);
|
||||
Crc16 ansi(Crc16::kAnsi);
|
||||
|
||||
Get<Radio>().GetIeeeEui64(extAddress);
|
||||
MeshCoP::ComputeJoinerId(extAddress, extAddress);
|
||||
|
||||
// Compute bloom filter (for steering data)
|
||||
for (size_t i = 0; i < sizeof(extAddress.m8); i++)
|
||||
{
|
||||
ccitt.Update(extAddress.m8[i]);
|
||||
ansi.Update(extAddress.m8[i]);
|
||||
}
|
||||
|
||||
mDiscoverCcittIndex = ccitt.Get();
|
||||
mDiscoverAnsiIndex = ansi.Get();
|
||||
MeshCoP::SteeringData::CalculateHashBitIndexes(extAddress, mDiscoverFilterIndexes);
|
||||
}
|
||||
|
||||
mDiscoverHandler = aCallback;
|
||||
@@ -3860,7 +3848,6 @@ void Mle::HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInf
|
||||
MeshCoP::Tlv meshcopTlv;
|
||||
MeshCoP::DiscoveryResponseTlv discoveryResponse;
|
||||
MeshCoP::NetworkNameTlv networkName;
|
||||
MeshCoP::SteeringDataTlv steeringData;
|
||||
otActiveScanResult result;
|
||||
uint16_t offset;
|
||||
uint16_t end;
|
||||
@@ -3908,20 +3895,27 @@ void Mle::HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInf
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kSteeringData:
|
||||
aMessage.Read(offset, sizeof(steeringData), &steeringData);
|
||||
VerifyOrExit(steeringData.IsValid(), error = OT_ERROR_PARSE);
|
||||
|
||||
if (mDiscoverEnableFiltering)
|
||||
if (meshcopTlv.GetLength() > 0)
|
||||
{
|
||||
VerifyOrExit((steeringData.GetBit(mDiscoverCcittIndex % steeringData.GetNumBits()) &&
|
||||
steeringData.GetBit(mDiscoverAnsiIndex % steeringData.GetNumBits())),
|
||||
OT_NOOP);
|
||||
MeshCoP::SteeringData &steeringData = static_cast<MeshCoP::SteeringData &>(result.mSteeringData);
|
||||
uint8_t dataLength = MeshCoP::SteeringData::kMaxLength;
|
||||
|
||||
if (meshcopTlv.GetLength() < dataLength)
|
||||
{
|
||||
dataLength = meshcopTlv.GetLength();
|
||||
}
|
||||
|
||||
steeringData.Init(dataLength);
|
||||
|
||||
SuccessOrExit(error = Tlv::ReadTlv(aMessage, offset, steeringData.GetData(), dataLength));
|
||||
|
||||
if (mDiscoverEnableFiltering)
|
||||
{
|
||||
VerifyOrExit(steeringData.Contains(mDiscoverFilterIndexes), OT_NOOP);
|
||||
}
|
||||
|
||||
didCheckSteeringData = true;
|
||||
}
|
||||
|
||||
didCheckSteeringData = true;
|
||||
result.mSteeringData.mLength = steeringData.GetSteeringDataLength();
|
||||
memcpy(result.mSteeringData.m8, steeringData.GetValue(), result.mSteeringData.mLength);
|
||||
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kJoinerUdpPort:
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "common/timer.hpp"
|
||||
#include "mac/mac.hpp"
|
||||
#include "meshcop/joiner_router.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "net/udp6.hpp"
|
||||
#include "thread/mle_tlvs.hpp"
|
||||
#include "thread/mle_types.hpp"
|
||||
@@ -1787,12 +1788,11 @@ private:
|
||||
Ip6::UdpSocket mSocket;
|
||||
uint32_t mTimeout;
|
||||
|
||||
DiscoverHandler mDiscoverHandler;
|
||||
void * mDiscoverContext;
|
||||
uint16_t mDiscoverCcittIndex;
|
||||
uint16_t mDiscoverAnsiIndex;
|
||||
bool mDiscoverInProgress;
|
||||
bool mDiscoverEnableFiltering;
|
||||
DiscoverHandler mDiscoverHandler;
|
||||
void * mDiscoverContext;
|
||||
MeshCoP::SteeringData::HashBitIndexes mDiscoverFilterIndexes;
|
||||
bool mDiscoverInProgress;
|
||||
bool mDiscoverEnableFiltering;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
|
||||
uint16_t mPreviousParentRloc;
|
||||
|
||||
@@ -92,6 +92,10 @@ MleRouter::MleRouter(Instance &aInstance)
|
||||
mDeviceMode.Set(mDeviceMode.Get() | DeviceMode::kModeFullThreadDevice | DeviceMode::kModeFullNetworkData);
|
||||
|
||||
SetRouterId(kInvalidRouterId);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
mSteeringData.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MleRouter::HandlePartitionChange(void)
|
||||
@@ -2756,27 +2760,21 @@ void MleRouter::SetSteeringData(const Mac::ExtAddress *aExtAddress)
|
||||
nullExtAddr.Clear();
|
||||
allowAnyExtAddr.Fill(0xff);
|
||||
|
||||
mSteeringData.Init();
|
||||
|
||||
if ((aExtAddress == NULL) || (*aExtAddress == nullExtAddr))
|
||||
{
|
||||
// Clear steering data
|
||||
mSteeringData.Clear();
|
||||
}
|
||||
else if (*aExtAddress == allowAnyExtAddr)
|
||||
{
|
||||
// Set steering data to 0xFF
|
||||
mSteeringData.SetLength(1);
|
||||
mSteeringData.Set();
|
||||
mSteeringData.SetToPermitAllJoiners();
|
||||
}
|
||||
else
|
||||
{
|
||||
Mac::ExtAddress joinerId;
|
||||
|
||||
// compute Joiner ID
|
||||
mSteeringData.Init();
|
||||
MeshCoP::ComputeJoinerId(*aExtAddress, joinerId);
|
||||
// compute Bloom Filter
|
||||
mSteeringData.ComputeBloomFilter(joinerId);
|
||||
mSteeringData.UpdateBloomFilter(joinerId);
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
@@ -2816,13 +2814,12 @@ void MleRouter::HandleDiscoveryRequest(const Message &aMessage, const Ip6::Messa
|
||||
if (discoveryRequest.IsJoiner())
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
|
||||
if (!mSteeringData.IsCleared())
|
||||
if (!mSteeringData.IsEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else // if steering data is not set out of band, fall back to network data
|
||||
#endif // OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
#endif
|
||||
{
|
||||
VerifyOrExit(Get<NetworkData::Leader>().IsJoiningEnabled(), error = OT_ERROR_SECURITY);
|
||||
}
|
||||
@@ -2861,7 +2858,6 @@ otError MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, uint1
|
||||
Tlv tlv;
|
||||
MeshCoP::DiscoveryResponseTlv discoveryResponse;
|
||||
MeshCoP::NetworkNameTlv networkName;
|
||||
const MeshCoP::Tlv * steeringData;
|
||||
uint16_t delay;
|
||||
|
||||
VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
@@ -2903,17 +2899,18 @@ otError MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, uint1
|
||||
SuccessOrExit(error = networkName.AppendTo(*message));
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
|
||||
// If steering data is set out of band, use that value.
|
||||
// Otherwise use the one from commissioning data.
|
||||
if (!mSteeringData.IsCleared())
|
||||
if (!mSteeringData.IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = mSteeringData.AppendTo(*message));
|
||||
SuccessOrExit(error = Tlv::AppendTlv(*message, MeshCoP::Tlv::kSteeringData, mSteeringData.GetData(),
|
||||
mSteeringData.GetLength()));
|
||||
}
|
||||
else
|
||||
#endif // OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
#endif
|
||||
{
|
||||
// Steering Data TLV
|
||||
const MeshCoP::Tlv *steeringData;
|
||||
|
||||
steeringData = Get<NetworkData::Leader>().GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
|
||||
|
||||
if (steeringData != NULL)
|
||||
|
||||
@@ -569,7 +569,7 @@ public:
|
||||
*
|
||||
*/
|
||||
void SetSteeringData(const Mac::ExtAddress *aExtAddress);
|
||||
#endif // OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method gets the assigned parent priority.
|
||||
@@ -856,8 +856,8 @@ private:
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
MeshCoP::SteeringDataTlv mSteeringData;
|
||||
#endif // OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
|
||||
MeshCoP::SteeringData mSteeringData;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
@@ -425,6 +425,28 @@ target_link_libraries(test-pskc
|
||||
|
||||
add_test(NAME test-pskc COMMAND test-pskc)
|
||||
|
||||
add_executable(test-steering-data
|
||||
${COMMON_SOURCES}
|
||||
test_steering_data.cpp
|
||||
)
|
||||
|
||||
target_include_directories(test-steering-data
|
||||
PRIVATE
|
||||
${COMMON_INCLUDES}
|
||||
)
|
||||
|
||||
target_compile_options(test-steering-data
|
||||
PRIVATE
|
||||
${COMMON_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_link_libraries(test-steering-data
|
||||
PRIVATE
|
||||
${COMMON_LIBS}
|
||||
)
|
||||
|
||||
add_test(NAME test-steering-data COMMAND test-steering-data)
|
||||
|
||||
add_executable(test-string
|
||||
${COMMON_SOURCES}
|
||||
test_string.cpp
|
||||
|
||||
@@ -123,6 +123,7 @@ check_PROGRAMS += \
|
||||
test-network-data \
|
||||
test-priority-queue \
|
||||
test-pskc \
|
||||
test-steering-data \
|
||||
test-string \
|
||||
test-timer \
|
||||
$(NULL)
|
||||
@@ -222,6 +223,9 @@ test_priority_queue_SOURCES = $(COMMON_SOURCES) test_priority_queue.cpp
|
||||
test_pskc_LDADD = $(COMMON_LDADD)
|
||||
test_pskc_SOURCES = $(COMMON_SOURCES) test_pskc.cpp
|
||||
|
||||
test_steering_data_LDADD = $(COMMON_LDADD)
|
||||
test_steering_data_SOURCES = $(COMMON_SOURCES) test_steering_data.cpp
|
||||
|
||||
test_string_LDADD = $(COMMON_LDADD)
|
||||
test_string_SOURCES = $(COMMON_SOURCES) test_string.cpp
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2020, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "test_platform.h"
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include "test_util.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
void TestSteeringData(void)
|
||||
{
|
||||
MeshCoP::SteeringData steeringData;
|
||||
MeshCoP::SteeringData::HashBitIndexes indexes;
|
||||
Mac::ExtAddress joinerId1;
|
||||
Mac::ExtAddress joinerId2;
|
||||
|
||||
const uint8_t kAddress1[sizeof(Mac::ExtAddress)] = {0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x16};
|
||||
const uint8_t kAddress2[sizeof(Mac::ExtAddress)] = {0xbe, 0xef, 0xca, 0xfe, 0xde, 0xad, 0xba, 0xbe};
|
||||
|
||||
joinerId1.Set(kAddress1);
|
||||
joinerId2.Set(kAddress2);
|
||||
|
||||
MeshCoP::SteeringData::CalculateHashBitIndexes(joinerId2, indexes);
|
||||
|
||||
steeringData.SetToPermitAllJoiners();
|
||||
|
||||
DumpBuffer("After SetToPermitAllJoiners()", steeringData.GetData(), steeringData.GetLength());
|
||||
VerifyOrQuit(steeringData.GetLength() == 1, "GetLength is incorrect after SetToPermitAllJoiners()");
|
||||
VerifyOrQuit(steeringData.PermitsAllJoiners(), "PermitsAllJoiners() failed after SetToPermitAllJoiners()");
|
||||
VerifyOrQuit(!steeringData.IsEmpty(), "IsEmpty() failed after SetToPermitAllJoiners()");
|
||||
VerifyOrQuit(steeringData.Contains(joinerId1), "Contains(joinerId1) failed after SetToPermitAllJoiners()");
|
||||
VerifyOrQuit(steeringData.Contains(joinerId2), "Contains(joinerId2) failed after SetToPermitAllJoiners()");
|
||||
VerifyOrQuit(steeringData.Contains(indexes), "Contains(indexes) failed after SetToPermitAllJoiners()");
|
||||
|
||||
steeringData.Clear();
|
||||
|
||||
DumpBuffer("After Clear()", steeringData.GetData(), steeringData.GetLength());
|
||||
VerifyOrQuit(steeringData.GetLength() == 1, "GetLength is incorrect after Clear()");
|
||||
VerifyOrQuit(!steeringData.PermitsAllJoiners(), "PermitsAllJoiners() failed after Clear()");
|
||||
VerifyOrQuit(steeringData.IsEmpty(), "IsEmpty() failed after Clear()");
|
||||
VerifyOrQuit(!steeringData.Contains(joinerId1), "Contains(joinerId1) failed after Clear()");
|
||||
VerifyOrQuit(!steeringData.Contains(joinerId2), "Contains(joinerId2) failed after Clear()");
|
||||
VerifyOrQuit(!steeringData.Contains(indexes), "Contains(indexes) failed after Clear()");
|
||||
|
||||
for (uint8_t len = 1; len <= MeshCoP::SteeringData::kMaxLength; len++)
|
||||
{
|
||||
printf("\n--------------------------------------------");
|
||||
|
||||
steeringData.Init(len);
|
||||
|
||||
VerifyOrQuit(steeringData.GetLength() == len, "GetLength is incorrect after Init()");
|
||||
VerifyOrQuit(steeringData.IsEmpty(), "IsEmpy() failed after Init()");
|
||||
VerifyOrQuit(!steeringData.PermitsAllJoiners(), "PermitsAllJoiners() failed after Init()");
|
||||
VerifyOrQuit(!steeringData.Contains(joinerId1), "Contains(joinerId1) failed after Init()");
|
||||
VerifyOrQuit(!steeringData.Contains(joinerId2), "Contains(joinerId2) failed after Init()");
|
||||
VerifyOrQuit(!steeringData.Contains(indexes), "Contains(indexes) failed after Init()");
|
||||
|
||||
steeringData.UpdateBloomFilter(joinerId1);
|
||||
DumpBuffer("After UpdateBloomFilter(joinerId1)", steeringData.GetData(), steeringData.GetLength());
|
||||
VerifyOrQuit(steeringData.GetLength() == len, "GetLength is incorrect after UpdateBloomFilter()");
|
||||
VerifyOrQuit(!steeringData.IsEmpty(), "IsEmpy() failed after UpdateBloomFilter()");
|
||||
VerifyOrQuit(!steeringData.PermitsAllJoiners(), "PermitsAllJoiners() failed after UpdateBloomFilter");
|
||||
VerifyOrQuit(steeringData.Contains(joinerId1), "Contains(joinerId1) failed after UpdateBloomFilter");
|
||||
|
||||
steeringData.UpdateBloomFilter(joinerId2);
|
||||
DumpBuffer("After UpdateBloomFilter(joinerId2)", steeringData.GetData(), steeringData.GetLength());
|
||||
VerifyOrQuit(steeringData.GetLength() == len, "GetLength is incorrect after UpdateBloomFilter()");
|
||||
VerifyOrQuit(!steeringData.IsEmpty(), "IsEmpy() failed after UpdateBloomFilter()");
|
||||
VerifyOrQuit(!steeringData.PermitsAllJoiners(), "PermitsAllJoiners() failed after UpdateBloomFilter");
|
||||
VerifyOrQuit(steeringData.Contains(joinerId1), "Contains(joinerId1) failed after UpdateBloomFilter");
|
||||
VerifyOrQuit(steeringData.Contains(joinerId2), "Contains(joinerId2) failed after UpdateBloomFilter");
|
||||
VerifyOrQuit(steeringData.Contains(indexes), "Contains(joinerId2) failed after UpdateBloomFilter");
|
||||
}
|
||||
|
||||
steeringData.Init(0);
|
||||
|
||||
VerifyOrQuit(steeringData.GetLength() == 0, "GetLength is incorrect after Init()");
|
||||
VerifyOrQuit(steeringData.IsEmpty(), "IsEmpy() failed after Init()");
|
||||
VerifyOrQuit(!steeringData.PermitsAllJoiners(), "PermitsAllJoiners() failed after Init()");
|
||||
VerifyOrQuit(!steeringData.Contains(joinerId1), "Contains(joinerId1) failed after Init()");
|
||||
VerifyOrQuit(!steeringData.Contains(joinerId2), "Contains(joinerId2) failed after Init()");
|
||||
VerifyOrQuit(!steeringData.Contains(indexes), "Contains(indexes) failed after Init()");
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ot::TestSteeringData();
|
||||
printf("\nAll tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user