[mac] adding Mac::ChannelMask class (#2560)

This commit adds a `Mac::ChannelMask` class to define a channel (a
`uint32_t` bit-vector specifying a set of channels). The `ChannelMask`
class provides methods to add/remove channel to the mask, intersect
two masks, and iterate through the channels in the mask. A unit test
for the new class is also added.
This commit is contained in:
Abtin Keshavarzian
2018-02-20 17:28:46 +00:00
committed by Jonathan Hui
parent db4759cc41
commit 4d339496e5
3 changed files with 264 additions and 19 deletions
+104
View File
@@ -29,6 +29,7 @@
#include <openthread/openthread.h>
#include "common/debug.hpp"
#include "mac/mac.hpp"
#include "mac/mac_frame.hpp"
#include "utils/wrap_string.h"
@@ -80,12 +81,115 @@ void TestMacHeader(void)
}
}
void VerifyChannelMaskContent(const Mac::ChannelMask &aMask, uint8_t *aChannels, uint8_t aLength)
{
uint8_t index = 0;
uint8_t channel;
for (channel = OT_RADIO_CHANNEL_MIN; channel <= OT_RADIO_CHANNEL_MAX; channel++)
{
if (index < aLength)
{
if (channel == aChannels[index])
{
index++;
VerifyOrQuit(aMask.ContainsChannel(channel), "ChannelMask.ContainsChannel() failed\n");
}
else
{
VerifyOrQuit(!aMask.ContainsChannel(channel), "ChannelMask.ContainsChannel() failed\n");
}
}
}
index = 0;
channel = Mac::ChannelMask::kChannelIteratorFirst;
while (aMask.GetNextChannel(channel) == OT_ERROR_NONE)
{
VerifyOrQuit(channel == aChannels[index++], "ChannelMask.GetNextChannel() failed\n");
}
VerifyOrQuit(index == aLength, "ChannelMask.GetNextChannel() failed\n");
if (aLength == 1)
{
VerifyOrQuit(aMask.IsSingleChannel(), "ChannelMask.IsSingleChannel() failed\n");
}
else
{
VerifyOrQuit(!aMask.IsSingleChannel(), "ChannelMask.IsSingleChannel() failed\n");
}
}
void TestMacChannelMask(void)
{
uint8_t all_channels[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26};
uint8_t channels1[] = {11, 14, 15, 20, 21, 26};
uint8_t channels2[] = {14, 21, 25};
uint8_t channels3[] = {14, 21};
uint8_t channles4[] = {20};
Mac::ChannelMask mask1;
Mac::ChannelMask mask2(OT_RADIO_SUPPORTED_CHANNELS);
printf("Testing Mac::ChannelMask\n");
VerifyOrQuit(mask1.IsEmpty(), "ChannelMask.IsEmpty failed\n");
VerifyOrQuit(!mask2.IsEmpty(), "ChannelMask.IsEmpty failed\n");
VerifyOrQuit(mask2.GetMask() == OT_RADIO_SUPPORTED_CHANNELS, "ChannelMask.GetMask() failed\n");
mask1.SetMask(OT_RADIO_SUPPORTED_CHANNELS);
VerifyOrQuit(!mask1.IsEmpty(), "ChannelMask.IsEmpty failed\n");
VerifyOrQuit(mask1.GetMask() == OT_RADIO_SUPPORTED_CHANNELS, "ChannelMask.GetMask() failed\n");
VerifyChannelMaskContent(mask1, all_channels, sizeof(all_channels));
// Test ChannelMask::RemoveChannel()
for (uint8_t index = 0; index < sizeof(all_channels) - 1; index++)
{
mask1.RemoveChannel(all_channels[index]);
VerifyChannelMaskContent(mask1, &all_channels[index + 1], sizeof(all_channels) - 1 - index);
}
mask1.Clear();
VerifyOrQuit(mask1.IsEmpty(), "ChannelMask.IsEmpty failed\n");
VerifyChannelMaskContent(mask1, NULL, 0);
for (uint16_t index = 0; index < sizeof(channels1); index++)
{
mask1.AddChannel(channels1[index]);
}
VerifyOrQuit(!mask1.IsEmpty(), "ChannelMask.IsEmpty failed\n");
VerifyChannelMaskContent(mask1, channels1, sizeof(channels1));
mask2.Clear();
for (uint16_t index = 0; index < sizeof(channels2); index++)
{
mask2.AddChannel(channels2[index]);
}
VerifyOrQuit(!mask2.IsEmpty(), "ChannelMask.IsEmpty failed\n");
VerifyChannelMaskContent(mask2, channels2, sizeof(channels2));
mask1.Intersect(mask2);
VerifyChannelMaskContent(mask1, channels3, sizeof(channels3));
mask2.Clear();
mask2.AddChannel(channles4[0]);
VerifyChannelMaskContent(mask2, channles4, sizeof(channles4));
}
} // namespace ot
#ifdef ENABLE_TEST_MAIN
int main(void)
{
ot::TestMacHeader();
ot::TestMacChannelMask();
printf("All tests passed\n");
return 0;
}