mirror of
https://github.com/espressif/openthread.git
synced 2026-08-24 19:29:52 +00:00
[mle] update RouteTlv to check number of allocated IDs (#8463)
This commit contains smaller enhancements in `RouteTlv`: - `RouteTlv::IsValid()` checks that number of allocated IDs in the Router ID Mask is less than max number of routers. - It also checks that the TLV contains correct number of Route Data entries matching the number of allocated router IDs. - A new method `SetRouteData()` is added to set all the data fields (link quality in/out and route cost) for a given router index. - These changes help ensure that messages containing invalid `RouteTlv` are rejected (avoid situation where we may have more allocated router IDs than max routers).
This commit is contained in:
@@ -342,6 +342,7 @@ LOCAL_SRC_FILES := \
|
||||
src/core/thread/mesh_forwarder_mtd.cpp \
|
||||
src/core/thread/mle.cpp \
|
||||
src/core/thread/mle_router.cpp \
|
||||
src/core/thread/mle_tlvs.cpp \
|
||||
src/core/thread/mle_types.cpp \
|
||||
src/core/thread/mlr_manager.cpp \
|
||||
src/core/thread/neighbor_table.cpp \
|
||||
|
||||
@@ -639,6 +639,7 @@ openthread_core_files = [
|
||||
"thread/mle.hpp",
|
||||
"thread/mle_router.cpp",
|
||||
"thread/mle_router.hpp",
|
||||
"thread/mle_tlvs.cpp",
|
||||
"thread/mle_tlvs.hpp",
|
||||
"thread/mle_types.cpp",
|
||||
"thread/mle_types.hpp",
|
||||
|
||||
@@ -209,6 +209,7 @@ set(COMMON_SOURCES
|
||||
thread/mesh_forwarder_mtd.cpp
|
||||
thread/mle.cpp
|
||||
thread/mle_router.cpp
|
||||
thread/mle_tlvs.cpp
|
||||
thread/mle_types.cpp
|
||||
thread/mlr_manager.cpp
|
||||
thread/neighbor_table.cpp
|
||||
|
||||
@@ -299,6 +299,7 @@ SOURCES_COMMON = \
|
||||
thread/mesh_forwarder_mtd.cpp \
|
||||
thread/mle.cpp \
|
||||
thread/mle_router.cpp \
|
||||
thread/mle_tlvs.cpp \
|
||||
thread/mle_types.cpp \
|
||||
thread/mlr_manager.cpp \
|
||||
thread/neighbor_table.cpp \
|
||||
|
||||
@@ -200,6 +200,33 @@ inline unsigned long ToUlong(uint32_t aUint32)
|
||||
return static_cast<unsigned long>(aUint32);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function counts the number of `1` bits in the binary representation of a given unsigned int bit-mask value.
|
||||
*
|
||||
* @tparam UintType The unsigned int type (MUST be `uint8_t`, uint16_t`, uint32_t`, or `uint64_t`).
|
||||
*
|
||||
* @param[in] aMask A bit mask.
|
||||
*
|
||||
* @returns The number of `1` bits in @p aMask.
|
||||
*
|
||||
*/
|
||||
template <typename UintType> uint8_t CountBitsInMask(UintType aMask)
|
||||
{
|
||||
static_assert(TypeTraits::IsSame<UintType, uint8_t>::kValue || TypeTraits::IsSame<UintType, uint16_t>::kValue ||
|
||||
TypeTraits::IsSame<UintType, uint32_t>::kValue || TypeTraits::IsSame<UintType, uint64_t>::kValue,
|
||||
"UintType must be `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`");
|
||||
|
||||
uint8_t count = 0;
|
||||
|
||||
while (aMask != 0)
|
||||
{
|
||||
aMask &= aMask - 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // NUM_UTILS_HPP_
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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 function for generating and processing MLE TLVs.
|
||||
*/
|
||||
|
||||
#include "mle_tlvs.hpp"
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Mle {
|
||||
|
||||
#if !OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
|
||||
|
||||
void RouteTlv::Init(void)
|
||||
{
|
||||
SetType(kRoute);
|
||||
SetLength(sizeof(*this) - sizeof(Tlv));
|
||||
mRouterIdMask.Clear();
|
||||
memset(mRouteData, 0, sizeof(mRouteData));
|
||||
}
|
||||
|
||||
bool RouteTlv::IsValid(void) const
|
||||
{
|
||||
bool isValid = false;
|
||||
uint8_t numAllocatedIds;
|
||||
|
||||
VerifyOrExit(GetLength() >= sizeof(mRouterIdSequence) + sizeof(mRouterIdMask));
|
||||
|
||||
numAllocatedIds = mRouterIdMask.GetNumberOfAllocatedIds();
|
||||
VerifyOrExit(numAllocatedIds <= Mle::kMaxRouters);
|
||||
|
||||
isValid = (GetRouteDataLength() >= numAllocatedIds);
|
||||
|
||||
exit:
|
||||
return isValid;
|
||||
}
|
||||
|
||||
#endif // #if !OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
|
||||
|
||||
} // namespace Mle
|
||||
} // namespace ot
|
||||
@@ -256,13 +256,7 @@ public:
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
SetType(kRoute);
|
||||
SetLength(sizeof(*this) - sizeof(Tlv));
|
||||
mRouterIdMask.Clear();
|
||||
memset(mRouteData, 0, sizeof(mRouteData));
|
||||
}
|
||||
void Init(void);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
@@ -271,7 +265,7 @@ public:
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return GetLength() >= sizeof(mRouterIdSequence) + sizeof(mRouterIdMask); }
|
||||
bool IsValid(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the Router ID Sequence value.
|
||||
@@ -340,18 +334,6 @@ public:
|
||||
*/
|
||||
uint8_t GetRouteCost(uint8_t aRouterIndex) const { return mRouteData[aRouterIndex] & kRouteCostMask; }
|
||||
|
||||
/**
|
||||
* This method sets the Route Cost value for a given Router index.
|
||||
*
|
||||
* @param[in] aRouterIndex The Router index.
|
||||
* @param[in] aRouteCost The Route Cost value.
|
||||
*
|
||||
*/
|
||||
void SetRouteCost(uint8_t aRouterIndex, uint8_t aRouteCost)
|
||||
{
|
||||
mRouteData[aRouterIndex] = (mRouteData[aRouterIndex] & ~kRouteCostMask) | aRouteCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Link Quality In value for a given Router index.
|
||||
*
|
||||
@@ -365,19 +347,6 @@ public:
|
||||
return static_cast<LinkQuality>((mRouteData[aRouterIndex] & kLinkQualityInMask) >> kLinkQualityInOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the Link Quality In value for a given Router index.
|
||||
*
|
||||
* @param[in] aRouterIndex The Router index.
|
||||
* @param[in] aLinkQuality The Link Quality In value for a given Router index.
|
||||
*
|
||||
*/
|
||||
void SetLinkQualityIn(uint8_t aRouterIndex, LinkQuality aLinkQuality)
|
||||
{
|
||||
mRouteData[aRouterIndex] = (mRouteData[aRouterIndex] & ~kLinkQualityInMask) |
|
||||
((aLinkQuality << kLinkQualityInOffset) & kLinkQualityInMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Link Quality Out value for a given Router index.
|
||||
*
|
||||
@@ -392,16 +361,19 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the Link Quality Out value for a given Router index.
|
||||
* This method sets the Route Data (Link Quality In/Out and Route Cost) for a given Router index.
|
||||
*
|
||||
* @param[in] aRouterIndex The Router index.
|
||||
* @param[in] aLinkQuality The Link Quality Out value for a given Router index.
|
||||
* @param[in] aRouterIndex The Router index.
|
||||
* @param[in] aLinkQualityIn The Link Quality In value.
|
||||
* @param[in] aLinkQualityOut The Link Quality Out value.
|
||||
* @param[in] aRouteCost The Route Cost value.
|
||||
*
|
||||
*/
|
||||
void SetLinkQualityOut(uint8_t aRouterIndex, LinkQuality aLinkQuality)
|
||||
void SetRouteData(uint8_t aRouterIndex, LinkQuality aLinkQualityIn, LinkQuality aLinkQualityOut, uint8_t aRouteCost)
|
||||
{
|
||||
mRouteData[aRouterIndex] = (mRouteData[aRouterIndex] & ~kLinkQualityOutMask) |
|
||||
((aLinkQuality << kLinkQualityOutOffset) & kLinkQualityOutMask);
|
||||
mRouteData[aRouterIndex] = (((aLinkQualityIn << kLinkQualityInOffset) & kLinkQualityInMask) |
|
||||
((aLinkQualityOut << kLinkQualityOutOffset) & kLinkQualityOutMask) |
|
||||
((aRouteCost << kRouteCostOffset) & kRouteCostMask));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -538,30 +510,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the Route Cost value for a given Router index.
|
||||
*
|
||||
* @param[in] aRouterIndex The Router index.
|
||||
* @param[in] aRouteCost The Route Cost value.
|
||||
*
|
||||
*/
|
||||
void SetRouteCost(uint8_t aRouterIndex, uint8_t aRouteCost)
|
||||
{
|
||||
if (aRouterIndex & 1)
|
||||
{
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2 + 1] = aRouteCost;
|
||||
}
|
||||
else
|
||||
{
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2] =
|
||||
(mRouteData[aRouterIndex + aRouterIndex / 2] & ~kRouteCostMask) |
|
||||
((aRouteCost >> kOddEntryOffset) & kRouteCostMask);
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2 + 1] = static_cast<uint8_t>(
|
||||
(mRouteData[aRouterIndex + aRouterIndex / 2 + 1] & ~(kRouteCostMask << kOddEntryOffset)) |
|
||||
((aRouteCost & kRouteCostMask) << kOddEntryOffset));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Link Quality In value for a given Router index.
|
||||
*
|
||||
@@ -570,26 +518,12 @@ public:
|
||||
* @returns The Link Quality In value for a given Router index.
|
||||
*
|
||||
*/
|
||||
uint8_t GetLinkQualityIn(uint8_t aRouterIndex) const
|
||||
LinkQuality GetLinkQualityIn(uint8_t aRouterIndex) const
|
||||
{
|
||||
int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
|
||||
return (mRouteData[aRouterIndex + aRouterIndex / 2] & (kLinkQualityInMask >> offset)) >>
|
||||
(kLinkQualityInOffset - offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the Link Quality In value for a given Router index.
|
||||
*
|
||||
* @param[in] aRouterIndex The Router index.
|
||||
* @param[in] aLinkQuality The Link Quality In value for a given Router index.
|
||||
*
|
||||
*/
|
||||
void SetLinkQualityIn(uint8_t aRouterIndex, uint8_t aLinkQuality)
|
||||
{
|
||||
int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2] =
|
||||
(mRouteData[aRouterIndex + aRouterIndex / 2] & ~(kLinkQualityInMask >> offset)) |
|
||||
((aLinkQuality << (kLinkQualityInOffset - offset)) & (kLinkQualityInMask >> offset));
|
||||
return static_cast<LinkQuality>(
|
||||
(mRouteData[aRouterIndex + aRouterIndex / 2] & (kLinkQualityInMask >> offset)) >>
|
||||
(kLinkQualityInOffset - offset));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -609,18 +543,19 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the Link Quality Out value for a given Router index.
|
||||
* This method sets the Route Data (Link Quality In/Out and Route Cost) for a given Router index.
|
||||
*
|
||||
* @param[in] aRouterIndex The Router index.
|
||||
* @param[in] aLinkQuality The Link Quality Out value for a given Router index.
|
||||
* @param[in] aRouterIndex The Router index.
|
||||
* @param[in] aLinkQualityIn The Link Quality In value.
|
||||
* @param[in] aLinkQualityOut The Link Quality Out value.
|
||||
* @param[in] aRouteCost The Route Cost value.
|
||||
*
|
||||
*/
|
||||
void SetLinkQualityOut(uint8_t aRouterIndex, LinkQuality aLinkQuality)
|
||||
void SetRouteData(uint8_t aRouterIndex, LinkQuality aLinkQualityIn, LinkQuality aLinkQualityOut, uint8_t aRouteCost)
|
||||
{
|
||||
int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2] =
|
||||
(mRouteData[aRouterIndex + aRouterIndex / 2] & ~(kLinkQualityOutMask >> offset)) |
|
||||
((aLinkQuality << (kLinkQualityOutOffset - offset)) & (kLinkQualityOutMask >> offset));
|
||||
SetLinkQualityIn(aRouterIndex, aLinkQualityIn);
|
||||
SetLinkQualityOut(aRouterIndex, aLinkQualityOut);
|
||||
SetRouteCost(aRouterIndex, aRouteCost);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -632,6 +567,39 @@ private:
|
||||
static constexpr uint8_t kRouteCostMask = 0xf << kRouteCostOffset;
|
||||
static constexpr uint8_t kOddEntryOffset = 4;
|
||||
|
||||
void SetRouteCost(uint8_t aRouterIndex, uint8_t aRouteCost)
|
||||
{
|
||||
if (aRouterIndex & 1)
|
||||
{
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2 + 1] = aRouteCost;
|
||||
}
|
||||
else
|
||||
{
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2] =
|
||||
(mRouteData[aRouterIndex + aRouterIndex / 2] & ~kRouteCostMask) |
|
||||
((aRouteCost >> kOddEntryOffset) & kRouteCostMask);
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2 + 1] = static_cast<uint8_t>(
|
||||
(mRouteData[aRouterIndex + aRouterIndex / 2 + 1] & ~(kRouteCostMask << kOddEntryOffset)) |
|
||||
((aRouteCost & kRouteCostMask) << kOddEntryOffset));
|
||||
}
|
||||
}
|
||||
|
||||
void SetLinkQualityIn(uint8_t aRouterIndex, uint8_t aLinkQuality)
|
||||
{
|
||||
int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2] =
|
||||
(mRouteData[aRouterIndex + aRouterIndex / 2] & ~(kLinkQualityInMask >> offset)) |
|
||||
((aLinkQuality << (kLinkQualityInOffset - offset)) & (kLinkQualityInMask >> offset));
|
||||
}
|
||||
|
||||
void SetLinkQualityOut(uint8_t aRouterIndex, LinkQuality aLinkQuality)
|
||||
{
|
||||
int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0);
|
||||
mRouteData[aRouterIndex + aRouterIndex / 2] =
|
||||
(mRouteData[aRouterIndex + aRouterIndex / 2] & ~(kLinkQualityOutMask >> offset)) |
|
||||
((aLinkQuality << (kLinkQualityOutOffset - offset)) & (kLinkQualityOutMask >> offset));
|
||||
}
|
||||
|
||||
uint8_t mRouterIdSequence;
|
||||
RouterIdSet mRouterIdMask;
|
||||
// Since we do hold 12 (compressible to 11) bits of data per router, each entry occupies 1.5 bytes,
|
||||
|
||||
@@ -64,6 +64,18 @@ DeviceMode::InfoString DeviceMode::ToString(void) const
|
||||
return string;
|
||||
}
|
||||
|
||||
uint8_t RouterIdSet::GetNumberOfAllocatedIds(void) const
|
||||
{
|
||||
uint8_t count = 0;
|
||||
|
||||
for (uint8_t byte : mRouterIdSet)
|
||||
{
|
||||
count += CountBitsInMask(byte);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
const char *RoleToString(DeviceRole aRole)
|
||||
{
|
||||
static const char *const kRoleStrings[] = {
|
||||
|
||||
@@ -540,7 +540,7 @@ public:
|
||||
* @retval FALSE If the Router ID bit is not set.
|
||||
*
|
||||
*/
|
||||
bool Contains(uint8_t aRouterId) const { return (mRouterIdSet[aRouterId / 8] & (0x80 >> (aRouterId % 8))) != 0; }
|
||||
bool Contains(uint8_t aRouterId) const { return (mRouterIdSet[aRouterId / 8] & MaskFor(aRouterId)) != 0; }
|
||||
|
||||
/**
|
||||
* This method sets a given Router ID.
|
||||
@@ -548,7 +548,7 @@ public:
|
||||
* @param[in] aRouterId The Router ID to set.
|
||||
*
|
||||
*/
|
||||
void Add(uint8_t aRouterId) { mRouterIdSet[aRouterId / 8] |= 0x80 >> (aRouterId % 8); }
|
||||
void Add(uint8_t aRouterId) { mRouterIdSet[aRouterId / 8] |= MaskFor(aRouterId); }
|
||||
|
||||
/**
|
||||
* This method removes a given Router ID.
|
||||
@@ -556,9 +556,19 @@ public:
|
||||
* @param[in] aRouterId The Router ID to remove.
|
||||
*
|
||||
*/
|
||||
void Remove(uint8_t aRouterId) { mRouterIdSet[aRouterId / 8] &= ~(0x80 >> (aRouterId % 8)); }
|
||||
void Remove(uint8_t aRouterId) { mRouterIdSet[aRouterId / 8] &= ~MaskFor(aRouterId); }
|
||||
|
||||
/**
|
||||
* This method calculates the number of allocated Router IDs in the set.
|
||||
*
|
||||
* @returns The number of allocated Router IDs in the set.
|
||||
*
|
||||
*/
|
||||
uint8_t GetNumberOfAllocatedIds(void) const;
|
||||
|
||||
private:
|
||||
static uint8_t MaskFor(uint8_t aRouterId) { return (0x80 >> (aRouterId % 8)); }
|
||||
|
||||
uint8_t mRouterIdSet[BitVectorBytes(Mle::kMaxRouterId + 1)];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
|
||||
@@ -559,9 +559,7 @@ void RouterTable::FillRouteTlv(Mle::RouteTlv &aRouteTlv, const Neighbor *aNeighb
|
||||
|
||||
if (router->GetRloc16() == Get<Mle::Mle>().GetRloc16())
|
||||
{
|
||||
aRouteTlv.SetLinkQualityIn(routerCount, kLinkQuality0);
|
||||
aRouteTlv.SetLinkQualityOut(routerCount, kLinkQuality0);
|
||||
aRouteTlv.SetRouteCost(routerCount, 1);
|
||||
aRouteTlv.SetRouteData(routerCount, kLinkQuality0, kLinkQuality0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -588,9 +586,7 @@ void RouterTable::FillRouteTlv(Mle::RouteTlv &aRouteTlv, const Neighbor *aNeighb
|
||||
routeCost = 0;
|
||||
}
|
||||
|
||||
aRouteTlv.SetRouteCost(routerCount, routeCost);
|
||||
aRouteTlv.SetLinkQualityOut(routerCount, router->GetLinkQualityOut());
|
||||
aRouteTlv.SetLinkQualityIn(routerCount, router->GetLinkQualityIn());
|
||||
aRouteTlv.SetRouteData(routerCount, router->GetLinkQualityIn(), router->GetLinkQualityOut(), routeCost);
|
||||
}
|
||||
|
||||
routerCount++;
|
||||
|
||||
@@ -131,6 +131,24 @@ void TestNumUtils(void)
|
||||
VerifyOrQuit(DivideAndRoundToClosest<uint8_t>(9, 10) == 1);
|
||||
VerifyOrQuit(DivideAndRoundToClosest<uint8_t>(10, 10) == 1);
|
||||
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(0) == 0);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(1) == 1);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(2) == 1);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(3) == 2);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(4) == 1);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(7) == 3);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(11) == 3);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(15) == 4);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(0x11) == 2);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(0xef) == 7);
|
||||
VerifyOrQuit(CountBitsInMask<uint8_t>(0xff) == 8);
|
||||
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0) == 0);
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0xff00) == 8);
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0xff) == 8);
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0xaa55) == 8);
|
||||
VerifyOrQuit(CountBitsInMask<uint16_t>(0xffff) == 16);
|
||||
|
||||
printf("TestNumUtils() passed\n");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user