mirror of
https://github.com/espressif/openthread.git
synced 2026-07-09 13:50:28 +00:00
fe1cf3a294
This commit updates how we prepare the MAC headers: - New `enum`s are defined in `Mac::Frame` to specify the frame `Type`, `Version`, `SecurityLevel`, etc. - `InitMacHeader()` will itself determine the Frame Control Field from the given address info. - It now uses `FrameBuilder` to prepare the headers. - New helper `MeshForwarder::PrepareMacHeaders()` is added which takes care of adding MAC (address, security header) along with any IE headers. - These changes ensure that PAN ID Compression bit is properly set on MAC frames when using 2015 version (ensure that PAN IDs are not omitted when both addresses use Extended format).
736 lines
29 KiB
C++
736 lines
29 KiB
C++
/*
|
|
* Copyright (c) 2016, 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 "common/code_utils.hpp"
|
|
#include "common/debug.hpp"
|
|
#include "mac/mac.hpp"
|
|
#include "mac/mac_frame.hpp"
|
|
#include "radio/radio.hpp"
|
|
|
|
#include "test_platform.h"
|
|
#include "test_util.h"
|
|
|
|
namespace ot {
|
|
|
|
bool CompareReversed(const uint8_t *aFirst, const uint8_t *aSecond, uint16_t aLength)
|
|
{
|
|
bool matches = true;
|
|
|
|
for (uint16_t i = 0; i < aLength; i++)
|
|
{
|
|
if (aFirst[i] != aSecond[aLength - 1 - i])
|
|
{
|
|
matches = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return matches;
|
|
}
|
|
|
|
bool CompareAddresses(const Mac::Address &aFirst, const Mac::Address &aSecond)
|
|
{
|
|
bool matches = false;
|
|
|
|
VerifyOrExit(aFirst.GetType() == aSecond.GetType());
|
|
|
|
switch (aFirst.GetType())
|
|
{
|
|
case Mac::Address::kTypeNone:
|
|
break;
|
|
case Mac::Address::kTypeShort:
|
|
VerifyOrExit(aFirst.GetShort() == aSecond.GetShort());
|
|
break;
|
|
case Mac::Address::kTypeExtended:
|
|
VerifyOrExit(aFirst.GetExtended() == aSecond.GetExtended());
|
|
break;
|
|
}
|
|
|
|
matches = true;
|
|
|
|
exit:
|
|
return matches;
|
|
}
|
|
|
|
void TestMacAddress(void)
|
|
{
|
|
const uint8_t kExtAddr[OT_EXT_ADDRESS_SIZE] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
|
|
const Mac::ShortAddress kShortAddr = 0x1234;
|
|
|
|
ot::Instance *instance;
|
|
Mac::Address addr;
|
|
Mac::ExtAddress extAddr;
|
|
uint8_t buffer[OT_EXT_ADDRESS_SIZE];
|
|
|
|
instance = testInitInstance();
|
|
VerifyOrQuit(instance != nullptr, "nullptr instance\n");
|
|
|
|
// Mac::ExtAddress
|
|
|
|
extAddr.GenerateRandom();
|
|
VerifyOrQuit(extAddr.IsLocal(), "Random Extended Address should have its Local bit set");
|
|
VerifyOrQuit(!extAddr.IsGroup(), "Random Extended Address should not have its Group bit set");
|
|
|
|
extAddr.CopyTo(buffer);
|
|
VerifyOrQuit(memcmp(extAddr.m8, buffer, OT_EXT_ADDRESS_SIZE) == 0);
|
|
|
|
extAddr.CopyTo(buffer, Mac::ExtAddress::kReverseByteOrder);
|
|
VerifyOrQuit(CompareReversed(extAddr.m8, buffer, OT_EXT_ADDRESS_SIZE));
|
|
|
|
extAddr.Set(kExtAddr);
|
|
VerifyOrQuit(memcmp(extAddr.m8, kExtAddr, OT_EXT_ADDRESS_SIZE) == 0);
|
|
|
|
extAddr.Set(kExtAddr, Mac::ExtAddress::kReverseByteOrder);
|
|
VerifyOrQuit(CompareReversed(extAddr.m8, kExtAddr, OT_EXT_ADDRESS_SIZE));
|
|
|
|
extAddr.SetLocal(true);
|
|
VerifyOrQuit(extAddr.IsLocal());
|
|
extAddr.SetLocal(false);
|
|
VerifyOrQuit(!extAddr.IsLocal());
|
|
extAddr.ToggleLocal();
|
|
VerifyOrQuit(extAddr.IsLocal());
|
|
extAddr.ToggleLocal();
|
|
VerifyOrQuit(!extAddr.IsLocal());
|
|
|
|
extAddr.SetGroup(true);
|
|
VerifyOrQuit(extAddr.IsGroup());
|
|
extAddr.SetGroup(false);
|
|
VerifyOrQuit(!extAddr.IsGroup());
|
|
extAddr.ToggleGroup();
|
|
VerifyOrQuit(extAddr.IsGroup());
|
|
extAddr.ToggleGroup();
|
|
VerifyOrQuit(!extAddr.IsGroup());
|
|
|
|
// Mac::Address
|
|
|
|
VerifyOrQuit(addr.IsNone(), "Address constructor failed");
|
|
VerifyOrQuit(addr.GetType() == Mac::Address::kTypeNone);
|
|
|
|
addr.SetShort(kShortAddr);
|
|
VerifyOrQuit(addr.GetType() == Mac::Address::kTypeShort);
|
|
VerifyOrQuit(addr.IsShort(), "Address::SetShort() failed");
|
|
VerifyOrQuit(!addr.IsExtended(), "Address::SetShort() failed");
|
|
VerifyOrQuit(addr.GetShort() == kShortAddr);
|
|
|
|
addr.SetExtended(extAddr);
|
|
VerifyOrQuit(addr.GetType() == Mac::Address::kTypeExtended);
|
|
VerifyOrQuit(!addr.IsShort(), "Address::SetExtended() failed");
|
|
VerifyOrQuit(addr.IsExtended(), "Address::SetExtended() failed");
|
|
VerifyOrQuit(addr.GetExtended() == extAddr);
|
|
|
|
addr.SetExtended(extAddr.m8, Mac::ExtAddress::kReverseByteOrder);
|
|
VerifyOrQuit(addr.GetType() == Mac::Address::kTypeExtended);
|
|
VerifyOrQuit(!addr.IsShort(), "Address::SetExtended() failed");
|
|
VerifyOrQuit(addr.IsExtended(), "Address::SetExtended() failed");
|
|
VerifyOrQuit(CompareReversed(addr.GetExtended().m8, extAddr.m8, OT_EXT_ADDRESS_SIZE),
|
|
"Address::SetExtended() reverse byte order failed");
|
|
|
|
addr.SetNone();
|
|
VerifyOrQuit(addr.GetType() == Mac::Address::kTypeNone);
|
|
VerifyOrQuit(addr.IsNone(), "Address:SetNone() failed");
|
|
VerifyOrQuit(!addr.IsShort(), "Address::SetNone() failed");
|
|
VerifyOrQuit(!addr.IsExtended(), "Address::SetNone() failed");
|
|
|
|
VerifyOrQuit(!addr.IsBroadcast(), "Address:SetNone() failed");
|
|
VerifyOrQuit(!addr.IsShortAddrInvalid());
|
|
|
|
addr.SetExtended(extAddr);
|
|
VerifyOrQuit(!addr.IsBroadcast());
|
|
VerifyOrQuit(!addr.IsShortAddrInvalid());
|
|
|
|
addr.SetShort(kShortAddr);
|
|
VerifyOrQuit(!addr.IsBroadcast());
|
|
VerifyOrQuit(!addr.IsShortAddrInvalid());
|
|
|
|
addr.SetShort(Mac::kShortAddrBroadcast);
|
|
VerifyOrQuit(addr.IsBroadcast());
|
|
VerifyOrQuit(!addr.IsShortAddrInvalid());
|
|
|
|
addr.SetShort(Mac::kShortAddrInvalid);
|
|
VerifyOrQuit(!addr.IsBroadcast());
|
|
VerifyOrQuit(addr.IsShortAddrInvalid());
|
|
|
|
testFreeInstance(instance);
|
|
}
|
|
|
|
void TestMacHeader(void)
|
|
{
|
|
enum AddrType : uint8_t
|
|
{
|
|
kNoneAddr,
|
|
kShrtAddr,
|
|
kExtdAddr,
|
|
};
|
|
|
|
enum PanIdMode
|
|
{
|
|
kSamePanIds,
|
|
kDiffPanIds,
|
|
};
|
|
|
|
struct TestCase
|
|
{
|
|
Mac::Frame::Version mVersion;
|
|
AddrType mSrcAddrType;
|
|
AddrType mDstAddrType;
|
|
PanIdMode mPanIdMode;
|
|
Mac::Frame::SecurityLevel mSecurity;
|
|
Mac::Frame::KeyIdMode mKeyIdMode;
|
|
uint8_t mHeaderLength;
|
|
uint8_t mFooterLength;
|
|
};
|
|
|
|
static constexpr Mac::Frame::Version kVer2006 = Mac::Frame::kVersion2006;
|
|
static constexpr Mac::Frame::Version kVer2015 = Mac::Frame::kVersion2015;
|
|
|
|
static constexpr Mac::Frame::SecurityLevel kNoSec = Mac::Frame::kSecurityNone;
|
|
static constexpr Mac::Frame::SecurityLevel kMic32 = Mac::Frame::kSecurityMic32;
|
|
|
|
static constexpr Mac::Frame::KeyIdMode kModeId1 = Mac::Frame::kKeyIdMode1;
|
|
static constexpr Mac::Frame::KeyIdMode kModeId2 = Mac::Frame::kKeyIdMode2;
|
|
|
|
static constexpr TestCase kTestCases[] = {
|
|
{kVer2006, kNoneAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 3, 2},
|
|
{kVer2006, kShrtAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 7, 2},
|
|
{kVer2006, kExtdAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 13, 2},
|
|
{kVer2006, kNoneAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 7, 2},
|
|
{kVer2006, kNoneAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 13, 2},
|
|
{kVer2006, kShrtAddr, kShrtAddr, kDiffPanIds, kNoSec, kModeId1, 11, 2},
|
|
{kVer2006, kShrtAddr, kExtdAddr, kDiffPanIds, kNoSec, kModeId1, 17, 2},
|
|
{kVer2006, kExtdAddr, kShrtAddr, kDiffPanIds, kNoSec, kModeId1, 17, 2},
|
|
{kVer2006, kExtdAddr, kExtdAddr, kDiffPanIds, kNoSec, kModeId1, 23, 2},
|
|
{kVer2006, kShrtAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 9, 2},
|
|
{kVer2006, kShrtAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 15, 2},
|
|
{kVer2006, kExtdAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 15, 2},
|
|
{kVer2006, kExtdAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 21, 2},
|
|
{kVer2006, kShrtAddr, kShrtAddr, kSamePanIds, kMic32, kModeId1, 15, 6},
|
|
{kVer2006, kShrtAddr, kShrtAddr, kSamePanIds, kMic32, kModeId2, 19, 6},
|
|
|
|
{kVer2015, kNoneAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 3, 2},
|
|
{kVer2015, kShrtAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 7, 2},
|
|
{kVer2015, kExtdAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 13, 2},
|
|
{kVer2015, kNoneAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 7, 2},
|
|
{kVer2015, kNoneAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 13, 2},
|
|
{kVer2015, kShrtAddr, kShrtAddr, kDiffPanIds, kNoSec, kModeId1, 11, 2},
|
|
{kVer2015, kShrtAddr, kExtdAddr, kDiffPanIds, kNoSec, kModeId1, 17, 2},
|
|
{kVer2015, kExtdAddr, kShrtAddr, kDiffPanIds, kNoSec, kModeId1, 17, 2},
|
|
{kVer2015, kShrtAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 9, 2},
|
|
{kVer2015, kShrtAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 15, 2},
|
|
{kVer2015, kExtdAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 15, 2},
|
|
{kVer2015, kExtdAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 21, 2},
|
|
{kVer2015, kShrtAddr, kShrtAddr, kSamePanIds, kMic32, kModeId1, 15, 6},
|
|
{kVer2015, kShrtAddr, kShrtAddr, kSamePanIds, kMic32, kModeId2, 19, 6},
|
|
};
|
|
|
|
const uint16_t kPanId1 = 0xbaba;
|
|
const uint16_t kPanId2 = 0xdede;
|
|
const uint16_t kShortAddr1 = 0x1234;
|
|
const uint16_t kShortAddr2 = 0x5678;
|
|
const uint8_t kExtAddr1[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
|
|
const uint8_t kExtAddr2[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
|
|
|
|
Mac::ExtAddress extAddr1;
|
|
Mac::ExtAddress extAddr2;
|
|
|
|
extAddr1.Set(kExtAddr1);
|
|
extAddr2.Set(kExtAddr2);
|
|
|
|
printf("TestMacHeader\n");
|
|
|
|
for (const TestCase &testCase : kTestCases)
|
|
{
|
|
uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
|
|
Mac::TxFrame frame;
|
|
Mac::Addresses addresses;
|
|
Mac::Address address;
|
|
Mac::PanIds panIds;
|
|
Mac::PanId panId;
|
|
|
|
frame.mPsdu = psdu;
|
|
frame.mLength = 0;
|
|
frame.mRadioType = 0;
|
|
|
|
switch (testCase.mSrcAddrType)
|
|
{
|
|
case kNoneAddr:
|
|
addresses.mSource.SetNone();
|
|
break;
|
|
case kShrtAddr:
|
|
addresses.mSource.SetShort(kShortAddr1);
|
|
break;
|
|
case kExtdAddr:
|
|
addresses.mSource.SetExtended(extAddr1);
|
|
break;
|
|
}
|
|
|
|
switch (testCase.mDstAddrType)
|
|
{
|
|
case kNoneAddr:
|
|
addresses.mDestination.SetNone();
|
|
break;
|
|
case kShrtAddr:
|
|
addresses.mDestination.SetShort(kShortAddr2);
|
|
break;
|
|
case kExtdAddr:
|
|
addresses.mDestination.SetExtended(extAddr2);
|
|
break;
|
|
}
|
|
|
|
switch (testCase.mPanIdMode)
|
|
{
|
|
case kSamePanIds:
|
|
panIds.mSource = panIds.mDestination = kPanId1;
|
|
break;
|
|
case kDiffPanIds:
|
|
panIds.mSource = kPanId1;
|
|
panIds.mDestination = kPanId2;
|
|
break;
|
|
}
|
|
|
|
frame.InitMacHeader(Mac::Frame::kTypeData, testCase.mVersion, addresses, panIds, testCase.mSecurity,
|
|
testCase.mKeyIdMode);
|
|
|
|
VerifyOrQuit(frame.GetHeaderLength() == testCase.mHeaderLength);
|
|
VerifyOrQuit(frame.GetFooterLength() == testCase.mFooterLength);
|
|
VerifyOrQuit(frame.GetLength() == testCase.mHeaderLength + testCase.mFooterLength);
|
|
|
|
VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeData);
|
|
VerifyOrQuit(!frame.IsAck());
|
|
VerifyOrQuit(frame.GetVersion() == testCase.mVersion);
|
|
VerifyOrQuit(frame.GetSecurityEnabled() == (testCase.mSecurity != kNoSec));
|
|
VerifyOrQuit(!frame.GetFramePending());
|
|
VerifyOrQuit(!frame.IsIePresent());
|
|
VerifyOrQuit(frame.GetAckRequest() == (testCase.mDstAddrType != kNoneAddr));
|
|
|
|
VerifyOrQuit(frame.IsSrcAddrPresent() == (testCase.mSrcAddrType != kNoneAddr));
|
|
SuccessOrQuit(frame.GetSrcAddr(address));
|
|
VerifyOrQuit(CompareAddresses(address, addresses.mSource));
|
|
VerifyOrQuit(frame.IsDstAddrPresent() == (testCase.mDstAddrType != kNoneAddr));
|
|
SuccessOrQuit(frame.GetDstAddr(address));
|
|
VerifyOrQuit(CompareAddresses(address, addresses.mDestination));
|
|
|
|
if (testCase.mDstAddrType != kNoneAddr)
|
|
{
|
|
VerifyOrQuit(frame.IsDstPanIdPresent());
|
|
SuccessOrQuit(frame.GetDstPanId(panId));
|
|
VerifyOrQuit(panId == panIds.mDestination);
|
|
}
|
|
|
|
if (frame.IsSrcPanIdPresent())
|
|
{
|
|
SuccessOrQuit(frame.GetSrcPanId(panId));
|
|
VerifyOrQuit(panId == panIds.mSource);
|
|
}
|
|
|
|
if (frame.GetSecurityEnabled())
|
|
{
|
|
uint8_t security;
|
|
uint8_t keyIdMode;
|
|
|
|
SuccessOrQuit(frame.GetSecurityLevel(security));
|
|
VerifyOrQuit(security == testCase.mSecurity);
|
|
|
|
SuccessOrQuit(frame.GetKeyIdMode(keyIdMode));
|
|
VerifyOrQuit(keyIdMode == testCase.mKeyIdMode);
|
|
}
|
|
|
|
printf(" %d, %d\n", testCase.mHeaderLength, testCase.mFooterLength);
|
|
}
|
|
}
|
|
|
|
void VerifyChannelMaskContent(const Mac::ChannelMask &aMask, uint8_t *aChannels, uint8_t aLength)
|
|
{
|
|
uint8_t index = 0;
|
|
uint8_t channel;
|
|
|
|
for (channel = Radio::kChannelMin; channel <= Radio::kChannelMax; channel++)
|
|
{
|
|
if (index < aLength)
|
|
{
|
|
if (channel == aChannels[index])
|
|
{
|
|
index++;
|
|
VerifyOrQuit(aMask.ContainsChannel(channel));
|
|
}
|
|
else
|
|
{
|
|
VerifyOrQuit(!aMask.ContainsChannel(channel));
|
|
}
|
|
}
|
|
}
|
|
|
|
index = 0;
|
|
channel = Mac::ChannelMask::kChannelIteratorFirst;
|
|
|
|
while (aMask.GetNextChannel(channel) == kErrorNone)
|
|
{
|
|
VerifyOrQuit(channel == aChannels[index++], "ChannelMask.GetNextChannel() failed");
|
|
}
|
|
|
|
VerifyOrQuit(index == aLength, "ChannelMask.GetNextChannel() failed");
|
|
|
|
if (aLength == 1)
|
|
{
|
|
VerifyOrQuit(aMask.IsSingleChannel());
|
|
}
|
|
else
|
|
{
|
|
VerifyOrQuit(!aMask.IsSingleChannel());
|
|
}
|
|
|
|
VerifyOrQuit(aLength == aMask.GetNumberOfChannels());
|
|
}
|
|
|
|
void TestMacChannelMask(void)
|
|
{
|
|
uint8_t allChannels[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26};
|
|
uint8_t channels1[] = {11, 14, 15, 16, 17, 20, 21, 22, 24, 25};
|
|
uint8_t channels2[] = {14, 21, 26};
|
|
uint8_t channels3[] = {14, 21};
|
|
uint8_t channles4[] = {20};
|
|
|
|
static const char kEmptyMaskString[] = "{ }";
|
|
static const char kAllChannelsString[] = "{ 11-26 }";
|
|
static const char kChannels1String[] = "{ 11, 14-17, 20-22, 24, 25 }";
|
|
static const char kChannels2String[] = "{ 14, 21, 26 }";
|
|
static const char kChannels3String[] = "{ 14, 21 }";
|
|
static const char kChannels4String[] = "{ 20 }";
|
|
|
|
Mac::ChannelMask mask1;
|
|
Mac::ChannelMask mask2(Radio::kSupportedChannels);
|
|
|
|
printf("Testing Mac::ChannelMask\n");
|
|
|
|
VerifyOrQuit(mask1.IsEmpty());
|
|
printf("empty = %s\n", mask1.ToString().AsCString());
|
|
VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kEmptyMaskString) == 0);
|
|
|
|
VerifyOrQuit(!mask2.IsEmpty());
|
|
VerifyOrQuit(mask2.GetMask() == Radio::kSupportedChannels);
|
|
printf("allChannels = %s\n", mask2.ToString().AsCString());
|
|
VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kAllChannelsString) == 0);
|
|
|
|
mask1.SetMask(Radio::kSupportedChannels);
|
|
VerifyOrQuit(!mask1.IsEmpty());
|
|
VerifyOrQuit(mask1.GetMask() == Radio::kSupportedChannels);
|
|
|
|
VerifyChannelMaskContent(mask1, allChannels, sizeof(allChannels));
|
|
|
|
// Test ChannelMask::RemoveChannel()
|
|
for (uint8_t index = 0; index < sizeof(allChannels) - 1; index++)
|
|
{
|
|
mask1.RemoveChannel(allChannels[index]);
|
|
VerifyChannelMaskContent(mask1, &allChannels[index + 1], sizeof(allChannels) - 1 - index);
|
|
}
|
|
|
|
mask1.Clear();
|
|
VerifyOrQuit(mask1.IsEmpty());
|
|
VerifyChannelMaskContent(mask1, nullptr, 0);
|
|
|
|
for (uint8_t channel : channels1)
|
|
{
|
|
mask1.AddChannel(channel);
|
|
}
|
|
|
|
printf("channels1 = %s\n", mask1.ToString().AsCString());
|
|
VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kChannels1String) == 0);
|
|
|
|
VerifyOrQuit(!mask1.IsEmpty());
|
|
VerifyChannelMaskContent(mask1, channels1, sizeof(channels1));
|
|
|
|
mask2.Clear();
|
|
|
|
for (uint8_t channel : channels2)
|
|
{
|
|
mask2.AddChannel(channel);
|
|
}
|
|
|
|
printf("channels2 = %s\n", mask2.ToString().AsCString());
|
|
VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kChannels2String) == 0);
|
|
|
|
VerifyOrQuit(!mask2.IsEmpty());
|
|
VerifyChannelMaskContent(mask2, channels2, sizeof(channels2));
|
|
|
|
mask1.Intersect(mask2);
|
|
VerifyChannelMaskContent(mask1, channels3, sizeof(channels3));
|
|
printf("channels3 = %s\n", mask1.ToString().AsCString());
|
|
VerifyOrQuit(strcmp(mask1.ToString().AsCString(), kChannels3String) == 0);
|
|
|
|
mask2.Clear();
|
|
mask2.AddChannel(channles4[0]);
|
|
VerifyChannelMaskContent(mask2, channles4, sizeof(channles4));
|
|
|
|
printf("channels4 = %s\n", mask2.ToString().AsCString());
|
|
VerifyOrQuit(strcmp(mask2.ToString().AsCString(), kChannels4String) == 0);
|
|
|
|
mask1.Clear();
|
|
mask2.Clear();
|
|
VerifyOrQuit(mask1 == mask2);
|
|
|
|
mask1.SetMask(Radio::kSupportedChannels);
|
|
mask2.SetMask(Radio::kSupportedChannels);
|
|
VerifyOrQuit(mask1 == mask2);
|
|
|
|
mask1.Clear();
|
|
VerifyOrQuit(mask1 != mask2);
|
|
}
|
|
|
|
void TestMacFrameApi(void)
|
|
{
|
|
uint8_t ack_psdu1[] = {0x02, 0x10, 0x5e, 0xd2, 0x9b};
|
|
uint8_t mac_cmd_psdu1[] = {0x6b, 0xdc, 0x85, 0xce, 0xfa, 0x47, 0x36, 0x07, 0xd9, 0x74, 0x45, 0x8d,
|
|
0xb2, 0x6e, 0x81, 0x25, 0xc9, 0xdb, 0xac, 0x2b, 0x0a, 0x0d, 0x00, 0x00,
|
|
0x00, 0x00, 0x01, 0x04, 0xaf, 0x14, 0xce, 0xaa, 0x5a, 0xe5};
|
|
|
|
Mac::Frame frame;
|
|
|
|
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
|
uint8_t data_psdu1[] = {0x29, 0xee, 0x53, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x05,
|
|
0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x01};
|
|
uint8_t mac_cmd_psdu2[] = {0x6b, 0xaa, 0x8d, 0xce, 0xfa, 0x00, 0x68, 0x01, 0x68, 0x0d,
|
|
0x08, 0x00, 0x00, 0x00, 0x01, 0x04, 0x0d, 0xed, 0x0b, 0x35,
|
|
0x0c, 0x80, 0x3f, 0x04, 0x4b, 0x88, 0x89, 0xd6, 0x59, 0xe1};
|
|
uint8_t scf; // SecurityControlField
|
|
#endif
|
|
|
|
// Imm-Ack, Sequence Number: 94
|
|
// Frame Control Field: 0x1002
|
|
// .... .... .... .010 = Frame Type: Ack (0x2)
|
|
// .... .... .... 0... = Security Enabled: False
|
|
// .... .... ...0 .... = Frame Pending: False
|
|
// .... .... ..0. .... = Acknowledge Request: False
|
|
// .... .... .0.. .... = PAN ID Compression: False
|
|
// .... ...0 .... .... = Sequence Number Suppression: False
|
|
// .... ..0. .... .... = Information Elements Present: False
|
|
// .... 00.. .... .... = Destination Addressing Mode: None (0x0)
|
|
// ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1)
|
|
// 00.. .... .... .... = Source Addressing Mode: None (0x0)
|
|
// Sequence Number: 94
|
|
// FCS: 0x9bd2 (Correct)
|
|
frame.mPsdu = ack_psdu1;
|
|
frame.mLength = sizeof(ack_psdu1);
|
|
VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeAck);
|
|
VerifyOrQuit(!frame.GetSecurityEnabled());
|
|
VerifyOrQuit(!frame.GetFramePending());
|
|
VerifyOrQuit(!frame.GetAckRequest());
|
|
VerifyOrQuit(!frame.IsIePresent());
|
|
VerifyOrQuit(!frame.IsDstPanIdPresent());
|
|
VerifyOrQuit(!frame.IsDstAddrPresent());
|
|
VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2006);
|
|
VerifyOrQuit(!frame.IsSrcAddrPresent());
|
|
VerifyOrQuit(frame.GetSequence() == 94);
|
|
|
|
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
|
// IEEE 802.15.4-2015 Data
|
|
// Sequence Number: 83
|
|
// Destination PAN: 0xface
|
|
// Destination: 16:6e:0a:00:00:00:00:01
|
|
// Extended Source: 16:6e:0a:00:00:00:00:05
|
|
// Auxiliary Security Header
|
|
// Security Control Field: 0x0d
|
|
frame.mPsdu = data_psdu1;
|
|
frame.mLength = sizeof(data_psdu1);
|
|
VerifyOrQuit(frame.IsVersion2015());
|
|
VerifyOrQuit(frame.IsDstPanIdPresent());
|
|
VerifyOrQuit(frame.IsDstAddrPresent());
|
|
VerifyOrQuit(frame.IsSrcAddrPresent());
|
|
SuccessOrQuit(frame.GetSecurityControlField(scf));
|
|
VerifyOrQuit(scf == 0x0d);
|
|
frame.SetSecurityControlField(0xff);
|
|
SuccessOrQuit(frame.GetSecurityControlField(scf));
|
|
VerifyOrQuit(scf == 0xff);
|
|
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
|
|
|
|
// IEEE 802.15.4-2006 Mac Command
|
|
// Sequence Number: 133
|
|
// Command Identifier: Data Request (0x04)
|
|
uint8_t commandId;
|
|
frame.mPsdu = mac_cmd_psdu1;
|
|
frame.mLength = sizeof(mac_cmd_psdu1);
|
|
VerifyOrQuit(frame.GetSequence() == 133);
|
|
VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2006);
|
|
VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeMacCmd);
|
|
SuccessOrQuit(frame.GetCommandId(commandId));
|
|
VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest);
|
|
SuccessOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdBeaconRequest));
|
|
SuccessOrQuit(frame.GetCommandId(commandId));
|
|
VerifyOrQuit(commandId == Mac::Frame::kMacCmdBeaconRequest);
|
|
|
|
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
|
// IEEE 802.15.4-2015 Mac Command
|
|
// Sequence Number: 141
|
|
// Header IEs
|
|
// CSL IE
|
|
// Header Termination 2 IE (Payload follows)
|
|
// Command Identifier: Data Request (0x04)
|
|
frame.mPsdu = mac_cmd_psdu2;
|
|
frame.mLength = sizeof(mac_cmd_psdu2);
|
|
VerifyOrQuit(frame.GetSequence() == 141);
|
|
VerifyOrQuit(frame.IsVersion2015());
|
|
VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeMacCmd);
|
|
SuccessOrQuit(frame.GetCommandId(commandId));
|
|
VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest);
|
|
printf("commandId:%d\n", commandId);
|
|
SuccessOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdOrphanNotification));
|
|
SuccessOrQuit(frame.GetCommandId(commandId));
|
|
VerifyOrQuit(commandId == Mac::Frame::kMacCmdOrphanNotification);
|
|
|
|
#endif
|
|
}
|
|
|
|
void TestMacFrameAckGeneration(void)
|
|
{
|
|
constexpr uint8_t kImmAckLength = 5;
|
|
|
|
Mac::RxFrame receivedFrame;
|
|
Mac::TxFrame ackFrame;
|
|
uint8_t ackFrameBuffer[100];
|
|
|
|
ackFrame.mPsdu = ackFrameBuffer;
|
|
ackFrame.mLength = sizeof(ackFrameBuffer);
|
|
|
|
// Received Frame 1
|
|
// IEEE 802.15.4 Data
|
|
// Frame Control Field: 0xdc61
|
|
// .... .... .... .001 = Frame Type: Data (0x1)
|
|
// .... .... .... 0... = Security Enabled: False
|
|
// .... .... ...0 .... = Frame Pending: False
|
|
// .... .... ..1. .... = Acknowledge Request: True
|
|
// .... .... .1.. .... = PAN ID Compression: True
|
|
// .... ...0 .... .... = Sequence Number Suppression: False
|
|
// .... ..0. .... .... = Information Elements Present: False
|
|
// .... 11.. .... .... = Destination Addressing Mode: Long/64-bit (0x3)
|
|
// ..01 .... .... .... = Frame Version: IEEE Std 802.15.4-2006 (1)
|
|
// 11.. .... .... .... = Source Addressing Mode: Long/64-bit (0x3)
|
|
// Sequence Number: 189
|
|
// Destination PAN: 0xface
|
|
// Destination: 16:6e:0a:00:00:00:00:01 (16:6e:0a:00:00:00:00:01)
|
|
// Extended Source: 16:6e:0a:00:00:00:00:02 (16:6e:0a:00:00:00:00:02)
|
|
uint8_t data_psdu1[] = {0x61, 0xdc, 0xbd, 0xce, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x02,
|
|
0x00, 0x00, 0x00, 0x00, 0x0a, 0x6e, 0x16, 0x7f, 0x33, 0xf0, 0x4d, 0x4c, 0x4d, 0x4c,
|
|
0x8b, 0xf0, 0x00, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc2,
|
|
0x57, 0x9c, 0x31, 0xb3, 0x2a, 0xa1, 0x86, 0xba, 0x9a, 0xed, 0x5a, 0xb9, 0xa3, 0x59,
|
|
0x88, 0xeb, 0xbb, 0x0d, 0xc3, 0xed, 0xeb, 0x8a, 0x53, 0xa6, 0xed, 0xf7, 0xdd, 0x45,
|
|
0x6e, 0xf7, 0x9a, 0x17, 0xb4, 0xab, 0xc6, 0x75, 0x71, 0x46, 0x37, 0x93, 0x4a, 0x32,
|
|
0xb1, 0x21, 0x9f, 0x9d, 0xb3, 0x65, 0x27, 0xd5, 0xfc, 0x50, 0x16, 0x90, 0xd2, 0xd4};
|
|
receivedFrame.mPsdu = data_psdu1;
|
|
receivedFrame.mLength = sizeof(data_psdu1);
|
|
|
|
ackFrame.GenerateImmAck(receivedFrame, false);
|
|
VerifyOrQuit(ackFrame.mLength == kImmAckLength);
|
|
VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kTypeAck);
|
|
VerifyOrQuit(!ackFrame.GetSecurityEnabled());
|
|
VerifyOrQuit(!ackFrame.GetFramePending());
|
|
|
|
VerifyOrQuit(!ackFrame.GetAckRequest());
|
|
VerifyOrQuit(!ackFrame.IsIePresent());
|
|
VerifyOrQuit(!ackFrame.IsDstPanIdPresent());
|
|
VerifyOrQuit(!ackFrame.IsDstAddrPresent());
|
|
VerifyOrQuit(!ackFrame.IsSrcAddrPresent());
|
|
VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kVersion2006);
|
|
VerifyOrQuit(ackFrame.GetSequence() == 189);
|
|
|
|
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
|
// Received Frame 2
|
|
// IEEE 802.15.4 Data
|
|
// Frame Control Field: 0xa869, Frame Type: Data, Security Enabled, Acknowledge Request, PAN ID Compression,
|
|
// Destination Addressing Mode: Short/16-bit, Frame Version: IEEE Std 802.15.4-2015, Source Addressing Mode:
|
|
// Short/16-bit
|
|
// .... .... .... .001 = Frame Type: Data (0x1)
|
|
// .... .... .... 1... = Security Enabled: True
|
|
// .... .... ...0 .... = Frame Pending: False
|
|
// .... .... ..1. .... = Acknowledge Request: True
|
|
// .... .... .1.. .... = PAN ID Compression: True
|
|
// .... ...0 .... .... = Sequence Number Suppression: False
|
|
// .... ..0. .... .... = Information Elements Present: False
|
|
// .... 10.. .... .... = Destination Addressing Mode: Short/16-bit (0x2)
|
|
// ..10 .... .... .... = Frame Version: IEEE Std 802.15.4-2015 (2)
|
|
// 10.. .... .... .... = Source Addressing Mode: Short/16-bit (0x2)
|
|
// Sequence Number: 142
|
|
// Destination PAN: 0xface
|
|
// Destination: 0x2402
|
|
// Source: 0x2400
|
|
// [Extended Source: 16:6e:0a:00:00:00:00:01 (16:6e:0a:00:00:00:00:01)]
|
|
// [Origin: 2]
|
|
// Auxiliary Security Header
|
|
// Security Control Field: 0x0d, Security Level: Encryption with 32-bit Message Integrity Code, Key Identifier
|
|
// Mode: Indexed Key using the Default Key Source
|
|
// .... .101 = Security Level: Encryption with 32-bit Message Integrity Code (0x5)
|
|
// ...0 1... = Key Identifier Mode: Indexed Key using the Default Key Source (0x1)
|
|
// ..0. .... = Frame Counter Suppression: False
|
|
// .0.. .... = ASN in Nonce: False
|
|
// 0... .... = Reserved: 0x0
|
|
// Frame Counter: 2
|
|
// Key Identifier Field
|
|
// Key Index: 0x01
|
|
// MIC: f94e5870
|
|
// [Key Number: 0]
|
|
// FCS: 0x8c40 (Correct)
|
|
uint8_t data_psdu2[] = {0x69, 0xa8, 0x8e, 0xce, 0xfa, 0x02, 0x24, 0x00, 0x24, 0x0d, 0x02,
|
|
0x00, 0x00, 0x00, 0x01, 0x6b, 0x64, 0x60, 0x08, 0x55, 0xb8, 0x10,
|
|
0x18, 0xc7, 0x40, 0x2e, 0xfb, 0xf3, 0xda, 0xf9, 0x4e, 0x58, 0x70};
|
|
receivedFrame.mPsdu = data_psdu2;
|
|
receivedFrame.mLength = sizeof(data_psdu2);
|
|
|
|
uint8_t ie_data[6] = {0x04, 0x0d, 0x21, 0x0c, 0x35, 0x0c};
|
|
Mac::CslIe *csl;
|
|
|
|
IgnoreError(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data)));
|
|
csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
|
|
VerifyOrQuit(ackFrame.mLength == 23);
|
|
VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kTypeAck);
|
|
VerifyOrQuit(ackFrame.GetSecurityEnabled());
|
|
VerifyOrQuit(ackFrame.IsIePresent());
|
|
VerifyOrQuit(!ackFrame.IsDstPanIdPresent());
|
|
VerifyOrQuit(ackFrame.IsDstAddrPresent());
|
|
VerifyOrQuit(!ackFrame.IsSrcAddrPresent());
|
|
VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kVersion2015);
|
|
VerifyOrQuit(ackFrame.GetSequence() == 142);
|
|
VerifyOrQuit(csl->GetPeriod() == 3125 && csl->GetPhase() == 3105);
|
|
|
|
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
|
ackFrame.SetCslIe(123, 456);
|
|
csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
|
|
VerifyOrQuit(csl->GetPeriod() == 123 && csl->GetPhase() == 456);
|
|
#endif
|
|
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
|
}
|
|
|
|
} // namespace ot
|
|
|
|
int main(void)
|
|
{
|
|
ot::TestMacAddress();
|
|
ot::TestMacHeader();
|
|
ot::TestMacChannelMask();
|
|
ot::TestMacFrameApi();
|
|
ot::TestMacFrameAckGeneration();
|
|
printf("All tests passed\n");
|
|
return 0;
|
|
}
|