mirror of
https://github.com/espressif/openthread.git
synced 2026-08-21 09:59:52 +00:00
[mac-frame] consolidate frame parsing and payload building (#13466)
This commit refactors IEEE 802.15.4 MAC frame parsing and payload construction in `Mac::Frame`, `TxFrame`, and `RxFrame`: - Introduces `Frame::ParseInfo::ParseFrom()` to consolidate frame header validation, parsing, and field extraction into a single, unified pass. Supports flexible parsing modes (`kParseAddrFields`, `kParseSecurityHeader`, and `kParseFully`). - Eliminates legacy index-search helpers (`FindPayloadIndex()`, `FindHeaderIeIndex()`, `SkipSecurityHeaderIndex()`, etc.) and replaces direct pointer indexing with `ParseInfo` and `FrameData`. - Introduces `Frame::Lengths` struct and `DetermineLengths()` to provide a clear breakdown of header, payload, footer, and maximum payload lengths. - Introduces `TxFrame::PayloadBuilder` (derived from `FrameBuilder`) to safely build and append frame payloads with automatic bounds checking, eliminating direct raw buffer manipulation of `GetPayload()`. - Updates `PrepareHeaders()`, `PrepareHeadersWithEmptyPayload()`, and `FinishPayload()` in `TxFrame` to manage header preparation and payload length calculation cleanly. - Updates `MessageFramer`, `Mac`, `DataPollSender`, and test suites to use the new header preparation and `PayloadBuilder` workflow.
This commit is contained in:
committed by
Jonathan Hui
parent
2c0d16d875
commit
60d0450efa
@@ -841,6 +841,8 @@ openthread_radio_sources = [
|
||||
"common/error.hpp",
|
||||
"common/frame_builder.cpp",
|
||||
"common/frame_builder.hpp",
|
||||
"common/frame_data.cpp",
|
||||
"common/frame_data.hpp",
|
||||
"common/log.cpp",
|
||||
"common/random.cpp",
|
||||
"common/string.cpp",
|
||||
|
||||
@@ -319,6 +319,7 @@ set(RADIO_COMMON_SOURCES
|
||||
common/binary_search.cpp
|
||||
common/error.cpp
|
||||
common/frame_builder.cpp
|
||||
common/frame_data.cpp
|
||||
common/log.cpp
|
||||
common/random.cpp
|
||||
common/string.cpp
|
||||
|
||||
@@ -86,4 +86,15 @@ exit:
|
||||
return data;
|
||||
}
|
||||
|
||||
Error FrameData::RemoveFooter(uint16_t aLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(GetLength() >= aLength, error = kErrorParse);
|
||||
SetLength(GetLength() - aLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -147,6 +147,16 @@ public:
|
||||
*/
|
||||
void SkipOver(uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Removes a footer of a given length from the end of the `FrameData`.
|
||||
*
|
||||
* @param[in] aLength The length of the footer (number of bytes) to remove.
|
||||
*
|
||||
* @retval kErrorNone Successfully removed the footer.
|
||||
* @retval kErrorParse The current data length is smaller than @p aLength.
|
||||
*/
|
||||
Error RemoveFooter(uint16_t aLength);
|
||||
|
||||
private:
|
||||
const void *ReadLength(uint16_t aLength) OT_LIFETIME_BOUND;
|
||||
};
|
||||
|
||||
@@ -568,7 +568,7 @@ Mac::TxFrame *DataPollSender::PrepareDataRequest(Mac::TxFrames &aTxFrames)
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
|
||||
Get<MessageFramer>().PrepareMacHeaders(*frame, buildInfo, nullptr);
|
||||
Get<MessageFramer>().PrepareMacHeaders(*frame, buildInfo);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
if (frame->Has<Mac::CslIe>())
|
||||
|
||||
+16
-15
@@ -725,7 +725,7 @@ TxFrame *Mac::PrepareBeaconRequest(TxFrames &aTxFrames)
|
||||
buildInfo.mCommandId = Frame::kMacCmdBeaconRequest;
|
||||
buildInfo.mVersion = Frame::kVersion2003;
|
||||
|
||||
buildInfo.PrepareHeadersIn(frame);
|
||||
frame.PrepareHeadersWithEmptyPayload(buildInfo);
|
||||
|
||||
LogInfo("Sending Beacon Request");
|
||||
|
||||
@@ -734,9 +734,9 @@ TxFrame *Mac::PrepareBeaconRequest(TxFrames &aTxFrames)
|
||||
|
||||
TxFrame *Mac::PrepareBeacon(TxFrames &aTxFrames)
|
||||
{
|
||||
TxFrame *frame;
|
||||
TxFrame::BuildInfo buildInfo;
|
||||
FrameBuilder builder;
|
||||
TxFrame *frame;
|
||||
TxFrame::BuildInfo buildInfo;
|
||||
TxFrame::PayloadBuilder builder;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
OT_ASSERT(!mTxBeaconRadioLinks.IsEmpty());
|
||||
@@ -753,16 +753,15 @@ TxFrame *Mac::PrepareBeacon(TxFrames &aTxFrames)
|
||||
buildInfo.mType = Frame::kTypeBeacon;
|
||||
buildInfo.mVersion = Frame::kVersion2003;
|
||||
|
||||
buildInfo.PrepareHeadersIn(*frame);
|
||||
frame->PrepareHeaders(buildInfo, builder);
|
||||
|
||||
builder.Init(frame->GetPayload(), frame->GetMaxPayloadLength());
|
||||
builder.Append<BeaconHeader>()->Init();
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE
|
||||
builder.Append<BeaconPayload>()->Init(Get<MeshCoP::NetworkIdentity>(), IsJoinable());
|
||||
#endif
|
||||
|
||||
frame->SetPayloadLength(builder.GetLength());
|
||||
frame->FinishPayload(builder);
|
||||
|
||||
LogBeacon("Sending");
|
||||
|
||||
@@ -1184,7 +1183,7 @@ void Mac::RecordFrameTransmitStatus(const TxFrame &aFrame, Error aError, uint8_t
|
||||
if (aError != kErrorNone)
|
||||
{
|
||||
LogFrameTxFailure(aFrame, aError, aRetryCount, aWillRetx);
|
||||
DumpDebg("TX ERR", aFrame.GetHeader(), 16);
|
||||
DumpDebg("TX ERR", aFrame.GetPsdu(), 16);
|
||||
|
||||
if (aWillRetx)
|
||||
{
|
||||
@@ -1475,7 +1474,7 @@ void Mac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
|
||||
}
|
||||
#endif
|
||||
|
||||
DumpDebg("TX", aFrame.GetHeader(), aFrame.GetLength());
|
||||
DumpDebg("TX", aFrame.GetPsdu(), aFrame.GetLength());
|
||||
FinishOperation();
|
||||
Get<MeshForwarder>().HandleSentFrame(aFrame, aError);
|
||||
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
|
||||
@@ -1488,7 +1487,7 @@ void Mac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
|
||||
case kOperationTransmitDataCsl:
|
||||
mCounters.mTxData++;
|
||||
|
||||
DumpDebg("TX", aFrame.GetHeader(), aFrame.GetLength());
|
||||
DumpDebg("TX", aFrame.GetPsdu(), aFrame.GetLength());
|
||||
FinishOperation();
|
||||
Get<CslTxScheduler>().HandleSentFrame(aFrame, aError);
|
||||
PerformNextOperation();
|
||||
@@ -1511,7 +1510,7 @@ void Mac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
|
||||
}
|
||||
#endif
|
||||
|
||||
DumpDebg("TX", aFrame.GetHeader(), aFrame.GetLength());
|
||||
DumpDebg("TX", aFrame.GetPsdu(), aFrame.GetLength());
|
||||
FinishOperation();
|
||||
Get<DataPollHandler>().HandleSentFrame(aFrame, aError);
|
||||
PerformNextOperation();
|
||||
@@ -1714,13 +1713,15 @@ Error Mac::ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neig
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
if (aFrame.IsWakeupFrame())
|
||||
{
|
||||
uint32_t sequence;
|
||||
uint8_t keyIndex;
|
||||
uint32_t sequence;
|
||||
uint8_t keyIndex;
|
||||
FrameData keySource;
|
||||
|
||||
// TODO: Avoid generating a new key if a wake-up frame was recently received already
|
||||
|
||||
IgnoreError(aFrame.GetKeyIndex(keyIndex));
|
||||
sequence = BigEndian::ReadUint32(aFrame.GetKeySource());
|
||||
aFrame.GetKeySource(keySource);
|
||||
sequence = BigEndian::ReadUint32(keySource.GetBytes());
|
||||
VerifyOrExit(DetermineKeyIndexFor(sequence) == keyIndex, error = kErrorSecurity);
|
||||
|
||||
macKey = &keyManager.GetTemporaryMacKey(sequence);
|
||||
@@ -2139,7 +2140,7 @@ void Mac::HandleReceivedFrame(RxFrame *aFrame, Error aError)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
DumpDebg("RX", aFrame->GetHeader(), aFrame->GetLength());
|
||||
DumpDebg("RX", aFrame->GetPsdu(), aFrame->GetLength());
|
||||
Get<MeshForwarder>().HandleReceivedFrame(*aFrame);
|
||||
|
||||
UpdateIdleMode();
|
||||
|
||||
+339
-436
File diff suppressed because it is too large
Load Diff
+194
-128
@@ -40,6 +40,8 @@
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/frame_builder.hpp"
|
||||
#include "common/frame_data.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "mac/mac_header_ie.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
@@ -148,6 +150,17 @@ public:
|
||||
*/
|
||||
typedef String<kInfoStringSize> InfoString;
|
||||
|
||||
/**
|
||||
* Represents the length breakdown of a MAC frame.
|
||||
*/
|
||||
struct Lengths
|
||||
{
|
||||
uint16_t mHeader; ///< Header length (in bytes).
|
||||
uint16_t mPayload; ///< Payload length (in bytes).
|
||||
uint16_t mFooter; ///< Footer length (in bytes).
|
||||
uint16_t mMaxPayload; ///< Maximum allowed payload length (in bytes).
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the frame.
|
||||
*
|
||||
@@ -183,10 +196,12 @@ public:
|
||||
/**
|
||||
* This method returns whether the frame is an IEEE 802.15.4 Wake-up frame.
|
||||
*
|
||||
* This is a placeholder implementation following removal of legacy Multipurpose frame format.
|
||||
*
|
||||
* @retval TRUE If this is a Wake-up frame.
|
||||
* @retval FALSE If this is not a Wake-up frame.
|
||||
*/
|
||||
bool IsWakeupFrame(void) const;
|
||||
bool IsWakeupFrame(void) const { return false; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -297,8 +312,9 @@ public:
|
||||
*
|
||||
* @param[out] aPanId The Destination PAN Identifier.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the Destination PAN Identifier.
|
||||
* @retval kErrorParse Failed to parse the PAN Identifier.
|
||||
* @retval kErrorNone Successfully retrieved the Destination PAN Identifier.
|
||||
* @retval kErrorNotFound Destination PAN Identifier is not present in the frame.
|
||||
* @retval kErrorParse Failed to parse the frame.
|
||||
*/
|
||||
Error GetDstPanId(PanId &aPanId) const;
|
||||
|
||||
@@ -315,7 +331,8 @@ public:
|
||||
*
|
||||
* @param[out] aAddress The Destination Address.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the Destination Address.
|
||||
* @retval kErrorNone Successfully retrieved the Destination Address.
|
||||
* @retval kErrorParse Failed to parse the frame.
|
||||
*/
|
||||
Error GetDstAddr(Address &aAddress) const;
|
||||
|
||||
@@ -332,7 +349,9 @@ public:
|
||||
*
|
||||
* @param[out] aPanId The Source PAN Identifier.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the Source PAN Identifier.
|
||||
* @retval kErrorNone Successfully retrieved the Source PAN Identifier.
|
||||
* @retval kErrorNotFound Source PAN Identifier is not present in the frame.
|
||||
* @retval kErrorParse Failed to parse the frame.
|
||||
*/
|
||||
Error GetSrcPanId(PanId &aPanId) const;
|
||||
|
||||
@@ -349,7 +368,8 @@ public:
|
||||
*
|
||||
* @param[out] aAddress The Source Address.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the Source Address.
|
||||
* @retval kErrorNone Successfully retrieved the Source Address.
|
||||
* @retval kErrorParse Failed to parse the frame.
|
||||
*/
|
||||
Error GetSrcAddr(Address &aAddress) const;
|
||||
|
||||
@@ -358,8 +378,9 @@ public:
|
||||
*
|
||||
* @param[out] aSecurityControlField The Security Control Field.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the Security Level Identifier.
|
||||
* @retval kErrorParse Failed to find the security control field in the frame.
|
||||
* @retval kErrorNone Successfully retrieved the Security Control Field.
|
||||
* @retval kErrorNotFound Frame does not have a security header (security is not enabled)
|
||||
* @retval kErrorParse Failed to parse the frame.
|
||||
*/
|
||||
Error GetSecurityControlField(uint8_t &aSecurityControlField) const;
|
||||
|
||||
@@ -368,8 +389,9 @@ public:
|
||||
*
|
||||
* @param[out] aSecurityLevel The Security Level Identifier.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the Security Level Identifier.
|
||||
* @retval kErrorParse Failed to parse MAC or security header.
|
||||
* @retval kErrorNone Successfully retrieved the Security Level Identifier.
|
||||
* @retval kErrorNotFound Frame does not have a security header (security is not enabled)
|
||||
* @retval kErrorParse Failed to parse MAC or security header.
|
||||
*/
|
||||
Error GetSecurityLevel(SecurityLevel &aSecurityLevel) const;
|
||||
|
||||
@@ -423,9 +445,9 @@ public:
|
||||
/**
|
||||
* Returns a pointer to the Key Source.
|
||||
*
|
||||
* @returns A pointer to the Key Source.
|
||||
* @param[out] aKeySource A `FrameData` to point to key source data bytes.
|
||||
*/
|
||||
const uint8_t *GetKeySource(void) const;
|
||||
void GetKeySource(FrameData &aKeySource) const;
|
||||
|
||||
/**
|
||||
* Sets the Key Source.
|
||||
@@ -439,8 +461,9 @@ public:
|
||||
*
|
||||
* @param[out] aKeyIndex The Key Index
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the Key Index.
|
||||
* @retval kErrorParse Failed to parse MAC or security header.
|
||||
* @retval kErrorNone Successfully retrieved the Key Index.
|
||||
* @retval kErrorNotFound Frame is using `kKeyIdMode0` which does not have any Key Index.
|
||||
* @retval kErrorParse Failed to parse MAC or security header.
|
||||
*/
|
||||
Error GetKeyIndex(uint8_t &aKeyIndex) const;
|
||||
|
||||
@@ -456,7 +479,9 @@ public:
|
||||
*
|
||||
* @param[out] aCommandId The Command ID.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the Command ID.
|
||||
* @retval kErrorNone Successfully retrieved the Command ID.
|
||||
* @retval kErrorNotFound The frame is not a MAC command.
|
||||
* @retval kErrorParse Failed to parse frame.
|
||||
*/
|
||||
Error GetCommandId(uint8_t &aCommandId) const;
|
||||
|
||||
@@ -470,89 +495,31 @@ public:
|
||||
bool IsDataRequestCommand(void) const;
|
||||
|
||||
/**
|
||||
* Returns the MAC header size.
|
||||
* Gets the frame payload as `FrameData`.
|
||||
*
|
||||
* @returns The MAC header size.
|
||||
* For MAC Command frames (`kTypeMacCmd`), the treatment of the Command ID field depends on the frame version:
|
||||
* - For 2015 version , the Command ID is part of the payload, so @p aPayloadData includes it.
|
||||
* - For earlier versions (2003/2006), the Command ID is part of the MAC header, so @p aPayloadData starts after
|
||||
* the Command ID.
|
||||
*
|
||||
* @param[out] aPayloadData A reference to a `FrameData` to return the frame payload.
|
||||
*
|
||||
* @retval kErrorNone Successfully retrieved the frame payload.
|
||||
* @retval kErrorParse Failed to parse the frame.
|
||||
*/
|
||||
uint8_t GetHeaderLength(void) const;
|
||||
Error GetPayload(FrameData &aPayloadData) const;
|
||||
|
||||
/**
|
||||
* Returns the MAC footer size.
|
||||
* Determines the length breakdown of the frame.
|
||||
*
|
||||
* @returns The MAC footer size.
|
||||
*/
|
||||
uint8_t GetFooterLength(void) const;
|
||||
|
||||
/**
|
||||
* Returns the current MAC Payload length.
|
||||
* @param[out] aLengths A reference to a `Lengths` structure to return the frame lengths.
|
||||
*
|
||||
* @returns The current MAC Payload length.
|
||||
* @retval kErrorNone Successfully calculated frame lengths.
|
||||
* @retval kErrorParse Failed to parse the frame.
|
||||
*/
|
||||
uint16_t GetPayloadLength(void) const;
|
||||
|
||||
/**
|
||||
* Returns the maximum MAC Payload length for the given MAC header and footer.
|
||||
*
|
||||
* @returns The maximum MAC Payload length for the given MAC header and footer.
|
||||
*/
|
||||
uint16_t GetMaxPayloadLength(void) const;
|
||||
|
||||
/**
|
||||
* Sets the MAC Payload length.
|
||||
*/
|
||||
void SetPayloadLength(uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the MAC Header.
|
||||
*
|
||||
* @returns A pointer to the MAC Header.
|
||||
*/
|
||||
uint8_t *GetHeader(void) { return GetPsdu(); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the MAC Header.
|
||||
*
|
||||
* @returns A pointer to the MAC Header.
|
||||
*/
|
||||
const uint8_t *GetHeader(void) const { return GetPsdu(); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the MAC Payload.
|
||||
*
|
||||
* @returns A pointer to the MAC Payload.
|
||||
*/
|
||||
uint8_t *GetPayload(void) { return AsNonConst(AsConst(this)->GetPayload()); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the MAC Payload.
|
||||
*
|
||||
* @returns A pointer to the MAC Payload.
|
||||
*/
|
||||
const uint8_t *GetPayload(void) const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to the MAC Footer.
|
||||
*
|
||||
* @returns A pointer to the MAC Footer.
|
||||
*/
|
||||
uint8_t *GetFooter(void) { return AsNonConst(AsConst(this)->GetFooter()); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the MAC Footer.
|
||||
*
|
||||
* @returns A pointer to the MAC Footer.
|
||||
*/
|
||||
const uint8_t *GetFooter(void) const;
|
||||
Error DetermineLengths(Lengths &aLengths) const;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
/**
|
||||
* Indicates whether the frame contains header IEs.
|
||||
*
|
||||
* @retval TRUE The frame contains header IEs.
|
||||
* @retval FALSE The frame contains no header IEs.
|
||||
*/
|
||||
bool HasAnyHeaderIe(void) const { return FindHeaderIeIndex() != kInvalidIndex; }
|
||||
|
||||
/**
|
||||
* Finds a specific Information Element (IE) in the frame.
|
||||
*
|
||||
@@ -706,21 +673,57 @@ protected:
|
||||
static constexpr uint8_t kInvalidSize = kInvalidIndex;
|
||||
static constexpr uint8_t kMaxPsduSize = kInvalidSize - 1;
|
||||
|
||||
void SetFrameControlField(uint16_t aFcf) { LittleEndian::WriteUint16(aFcf, mPsdu); }
|
||||
void UpdateFcfFlag(bool aSet, uint16_t aBitFlag);
|
||||
uint8_t SkipSequenceIndex(void) const;
|
||||
uint8_t FindDstPanIdIndex(void) const;
|
||||
uint8_t FindDstAddrIndex(void) const;
|
||||
uint8_t FindSrcPanIdIndex(void) const;
|
||||
uint8_t FindSrcAddrIndex(void) const;
|
||||
uint8_t SkipAddrFieldIndex(void) const;
|
||||
uint8_t FindSecurityHeaderIndex(void) const;
|
||||
uint8_t SkipSecurityHeaderIndex(void) const;
|
||||
uint8_t FindPayloadIndex(void) const;
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
uint8_t FindHeaderIeIndex(void) const;
|
||||
#endif
|
||||
enum ParseMode : uint8_t
|
||||
{
|
||||
kParseAddrFields,
|
||||
kParseSecurityHeader,
|
||||
kParseFully,
|
||||
};
|
||||
|
||||
class ParseInfo
|
||||
{
|
||||
public:
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Mac Header Address Info
|
||||
uint16_t mFcf;
|
||||
PanIds mPanIds;
|
||||
Addresses mAddrs;
|
||||
uint8_t mSequenceNum;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Aux Security Header
|
||||
uint8_t mSecCtl;
|
||||
SecurityLevel mSecurityLevel;
|
||||
KeyIdMode mKeyIdMode;
|
||||
uint8_t mKeyIndex;
|
||||
uint8_t mMicSize;
|
||||
uint32_t mFrameCounter;
|
||||
FrameData mKeySource;
|
||||
uint8_t *mFrameCounterBytes;
|
||||
uint8_t *mKeyIndexByte;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Header IEs
|
||||
FrameData mIeData;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// MAC Command ID
|
||||
uint8_t mCommandId;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Header and Payload breakdown
|
||||
FrameData mHeader;
|
||||
FrameData mPayload;
|
||||
|
||||
Error ParseFrom(const Frame &aFrame, ParseMode aMode);
|
||||
|
||||
private:
|
||||
static Error ParseAddress(FrameData &aFrameData, AddrMode aAddrMode, Address &aAddress);
|
||||
};
|
||||
|
||||
void UpdateFcfFlag(bool aSet, uint16_t aBitFlag);
|
||||
|
||||
static uint16_t GetType(uint16_t aFcf) { return (aFcf & kFcfFrameTypeMask); }
|
||||
static AddrMode ReadDstAddrMode(uint16_t aFcf) { return As<AddrMode>(ReadBits<uint16_t, kFcfDstAddrMask>(aFcf)); }
|
||||
static AddrMode ReadSrcAddrMode(uint16_t aFcf) { return As<AddrMode>(ReadBits<uint16_t, kFcfSrcAddrMask>(aFcf)); }
|
||||
static bool IsSeqSuppressed(uint16_t aFcf) { return IsVersion2015(aFcf) && ((aFcf & kFcfSeqSuppression) != 0); }
|
||||
@@ -754,7 +757,6 @@ private:
|
||||
const HeaderIe *FindHeaderIe(HeaderIeMatcher aMatcher) const;
|
||||
HeaderIe *FindHeaderIe(HeaderIeMatcher aMatcher) { return AsNonConst(AsConst(this)->FindHeaderIe(aMatcher)); }
|
||||
#endif
|
||||
Error ReadAddressAt(uint8_t aIndex, AddrMode aAddrMode, Address &aAddress) const;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -813,36 +815,16 @@ public:
|
||||
/**
|
||||
* Represents the information to use to build the frame.
|
||||
*/
|
||||
struct BuildInfo : public Clearable<BuildInfo>
|
||||
class BuildInfo : public Clearable<BuildInfo>
|
||||
{
|
||||
friend class TxFrame;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initializes the `BuildInfo` by clearing all its fields (setting all bytes to zero).
|
||||
*/
|
||||
BuildInfo(void) { Clear(); }
|
||||
|
||||
/**
|
||||
* Prepares MAC headers based on `BuildInfo` fields in a given `TxFrame`.
|
||||
*
|
||||
* This method uses the `BuildInfo` structure to construct the MAC address and security headers in @p aTxFrame.
|
||||
* It determines the Frame Control Field (FCF), including setting the appropriate frame type, security level,
|
||||
* and addressing mode flags. It populates the source and destination addresses and PAN IDs within the MAC
|
||||
* header based on the information provided in the `BuildInfo` structure.
|
||||
*
|
||||
* It sets the Ack Request bit in the FCF if the following criteria are met:
|
||||
* - A destination address is present
|
||||
* - The destination address is not the broadcast address
|
||||
* - The frame type is not an ACK frame
|
||||
*
|
||||
* The header IE entries are prepared based on `mAppendTimeIe` and `mAppendCslIe` flags and the IE Present
|
||||
* flag in FCF is determined accordingly.
|
||||
*
|
||||
* The Frame Pending flag in FCF is not set. It may need to be set separately depending on the specific
|
||||
* requirements of the frame being transmitted.
|
||||
*
|
||||
* @param[in,out] aTxFrame The `TxFrame` instance in which to prepare and append the MAC headers.
|
||||
*/
|
||||
void PrepareHeadersIn(TxFrame &aTxFrame) const;
|
||||
|
||||
Type mType; ///< Frame type.
|
||||
Version mVersion; ///< Frame version.
|
||||
Addresses mAddrs; ///< Frame source and destination addresses.
|
||||
@@ -861,8 +843,92 @@ public:
|
||||
#endif
|
||||
bool mEmptyPayload : 1; ///< Whether payload is empty (to decide about appending Termination2 IE).
|
||||
#endif
|
||||
|
||||
private:
|
||||
void PrepareHeadersIn(TxFrame &aTxFrame) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class for building the payload of a `TxFrame`.
|
||||
*/
|
||||
class PayloadBuilder : public FrameBuilder
|
||||
{
|
||||
friend class TxFrame;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Gets the header length of the frame being built.
|
||||
*
|
||||
* @returns The header length (in bytes).
|
||||
*/
|
||||
uint16_t GetHeaderLength(void) const { return mLengths.mHeader; }
|
||||
|
||||
/**
|
||||
* Gets the footer length of the frame being built.
|
||||
*
|
||||
* @returns The footer length (in bytes).
|
||||
*/
|
||||
uint16_t GetFooterLength(void) const { return mLengths.mFooter; }
|
||||
|
||||
private:
|
||||
void InitFrom(TxFrame &aFrame);
|
||||
uint16_t GetTotalLength(void) const { return GetLength() + mLengths.mHeader + mLengths.mFooter; }
|
||||
|
||||
Lengths mLengths;
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepares MAC headers in the frame based on `BuildInfo` settings and initializes a `PayloadBuilder`.
|
||||
*
|
||||
* This method uses the `BuildInfo` structure to construct the MAC address and security headers in the frame.
|
||||
* It determines the Frame Control Field (FCF), including setting the appropriate frame type, security level,
|
||||
* and addressing mode flags. It populates the source and destination addresses and PAN IDs within the MAC
|
||||
* header based on the information provided in the `BuildInfo` structure.
|
||||
*
|
||||
* It sets the Ack Request bit in the FCF if the following criteria are met:
|
||||
* - A destination address is present
|
||||
* - The destination address is not the broadcast address
|
||||
* - The frame type is not an ACK frame
|
||||
*
|
||||
* The header IE entries are prepared based on `mAppendTimeIe` and `mAppendCslIe` flags and the IE Present
|
||||
* flag in FCF is determined accordingly.
|
||||
*
|
||||
* The Frame Pending flag in FCF is not set. It may need to be set separately depending on the specific
|
||||
* requirements of the frame being transmitted.
|
||||
*
|
||||
* The provided @p aPayloadBuilder is initialized to allow building and appending payload bytes directly
|
||||
* into the frame buffer following the prepared headers. It is set up with the maximum available payload
|
||||
* capacity based on the frame header and footer lengths and its MTU. Callers can use @p aPayloadBuilder to
|
||||
* construct the frame payload. Once payload construction is complete, `FinishPayload()` can be called to update
|
||||
* and finalize the total frame length.
|
||||
*
|
||||
* For MAC Command frames (`kTypeMacCmd`), whether the Command ID field is treated as part of the header or
|
||||
* payload depends on the frame version (see `GetPayload()`). The same rules apply to @p aPayloadBuilder here:
|
||||
* - For 2015 version, the Command ID is part of the payload, so @p aPayloadBuilder starts before the Command ID.
|
||||
* - For earlier versions (2003/2006), the Command ID is part of the MAC header, so @p aPayloadBuilder starts
|
||||
* after the Command ID.
|
||||
*
|
||||
* @param[in] aBuildInfo The `BuildInfo` containing settings for the MAC headers.
|
||||
* @param[out] aPayloadBuilder A reference to a `PayloadBuilder` to initialize for payload construction.
|
||||
*/
|
||||
void PrepareHeaders(const BuildInfo &aBuildInfo, PayloadBuilder &aPayloadBuilder);
|
||||
|
||||
/**
|
||||
* Finishes building the frame payload and updates the total frame length.
|
||||
*
|
||||
* @param[in] aPayloadBuilder The `PayloadBuilder` used to construct the payload.
|
||||
*/
|
||||
void FinishPayload(const PayloadBuilder &aPayloadBuilder) { SetLength(aPayloadBuilder.GetTotalLength()); }
|
||||
|
||||
/**
|
||||
* Prepares MAC headers in the frame assuming an empty payload.
|
||||
*
|
||||
* See `PrepareHeaders()` for more details on how the MAC headers are constructed.
|
||||
*
|
||||
* @param[in] aBuildInfo The `BuildInfo` structure containing settings for the MAC headers.
|
||||
*/
|
||||
void PrepareHeadersWithEmptyPayload(const BuildInfo &aBuildInfo) { aBuildInfo.PrepareHeadersIn(*this); }
|
||||
|
||||
/**
|
||||
* Copies the PSDU and all attributes (except for frame link type) from another frame.
|
||||
*
|
||||
|
||||
@@ -68,7 +68,7 @@ Error ScanResult::PopulateFromBeacon(const Mac::RxFrame *aBeaconFrame)
|
||||
const Mac::BeaconHeader *beaconHeader;
|
||||
const Mac::BeaconPayload *beaconPayload;
|
||||
|
||||
frameData.Init(aBeaconFrame->GetPayload(), aBeaconFrame->GetPayloadLength());
|
||||
SuccessOrExit(aBeaconFrame->GetPayload(frameData));
|
||||
|
||||
beaconHeader = frameData.Read<Mac::BeaconHeader>();
|
||||
VerifyOrExit((beaconHeader != nullptr) && beaconHeader->IsValid());
|
||||
|
||||
@@ -617,7 +617,7 @@ void SubMac::ReprocessSecurityForRetx(TxFrame &aFrame)
|
||||
// it contains Header IEs. The frame is first restored back to
|
||||
// plaintext and then re-encrypted with a new frame counter value.
|
||||
|
||||
VerifyOrExit(aFrame.GetSecurityEnabled() && aFrame.HasAnyHeaderIe());
|
||||
VerifyOrExit(aFrame.GetSecurityEnabled() && aFrame.IsIePresent());
|
||||
|
||||
// When transmit security is handled by `SubMac`, the AES key is already set
|
||||
// on `aFrame`. However, when transmit security is delegated to the radio
|
||||
|
||||
@@ -100,6 +100,24 @@ public:
|
||||
*/
|
||||
const uint8_t *GetPsdu(void) const { return mPsdu; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the PSDU starting at a given index.
|
||||
*
|
||||
* @param[in] aIndex The index to start from.
|
||||
*
|
||||
* @returns A pointer to the PSDU starting at @p aIndex.
|
||||
*/
|
||||
uint8_t *GetPsduStartingAt(uint16_t aIndex) { return mPsdu + aIndex; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the PSDU starting at a given index.
|
||||
*
|
||||
* @param[in] aIndex The index to start from.
|
||||
*
|
||||
* @returns A pointer to the PSDU starting at @p aIndex.
|
||||
*/
|
||||
const uint8_t *GetPsduStartingAt(uint16_t aIndex) const { return mPsdu + aIndex; }
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
/**
|
||||
* Gets the radio link type of the frame.
|
||||
|
||||
@@ -1012,7 +1012,7 @@ void MeshForwarder::HandleReceivedFrame(Mac::RxFrame &aFrame)
|
||||
|
||||
VerifyOrExit(mEnabled, error = kErrorInvalidState);
|
||||
|
||||
rxInfo.mFrameData.Init(aFrame.GetPayload(), aFrame.GetPayloadLength());
|
||||
SuccessOrExit(error = aFrame.GetPayload(rxInfo.mFrameData));
|
||||
|
||||
SuccessOrExit(error = aFrame.GetSrcAddr(rxInfo.mMacAddrs.mSource));
|
||||
SuccessOrExit(error = aFrame.GetDstAddr(rxInfo.mMacAddrs.mDestination));
|
||||
|
||||
@@ -53,9 +53,17 @@ void MessageFramer::DetermineMacSourceAddress(const Ip6::Address &aIp6Addr, Mac:
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame,
|
||||
Mac::TxFrame::BuildInfo &aBuildInfo,
|
||||
const Message *aMessage)
|
||||
void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::BuildInfo &aBuildInfo)
|
||||
{
|
||||
Mac::TxFrame::PayloadBuilder builder;
|
||||
|
||||
PrepareMacHeaders(aTxFrame, aBuildInfo, builder, nullptr);
|
||||
}
|
||||
|
||||
void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame,
|
||||
Mac::TxFrame::BuildInfo &aBuildInfo,
|
||||
Mac::TxFrame::PayloadBuilder &aPayloadBuilder,
|
||||
const Message *aMessage)
|
||||
{
|
||||
const Neighbor *neighbor;
|
||||
|
||||
@@ -110,9 +118,9 @@ void MessageFramer::PrepareMacHeaders(Mac::TxFrame &aTxFrame,
|
||||
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Prepare MAC headers
|
||||
// Prepare MAC headers and init `aPayloadBuilder`.
|
||||
|
||||
aBuildInfo.PrepareHeadersIn(aTxFrame);
|
||||
aTxFrame.PrepareHeaders(aBuildInfo, aPayloadBuilder);
|
||||
|
||||
OT_UNUSED_VARIABLE(aMessage);
|
||||
OT_UNUSED_VARIABLE(neighbor);
|
||||
@@ -136,10 +144,9 @@ void MessageFramer::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
buildInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
|
||||
PrepareMacHeaders(aFrame, buildInfo, nullptr);
|
||||
PrepareMacHeaders(aFrame, buildInfo);
|
||||
|
||||
aFrame.SetAckRequest(aAckRequest);
|
||||
aFrame.SetPayloadLength(0);
|
||||
}
|
||||
|
||||
uint16_t MessageFramer::PrepareFrame(Mac::TxFrame &aFrame,
|
||||
@@ -150,11 +157,11 @@ uint16_t MessageFramer::PrepareFrame(Mac::TxFrame &aFrame,
|
||||
uint16_t aMeshDest,
|
||||
bool aAddFragHeader)
|
||||
{
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
uint16_t payloadLength;
|
||||
uint16_t origMsgOffset;
|
||||
uint16_t nextOffset;
|
||||
FrameBuilder frameBuilder;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
Mac::TxFrame::PayloadBuilder frameBuilder;
|
||||
uint16_t payloadLength;
|
||||
uint16_t origMsgOffset;
|
||||
uint16_t nextOffset;
|
||||
|
||||
start:
|
||||
buildInfo.Clear();
|
||||
@@ -202,9 +209,7 @@ start:
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mAddrs = aMacAddrs;
|
||||
|
||||
PrepareMacHeaders(aFrame, buildInfo, &aMessage);
|
||||
|
||||
frameBuilder.Init(aFrame.GetPayload(), aFrame.GetMaxPayloadLength());
|
||||
PrepareMacHeaders(aFrame, buildInfo, frameBuilder, &aMessage);
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
@@ -229,10 +234,10 @@ start:
|
||||
// then adding the fixed `kMeshHeaderFrameFcsSize` instead
|
||||
// (updating the FCS size in the calculation of footer length).
|
||||
|
||||
maxPayloadLength = kMeshHeaderFrameMtu - aFrame.GetHeaderLength() -
|
||||
(aFrame.GetFooterLength() - aFrame.GetFcsSize() + kMeshHeaderFrameFcsSize);
|
||||
maxPayloadLength = kMeshHeaderFrameMtu - frameBuilder.GetHeaderLength() -
|
||||
(frameBuilder.GetFooterLength() - aFrame.GetFcsSize() + kMeshHeaderFrameFcsSize);
|
||||
|
||||
frameBuilder.Init(aFrame.GetPayload(), maxPayloadLength);
|
||||
frameBuilder.SetMaxLength(Min(maxPayloadLength, frameBuilder.GetMaxLength()));
|
||||
|
||||
meshHeader.Init(aMeshSource, aMeshDest, kMeshHeaderHopsLeft);
|
||||
|
||||
@@ -331,7 +336,8 @@ start:
|
||||
|
||||
// Copy IPv6 Payload
|
||||
SuccessOrAssert(frameBuilder.AppendBytesFromMessage(aMessage, aMessage.GetOffset(), payloadLength));
|
||||
aFrame.SetPayloadLength(frameBuilder.GetLength());
|
||||
|
||||
aFrame.FinishPayload(frameBuilder);
|
||||
|
||||
nextOffset = aMessage.GetOffset() + payloadLength;
|
||||
|
||||
@@ -352,7 +358,8 @@ start:
|
||||
|
||||
uint16_t MessageFramer::PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs)
|
||||
{
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
Mac::TxFrame::PayloadBuilder frameBuilder;
|
||||
|
||||
buildInfo.mType = Mac::Frame::kTypeData;
|
||||
buildInfo.mAddrs = aMacAddrs;
|
||||
@@ -360,12 +367,10 @@ uint16_t MessageFramer::PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage
|
||||
buildInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1;
|
||||
buildInfo.mPanIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());
|
||||
|
||||
PrepareMacHeaders(aFrame, buildInfo, &aMessage);
|
||||
PrepareMacHeaders(aFrame, buildInfo, frameBuilder, &aMessage);
|
||||
|
||||
// write payload
|
||||
OT_ASSERT(aMessage.GetLength() <= aFrame.GetMaxPayloadLength());
|
||||
aMessage.ReadBytes(0, aFrame.GetPayload(), aMessage.GetLength());
|
||||
aFrame.SetPayloadLength(aMessage.GetLength());
|
||||
SuccessOrAssert(frameBuilder.AppendBytesFromMessage(aMessage, 0, aMessage.GetLength()));
|
||||
aFrame.FinishPayload(frameBuilder);
|
||||
|
||||
return aMessage.GetLength();
|
||||
}
|
||||
|
||||
@@ -131,7 +131,11 @@ private:
|
||||
// (requiring one hop) and one as additional guard increment.
|
||||
static constexpr uint8_t kMeshHeaderHopsLeft = Mle::kMaxRouteCost + 3;
|
||||
|
||||
void PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::BuildInfo &aBuildInfo, const Message *aMessage);
|
||||
void PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::BuildInfo &aBuildInfo);
|
||||
void PrepareMacHeaders(Mac::TxFrame &aTxFrame,
|
||||
Mac::TxFrame::BuildInfo &aBuildInfo,
|
||||
Mac::TxFrame::PayloadBuilder &aPayloadBuilder,
|
||||
const Message *aMessage);
|
||||
|
||||
uint16_t mFragTag;
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ TEST(RadioSpinelTransmit, shouldPassDesiredTxPowerToRadioPlatform)
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
txFrame.PrepareHeadersWithEmptyPayload(buildInfo);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mTxPower = kTxPower;
|
||||
@@ -120,7 +120,7 @@ TEST(RadioSpinelTransmit, shouldCauseSwitchingToRxChannelAfterTxDone)
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
txFrame.PrepareHeadersWithEmptyPayload(buildInfo);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mTxPower = kTxPower;
|
||||
@@ -166,7 +166,7 @@ TEST(RadioSpinelTransmit, shouldSkipCsmaCaWhenDisabled)
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
txFrame.PrepareHeadersWithEmptyPayload(buildInfo);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mCsmaCaEnabled = false;
|
||||
@@ -222,7 +222,7 @@ TEST(RadioSpinelTransmit, shouldPerformCsmaCaWhenEnabled)
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
txFrame.PrepareHeadersWithEmptyPayload(buildInfo);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mCsmaCaEnabled = true;
|
||||
@@ -272,7 +272,7 @@ TEST(RadioSpinelTransmit, shouldNotCauseSwitchingToRxAfterTxDoneIfNotRxOnWhenIdl
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
txFrame.PrepareHeadersWithEmptyPayload(buildInfo);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mTxPower = kTxPower;
|
||||
@@ -348,7 +348,7 @@ TEST(RadioSpinelTransmit, shouldSkipCsmaBackoffWhenCsmaCaIsEnabledAndMaxBackoffs
|
||||
buildInfo.mPanIds.SetDestination(kDstPanId);
|
||||
buildInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
|
||||
|
||||
buildInfo.PrepareHeadersIn(txFrame);
|
||||
txFrame.PrepareHeadersWithEmptyPayload(buildInfo);
|
||||
}
|
||||
|
||||
txFrame.mInfo.mTxInfo.mCsmaCaEnabled = true;
|
||||
|
||||
@@ -294,6 +294,7 @@ void TestMacHeader(void)
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
Mac::Address address;
|
||||
Mac::PanId panId;
|
||||
Mac::Frame::Lengths lengths;
|
||||
|
||||
frame.mPsdu = psdu;
|
||||
frame.mLength = 0;
|
||||
@@ -360,10 +361,12 @@ void TestMacHeader(void)
|
||||
buildInfo.mKeyIdMode = testCase.mKeyIdMode;
|
||||
buildInfo.mSuppressSequence = testCase.mSuppressSequence;
|
||||
|
||||
buildInfo.PrepareHeadersIn(frame);
|
||||
frame.PrepareHeadersWithEmptyPayload(buildInfo);
|
||||
|
||||
VerifyOrQuit(frame.GetHeaderLength() == testCase.mHeaderLength);
|
||||
VerifyOrQuit(frame.GetFooterLength() == testCase.mFooterLength);
|
||||
SuccessOrQuit(frame.DetermineLengths(lengths));
|
||||
|
||||
VerifyOrQuit(lengths.mHeader == testCase.mHeaderLength);
|
||||
VerifyOrQuit(lengths.mFooter == testCase.mFooterLength);
|
||||
VerifyOrQuit(frame.GetLength() == testCase.mHeaderLength + testCase.mFooterLength);
|
||||
|
||||
VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeData);
|
||||
@@ -666,8 +669,10 @@ void TestMacFrameApi(void)
|
||||
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 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, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00};
|
||||
|
||||
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};
|
||||
|
||||
Reference in New Issue
Block a user