[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:
Abtin Keshavarzian
2020-06-04 13:20:17 -07:00
committed by GitHub
parent 06025122c0
commit 1d9b705a48
13 changed files with 434 additions and 189 deletions
+6 -15
View File
@@ -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)
+3 -11
View File
@@ -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,
+74
View File
@@ -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;
+151
View File
@@ -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.
*
+4 -29
View File
@@ -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
+6 -81
View File
@@ -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
View File
@@ -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:
+6 -6
View File
@@ -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;
+15 -18
View File
@@ -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)
+3 -3
View File
@@ -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
+22
View File
@@ -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
+4
View File
@@ -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
+120
View File
@@ -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;
}