diff --git a/examples/platforms/utils/mac_frame.cpp b/examples/platforms/utils/mac_frame.cpp index 353e02481..eab13986c 100644 --- a/examples/platforms/utils/mac_frame.cpp +++ b/examples/platforms/utils/mac_frame.cpp @@ -230,7 +230,7 @@ uint8_t otMacFrameGenerateCslIeTemplate(uint8_t *aDest) { assert(aDest != nullptr); - reinterpret_cast(aDest)->SetId(Mac::Frame::kHeaderIeCsl); + reinterpret_cast(aDest)->SetId(Mac::CslIe::kHeaderIeId); reinterpret_cast(aDest)->SetLength(sizeof(Mac::CslIe)); return sizeof(Mac::HeaderIe) + sizeof(Mac::CslIe); @@ -244,7 +244,7 @@ uint8_t otMacFrameGenerateEnhAckProbingIe(uint8_t *aDest, const uint8_t *aIeData assert(aDest != nullptr); - reinterpret_cast(aDest)->SetId(Mac::Frame::kHeaderIeVendor); + reinterpret_cast(aDest)->SetId(Mac::ThreadIe::kHeaderIeId); reinterpret_cast(aDest)->SetLength(len); aDest += sizeof(Mac::HeaderIe); diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index d401891d8..2d1fdd484 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -903,6 +903,7 @@ TxFrame *Mac::PrepareDataRequest(void) TxFrame *frame = nullptr; Address src, dst; uint16_t fcf; + bool iePresent = Get().CalcIePresent(nullptr); #if OPENTHREAD_CONFIG_MULTI_RADIO RadioType radio; @@ -915,7 +916,13 @@ TxFrame *Mac::PrepareDataRequest(void) #endif fcf = Frame::kFcfFrameMacCmd | Frame::kFcfPanidCompression | Frame::kFcfAckRequest | Frame::kFcfSecurityEnabled; - UpdateFrameControlField(nullptr, /* aIsTimeSync */ false, fcf); + + if (iePresent) + { + fcf |= Frame::kFcfIePresent; + } + + fcf |= Get().CalcFrameVersion(Get().FindNeighbor(dst), iePresent); if (dst.IsExtended()) { @@ -938,7 +945,10 @@ TxFrame *Mac::PrepareDataRequest(void) frame->SetSrcAddr(src); frame->SetDstAddr(dst); #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - IgnoreError(AppendHeaderIe(false, *frame)); + if (iePresent) + { + Get().AppendHeaderIe(nullptr, *frame); + } #endif IgnoreError(frame->SetCommandId(Frame::kMacCmdDataRequest)); @@ -2565,7 +2575,7 @@ bool Mac::IsCslEnabled(void) const #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE void Mac::ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr) { - const uint8_t *cur = aFrame.GetHeaderIe(Frame::kHeaderIeCsl); + const uint8_t *cur = aFrame.GetHeaderIe(CslIe::kHeaderIeId); Child * child = Get().FindChild(aSrcAddr, Child::kInStateAnyExceptInvalid); const CslIe * csl; @@ -2615,109 +2625,5 @@ exit: } #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT -otError Mac::AppendHeaderIe(bool aIsTimeSync, TxFrame &aFrame) const -{ - OT_UNUSED_VARIABLE(aIsTimeSync); - - const size_t kMaxNumHeaderIe = 3; // TimeSync + CSL + Termination2 - HeaderIe ieList[kMaxNumHeaderIe]; - otError error = OT_ERROR_NONE; - uint8_t ieCount = 0; - - VerifyOrExit(aFrame.IsVersion2015() && aFrame.IsIePresent()); - -#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - if (aIsTimeSync) - { - ieList[ieCount].Init(); - ieList[ieCount].SetId(Frame::kHeaderIeVendor); - ieList[ieCount].SetLength(sizeof(TimeIe)); - ieCount++; - } -#endif - -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (IsCslEnabled()) - { - OT_ASSERT(aFrame.GetSecurityEnabled()); - - aFrame.mInfo.mTxInfo.mCslPresent = true; - ieList[ieCount].Init(); - ieList[ieCount].SetId(Frame::kHeaderIeCsl); - ieList[ieCount].SetLength(sizeof(CslIe)); - ieCount++; - } - else -#endif - { - aFrame.mInfo.mTxInfo.mCslPresent = false; - } - - if (ieCount > 0) - { - ieList[ieCount].Init(); - ieList[ieCount].SetId(Frame::kHeaderIeTermination2); - ieList[ieCount].SetLength(0); - - SuccessOrExit(error = aFrame.AppendHeaderIe(ieList, ++ieCount)); - } - -#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - if (aIsTimeSync) - { - uint8_t *cur = aFrame.GetHeaderIe(Frame::kHeaderIeVendor); - TimeIe * ie = reinterpret_cast(cur + sizeof(HeaderIe)); - - ie->Init(); - } -#endif - -exit: - return error; -} -#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - -void Mac::UpdateFrameControlField(const Neighbor *aNeighbor, bool aIsTimeSync, uint16_t &aFcf) const -{ - OT_UNUSED_VARIABLE(aIsTimeSync); - OT_UNUSED_VARIABLE(aNeighbor); - -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT -#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - if (aIsTimeSync) - { - aFcf |= Frame::kFcfFrameVersion2015 | Frame::kFcfIePresent; - } - else -#endif -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (IsCslEnabled()) - { - aFcf |= Frame::kFcfFrameVersion2015 | Frame::kFcfIePresent; - } - else -#endif -#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - if (aNeighbor != nullptr && !Mle::MleRouter::IsActiveRouter(aNeighbor->GetRloc16()) && - static_cast(aNeighbor)->IsCslSynchronized()) - { - aFcf |= Frame::kFcfFrameVersion2015; - } - else -#endif -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE - if (aNeighbor != nullptr && aNeighbor->IsEnhAckProbingActive()) - { - aFcf |= Frame::kFcfFrameVersion2015; ///< Set version to 2015 to fetch Link Metrics data in Enh-ACK. - } - else -#endif -#endif - { - aFcf |= Frame::kFcfFrameVersion2006; - } -} - } // namespace Mac } // namespace ot diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index 9ab8926b7..a169eecce 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -746,35 +746,6 @@ public: #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - /** - * This method appends header IEs to a TX-frame according to its - * frame control field and if time sync is enabled. - * - * @param[in] aIsTimeSync A boolean indicates if time sync is being used. - * @param[in,out] aFrame A reference to the TX-frame to which the IEs will be appended. - * - * @retval OT_ERROR_NONE If append header IEs successfully. - * @retval OT_ERROR_NOT_FOUND If cannot find header IE position in the frame. - * - */ - otError AppendHeaderIe(bool aIsTimeSync, TxFrame &aFrame) const; -#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - - /** - * This method updates frame control field. - * - * If the frame would contain header IEs, IE present field would be set. - * If this is a CSL transmission frame or header IE is present in this frame, - * the version should be set to 2015. Otherwise, the version would be set to 2006. - * - * @param[in] aNeighbor A pointer to the destination device, could be `nullptr`. - * @param[in] aIsTimeSync A boolean indicates if time sync is being used. - * @param[out] aFcf A reference to the frame control field to set. - * - */ - void UpdateFrameControlField(const Neighbor *aNeighbor, bool aIsTimeSync, uint16_t &aFcf) const; - private: enum { diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp index bdbb03016..eb3f0ab10 100644 --- a/src/core/mac/mac_frame.cpp +++ b/src/core/mac/mac_frame.cpp @@ -50,6 +50,13 @@ using ot::Encoding::LittleEndian::ReadUint32; using ot::Encoding::LittleEndian::WriteUint16; using ot::Encoding::LittleEndian::WriteUint32; +void HeaderIe::Init(uint16_t aId, uint8_t aLen) +{ + Init(); + SetId(aId); + SetLength(aLen); +} + void Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl) { mLength = CalculateAddrFieldSize(aFcf); @@ -829,7 +836,7 @@ uint8_t Frame::FindPayloadIndex(void) const index += ie->GetLength(); VerifyOrExit(index + footerLength <= mLength, index = kInvalidIndex); - if (ie->GetId() == kHeaderIeTermination2) + if (ie->GetId() == Termination2Ie::kHeaderIeId) { break; } @@ -886,25 +893,59 @@ exit: return index; } -otError Frame::AppendHeaderIe(HeaderIe *aIeList, uint8_t aIeCount) +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT +template otError Frame::AppendHeaderIeAt(uint8_t &aIndex) { - otError error = OT_ERROR_NONE; - uint16_t index = FindHeaderIeIndex(); + otError error = OT_ERROR_NONE; - VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_NOT_FOUND); + SuccessOrExit(error = InitIeHeaderAt(aIndex, IeType::kHeaderIeId, IeType::kIeContentSize)); - for (uint8_t i = 0; i < aIeCount; i++) - { - memcpy(&mPsdu[index], &aIeList[i], sizeof(HeaderIe)); - - index += sizeof(HeaderIe) + aIeList[i].GetLength(); - mLength += sizeof(HeaderIe) + aIeList[i].GetLength(); - } + InitIeContentAt(aIndex); exit: return error; } +otError Frame::InitIeHeaderAt(uint8_t &aIndex, uint8_t ieId, uint8_t ieContentSize) +{ + otError error = OT_ERROR_NONE; + + if (aIndex == 0) + { + aIndex = FindHeaderIeIndex(); + } + + VerifyOrExit(aIndex != kInvalidIndex, error = OT_ERROR_NOT_FOUND); + + reinterpret_cast(mPsdu + aIndex)->Init(ieId, ieContentSize); + aIndex += sizeof(HeaderIe); + + mLength += sizeof(HeaderIe) + ieContentSize; +exit: + return error; +} + +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE +template <> void Frame::InitIeContentAt(uint8_t &aIndex) +{ + reinterpret_cast(mPsdu + aIndex)->Init(); + aIndex += sizeof(TimeIe); +} +#endif + +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +template <> void Frame::InitIeContentAt(uint8_t &aIndex) +{ + aIndex += sizeof(CslIe); +} +#endif + +template <> void Frame::InitIeContentAt(uint8_t &aIndex) +{ + OT_UNUSED_VARIABLE(aIndex); +} +#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT + const uint8_t *Frame::GetHeaderIe(uint8_t aIeId) const { uint8_t index = FindHeaderIeIndex(); @@ -948,7 +989,7 @@ const uint8_t *Frame::GetThreadIe(uint8_t aSubType) const { const HeaderIe *ie = reinterpret_cast(&mPsdu[index]); - if (ie->GetId() == kHeaderIeVendor) + if (ie->GetId() == VendorIeHeader::kHeaderIeId) { const VendorIeHeader *vendorIe = reinterpret_cast(reinterpret_cast(ie) + sizeof(HeaderIe)); @@ -972,7 +1013,7 @@ exit: #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE void Frame::SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase) { - uint8_t *cur = GetHeaderIe(Frame::kHeaderIeCsl); + uint8_t *cur = GetHeaderIe(CslIe::kHeaderIeId); CslIe * csl; VerifyOrExit(cur != nullptr); @@ -1002,7 +1043,7 @@ const TimeIe *Frame::GetTimeIe(void) const const TimeIe * timeIe = nullptr; const uint8_t *cur = nullptr; - cur = GetHeaderIe(kHeaderIeVendor); + cur = GetHeaderIe(VendorIeHeader::kHeaderIeId); VerifyOrExit(cur != nullptr); cur += sizeof(HeaderIe); @@ -1079,6 +1120,17 @@ uint8_t Frame::GetFcsSize(void) const } #endif +// Explicit instantiation +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE +template otError Frame::AppendHeaderIeAt(uint8_t &aIndex); +#endif +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +template otError Frame::AppendHeaderIeAt(uint8_t &aIndex); +#endif +template otError Frame::AppendHeaderIeAt(uint8_t &aIndex); +#endif + void TxFrame::CopyFrom(const TxFrame &aFromFrame) { uint8_t * psduBuffer = mPsdu; diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp index c8e0672b9..0ed4636b3 100644 --- a/src/core/mac/mac_frame.hpp +++ b/src/core/mac/mac_frame.hpp @@ -71,6 +71,15 @@ public: */ void Init(void) { mFields.m16 = 0; } + /** + * This method initializes the Header IE with Id and Length. + * + * @param[in] aId The IE Element Id. + * @param[in] aLen The IE content length. + * + */ + void Init(uint16_t aId, uint8_t aLen); + /** * This method returns the IE Element Id. * @@ -144,6 +153,12 @@ OT_TOOL_PACKED_BEGIN class VendorIeHeader { public: + enum : uint8_t + { + kHeaderIeId = 0x00, + kIeContentSize = sizeof(uint8_t) * 4, + }; + /** * This method returns the Vendor OUI. * @@ -205,6 +220,12 @@ public: kVendorIeTime = 0x01, }; + enum + { + kHeaderIeId = VendorIeHeader::kHeaderIeId, + kIeContentSize = VendorIeHeader::kIeContentSize + sizeof(uint8_t) + sizeof(uint64_t), + }; + /** * This method initializes the time IE. * @@ -257,6 +278,12 @@ private: class ThreadIe { public: + enum : uint8_t + { + kHeaderIeId = VendorIeHeader::kHeaderIeId, + kIeContentSize = VendorIeHeader::kIeContentSize, + }; + enum : uint32_t { kVendorOuiThreadCompanyId = 0xeab89b, @@ -348,10 +375,6 @@ public: kMacCmdCoordinatorRealignment = 8, kMacCmdGtsRequest = 9, - kHeaderIeVendor = 0x00, - kHeaderIeCsl = 0x1a, - kHeaderIeTermination2 = 0x7f, - kImmAckLength = kFcfSize + kDsnSize + k154FcsSize, kInfoStringSize = 128, ///< Max chars needed for the info string representation (@sa ToInfoString()). @@ -923,16 +946,22 @@ public: #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT /** - * This method appends Header IEs to MAC header. + * This template method appends an Header IE at specified index in this frame. * - * @param[in] aIeList The pointer to the Header IEs array. - * @param[in] aIeCount The number of Header IEs in the array. + * @param[in,out] aIndex The index to append IE. If `aIndex` is `0` on input, this method finds the index + * for the first IE and appends the IE at that position. If the position is not found + * successfully, `aIndex` will be set to `kInvalidIndex`. Otherwise the IE will be + * appended at `aIndex` on input. And on output, `aIndex` will be set to the end of the + * IE just appended. * - * @retval OT_ERROR_NONE Successfully appended the Header IEs. - * @retval OT_ERROR_FAILED If IE Present bit is not set. + * @tparam IeType The Header IE type, it MUST contain an enum `kHeaderIeId` equal to the IE's Id + * and an enum `kIeContentSize` indicating the IE body's size. + * + * @retval OT_ERROR_NONE Successfully appended the Header IE. + * @retval OT_ERROR_NOT_FOUND The position for first IE is not found. * */ - otError AppendHeaderIe(HeaderIe *aIeList, uint8_t aIeCount); + template otError AppendHeaderIeAt(uint8_t &aIndex); /** * This method returns a pointer to the Header IE. @@ -1091,6 +1120,9 @@ protected: uint8_t FindPayloadIndex(void) const; #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT uint8_t FindHeaderIeIndex(void) const; + + otError InitIeHeaderAt(uint8_t &aIndex, uint8_t ieId, uint8_t ieContentSize); + template void InitIeContentAt(uint8_t &aIndex); #endif static uint8_t GetKeySourceLength(uint8_t aKeyIdMode); @@ -1642,6 +1674,12 @@ OT_TOOL_PACKED_BEGIN class CslIe { public: + enum : uint8_t + { + kHeaderIeId = 0x1a, + kIeContentSize = sizeof(uint16_t) * 2, + }; + /** * This method returns the CSL Period. * @@ -1679,6 +1717,22 @@ private: uint16_t mPeriod; } OT_TOOL_PACKED_END; +/** + * This class implements Termination2 IE. + * + * This class is empty for template specialization. + * + */ +class Termination2Ie +{ +public: + enum : uint8_t + { + kHeaderIeId = 0x7f, + kIeContentSize = 0, + }; +}; + /** * @} * diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index fe66949cb..cf88b6fc5 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -154,7 +154,8 @@ exit: void MeshForwarder::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest) { - uint16_t fcf = 0; + uint16_t fcf = 0; + bool iePresent = CalcIePresent(nullptr); Mac::Address macSource; macSource.SetShort(Get().GetShortAddress()); @@ -166,6 +167,13 @@ void MeshForwarder::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address & fcf = Mac::Frame::kFcfFrameData | Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfSecurityEnabled; + if (iePresent) + { + fcf |= Mac::Frame::kFcfIePresent; + } + + fcf |= CalcFrameVersion(Get().FindNeighbor(aMacDest), iePresent); + if (aAckRequest) { fcf |= Mac::Frame::kFcfAckRequest; @@ -173,7 +181,6 @@ void MeshForwarder::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address & fcf |= (aMacDest.IsShort()) ? Mac::Frame::kFcfDstAddrShort : Mac::Frame::kFcfDstAddrExt; fcf |= (macSource.IsShort()) ? Mac::Frame::kFcfSrcAddrShort : Mac::Frame::kFcfSrcAddrExt; - Get().UpdateFrameControlField(Get().FindNeighbor(aMacDest), false, fcf); aFrame.InitMacHeader(fcf, Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32); @@ -187,7 +194,10 @@ void MeshForwarder::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address & aFrame.SetSrcAddr(macSource); aFrame.SetFramePending(false); #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - IgnoreError(Get().AppendHeaderIe(false, aFrame)); + if (iePresent) + { + AppendHeaderIe(nullptr, aFrame); + } #endif aFrame.SetPayloadLength(0); } @@ -585,17 +595,23 @@ uint16_t MeshForwarder::PrepareDataFrame(Mac::TxFrame & aFrame, uint16_t dstpan; uint8_t secCtl; uint16_t nextOffset; + bool iePresent = CalcIePresent(&aMessage); start: // Initialize MAC header fcf = Mac::Frame::kFcfFrameData; - Get().UpdateFrameControlField(Get().FindNeighbor(aMacDest), aMessage.IsTimeSync(), fcf); - fcf |= (aMacDest.IsShort()) ? Mac::Frame::kFcfDstAddrShort : Mac::Frame::kFcfDstAddrExt; fcf |= (aMacSource.IsShort()) ? Mac::Frame::kFcfSrcAddrShort : Mac::Frame::kFcfSrcAddrExt; + if (iePresent) + { + fcf |= Mac::Frame::kFcfIePresent; + } + + fcf |= CalcFrameVersion(Get().FindNeighbor(aMacDest), iePresent); + // All unicast frames request ACK if (aMacDest.IsExtended() || !aMacDest.IsBroadcast()) { @@ -663,7 +679,10 @@ start: aFrame.SetSrcAddr(aMacSource); #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - IgnoreError(Get().AppendHeaderIe(aMessage.IsTimeSync(), aFrame)); + if (iePresent) + { + AppendHeaderIe(&aMessage, aFrame); + } #endif payload = aFrame.GetPayload(); @@ -1491,6 +1510,78 @@ exit: } #endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE +bool MeshForwarder::CalcIePresent(const Message *aMessage) +{ + bool iePresent = false; + + OT_UNUSED_VARIABLE(aMessage); + +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + iePresent |= (aMessage != nullptr && aMessage->IsTimeSync()); +#endif +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + iePresent |= Get().IsCslEnabled(); +#endif + + return iePresent; +} + +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT +void MeshForwarder::AppendHeaderIe(const Message *aMessage, Mac::Frame &aFrame) +{ + uint8_t index = 0; + bool iePresent = false; + + OT_UNUSED_VARIABLE(aMessage); + +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + if (aMessage != nullptr && aMessage->IsTimeSync()) + { + IgnoreError(aFrame.AppendHeaderIeAt(index)); + iePresent = true; + } +#endif +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + if (Get().IsCslEnabled()) + { + IgnoreError(aFrame.AppendHeaderIeAt(index)); + iePresent = true; + } +#endif + + if (iePresent) + { + IgnoreError(aFrame.AppendHeaderIeAt(index)); + } +} +#endif + +uint16_t MeshForwarder::CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent) +{ + uint16_t version = Mac::Frame::kFcfFrameVersion2006; + OT_UNUSED_VARIABLE(aNeighbor); + + if (aIePresent) + { + version = Mac::Frame::kFcfFrameVersion2015; + } +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE + else if (aNeighbor != nullptr && !Mle::MleRouter::IsActiveRouter(aNeighbor->GetRloc16()) && + static_cast(aNeighbor)->IsCslSynchronized()) + { + version = Mac::Frame::kFcfFrameVersion2015; + } +#endif +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE + else if (aNeighbor != nullptr && aNeighbor->IsEnhAckProbingActive()) + { + version = Mac::Frame::kFcfFrameVersion2015; ///< Set version to 2015 to fetch Link Metrics data in Enh-ACK. + } +#endif + + return version; +} + // LCOV_EXCL_START #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1) diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 5a85bb9e1..152d1b8c4 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -44,6 +44,7 @@ #include "mac/channel_mask.hpp" #include "mac/data_poll_sender.hpp" #include "mac/mac.hpp" +#include "mac/mac_frame.hpp" #include "net/ip6.hpp" #include "thread/address_resolver.hpp" #include "thread/indirect_sender.hpp" @@ -475,6 +476,12 @@ private: otError GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, uint16_t &aMeshDest); + bool CalcIePresent(const Message *aMessage); + uint16_t CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent); +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT + void AppendHeaderIe(const Message *aMessage, Mac::Frame &aFrame); +#endif + void PauseMessageTransmissions(void) { mTxPaused = true; } void ResumeMessageTransmissions(void); diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 4d873165b..fa1b335b8 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -342,29 +342,28 @@ void MeshForwarder::RemoveDataResponseMessages(void) void MeshForwarder::SendMesh(Message &aMessage, Mac::TxFrame &aFrame) { uint16_t fcf; + bool iePresent = CalcIePresent(&aMessage); // initialize MAC header fcf = Mac::Frame::kFcfFrameData | Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort | Mac::Frame::kFcfAckRequest | Mac::Frame::kFcfSecurityEnabled; - Get().UpdateFrameControlField(nullptr, aMessage.IsTimeSync(), fcf); + + if (iePresent) + { + fcf |= Mac::Frame::kFcfIePresent; + } + + fcf |= CalcFrameVersion(Get().FindNeighbor(mMacDest), iePresent); aFrame.InitMacHeader(fcf, Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32); aFrame.SetDstPanId(Get().GetPanId()); aFrame.SetDstAddr(mMacDest.GetShort()); aFrame.SetSrcAddr(mMacSource.GetShort()); -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (Get().IsCslEnabled()) +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT + if (iePresent) { - Mac::HeaderIe ieList[2]; // CSL + Termination - - ieList[0].Init(); - ieList[0].SetId(Mac::Frame::kHeaderIeCsl); - ieList[0].SetLength(sizeof(Mac::CslIe)); - ieList[1].Init(); - ieList[1].SetId(Mac::Frame::kHeaderIeTermination2); - ieList[1].SetLength(0); - IgnoreError(aFrame.AppendHeaderIe(ieList, 2)); + AppendHeaderIe(&aMessage, aFrame); } #endif diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp index ef6102bb0..12609e873 100644 --- a/tests/unit/test_mac_frame.cpp +++ b/tests/unit/test_mac_frame.cpp @@ -620,7 +620,7 @@ void TestMacFrameAckGeneration(void) Mac::CslIe *csl; IgnoreError(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data))); - csl = reinterpret_cast(ackFrame.GetHeaderIe(Mac::Frame::kHeaderIeCsl) + sizeof(Mac::HeaderIe)); + csl = reinterpret_cast(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + 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, @@ -642,7 +642,7 @@ void TestMacFrameAckGeneration(void) #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE ackFrame.SetCslIe(123, 456); - csl = reinterpret_cast(ackFrame.GetHeaderIe(Mac::Frame::kHeaderIeCsl) + sizeof(Mac::HeaderIe)); + csl = reinterpret_cast(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe)); VerifyOrQuit(csl->GetPeriod() == 123 && csl->GetPhase() == 456, "Mac::Frame::SetCslIe failed, CslIe incorrect\n"); #endif #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)