From 09698fae24521ab6f10f7df3fab5b1619f43bfca Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 1 Oct 2024 11:37:17 -0700 Subject: [PATCH] [mac-frame] add `TxFrame::Info` and simplify mac header preparation (#10689) This commit simplifies the preparation of MAC and security frames. It introduces a `TxFrame::Info` structure that provides information about the frame, such as its type, version, source and destination addresses, PAN IDs, security level, and key ID mode. A new method `PrepareHeadersIn()` is added, which uses the `Info` structure to construct the MAC address and security headers in a given `TxFrame`. This approach replaces the earlier `Mac::Frame::InitMacHeader()` where all the information was passed as a list of input arguments. The `TxFrame::Info` approach simplifies the code and allows for future extension to accommodate other parameters (e.g., Header IE entries). --- src/core/common/frame_builder.cpp | 16 +++- src/core/common/frame_builder.hpp | 36 ++++++++- src/core/mac/data_poll_sender.cpp | 24 +++--- src/core/mac/mac.cpp | 34 ++++---- src/core/mac/mac_frame.cpp | 106 ++++++++++++------------- src/core/mac/mac_frame.hpp | 64 +++++++++------ src/core/thread/mesh_forwarder.cpp | 73 ++++++++--------- src/core/thread/mesh_forwarder.hpp | 8 +- src/core/thread/mesh_forwarder_ftd.cpp | 11 ++- tests/unit/test_mac_frame.cpp | 58 +++++++------- 10 files changed, 245 insertions(+), 185 deletions(-) diff --git a/src/core/common/frame_builder.cpp b/src/core/common/frame_builder.cpp index abc647819c6..4eba998f6c6 100644 --- a/src/core/common/frame_builder.cpp +++ b/src/core/common/frame_builder.cpp @@ -45,11 +45,11 @@ namespace ot { -void FrameBuilder::Init(void *aBuffer, uint16_t aLength) +void FrameBuilder::Init(void *aBuffer, uint16_t aMaxLength) { mBuffer = static_cast(aBuffer); mLength = 0; - mMaxLength = aLength; + mMaxLength = aMaxLength; } Error FrameBuilder::AppendUint8(uint8_t aUint8) { return Append(aUint8); } @@ -118,6 +118,18 @@ Error FrameBuilder::AppendBytesFromMessage(const Message &aMessage, uint16_t aOf } #endif +void *FrameBuilder::AppendLength(uint16_t aLength) +{ + void *buffer = nullptr; + + VerifyOrExit(CanAppend(aLength)); + buffer = &mBuffer[mLength]; + mLength += aLength; + +exit: + return buffer; +} + void FrameBuilder::WriteBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength) { memcpy(mBuffer + aOffset, aBuffer, aLength); diff --git a/src/core/common/frame_builder.hpp b/src/core/common/frame_builder.hpp index 4b8df2158c8..08089138b6b 100644 --- a/src/core/common/frame_builder.hpp +++ b/src/core/common/frame_builder.hpp @@ -55,9 +55,9 @@ class FrameBuilder * `FrameBuilder` MUST be initialized before its other methods are used. * * @param[in] aBuffer A pointer to a buffer. - * @param[in] aLength The data length (number of bytes in @p aBuffer). + * @param[in] aLength The max data length (number of bytes in @p aBuffer). */ - void Init(void *aBuffer, uint16_t aLength); + void Init(void *aBuffer, uint16_t aMaxLength); /** * Returns a pointer to the start of `FrameBuilder` buffer. @@ -211,6 +211,38 @@ class FrameBuilder return AppendBytes(&aObject, sizeof(ObjectType)); } + /** + * Appends the given number of bytes to the `FrameBuilder`. + * + * This method reserves @p aLength bytes at the current position of the `FrameBuilder` and returns a pointer to the + * start of this reserved buffer if successful. The reserved bytes are left uninitialized. The caller is + * responsible for initializing them. + * + * @param[in] aLength The number of bytes to append. + * + * @returns A pointer to the start of the appended bytes if successful, or `nullptr` if there are not enough + * remaining bytes to append @p aLength bytes. + */ + void *AppendLength(uint16_t aLength); + + /** + * Appends an object to the `FrameBuilder`. + * + * @tparam ObjectType The object type to append. + * + * This method reserves bytes in `FrameBuilder` to accommodate an `ObjectType` and returns a pointer to the + * appended `ObjectType`. The `ObjectType` bytes are left uninitialized. Caller is responsible to initialize them. + * + * @returns A pointer the appended `ObjectType` if successful, or `nullptr` if there are not enough remaining + * bytes to append an `ObjectType`. + */ + template ObjectType *Append(void) + { + static_assert(!TypeTraits::IsPointer::kValue, "ObjectType must not be a pointer"); + + return static_cast(AppendLength(sizeof(ObjectType))); + } + /** * Writes bytes in `FrameBuilder` at a given offset overwriting the previously appended content. * diff --git a/src/core/mac/data_poll_sender.cpp b/src/core/mac/data_poll_sender.cpp index 623bbe2861f..e6deb02e356 100644 --- a/src/core/mac/data_poll_sender.cpp +++ b/src/core/mac/data_poll_sender.cpp @@ -542,33 +542,35 @@ uint32_t DataPollSender::GetDefaultPollPeriod(void) const Mac::TxFrame *DataPollSender::PrepareDataRequest(Mac::TxFrames &aTxFrames) { - Mac::TxFrame *frame = nullptr; - Mac::Addresses addresses; - Mac::PanIds panIds; + Mac::TxFrame *frame = nullptr; + Mac::TxFrame::Info frameInfo; #if OPENTHREAD_CONFIG_MULTI_RADIO Mac::RadioType radio; - SuccessOrExit(GetPollDestinationAddress(addresses.mDestination, radio)); + SuccessOrExit(GetPollDestinationAddress(frameInfo.mAddrs.mDestination, radio)); frame = &aTxFrames.GetTxFrame(radio); #else - SuccessOrExit(GetPollDestinationAddress(addresses.mDestination)); + SuccessOrExit(GetPollDestinationAddress(frameInfo.mAddrs.mDestination)); frame = &aTxFrames.GetTxFrame(); #endif - if (addresses.mDestination.IsExtended()) + if (frameInfo.mAddrs.mDestination.IsExtended()) { - addresses.mSource.SetExtended(Get().GetExtAddress()); + frameInfo.mAddrs.mSource.SetExtended(Get().GetExtAddress()); } else { - addresses.mSource.SetShort(Get().GetShortAddress()); + frameInfo.mAddrs.mSource.SetShort(Get().GetShortAddress()); } - panIds.SetBothSourceDestination(Get().GetPanId()); + frameInfo.mPanIds.SetBothSourceDestination(Get().GetPanId()); - Get().PrepareMacHeaders(*frame, Mac::Frame::kTypeMacCmd, addresses, panIds, - Mac::Frame::kSecurityEncMic32, Mac::Frame::kKeyIdMode1, nullptr); + frameInfo.mType = Mac::Frame::kTypeMacCmd; + frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32; + frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1; + + Get().PrepareMacHeaders(*frame, frameInfo, nullptr); #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE if (frame->HasCslIe()) diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 2a119cda2d1..ca9c28057b9 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -722,15 +722,17 @@ void Mac::FinishOperation(void) TxFrame *Mac::PrepareBeaconRequest(void) { - TxFrame &frame = mLinks.GetTxFrames().GetBroadcastTxFrame(); - Addresses addrs; - PanIds panIds; + TxFrame &frame = mLinks.GetTxFrames().GetBroadcastTxFrame(); + TxFrame::Info frameInfo; - addrs.mSource.SetNone(); - addrs.mDestination.SetShort(kShortAddrBroadcast); - panIds.SetDestination(kShortAddrBroadcast); + frameInfo.mAddrs.mSource.SetNone(); + frameInfo.mAddrs.mDestination.SetShort(kShortAddrBroadcast); + frameInfo.mPanIds.SetDestination(kShortAddrBroadcast); - frame.InitMacHeader(Frame::kTypeMacCmd, Frame::kVersion2003, addrs, panIds, Frame::kSecurityNone); + frameInfo.mType = Frame::kTypeMacCmd; + frameInfo.mVersion = Frame::kVersion2003; + + frameInfo.PrepareHeadersIn(frame); IgnoreError(frame.SetCommandId(Frame::kMacCmdBeaconRequest)); @@ -741,10 +743,9 @@ TxFrame *Mac::PrepareBeaconRequest(void) TxFrame *Mac::PrepareBeacon(void) { - TxFrame *frame; - Beacon *beacon = nullptr; - Addresses addrs; - PanIds panIds; + TxFrame *frame; + TxFrame::Info frameInfo; + Beacon *beacon = nullptr; #if OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE uint8_t beaconLength; BeaconPayload *beaconPayload = nullptr; @@ -758,11 +759,14 @@ TxFrame *Mac::PrepareBeacon(void) frame = &mLinks.GetTxFrames().GetBroadcastTxFrame(); #endif - addrs.mSource.SetExtended(GetExtAddress()); - panIds.SetSource(mPanId); - addrs.mDestination.SetNone(); + frameInfo.mAddrs.mSource.SetExtended(GetExtAddress()); + frameInfo.mPanIds.SetSource(mPanId); + frameInfo.mAddrs.mDestination.SetNone(); + + frameInfo.mType = Frame::kTypeBeacon; + frameInfo.mVersion = Frame::kVersion2003; - frame->InitMacHeader(Frame::kTypeBeacon, Frame::kVersion2003, addrs, panIds, Frame::kSecurityNone); + frameInfo.PrepareHeadersIn(*frame); beacon = reinterpret_cast(frame->GetPayload()); beacon->Init(); diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp index 1fc2154c60a..cc09f50a7a0 100644 --- a/src/core/mac/mac_frame.cpp +++ b/src/core/mac/mac_frame.cpp @@ -48,20 +48,15 @@ namespace ot { namespace Mac { -void Frame::InitMacHeader(Type aType, - Version aVersion, - const Addresses &aAddrs, - const PanIds &aPanIds, - SecurityLevel aSecurityLevel, - KeyIdMode aKeyIdMode, - bool aSuppressSequence) +void TxFrame::Info::PrepareHeadersIn(TxFrame &aTxFrame) const { uint16_t fcf; FrameBuilder builder; + uint8_t micSize = 0; - fcf = static_cast(aType) | static_cast(aVersion); + fcf = static_cast(mType) | static_cast(mVersion); - switch (aAddrs.mSource.GetType()) + switch (mAddrs.mSource.GetType()) { case Address::kTypeNone: fcf |= kFcfSrcAddrNone; @@ -74,30 +69,30 @@ void Frame::InitMacHeader(Type aType, break; } - switch (aAddrs.mDestination.GetType()) + switch (mAddrs.mDestination.GetType()) { case Address::kTypeNone: fcf |= kFcfDstAddrNone; break; case Address::kTypeShort: fcf |= kFcfDstAddrShort; - fcf |= ((aAddrs.mDestination.GetShort() == kShortAddrBroadcast) ? 0 : kFcfAckRequest); + fcf |= ((mAddrs.mDestination.GetShort() == kShortAddrBroadcast) ? 0 : kFcfAckRequest); break; case Address::kTypeExtended: fcf |= (kFcfDstAddrExt | kFcfAckRequest); break; } - if (aType == kTypeAck) + if (mType == kTypeAck) { fcf &= ~kFcfAckRequest; } - fcf |= (aSecurityLevel != kSecurityNone) ? kFcfSecurityEnabled : 0; + fcf |= (mSecurityLevel != kSecurityNone) ? kFcfSecurityEnabled : 0; // PAN ID compression - switch (aVersion) + switch (mVersion) { case kVersion2003: case kVersion2006: @@ -114,14 +109,14 @@ void Frame::InitMacHeader(Type aType, // PAN ID Compression field shall be set to zero, and both Destination PAN ID // field and Source PAN ID fields shall be included in the transmitted frame. - if (!aAddrs.mSource.IsNone() && !aAddrs.mDestination.IsNone() && - (aPanIds.GetSource() == aPanIds.GetDestination())) + if (!mAddrs.mSource.IsNone() && !mAddrs.mDestination.IsNone() && + (mPanIds.GetSource() == mPanIds.GetDestination())) { fcf |= kFcfPanidCompression; } // Sequence Number Suppression bit was reserved, and must not be set on initialization. - OT_ASSERT(!aSuppressSequence); + OT_ASSERT(!mSuppressSequence); break; case kVersion2015: @@ -146,12 +141,12 @@ void Frame::InitMacHeader(Type aType, // | 14 | Short | Short | Present | Not Present | 1 | // +----+--------------+--------------+--------------+--------------+--------------+ - if (aAddrs.mDestination.IsNone()) + if (mAddrs.mDestination.IsNone()) { // Dst addr not present - rows 1,2,5,6. - if ((aAddrs.mSource.IsNone() && aPanIds.IsDestinationPresent()) || // Row 2. - (!aAddrs.mSource.IsNone() && !aPanIds.IsDestinationPresent() && !aPanIds.IsSourcePresent())) // Row 6. + if ((mAddrs.mSource.IsNone() && mPanIds.IsDestinationPresent()) || // Row 2. + (!mAddrs.mSource.IsNone() && !mPanIds.IsDestinationPresent() && !mPanIds.IsSourcePresent())) // Row 6. { fcf |= kFcfPanidCompression; } @@ -159,11 +154,11 @@ void Frame::InitMacHeader(Type aType, break; } - if (aAddrs.mSource.IsNone()) + if (mAddrs.mSource.IsNone()) { // Dst addr present, Src addr not present - rows 3,4. - if (!aPanIds.IsDestinationPresent()) // Row 4. + if (!mPanIds.IsDestinationPresent()) // Row 4. { fcf |= kFcfPanidCompression; } @@ -173,16 +168,16 @@ void Frame::InitMacHeader(Type aType, // Both addresses are present - rows 7 to 14. - if (aAddrs.mSource.IsExtended() && aAddrs.mDestination.IsExtended()) + if (mAddrs.mSource.IsExtended() && mAddrs.mDestination.IsExtended()) { // Both addresses are extended - rows 7,8. - if (aPanIds.IsDestinationPresent()) // Row 7. + if (mPanIds.IsDestinationPresent()) // Row 7. { break; } } - else if (aPanIds.GetSource() != aPanIds.GetDestination()) // Rows 9-14. + else if (mPanIds.GetSource() != mPanIds.GetDestination()) // Rows 9-14. { break; } @@ -192,51 +187,53 @@ void Frame::InitMacHeader(Type aType, break; } - if (aSuppressSequence) + if (mSuppressSequence) { fcf |= kFcfSequenceSuppression; } - builder.Init(mPsdu, GetMtu()); + builder.Init(aTxFrame.mPsdu, aTxFrame.GetMtu()); IgnoreError(builder.AppendLittleEndianUint16(fcf)); if (IsSequencePresent(fcf)) { - IgnoreError(builder.AppendUint8(0)); // Seq number + builder.Append(); // Place holder for seq number } if (IsDstPanIdPresent(fcf)) { - IgnoreError(builder.AppendLittleEndianUint16(aPanIds.GetDestination())); + IgnoreError(builder.AppendLittleEndianUint16(mPanIds.GetDestination())); } - IgnoreError(builder.AppendMacAddress(aAddrs.mDestination)); + IgnoreError(builder.AppendMacAddress(mAddrs.mDestination)); if (IsSrcPanIdPresent(fcf)) { - IgnoreError(builder.AppendLittleEndianUint16(aPanIds.GetSource())); + IgnoreError(builder.AppendLittleEndianUint16(mPanIds.GetSource())); } - IgnoreError(builder.AppendMacAddress(aAddrs.mSource)); + IgnoreError(builder.AppendMacAddress(mAddrs.mSource)); - mLength = builder.GetLength(); + aTxFrame.mLength = builder.GetLength(); - if (aSecurityLevel != kSecurityNone) + if (mSecurityLevel != kSecurityNone) { - uint8_t secCtl = static_cast(aSecurityLevel) | static_cast(aKeyIdMode); + uint8_t secCtl = static_cast(mSecurityLevel) | static_cast(mKeyIdMode); IgnoreError(builder.AppendUint8(secCtl)); + builder.AppendLength(CalculateSecurityHeaderSize(secCtl) - sizeof(secCtl)); - mLength += CalculateSecurityHeaderSize(secCtl); - mLength += CalculateMicSize(secCtl); + micSize = CalculateMicSize(secCtl); } - if (aType == kTypeMacCmd) + if (mType == kTypeMacCmd) { - mLength += kCommandIdSize; + builder.Append(); // Placeholder for Command ID } - mLength += GetFcsSize(); + builder.AppendLength(micSize + aTxFrame.GetFcsSize()); + + aTxFrame.mLength = builder.GetLength(); } void Frame::SetFrameControlField(uint16_t aFcf) @@ -1546,13 +1543,12 @@ void TxFrame::GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending) #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength) { - Error error = kErrorNone; - Address address; - PanId panId; - Addresses addrs; - PanIds panIds; - uint8_t securityLevel = kSecurityNone; - uint8_t keyIdMode = kKeyIdMode0; + Error error = kErrorNone; + Info frameInfo; + Address address; + PanId panId; + uint8_t securityLevel = kSecurityNone; + uint8_t keyIdMode = kKeyIdMode0; // Validate the received frame. @@ -1569,8 +1565,8 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, con // Check `aRxFrame` has a valid source, which is then used as // ack frames destination. - SuccessOrExit(error = aRxFrame.GetSrcAddr(addrs.mDestination)); - VerifyOrExit(!addrs.mDestination.IsNone(), error = kErrorParse); + SuccessOrExit(error = aRxFrame.GetSrcAddr(frameInfo.mAddrs.mDestination)); + VerifyOrExit(!frameInfo.mAddrs.mDestination.IsNone(), error = kErrorParse); if (aRxFrame.GetSecurityEnabled()) { @@ -1583,12 +1579,12 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, con if (aRxFrame.IsSrcPanIdPresent()) { SuccessOrExit(error = aRxFrame.GetSrcPanId(panId)); - panIds.SetDestination(panId); + frameInfo.mPanIds.SetDestination(panId); } else if (aRxFrame.IsDstPanIdPresent()) { SuccessOrExit(error = aRxFrame.GetDstPanId(panId)); - panIds.SetDestination(panId); + frameInfo.mPanIds.SetDestination(panId); } // Prepare the ack frame @@ -1596,8 +1592,12 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, con mChannel = aRxFrame.mChannel; ClearAllBytes(mInfo.mTxInfo); - InitMacHeader(kTypeAck, kVersion2015, addrs, panIds, static_cast(securityLevel), - static_cast(keyIdMode)); + frameInfo.mType = kTypeAck; + frameInfo.mVersion = kVersion2015; + frameInfo.mSecurityLevel = static_cast(securityLevel); + frameInfo.mKeyIdMode = static_cast(keyIdMode); + + frameInfo.PrepareHeadersIn(*this); SetFramePending(aIsFramePending); SetIePresent(aIeLength != 0); diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp index 1dad47ec4d7..588363b235c 100644 --- a/src/core/mac/mac_frame.hpp +++ b/src/core/mac/mac_frame.hpp @@ -155,31 +155,6 @@ class Frame : public otRadioFrame */ bool IsEmpty(void) const { return (mLength == 0); } - /** - * Initializes the MAC header. - * - * Determines and writes the Frame Control Field (FCF) and Security Control in the frame along with - * given source and destination addresses and PAN IDs. - * - * The Ack Request bit in FCF is set if there is destination and it is not broadcast and frame type @p aType is not - * ACK. The Frame Pending and IE Present bits are not set. - * - * @param[in] aType Frame type. - * @param[in] aVersion Frame version. - * @param[in] aAddrs Frame source and destination addresses (each can be none, short, or extended). - * @param[in] aPanIds Source and destination PAN IDs. - * @param[in] aSecurityLevel Frame security level. - * @param[in] aKeyIdMode Frame security key ID mode. - * @param[in] aSuppressSequence Whether to suppress sequence number. - */ - void InitMacHeader(Type aType, - Version aVersion, - const Addresses &aAddrs, - const PanIds &aPanIds, - SecurityLevel aSecurityLevel, - KeyIdMode aKeyIdMode = kKeyIdMode0, - bool aSuppressSequence = false); - /** * Validates the frame. * @@ -1136,6 +1111,45 @@ class RxFrame : public Frame class TxFrame : public Frame { public: + /** + * Represents header information. + */ + struct Info : public Clearable + { + /** + * Initializes the `Info` by clearing all its fields (setting all bytes to zero). + */ + Info(void) { Clear(); } + + /** + * Prepares MAC headers based on `Info` fields in a given `TxFrame`. + * + * This method uses the `Info` 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 `Info` 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 Frame Pending and IE Present flags in the FCF are not set. They 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. + PanIds mPanIds; ///< Source and destination PAN Ids. + SecurityLevel mSecurityLevel; ///< Frame security level. + KeyIdMode mKeyIdMode; ///< Frame security key ID mode. + bool mSuppressSequence : 1; ///< Whether to suppress seq number. + }; + /** * Sets the channel on which to send the frame. * diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index e5888faf26d..e7b16066bb4 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -162,21 +162,23 @@ void MeshForwarder::Stop(void) void MeshForwarder::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest) { - Mac::Addresses addresses; - Mac::PanIds panIds; + Mac::TxFrame::Info frameInfo; - addresses.mSource.SetShort(Get().GetShortAddress()); + frameInfo.mAddrs.mSource.SetShort(Get().GetShortAddress()); - if (addresses.mSource.IsShortAddrInvalid() || aMacDest.IsExtended()) + if (frameInfo.mAddrs.mSource.IsShortAddrInvalid() || aMacDest.IsExtended()) { - addresses.mSource.SetExtended(Get().GetExtAddress()); + frameInfo.mAddrs.mSource.SetExtended(Get().GetExtAddress()); } - addresses.mDestination = aMacDest; - panIds.SetBothSourceDestination(Get().GetPanId()); + frameInfo.mAddrs.mDestination = aMacDest; + frameInfo.mPanIds.SetBothSourceDestination(Get().GetPanId()); - PrepareMacHeaders(aFrame, Mac::Frame::kTypeData, addresses, panIds, Mac::Frame::kSecurityEncMic32, - Mac::Frame::kKeyIdMode1, nullptr); + frameInfo.mType = Mac::Frame::kTypeData; + frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32; + frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1; + + PrepareMacHeaders(aFrame, frameInfo, nullptr); aFrame.SetAckRequest(aAckRequest); aFrame.SetPayloadLength(0); @@ -836,26 +838,20 @@ Mac::TxFrame *MeshForwarder::HandleFrameRequest(Mac::TxFrames &aTxFrames) return frame; } -void MeshForwarder::PrepareMacHeaders(Mac::TxFrame &aFrame, - Mac::Frame::Type aFrameType, - const Mac::Addresses &aMacAddrs, - const Mac::PanIds &aPanIds, - Mac::Frame::SecurityLevel aSecurityLevel, - Mac::Frame::KeyIdMode aKeyIdMode, - const Message *aMessage) +void MeshForwarder::PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::Info &aTxFrameInfo, const Message *aMessage) { - bool iePresent; - Mac::Frame::Version version; + bool iePresent; iePresent = CalcIePresent(aMessage); - version = CalcFrameVersion(Get().FindNeighbor(aMacAddrs.mDestination), iePresent); + aTxFrameInfo.mVersion = + CalcFrameVersion(Get().FindNeighbor(aTxFrameInfo.mAddrs.mDestination), iePresent); - aFrame.InitMacHeader(aFrameType, version, aMacAddrs, aPanIds, aSecurityLevel, aKeyIdMode); + aTxFrameInfo.PrepareHeadersIn(aTxFrame); #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT if (iePresent) { - AppendHeaderIe(aMessage, aFrame); + AppendHeaderIe(aMessage, aTxFrame); } #endif } @@ -879,59 +875,58 @@ uint16_t MeshForwarder::PrepareDataFrame(Mac::TxFrame &aFrame, uint16_t aMeshDest, bool aAddFragHeader) { - Mac::Frame::SecurityLevel securityLevel; - Mac::Frame::KeyIdMode keyIdMode; - Mac::PanIds panIds; - uint16_t payloadLength; - uint16_t origMsgOffset; - uint16_t nextOffset; - FrameBuilder frameBuilder; + Mac::TxFrame::Info frameInfo; + uint16_t payloadLength; + uint16_t origMsgOffset; + uint16_t nextOffset; + FrameBuilder frameBuilder; start: - - securityLevel = Mac::Frame::kSecurityNone; - keyIdMode = Mac::Frame::kKeyIdMode1; + frameInfo.Clear(); if (aMessage.IsLinkSecurityEnabled()) { - securityLevel = Mac::Frame::kSecurityEncMic32; + frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32; switch (aMessage.GetSubType()) { case Message::kSubTypeJoinerEntrust: - keyIdMode = Mac::Frame::kKeyIdMode0; + frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode0; break; case Message::kSubTypeMleAnnounce: - keyIdMode = Mac::Frame::kKeyIdMode2; + frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode2; break; default: - // Use the `kKeyIdMode1` + frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1; break; } } - panIds.SetBothSourceDestination(Get().GetPanId()); + frameInfo.mPanIds.SetBothSourceDestination(Get().GetPanId()); switch (aMessage.GetSubType()) { case Message::kSubTypeMleAnnounce: aFrame.SetChannel(aMessage.GetChannel()); aFrame.SetRxChannelAfterTxDone(Get().GetPanChannel()); - panIds.SetDestination(Mac::kPanIdBroadcast); + frameInfo.mPanIds.SetDestination(Mac::kPanIdBroadcast); break; case Message::kSubTypeMleDiscoverRequest: case Message::kSubTypeMleDiscoverResponse: - panIds.SetDestination(aMessage.GetPanId()); + frameInfo.mPanIds.SetDestination(aMessage.GetPanId()); break; default: break; } - PrepareMacHeaders(aFrame, Mac::Frame::kTypeData, aMacAddrs, panIds, securityLevel, keyIdMode, &aMessage); + frameInfo.mType = Mac::Frame::kTypeData; + frameInfo.mAddrs = aMacAddrs; + + PrepareMacHeaders(aFrame, frameInfo, &aMessage); frameBuilder.Init(aFrame.GetPayload(), aFrame.GetMaxPayloadLength()); diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 9499f65e0a2..077820f470c 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -509,13 +509,7 @@ class MeshForwarder : public InstanceLocator, private NonCopyable void HandleFragment(RxInfo &aRxInfo); void HandleLowpanHc(RxInfo &aRxInfo); - void PrepareMacHeaders(Mac::TxFrame &aFrame, - Mac::Frame::Type aFrameType, - const Mac::Addresses &aMacAddr, - const Mac::PanIds &aPanIds, - Mac::Frame::SecurityLevel aSecurityLevel, - Mac::Frame::KeyIdMode aKeyIdMode, - const Message *aMessage); + void PrepareMacHeaders(Mac::TxFrame &aTxFrame, Mac::TxFrame::Info &aTxFrameInfo, const Message *aMessage); uint16_t PrepareDataFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs, diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 6e2ab0d8fd9..f91e53245dc 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -328,12 +328,15 @@ void MeshForwarder::RemoveDataResponseMessages(void) void MeshForwarder::SendMesh(Message &aMessage, Mac::TxFrame &aFrame) { - Mac::PanIds panIds; + Mac::TxFrame::Info frameInfo; - panIds.SetBothSourceDestination(Get().GetPanId()); + frameInfo.mType = Mac::Frame::kTypeData; + frameInfo.mAddrs = mMacAddrs; + frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32; + frameInfo.mKeyIdMode = Mac::Frame::kKeyIdMode1; + frameInfo.mPanIds.SetBothSourceDestination(Get().GetPanId()); - PrepareMacHeaders(aFrame, Mac::Frame::kTypeData, mMacAddrs, panIds, Mac::Frame::kSecurityEncMic32, - Mac::Frame::kKeyIdMode1, &aMessage); + PrepareMacHeaders(aFrame, frameInfo, &aMessage); // write payload OT_ASSERT(aMessage.GetLength() <= aFrame.GetMaxPayloadLength()); diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp index 41bfd8d6254..b29fb1d1db1 100644 --- a/tests/unit/test_mac_frame.cpp +++ b/tests/unit/test_mac_frame.cpp @@ -290,44 +290,43 @@ void TestMacHeader(void) uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE]; uint8_t offset; - Mac::TxFrame frame; - Mac::Addresses addresses; - Mac::Address address; - Mac::PanIds panIds; - Mac::PanId panId; + Mac::TxFrame frame; + Mac::TxFrame::Info frameInfo; + Mac::Address address; + Mac::PanId panId; frame.mPsdu = psdu; frame.mLength = 0; frame.mRadioType = 0; - VerifyOrQuit(addresses.mSource.IsNone()); - VerifyOrQuit(addresses.mDestination.IsNone()); - VerifyOrQuit(!panIds.IsSourcePresent()); - VerifyOrQuit(!panIds.IsDestinationPresent()); + VerifyOrQuit(frameInfo.mAddrs.mSource.IsNone()); + VerifyOrQuit(frameInfo.mAddrs.mDestination.IsNone()); + VerifyOrQuit(!frameInfo.mPanIds.IsSourcePresent()); + VerifyOrQuit(!frameInfo.mPanIds.IsDestinationPresent()); switch (testCase.mSrcAddrType) { case kNoneAddr: - addresses.mSource.SetNone(); + frameInfo.mAddrs.mSource.SetNone(); break; case kShrtAddr: - addresses.mSource.SetShort(kShortAddr1); + frameInfo.mAddrs.mSource.SetShort(kShortAddr1); break; case kExtdAddr: - addresses.mSource.SetExtended(extAddr1); + frameInfo.mAddrs.mSource.SetExtended(extAddr1); break; } switch (testCase.mDstAddrType) { case kNoneAddr: - addresses.mDestination.SetNone(); + frameInfo.mAddrs.mDestination.SetNone(); break; case kShrtAddr: - addresses.mDestination.SetShort(kShortAddr2); + frameInfo.mAddrs.mDestination.SetShort(kShortAddr2); break; case kExtdAddr: - addresses.mDestination.SetExtended(extAddr2); + frameInfo.mAddrs.mDestination.SetExtended(extAddr2); break; } @@ -336,10 +335,10 @@ void TestMacHeader(void) case kNoPanId: break; case kUsePanId1: - panIds.SetSource(kPanId1); + frameInfo.mPanIds.SetSource(kPanId1); break; case kUsePanId2: - panIds.SetSource(kPanId2); + frameInfo.mPanIds.SetSource(kPanId2); break; } @@ -348,15 +347,20 @@ void TestMacHeader(void) case kNoPanId: break; case kUsePanId1: - panIds.SetDestination(kPanId1); + frameInfo.mPanIds.SetDestination(kPanId1); break; case kUsePanId2: - panIds.SetDestination(kPanId2); + frameInfo.mPanIds.SetDestination(kPanId2); break; } - frame.InitMacHeader(Mac::Frame::kTypeData, testCase.mVersion, addresses, panIds, testCase.mSecurity, - testCase.mKeyIdMode, testCase.mSuppressSequence); + frameInfo.mType = Mac::Frame::kTypeData; + frameInfo.mVersion = testCase.mVersion; + frameInfo.mSecurityLevel = testCase.mSecurity; + frameInfo.mKeyIdMode = testCase.mKeyIdMode; + frameInfo.mSuppressSequence = testCase.mSuppressSequence; + + frameInfo.PrepareHeadersIn(frame); VerifyOrQuit(frame.GetHeaderLength() == testCase.mHeaderLength); VerifyOrQuit(frame.GetFooterLength() == testCase.mFooterLength); @@ -372,25 +376,25 @@ void TestMacHeader(void) VerifyOrQuit(frame.IsSrcAddrPresent() == (testCase.mSrcAddrType != kNoneAddr)); SuccessOrQuit(frame.GetSrcAddr(address)); - VerifyOrQuit(CompareAddresses(address, addresses.mSource)); + VerifyOrQuit(CompareAddresses(address, frameInfo.mAddrs.mSource)); VerifyOrQuit(frame.IsDstAddrPresent() == (testCase.mDstAddrType != kNoneAddr)); SuccessOrQuit(frame.GetDstAddr(address)); - VerifyOrQuit(CompareAddresses(address, addresses.mDestination)); + VerifyOrQuit(CompareAddresses(address, frameInfo.mAddrs.mDestination)); VerifyOrQuit(frame.IsDstPanIdPresent() == (testCase.mDstPanIdMode != kNoPanId)); if (frame.IsDstPanIdPresent()) { SuccessOrQuit(frame.GetDstPanId(panId)); - VerifyOrQuit(panId == panIds.GetDestination()); - VerifyOrQuit(panIds.IsDestinationPresent()); + VerifyOrQuit(panId == frameInfo.mPanIds.GetDestination()); + VerifyOrQuit(frameInfo.mPanIds.IsDestinationPresent()); } if (frame.IsSrcPanIdPresent()) { SuccessOrQuit(frame.GetSrcPanId(panId)); - VerifyOrQuit(panId == panIds.GetSource()); - VerifyOrQuit(panIds.IsSourcePresent()); + VerifyOrQuit(panId == frameInfo.mPanIds.GetSource()); + VerifyOrQuit(frameInfo.mPanIds.IsSourcePresent()); } if (frame.GetSecurityEnabled())