mirror of
https://github.com/espressif/openthread.git
synced 2026-10-31 11:36:27 +00:00
[meshcop] move SteeringData to its own source files (#12277)
The `SteeringData` class and its related methods are moved from `meshcop.hpp` and `meshcop.cpp` to new dedicated files `steering_data.hpp` and `steering_data.cpp`. This change addresses a circular include dependency issue, allowing `SteeringData` to be included more easily in other parts of the codebase, such as `meshcop_tlvs.hpp`, without requiring forward declarations or pulling in unnecessary dependencies from the larger `meshcop.hpp` header.
This commit is contained in:
@@ -424,6 +424,8 @@ openthread_core_files = [
|
||||
"meshcop/panid_query_client.hpp",
|
||||
"meshcop/secure_transport.cpp",
|
||||
"meshcop/secure_transport.hpp",
|
||||
"meshcop/steering_data.cpp",
|
||||
"meshcop/steering_data.hpp",
|
||||
"meshcop/tcat_agent.cpp",
|
||||
"meshcop/tcat_agent.hpp",
|
||||
"meshcop/timestamp.cpp",
|
||||
|
||||
@@ -181,6 +181,7 @@ set(COMMON_SOURCES
|
||||
meshcop/network_name.cpp
|
||||
meshcop/panid_query_client.cpp
|
||||
meshcop/secure_transport.cpp
|
||||
meshcop/steering_data.cpp
|
||||
meshcop/tcat_agent.cpp
|
||||
meshcop/timestamp.cpp
|
||||
net/checksum.cpp
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
|
||||
#include "meshcop.hpp"
|
||||
|
||||
#include "common/crc.hpp"
|
||||
#include "instance/instance.hpp"
|
||||
|
||||
namespace ot {
|
||||
@@ -188,164 +187,6 @@ JoinerDiscerner::InfoString JoinerDiscerner::ToString(void) const
|
||||
return string;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// SteeringData
|
||||
|
||||
Error SteeringData::Init(uint8_t aLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsValueInRange(aLength, kMinLength, kMaxLength), error = kErrorInvalidArgs);
|
||||
|
||||
mLength = aLength;
|
||||
ClearAllBytes(m8);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error SteeringData::Init(uint8_t aLength, const uint8_t *aData)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Init(aLength));
|
||||
memcpy(m8, aData, mLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void SteeringData::SetToPermitAllJoiners(void)
|
||||
{
|
||||
IgnoreError(Init(1));
|
||||
m8[0] = kPermitAll;
|
||||
}
|
||||
|
||||
Error SteeringData::UpdateBloomFilter(const Mac::ExtAddress &aJoinerId)
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
CalculateHashBitIndexes(aJoinerId, indexes);
|
||||
|
||||
return UpdateBloomFilter(indexes);
|
||||
}
|
||||
|
||||
Error SteeringData::UpdateBloomFilter(const JoinerDiscerner &aDiscerner)
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
CalculateHashBitIndexes(aDiscerner, indexes);
|
||||
|
||||
return UpdateBloomFilter(indexes);
|
||||
}
|
||||
|
||||
Error SteeringData::UpdateBloomFilter(const HashBitIndexes &aIndexes)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsValid(), error = kErrorInvalidArgs);
|
||||
|
||||
SetBit(aIndexes.mIndex[0] % GetNumBits());
|
||||
SetBit(aIndexes.mIndex[1] % GetNumBits());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error SteeringData::MergeBloomFilterWith(const SteeringData &aOther)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsValid(), error = kErrorInvalidArgs);
|
||||
VerifyOrExit(aOther.IsValid(), error = kErrorInvalidArgs);
|
||||
|
||||
VerifyOrExit(GetLength() % aOther.GetLength() == 0, error = kErrorInvalidArgs);
|
||||
|
||||
for (uint8_t index = 0; index < GetLength(); index++)
|
||||
{
|
||||
m8[index] |= aOther.m8[index % aOther.GetLength()];
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool SteeringData::Contains(const Mac::ExtAddress &aJoinerId) const
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
CalculateHashBitIndexes(aJoinerId, indexes);
|
||||
|
||||
return Contains(indexes);
|
||||
}
|
||||
|
||||
bool SteeringData::Contains(const JoinerDiscerner &aDiscerner) const
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
CalculateHashBitIndexes(aDiscerner, indexes);
|
||||
|
||||
return Contains(indexes);
|
||||
}
|
||||
|
||||
bool SteeringData::Contains(const HashBitIndexes &aIndexes) const
|
||||
{
|
||||
bool contains = false;
|
||||
|
||||
VerifyOrExit(IsValid());
|
||||
contains = GetBit(aIndexes.mIndex[0] % GetNumBits()) && GetBit(aIndexes.mIndex[1] % GetNumBits());
|
||||
|
||||
exit:
|
||||
return contains;
|
||||
}
|
||||
|
||||
void SteeringData::CalculateHashBitIndexes(const Mac::ExtAddress &aJoinerId, HashBitIndexes &aIndexes)
|
||||
{
|
||||
aIndexes.mIndex[0] = CrcCalculator<uint16_t>(kCrc16CcittPolynomial).Feed(aJoinerId);
|
||||
aIndexes.mIndex[1] = CrcCalculator<uint16_t>(kCrc16AnsiPolynomial).Feed(aJoinerId);
|
||||
}
|
||||
|
||||
void SteeringData::CalculateHashBitIndexes(const JoinerDiscerner &aDiscerner, HashBitIndexes &aIndexes)
|
||||
{
|
||||
Mac::ExtAddress address;
|
||||
|
||||
address.Clear();
|
||||
aDiscerner.CopyTo(address);
|
||||
|
||||
CalculateHashBitIndexes(address, aIndexes);
|
||||
}
|
||||
|
||||
bool SteeringData::DoesAllMatch(uint8_t aMatch) const
|
||||
{
|
||||
bool matches = false;
|
||||
|
||||
VerifyOrExit(IsValid());
|
||||
|
||||
for (uint8_t i = 0; i < mLength; i++)
|
||||
{
|
||||
if (m8[i] != aMatch)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
matches = true;
|
||||
|
||||
exit:
|
||||
return matches;
|
||||
}
|
||||
|
||||
SteeringData::InfoString SteeringData::ToString(void) const
|
||||
{
|
||||
InfoString string;
|
||||
|
||||
string.Append("[");
|
||||
string.AppendHexBytes(GetData(), Min(GetLength(), kMaxLength));
|
||||
string.Append("]");
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId)
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include <openthread/commissioner.h>
|
||||
#include <openthread/instance.h>
|
||||
#include <openthread/joiner.h>
|
||||
#include <openthread/steering_data.h>
|
||||
|
||||
#include "coap/coap.hpp"
|
||||
#include "common/as_core_type.hpp"
|
||||
@@ -53,6 +52,7 @@
|
||||
#include "common/string.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "meshcop/meshcop_tlvs.hpp"
|
||||
#include "meshcop/steering_data.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
@@ -226,215 +226,6 @@ private:
|
||||
void CopyTo(Mac::ExtAddress &aExtAddress) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents Steering Data (bloom filter).
|
||||
*/
|
||||
class SteeringData : public otSteeringData
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kMinLength = OT_STEERING_DATA_MIN_LENGTH; ///< Minimum Steering Data length (in bytes).
|
||||
static constexpr uint8_t kMaxLength = OT_STEERING_DATA_MAX_LENGTH; ///< Maximum Steering Data length (in bytes).
|
||||
|
||||
static constexpr uint16_t kInfoStringSize = 45; ///< Size of `InfoString` to use with `ToString()`.
|
||||
|
||||
/**
|
||||
* Defines the fixed-length `String` object returned from `ToString()`.
|
||||
*/
|
||||
typedef String<kInfoStringSize> InfoString;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
static constexpr uint8_t kNumIndexes = 2; ///< Number of hash bit indexes.
|
||||
|
||||
uint16_t mIndex[kNumIndexes]; ///< The hash bit index array.
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the Steering Data and clears the bloom filter.
|
||||
*
|
||||
* @param[in] aLength The Steering Data length (in bytes).
|
||||
*
|
||||
* @retval kErrorSuccess Successfully initialized the Steering Data.
|
||||
* @retval kErrorInvalidArgs @p aLength is not valid.
|
||||
*/
|
||||
Error Init(uint8_t aLength);
|
||||
|
||||
/**
|
||||
* Initializes the Steering Data.
|
||||
*
|
||||
* @param[in] aLength The Steering Data length (in bytes).
|
||||
* @param[in] aData A pointer to a buffer containing the data bytes.
|
||||
*
|
||||
* @retval kErrorSuccess Successfully initialized the Steering Data.
|
||||
* @retval kErrorInvalidArgs @p aLength is not valid.
|
||||
*/
|
||||
Error Init(uint8_t aLength, const uint8_t *aData);
|
||||
|
||||
/**
|
||||
* Checks whether the Steering Data has a valid length.
|
||||
*
|
||||
* @returns TRUE if the Steering Data's length is valid (within min to max range), FALSE otherwise.
|
||||
*/
|
||||
bool IsValid(void) const { return IsValueInRange(mLength, kMinLength, kMaxLength); }
|
||||
|
||||
/**
|
||||
* 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) { IgnoreError(Init(1)); }
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Returns the Steering Data length (in bytes).
|
||||
*
|
||||
* @returns The Steering Data length (in bytes).
|
||||
*/
|
||||
uint8_t GetLength(void) const { return mLength; }
|
||||
|
||||
/**
|
||||
* Gets the Steering Data buffer (bloom filter).
|
||||
*
|
||||
* @returns A pointer to the Steering Data buffer.
|
||||
*/
|
||||
const uint8_t *GetData(void) const { return m8; }
|
||||
|
||||
/**
|
||||
* Gets the Steering Data buffer (bloom filter).
|
||||
*
|
||||
* @returns A pointer to the Steering Data buffer.
|
||||
*/
|
||||
uint8_t *GetData(void) { return m8; }
|
||||
|
||||
/**
|
||||
* Updates the bloom filter adding the given Joiner ID.
|
||||
*
|
||||
* @param[in] aJoinerId The Joiner ID to add to bloom filter.
|
||||
*
|
||||
* @retval kErrorNone Successfully updated the bloom filter.
|
||||
* @retval kErrorInvalidArgs The Steering Data's length is invalid.
|
||||
*/
|
||||
Error UpdateBloomFilter(const Mac::ExtAddress &aJoinerId);
|
||||
|
||||
/**
|
||||
* Updates the bloom filter adding a given Joiner Discerner.
|
||||
*
|
||||
* @param[in] aDiscerner The Joiner Discerner to add to bloom filter.
|
||||
*
|
||||
* @retval kErrorNone Successfully updated the bloom filter.
|
||||
* @retval kErrorInvalidArgs The Steering Data's length is invalid.
|
||||
*/
|
||||
Error UpdateBloomFilter(const JoinerDiscerner &aDiscerner);
|
||||
|
||||
/**
|
||||
* Merges the bloom filter by combining it with another steering data filter.
|
||||
*
|
||||
* Both bloom filters must have valid lengths (non-zero and not exceeding `kMaxLength`).
|
||||
*
|
||||
* The bloom filter from @p aOther must have a length that is a divisor of the current filter's length.
|
||||
*
|
||||
* @param[in] aOther The other bloom filter to combine with current filter.
|
||||
*
|
||||
* @retval kErrorNone Successfully merged @p aOther into the current bloom filter.
|
||||
* @retval kErrorInvalidArgs The filter lengths are not valid or they cannot be merged.
|
||||
*/
|
||||
Error MergeBloomFilterWith(const SteeringData &aOther);
|
||||
|
||||
/**
|
||||
* 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); }
|
||||
|
||||
/**
|
||||
* 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); }
|
||||
|
||||
/**
|
||||
* Indicates whether the bloom filter contains a given Joiner ID.
|
||||
*
|
||||
* @param[in] aJoinerId A Joiner ID.
|
||||
*
|
||||
* @returns TRUE if the bloom filter contains @p aJoinerId, FALSE otherwise.
|
||||
*/
|
||||
bool Contains(const Mac::ExtAddress &aJoinerId) const;
|
||||
|
||||
/**
|
||||
* Indicates whether the bloom filter contains a given Joiner Discerner.
|
||||
*
|
||||
* @param[in] aDiscerner A Joiner Discerner.
|
||||
*
|
||||
* @returns TRUE if the bloom filter contains @p aDiscerner, FALSE otherwise.
|
||||
*/
|
||||
bool Contains(const JoinerDiscerner &aDiscerner) const;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Converts the Steering Data to a human-readable string representation.
|
||||
*
|
||||
* @returns An `InfoString` representation of the Steering Data.
|
||||
*/
|
||||
InfoString ToString(void) const;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Calculates the bloom filter hash bit indexes from a given Joiner Discerner.
|
||||
*
|
||||
* The first hash bit index is derived using CRC16-CCITT and second one using CRC16-ANSI.
|
||||
*
|
||||
* @param[in] aDiscerner The Joiner Discerner 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 JoinerDiscerner &aDiscerner, HashBitIndexes &aIndexes);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kPermitAll = 0xff;
|
||||
|
||||
uint8_t GetNumBits(void) const { return (mLength * kBitsPerByte); }
|
||||
|
||||
uint8_t BitIndex(uint8_t aBit) const { return (mLength - 1 - (aBit / kBitsPerByte)); }
|
||||
uint8_t BitFlag(uint8_t aBit) const { return static_cast<uint8_t>(1U << (aBit % kBitsPerByte)); }
|
||||
|
||||
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;
|
||||
Error UpdateBloomFilter(const HashBitIndexes &aIndexes);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a Commissioning Dataset.
|
||||
*/
|
||||
@@ -592,7 +383,6 @@ void LogCertMessage(const char *aText, const Coap::Message &aMessage);
|
||||
|
||||
DefineCoreType(otJoinerPskd, MeshCoP::JoinerPskd);
|
||||
DefineCoreType(otJoinerDiscerner, MeshCoP::JoinerDiscerner);
|
||||
DefineCoreType(otSteeringData, MeshCoP::SteeringData);
|
||||
DefineCoreType(otCommissioningDataset, MeshCoP::CommissioningDataset);
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "meshcop/extended_panid.hpp"
|
||||
#include "meshcop/network_name.hpp"
|
||||
#include "meshcop/steering_data.hpp"
|
||||
#include "meshcop/timestamp.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
#include "radio/radio.hpp"
|
||||
@@ -318,8 +319,6 @@ typedef UintTlvInfo<Tlv::kNetworkKeySequence, uint32_t> NetworkKeySequenceTlv;
|
||||
*/
|
||||
typedef SimpleTlvInfo<Tlv::kMeshLocalPrefix, Ip6::NetworkPrefix> MeshLocalPrefixTlv;
|
||||
|
||||
class SteeringData;
|
||||
|
||||
/**
|
||||
* Implements Steering Data TLV generation and parsing.
|
||||
*/
|
||||
@@ -371,7 +370,7 @@ public:
|
||||
Error CopyTo(SteeringData &aSteeringData) const;
|
||||
|
||||
private:
|
||||
uint8_t mSteeringData[OT_STEERING_DATA_MAX_LENGTH];
|
||||
uint8_t mSteeringData[SteeringData::kMaxLength];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements MeshCoP Steering Data.
|
||||
*/
|
||||
|
||||
#include "steering_data.hpp"
|
||||
|
||||
#include "common/clearable.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/crc.hpp"
|
||||
#include "common/num_utils.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
|
||||
Error SteeringData::Init(uint8_t aLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsValueInRange(aLength, kMinLength, kMaxLength), error = kErrorInvalidArgs);
|
||||
|
||||
mLength = aLength;
|
||||
ClearAllBytes(m8);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error SteeringData::Init(uint8_t aLength, const uint8_t *aData)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Init(aLength));
|
||||
memcpy(m8, aData, mLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void SteeringData::SetToPermitAllJoiners(void)
|
||||
{
|
||||
IgnoreError(Init(1));
|
||||
m8[0] = kPermitAll;
|
||||
}
|
||||
|
||||
Error SteeringData::UpdateBloomFilter(const Mac::ExtAddress &aJoinerId)
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
CalculateHashBitIndexes(aJoinerId, indexes);
|
||||
|
||||
return UpdateBloomFilter(indexes);
|
||||
}
|
||||
|
||||
Error SteeringData::UpdateBloomFilter(const JoinerDiscerner &aDiscerner)
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
CalculateHashBitIndexes(aDiscerner, indexes);
|
||||
|
||||
return UpdateBloomFilter(indexes);
|
||||
}
|
||||
|
||||
Error SteeringData::UpdateBloomFilter(const HashBitIndexes &aIndexes)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsValid(), error = kErrorInvalidArgs);
|
||||
|
||||
SetBit(aIndexes.mIndex[0] % GetNumBits());
|
||||
SetBit(aIndexes.mIndex[1] % GetNumBits());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error SteeringData::MergeBloomFilterWith(const SteeringData &aOther)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsValid(), error = kErrorInvalidArgs);
|
||||
VerifyOrExit(aOther.IsValid(), error = kErrorInvalidArgs);
|
||||
|
||||
VerifyOrExit(GetLength() % aOther.GetLength() == 0, error = kErrorInvalidArgs);
|
||||
|
||||
for (uint8_t index = 0; index < GetLength(); index++)
|
||||
{
|
||||
m8[index] |= aOther.m8[index % aOther.GetLength()];
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool SteeringData::Contains(const Mac::ExtAddress &aJoinerId) const
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
CalculateHashBitIndexes(aJoinerId, indexes);
|
||||
|
||||
return Contains(indexes);
|
||||
}
|
||||
|
||||
bool SteeringData::Contains(const JoinerDiscerner &aDiscerner) const
|
||||
{
|
||||
HashBitIndexes indexes;
|
||||
|
||||
CalculateHashBitIndexes(aDiscerner, indexes);
|
||||
|
||||
return Contains(indexes);
|
||||
}
|
||||
|
||||
bool SteeringData::Contains(const HashBitIndexes &aIndexes) const
|
||||
{
|
||||
bool contains = false;
|
||||
|
||||
VerifyOrExit(IsValid());
|
||||
contains = GetBit(aIndexes.mIndex[0] % GetNumBits()) && GetBit(aIndexes.mIndex[1] % GetNumBits());
|
||||
|
||||
exit:
|
||||
return contains;
|
||||
}
|
||||
|
||||
void SteeringData::CalculateHashBitIndexes(const Mac::ExtAddress &aJoinerId, HashBitIndexes &aIndexes)
|
||||
{
|
||||
aIndexes.mIndex[0] = CrcCalculator<uint16_t>(kCrc16CcittPolynomial).Feed(aJoinerId);
|
||||
aIndexes.mIndex[1] = CrcCalculator<uint16_t>(kCrc16AnsiPolynomial).Feed(aJoinerId);
|
||||
}
|
||||
|
||||
void SteeringData::CalculateHashBitIndexes(const JoinerDiscerner &aDiscerner, HashBitIndexes &aIndexes)
|
||||
{
|
||||
Mac::ExtAddress address;
|
||||
|
||||
address.Clear();
|
||||
aDiscerner.CopyTo(address);
|
||||
|
||||
CalculateHashBitIndexes(address, aIndexes);
|
||||
}
|
||||
|
||||
bool SteeringData::DoesAllMatch(uint8_t aMatch) const
|
||||
{
|
||||
bool matches = false;
|
||||
|
||||
VerifyOrExit(IsValid());
|
||||
|
||||
for (uint8_t i = 0; i < mLength; i++)
|
||||
{
|
||||
if (m8[i] != aMatch)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
matches = true;
|
||||
|
||||
exit:
|
||||
return matches;
|
||||
}
|
||||
|
||||
SteeringData::InfoString SteeringData::ToString(void) const
|
||||
{
|
||||
InfoString string;
|
||||
|
||||
string.Append("[");
|
||||
string.AppendHexBytes(GetData(), Min(GetLength(), kMaxLength));
|
||||
string.Append("]");
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for MeshCoP Steering Data.
|
||||
*/
|
||||
|
||||
#ifndef OT_CORE_MESHCOP_STEERING_DATA_HPP_
|
||||
#define OT_CORE_MESHCOP_STEERING_DATA_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/steering_data.h>
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/error.hpp"
|
||||
#include "common/string.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
|
||||
class JoinerDiscerner;
|
||||
|
||||
/**
|
||||
* Represents Steering Data (bloom filter).
|
||||
*/
|
||||
class SteeringData : public otSteeringData
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kMinLength = OT_STEERING_DATA_MIN_LENGTH; ///< Minimum Steering Data length (in bytes).
|
||||
static constexpr uint8_t kMaxLength = OT_STEERING_DATA_MAX_LENGTH; ///< Maximum Steering Data length (in bytes).
|
||||
|
||||
static constexpr uint16_t kInfoStringSize = 45; ///< Size of `InfoString` to use with `ToString()`.
|
||||
|
||||
/**
|
||||
* Defines the fixed-length `String` object returned from `ToString()`.
|
||||
*/
|
||||
typedef String<kInfoStringSize> InfoString;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
static constexpr uint8_t kNumIndexes = 2; ///< Number of hash bit indexes.
|
||||
|
||||
uint16_t mIndex[kNumIndexes]; ///< The hash bit index array.
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the Steering Data and clears the bloom filter.
|
||||
*
|
||||
* @param[in] aLength The Steering Data length (in bytes).
|
||||
*
|
||||
* @retval kErrorSuccess Successfully initialized the Steering Data.
|
||||
* @retval kErrorInvalidArgs @p aLength is not valid.
|
||||
*/
|
||||
Error Init(uint8_t aLength);
|
||||
|
||||
/**
|
||||
* Initializes the Steering Data.
|
||||
*
|
||||
* @param[in] aLength The Steering Data length (in bytes).
|
||||
* @param[in] aData A pointer to a buffer containing the data bytes.
|
||||
*
|
||||
* @retval kErrorSuccess Successfully initialized the Steering Data.
|
||||
* @retval kErrorInvalidArgs @p aLength is not valid.
|
||||
*/
|
||||
Error Init(uint8_t aLength, const uint8_t *aData);
|
||||
|
||||
/**
|
||||
* Checks whether the Steering Data has a valid length.
|
||||
*
|
||||
* @returns TRUE if the Steering Data's length is valid (within min to max range), FALSE otherwise.
|
||||
*/
|
||||
bool IsValid(void) const { return IsValueInRange(mLength, kMinLength, kMaxLength); }
|
||||
|
||||
/**
|
||||
* 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) { IgnoreError(Init(1)); }
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Returns the Steering Data length (in bytes).
|
||||
*
|
||||
* @returns The Steering Data length (in bytes).
|
||||
*/
|
||||
uint8_t GetLength(void) const { return mLength; }
|
||||
|
||||
/**
|
||||
* Gets the Steering Data buffer (bloom filter).
|
||||
*
|
||||
* @returns A pointer to the Steering Data buffer.
|
||||
*/
|
||||
const uint8_t *GetData(void) const { return m8; }
|
||||
|
||||
/**
|
||||
* Gets the Steering Data buffer (bloom filter).
|
||||
*
|
||||
* @returns A pointer to the Steering Data buffer.
|
||||
*/
|
||||
uint8_t *GetData(void) { return m8; }
|
||||
|
||||
/**
|
||||
* Updates the bloom filter adding the given Joiner ID.
|
||||
*
|
||||
* @param[in] aJoinerId The Joiner ID to add to bloom filter.
|
||||
*
|
||||
* @retval kErrorNone Successfully updated the bloom filter.
|
||||
* @retval kErrorInvalidArgs The Steering Data's length is invalid.
|
||||
*/
|
||||
Error UpdateBloomFilter(const Mac::ExtAddress &aJoinerId);
|
||||
|
||||
/**
|
||||
* Updates the bloom filter adding a given Joiner Discerner.
|
||||
*
|
||||
* @param[in] aDiscerner The Joiner Discerner to add to bloom filter.
|
||||
*
|
||||
* @retval kErrorNone Successfully updated the bloom filter.
|
||||
* @retval kErrorInvalidArgs The Steering Data's length is invalid.
|
||||
*/
|
||||
Error UpdateBloomFilter(const JoinerDiscerner &aDiscerner);
|
||||
|
||||
/**
|
||||
* Merges the bloom filter by combining it with another steering data filter.
|
||||
*
|
||||
* Both bloom filters must have valid lengths (non-zero and not exceeding `kMaxLength`).
|
||||
*
|
||||
* The bloom filter from @p aOther must have a length that is a divisor of the current filter's length.
|
||||
*
|
||||
* @param[in] aOther The other bloom filter to combine with current filter.
|
||||
*
|
||||
* @retval kErrorNone Successfully merged @p aOther into the current bloom filter.
|
||||
* @retval kErrorInvalidArgs The filter lengths are not valid or they cannot be merged.
|
||||
*/
|
||||
Error MergeBloomFilterWith(const SteeringData &aOther);
|
||||
|
||||
/**
|
||||
* 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); }
|
||||
|
||||
/**
|
||||
* 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); }
|
||||
|
||||
/**
|
||||
* Indicates whether the bloom filter contains a given Joiner ID.
|
||||
*
|
||||
* @param[in] aJoinerId A Joiner ID.
|
||||
*
|
||||
* @returns TRUE if the bloom filter contains @p aJoinerId, FALSE otherwise.
|
||||
*/
|
||||
bool Contains(const Mac::ExtAddress &aJoinerId) const;
|
||||
|
||||
/**
|
||||
* Indicates whether the bloom filter contains a given Joiner Discerner.
|
||||
*
|
||||
* @param[in] aDiscerner A Joiner Discerner.
|
||||
*
|
||||
* @returns TRUE if the bloom filter contains @p aDiscerner, FALSE otherwise.
|
||||
*/
|
||||
bool Contains(const JoinerDiscerner &aDiscerner) const;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Converts the Steering Data to a human-readable string representation.
|
||||
*
|
||||
* @returns An `InfoString` representation of the Steering Data.
|
||||
*/
|
||||
InfoString ToString(void) const;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Calculates the bloom filter hash bit indexes from a given Joiner Discerner.
|
||||
*
|
||||
* The first hash bit index is derived using CRC16-CCITT and second one using CRC16-ANSI.
|
||||
*
|
||||
* @param[in] aDiscerner The Joiner Discerner 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 JoinerDiscerner &aDiscerner, HashBitIndexes &aIndexes);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kPermitAll = 0xff;
|
||||
|
||||
uint8_t GetNumBits(void) const { return (mLength * kBitsPerByte); }
|
||||
|
||||
uint8_t BitIndex(uint8_t aBit) const { return (mLength - 1 - (aBit / kBitsPerByte)); }
|
||||
uint8_t BitFlag(uint8_t aBit) const { return static_cast<uint8_t>(1U << (aBit % kBitsPerByte)); }
|
||||
|
||||
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;
|
||||
Error UpdateBloomFilter(const HashBitIndexes &aIndexes);
|
||||
};
|
||||
|
||||
} // namespace MeshCoP
|
||||
|
||||
DefineCoreType(otSteeringData, MeshCoP::SteeringData);
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OT_CORE_MESHCOP_STEERING_DATA_HPP_
|
||||
Reference in New Issue
Block a user