[mac-frame] add util functions to generate ack (#4884)

This commit adds mac frame util functions to generate acks (both Imm
and Enh acks) from a received frame. These funtions are utils APIs for
platforms which don't provide ack generation.

This commit also introduces compile options for CSL to control the CSL
IE related part.
This commit is contained in:
Li Cao
2020-05-12 22:20:03 -07:00
committed by GitHub
parent 8e84e05429
commit cd9558ca91
11 changed files with 518 additions and 3 deletions
+1
View File
@@ -423,6 +423,7 @@ jobs:
./script/test build
- name: Run
run: |
./script/test unit
./script/test cert_suite tests/scripts/thread-cert/v1_2_*
- name: Codecov
uses: codecov/codecov-action@v1
+5
View File
@@ -86,6 +86,11 @@ if(OT_COMMISSIONER)
list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_COMMISSIONER_ENABLE=1")
endif()
option(OT_CSL_RECEIVER "enable csl receiver")
if(OT_CSL_RECEIVER)
list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE=1")
endif()
option(OT_DHCP6_CLIENT "enable DHCP6 client support")
if(OT_DHCP6_CLIENT)
list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE=1")
+4
View File
@@ -123,6 +123,10 @@ ifeq ($(CHILD_SUPERVISION),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE=1
endif
ifeq ($(CSL_RECEIVER),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE=1
endif
ifeq ($(DEBUG),1)
configure_OPTIONS += --enable-debug --disable-optimization
endif
+34
View File
@@ -28,6 +28,7 @@
#include "mac_frame.h"
#include <assert.h>
#include "mac/mac_frame.hpp"
using namespace ot;
@@ -125,3 +126,36 @@ void otMacFrameProcessTransmitAesCcm(otRadioFrame *aFrame, const otExtAddress *a
{
static_cast<Mac::TxFrame *>(aFrame)->ProcessTransmitAesCcm(*static_cast<const Mac::ExtAddress *>(aExtAddress));
}
bool otMacFrameIsVersion2015(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->IsVersion2015();
}
void otMacFrameGenerateImmAck(const otRadioFrame *aFrame, bool aIsFramePending, otRadioFrame *aAckFrame)
{
assert(aFrame != NULL && aAckFrame != NULL);
static_cast<Mac::TxFrame *>(aAckFrame)->GenerateImmAck(*static_cast<const Mac::RxFrame *>(aFrame), aIsFramePending);
}
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
otError otMacFrameGenerateEnhAck(const otRadioFrame *aFrame,
bool aIsFramePending,
const uint8_t * aIeData,
uint8_t aIeLength,
otRadioFrame * aAckFrame)
{
assert(aFrame != NULL && aAckFrame != NULL);
return static_cast<Mac::TxFrame *>(aAckFrame)->GenerateEnhAck(*static_cast<const Mac::RxFrame *>(aFrame),
aIsFramePending, aIeData, aIeLength);
}
#if OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
void otMacFrameSetCslIe(otRadioFrame *aFrame, uint16_t aCslPeriod, uint16_t aCslPhase)
{
static_cast<Mac::Frame *>(aFrame)->SetCslIe(aCslPeriod, aCslPhase);
}
#endif // OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+50
View File
@@ -161,6 +161,56 @@ uint8_t otMacFrameGetSequence(const otRadioFrame *aFrame);
*/
void otMacFrameProcessTransmitAesCcm(otRadioFrame *aFrame, const otExtAddress *aExtAddress);
/**
* Tell if the version of @p aFrame is 2015.
*
* @param[in] aFrame A pointer to the frame.
*
* @retval true It is a version 2015 frame.
* @retval false It is not a version 2015 frame.
*
*/
bool otMacFrameIsVersion2015(const otRadioFrame *aFrame);
/**
* Generate Imm-Ack for @p aFrame.
*
* @param[in] aFrame A pointer to the frame.
* @param[in] aIsFramePending Value of the ACK's frame pending bit.
* @param[out] aAckFrame A pointer to the ack frame to be generated.
*
*/
void otMacFrameGenerateImmAck(const otRadioFrame *aFrame, bool aIsFramePending, otRadioFrame *aAckFrame);
/**
* Generate Enh-Ack for @p aFrame.
*
* @param[in] aFrame A pointer to the frame.
* @param[in] aIsFramePending Value of the ACK's frame pending bit.
* @param[in] aIeData A pointer to the IE data portion of the ACK to be sent.
* @param[in] aIeLength The length of IE data portion of the ACK to be sent.
* @param[out] aAckFrame A pointer to the ack frame to be generated.
*
* @retval OT_ERROR_NONE Successfully generated Enh Ack in @p aAckFrame.
* @retval OT_ERROR_PARSE @p aFrame has incorrect format.
*
*/
otError otMacFrameGenerateEnhAck(const otRadioFrame *aFrame,
bool aIsFramePending,
const uint8_t * aIeData,
uint8_t aIeLength,
otRadioFrame * aAckFrame);
/**
* Set CSL IE content into the frame.
*
* @param[inout] aFrame A pointer to the frame to be modified.
* @param[in] aCslPeriod CSL Period in CSL IE.
* @param[in] aCslPhase CSL Phase in CSL IE.
*
*/
void otMacFrameSetCslIe(otRadioFrame *aFrame, uint16_t aCslPeriod, uint16_t aCslPhase);
#ifdef __cplusplus
} // extern "C"
#endif
+6
View File
@@ -92,6 +92,12 @@ build_simulation()
fi
if [[ "${version}" == "1.2" ]]; then
options+=(
"-DOT_CSL_RECEIVER=ON"
)
fi
local builddir="${OT_BUILDDIR}/cmake/openthread-simulation-${version}"
(mkdir -p "${builddir}" \
&& cd "${builddir}" \
+24 -1
View File
@@ -212,12 +212,13 @@
* Define as 1 to support IEEE 802.15.4-2015 Header IE (Information Element) generation and parsing, it must be set
* to support following features:
* 1. Time synchronization service feature (i.e., OPENTHREAD_CONFIG_TIME_SYNC_ENABLE is set).
* 2. Thread 1.2.
*
* @note If it's enabled, platform must support interrupt context and concurrent access AES.
*
*/
#ifndef OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE || (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
#define OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 1
#else
#define OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 0
@@ -254,4 +255,26 @@
#define OPENTHREAD_CONFIG_MAC_RETX_POLL_PERIOD 1000
#endif
/**
* @def OPENTHREAD_CONFIG_CSL_TRANSMITTER_ENABLE
*
* This setting configures the CSL transmitter feature in Thread 1.2.
* This is compulsory for 1.2 FTD.
*
*/
#define OPENTHREAD_CONFIG_CSL_TRANSMITTER_ENABLE \
(OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) && OPENTHREAD_FTD
/**
* @def OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
*
* This setting configures the CSL receiver feature in Thread 1.2.
* This is compulsory for 1.2 MTD, optional for 1.2 FTD.
*
*/
#ifndef OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
#define OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE \
(OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) && OPENTHREAD_MTD
#endif
#endif // CONFIG_MAC_H_
@@ -480,6 +480,21 @@
#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#if OPENTHREAD_CONFIG_CSL_TRANSMITTER_ENABLE
#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_CSL_TRANSMITTER_ENABLE"
#endif
#if (!OPENTHREAD_FTD)
#error "FTD is required for OPENTHREAD_CONFIG_CSL_TRANSMITTER_ENABLE"
#endif
#endif // OPENTHREAD_CONFIG_CSL_TRANSMITTER_ENABLE
#if OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE"
#endif
#endif // OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
#if OPENTHREAD_CONFIG_DUA_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_DUA_ENABLE"
#endif
+145
View File
@@ -186,7 +186,11 @@ void Frame::SetDstPanId(PanId aPanId)
uint8_t Frame::FindDstAddrIndex(void) const
{
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
return kFcfSize + kDsnSize + (IsDstPanIdPresent() ? sizeof(PanId) : 0);
#else
return kFcfSize + kDsnSize + sizeof(PanId);
#endif
}
otError Frame::GetDstAddr(Address &aAddress) const
@@ -970,6 +974,20 @@ exit:
}
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
#if OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
void Frame::SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase)
{
uint8_t *cur = GetHeaderIe(Frame::kHeaderIeCsl);
CslIe * csl;
OT_ASSERT(cur != NULL);
csl = reinterpret_cast<CslIe *>(cur + sizeof(HeaderIe));
csl->SetPeriod(aCslPeriod);
csl->SetPhase(aCslPhase);
}
#endif // OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
const TimeIe *Frame::GetTimeIe(void) const
{
@@ -1048,6 +1066,133 @@ exit:
#endif // OPENTHREAD_RADIO
}
void TxFrame::GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending)
{
uint16_t fcf = kFcfFrameAck | aFrame.GetVersion();
mChannel = aFrame.mChannel;
memset(&mInfo.mTxInfo, 0, sizeof(mInfo.mTxInfo));
if (aIsFramePending)
{
fcf |= kFcfFramePending;
}
Encoding::LittleEndian::WriteUint16(fcf, mPsdu);
mPsdu[kSequenceIndex] = aFrame.GetSequence();
mLength = kImmAckLength;
}
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
otError TxFrame::GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength)
{
otError error = OT_ERROR_NONE;
uint16_t fcf = kFcfFrameAck | kFcfFrameVersion2015 | kFcfSrcAddrNone;
Address address;
PanId panId;
uint8_t footerLength;
uint8_t securityControlField;
uint32_t frameCounter;
uint8_t keyId;
mChannel = aFrame.mChannel;
memset(&mInfo.mTxInfo, 0, sizeof(mInfo.mTxInfo));
// Set frame control field
if (aIsFramePending)
{
fcf |= kFcfFramePending;
}
if (aFrame.GetSecurityEnabled())
{
fcf |= kFcfSecurityEnabled;
}
if (aFrame.IsPanIdCompressed())
{
fcf |= kFcfPanidCompression;
}
// Destination address mode
if ((aFrame.GetFrameControlField() & kFcfSrcAddrMask) == kFcfSrcAddrExt)
{
fcf |= kFcfDstAddrExt;
}
else if ((aFrame.GetFrameControlField() & kFcfSrcAddrMask) == kFcfSrcAddrShort)
{
fcf |= kFcfDstAddrShort;
}
else
{
fcf |= kFcfDstAddrNone;
}
if (aIeLength > 0)
{
fcf |= kFcfIePresent;
}
Encoding::LittleEndian::WriteUint16(fcf, mPsdu);
// Set sequence number
mPsdu[kSequenceIndex] = aFrame.GetSequence();
// Set address field
if (aFrame.IsSrcPanIdPresent())
{
SuccessOrExit(error = aFrame.GetSrcPanId(panId));
}
else if (aFrame.IsDstPanIdPresent())
{
SuccessOrExit(error = aFrame.GetDstPanId(panId));
}
else
{
ExitNow(error = OT_ERROR_PARSE);
}
if (IsDstPanIdPresent())
{
SetDstPanId(panId);
}
if (aFrame.IsSrcAddrPresent())
{
SuccessOrExit(error = aFrame.GetSrcAddr(address));
SetDstAddr(address);
}
// Set security header
SuccessOrExit(error = aFrame.GetSecurityControlField(securityControlField));
SuccessOrExit(error = aFrame.GetFrameCounter(frameCounter));
SuccessOrExit(error = aFrame.GetKeyId(keyId));
SetPsduLength(kMaxPsduSize); // At this time the length of ACK hasn't been determined, set it to
// `kMaxPsduSize` to call methods that check frame length.
SetSecurityControlField(securityControlField);
SetFrameCounter(frameCounter);
SetKeyId(keyId);
// Set header IE
if (aIeLength > 0)
{
OT_ASSERT(aIeData != NULL);
memcpy(GetPsdu() + FindHeaderIeIndex(), aIeData, aIeLength);
}
// Set frame length
footerLength = GetFooterLength();
OT_ASSERT(footerLength != kInvalidIndex);
mLength = FindHeaderIeIndex() + aIeLength + GetFooterLength();
exit:
return error;
}
#endif
// LCOV_EXCL_START
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
+104 -1
View File
@@ -314,9 +314,12 @@ public:
kMacCmdGtsRequest = 9,
kHeaderIeVendor = 0x00,
kHeaderIeCsl = 0x1a,
kHeaderIeTermination2 = 0x7f,
kInfoStringSize = 110, ///< Max chars needed for the info string representation (@sa ToInfoString()).
kImmAckLength = kFcfSize + kDsnSize + kFcsSize,
};
/**
@@ -428,6 +431,15 @@ public:
*/
void SetAckRequest(bool aAckRequest);
/**
* This method indicates whether or not the PanId Compression bit is set.
*
* @retval TRUE If the PanId Compression bit is set.
* @retval FALSE If the PanId Compression bit is not set.
*
*/
bool IsPanIdCompressed(void) const { return (GetFrameControlField() & kFcfPanidCompression) != 0; }
/**
* This method indicates whether or not IEs present.
*
@@ -522,6 +534,14 @@ public:
*/
void SetDstAddr(const Address &aAddress);
/**
* This method indicates whether or not the Source Address is present for this object.
*
* @retval TRUE if the Source Address is present, FALSE otherwise.
*
*/
bool IsSrcPanIdPresent(void) const { return IsSrcPanIdPresent(GetFrameControlField()); };
/**
* This method gets the Source PAN Identifier.
*
@@ -907,6 +927,18 @@ public:
*
*/
const uint8_t *GetHeaderIe(uint8_t aIeId) const;
#if OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
/**
* This method finds CSL IE in the frame and modify its content.
*
* @param[in] aCslPeriod CSL Period in CSL IE.
* @param[in] aCslPhase CSL Phase in CSL IE.
*
*/
void SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase);
#endif // OPENTHREAD_CONFIG_CSL_RECEIVER_ENABLE
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
/**
@@ -933,11 +965,12 @@ public:
*/
InfoString ToInfoString(void) const;
private:
protected:
enum
{
kInvalidIndex = 0xff,
kInvalidSize = kInvalidIndex,
kMaxPsduSize = kInvalidSize - 1,
kSequenceIndex = kFcfSize,
};
@@ -974,6 +1007,8 @@ private:
class RxFrame : public Frame
{
public:
friend class TxFrame;
/**
* This method returns the RSSI in dBm used for reception.
*
@@ -1193,6 +1228,29 @@ public:
*/
void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { mInfo.mTxInfo.mIeInfo->mTimeSyncSeq = aTimeSyncSeq; }
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
/**
* Generate Imm-Ack in this frame object.
*
* @param[in] aFrame A reference to the frame received.
* @param[in] aIsFramePending Value of the ACK's frame pending bit.
*
*/
void GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending);
/**
* Generate Enh-Ack in this frame object.
*
* @param[in] aFrame A reference to the frame received.
* @param[in] aIsFramePending Value of the ACK's frame pending bit.
* @param[in] aIeData A pointer to the IE data portion of the ACK to be sent.
* @param[in] aIeLength The length of IE data portion of the ACK to be sent.
*
* @retval OT_ERROR_NONE Successfully generated Enh Ack.
* @retval OT_ERROR_PARSE @p aFrame has incorrect format.
*
*/
otError GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength);
};
OT_TOOL_PACKED_BEGIN
@@ -1411,6 +1469,51 @@ private:
ExtendedPanId mExtendedPanId;
} OT_TOOL_PACKED_END;
/**
* This class implements CSL IE data structure.
*
*/
OT_TOOL_PACKED_BEGIN
class CslIe
{
public:
/**
* This method returns the CSL Period.
*
* @returns the CSL Period.
*
*/
uint16_t GetPeriod(void) const { return Encoding::LittleEndian::HostSwap16(mPeriod); }
/**
* This method sets the CSL Period.
*
* @param[in] aPeriod The CSL Period.
*
*/
void SetPeriod(uint16_t aPeriod) { mPeriod = Encoding::LittleEndian::HostSwap16(aPeriod); }
/**
* This method returns the CSL Phase.
*
* @returns the CSL Phase.
*
*/
uint16_t GetPhase(void) const { return Encoding::LittleEndian::HostSwap16(mPhase); }
/**
* This method sets the CSL Phase.
*
* @param[in] aPhase The CSL Phase.
*
*/
void SetPhase(uint16_t aPhase) { mPhase = Encoding::LittleEndian::HostSwap16(aPhase); }
private:
uint16_t mPhase;
uint16_t mPeriod;
} OT_TOOL_PACKED_END;
/**
* @}
*
+130 -1
View File
@@ -279,7 +279,6 @@ void TestMacHeader(void)
frame.mLength = 0;
frame.InitMacHeader(tests[i].fcf, tests[i].secCtl);
VerifyOrQuit(frame.GetHeaderLength() == tests[i].headerLength, "MacHeader test failed");
VerifyOrQuit(frame.GetFooterLength() == tests[i].footerLength, "MacHeader test failed");
VerifyOrQuit(frame.GetLength() == tests[i].headerLength + tests[i].footerLength, "MacHeader test failed");
@@ -473,6 +472,135 @@ void TestMacFrameApi(void)
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
}
void TestMacFrameAckGeneration(void)
{
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 == Mac::Frame::kImmAckLength,
"Mac::Frame::GenerateImmAck() failed, length incorrect\n");
VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kFcfFrameAck,
"Mac::Frame::GenerateImmAck() failed, GetType() incorrect\n");
VerifyOrQuit(ackFrame.GetSecurityEnabled() == false,
"Mac::Frame::GenerateImmAck failed, GetSecurityEnabled() incorrect\n");
VerifyOrQuit(ackFrame.GetFramePending() == false,
"Mac::Frame::GenerateImmAck failed, GetFramePending() incorrect\n");
VerifyOrQuit(ackFrame.GetAckRequest() == false, "Mac::Frame::GenerateImmAck failed, GetAckRequest() incorrect\n");
VerifyOrQuit(ackFrame.IsIePresent() == false, "Mac::Frame::GenerateImmAck failed, IsIePresent() incorrect\n");
VerifyOrQuit(ackFrame.IsDstPanIdPresent() == false,
"Mac::Frame::GenerateImmAck failed, IsDstPanIdPresent() incorrect\n");
VerifyOrQuit(ackFrame.IsDstAddrPresent() == false,
"Mac::Frame::GenerateImmAck failed, IsDstAddrPresent() incorrect\n");
VerifyOrQuit(ackFrame.IsSrcAddrPresent() == false,
"Mac::Frame::GenerateImmAck failed, IsSrcAddrPresent() incorrect\n");
VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kFcfFrameVersion2006,
"Mac::Frame::GenerateImmAck failed, GetVersion() incorrect\n");
VerifyOrQuit(ackFrame.GetSequence() == 189, "Mac::Frame::GenerateImmAck failed, GetSequence() incorrect\n");
#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;
ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data));
csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::Frame::kHeaderIeCsl) + sizeof(Mac::HeaderIe));
VerifyOrQuit(ackFrame.mLength == 23,
"Mac::Frame::GenerateEnhAck() failed, length incorrect\n"); // 23 is the length of the correct ack
VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kFcfFrameAck,
"Mac::Frame::GenerateEnhAck() failed, GetType() incorrect\n");
VerifyOrQuit(ackFrame.GetSecurityEnabled() == true,
"Mac::Frame::GenerateEnhAck failed, GetSecurityEnabled() incorrect\n");
VerifyOrQuit(ackFrame.IsIePresent() == true, "Mac::Frame::GenerateEnhAck failed, IsIePresent() incorrect\n");
VerifyOrQuit(ackFrame.IsDstPanIdPresent() == false,
"Mac::Frame::GenerateEnhAck failed, IsDstPanIdPresent() incorrect\n");
VerifyOrQuit(ackFrame.IsDstAddrPresent() == true,
"Mac::Frame::GenerateEnhAck failed, IsDstAddrPresent() incorrect\n");
VerifyOrQuit(ackFrame.IsSrcAddrPresent() == false,
"Mac::Frame::GenerateEnhAck failed, IsSrcAddrPresent() incorrect\n");
VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kFcfFrameVersion2015,
"Mac::Frame::GenerateEnhAck failed, GetVersion() incorrect\n");
VerifyOrQuit(ackFrame.GetSequence() == 142, "Mac::Frame::GenerateEnhAck failed, GetSequence() incorrect\n");
VerifyOrQuit(csl->GetPeriod() == 3125 && csl->GetPhase() == 3105,
"Mac::Frame::GenerateEnhAck failed, CslIe incorrect\n");
ackFrame.SetCslIe(123, 456);
csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::Frame::kHeaderIeCsl) + sizeof(Mac::HeaderIe));
VerifyOrQuit(csl->GetPeriod() == 123 && csl->GetPhase() == 456, "Mac::Frame::SetCslIe failed, CslIe incorrect\n");
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
}
} // namespace ot
int main(void)
@@ -482,6 +610,7 @@ int main(void)
ot::TestMacHeader();
ot::TestMacChannelMask();
ot::TestMacFrameApi();
ot::TestMacFrameAckGeneration();
printf("All tests passed\n");
return 0;
}