mirror of
https://github.com/espressif/openthread.git
synced 2026-07-31 16:17:47 +00:00
[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:
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user