From fe1cf3a294c6067100e6db84c599ebe392cea206 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 17 Jan 2023 20:01:26 -0800 Subject: [PATCH] [mac-frame] update `InitMacHeader()` (#8660) This commit updates how we prepare the MAC headers: - New `enum`s are defined in `Mac::Frame` to specify the frame `Type`, `Version`, `SecurityLevel`, etc. - `InitMacHeader()` will itself determine the Frame Control Field from the given address info. - It now uses `FrameBuilder` to prepare the headers. - New helper `MeshForwarder::PrepareMacHeaders()` is added which takes care of adding MAC (address, security header) along with any IE headers. - These changes ensure that PAN ID Compression bit is properly set on MAC frames when using 2015 version (ensure that PAN IDs are not omitted when both addresses use Extended format). --- examples/platforms/utils/mac_frame.cpp | 6 +- src/core/BUILD.gn | 2 + src/core/CMakeLists.txt | 1 + src/core/Makefile.am | 1 + src/core/common/frame_builder.cpp | 36 ++++ src/core/common/frame_builder.hpp | 16 +- src/core/mac/data_poll_sender.cpp | 51 ++--- src/core/mac/mac.cpp | 50 ++--- src/core/mac/mac_frame.cpp | 173 ++++++++++++----- src/core/mac/mac_frame.hpp | 203 ++++++++++++------- src/core/mac/mac_types.hpp | 10 + src/core/radio/trel_link.cpp | 4 +- src/core/radio/trel_link.hpp | 1 + src/core/thread/link_metrics_types.cpp | 6 +- src/core/thread/link_metrics_types.hpp | 4 +- src/core/thread/mesh_forwarder.cpp | 191 ++++++------------ src/core/thread/mesh_forwarder.hpp | 13 +- src/core/thread/mesh_forwarder_ftd.cpp | 28 +-- src/core/thread/mle.cpp | 2 +- src/core/thread/mle.hpp | 3 +- tests/unit/test_mac_frame.cpp | 259 ++++++++++++++++++++----- 21 files changed, 664 insertions(+), 396 deletions(-) diff --git a/examples/platforms/utils/mac_frame.cpp b/examples/platforms/utils/mac_frame.cpp index d092e4c7c..0ae88db34 100644 --- a/examples/platforms/utils/mac_frame.cpp +++ b/examples/platforms/utils/mac_frame.cpp @@ -68,17 +68,17 @@ exit: bool otMacFrameIsAck(const otRadioFrame *aFrame) { - return static_cast(aFrame)->GetType() == Mac::Frame::kFcfFrameAck; + return static_cast(aFrame)->GetType() == Mac::Frame::kTypeAck; } bool otMacFrameIsData(const otRadioFrame *aFrame) { - return static_cast(aFrame)->GetType() == Mac::Frame::kFcfFrameData; + return static_cast(aFrame)->GetType() == Mac::Frame::kTypeData; } bool otMacFrameIsCommand(const otRadioFrame *aFrame) { - return static_cast(aFrame)->GetType() == Mac::Frame::kFcfFrameMacCmd; + return static_cast(aFrame)->GetType() == Mac::Frame::kTypeMacCmd; } bool otMacFrameIsDataRequest(const otRadioFrame *aFrame) diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 2d2a9cc39..997cd638a 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -726,6 +726,8 @@ openthread_radio_sources = [ "common/binary_search.cpp", "common/binary_search.hpp", "common/error.hpp", + "common/frame_builder.cpp", + "common/frame_builder.hpp", "common/instance.cpp", "common/log.cpp", "common/random.cpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 078ab4ed8..7b4356f37 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -255,6 +255,7 @@ set(RADIO_COMMON_SOURCES api/tasklet_api.cpp common/binary_search.cpp common/error.cpp + common/frame_builder.cpp common/instance.cpp common/log.cpp common/random.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index c02878c12..282c89018 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -345,6 +345,7 @@ RADIO_SOURCES_COMMON = \ api/tasklet_api.cpp \ common/binary_search.cpp \ common/error.cpp \ + common/frame_builder.cpp \ common/instance.cpp \ common/log.cpp \ common/random.cpp \ diff --git a/src/core/common/frame_builder.cpp b/src/core/common/frame_builder.cpp index 61620b6a6..88247ca67 100644 --- a/src/core/common/frame_builder.cpp +++ b/src/core/common/frame_builder.cpp @@ -33,6 +33,16 @@ #include "frame_builder.hpp" +#include + +#include "common/code_utils.hpp" +#include "common/debug.hpp" +#include "common/encoding.hpp" + +#if OPENTHREAD_FTD || OPENTHREAD_MTD +#include "common/message.hpp" +#endif + namespace ot { void FrameBuilder::Init(void *aBuffer, uint16_t aLength) @@ -76,6 +86,31 @@ exit: return error; } +Error FrameBuilder::AppendMacAddress(const Mac::Address &aMacAddress) +{ + Error error = kErrorNone; + + switch (aMacAddress.GetType()) + { + case Mac::Address::kTypeNone: + break; + + case Mac::Address::kTypeShort: + error = AppendLittleEndianUint16(aMacAddress.GetShort()); + break; + + case Mac::Address::kTypeExtended: + VerifyOrExit(CanAppend(sizeof(Mac::ExtAddress)), error = kErrorNoBufs); + aMacAddress.GetExtended().CopyTo(mBuffer + mLength, Mac::ExtAddress::kReverseByteOrder); + mLength += sizeof(Mac::ExtAddress); + break; + } + +exit: + return error; +} + +#if OPENTHREAD_FTD || OPENTHREAD_MTD Error FrameBuilder::AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength) { Error error = kErrorNone; @@ -87,6 +122,7 @@ Error FrameBuilder::AppendBytesFromMessage(const Message &aMessage, uint16_t aOf exit: return error; } +#endif void FrameBuilder::WriteBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength) { diff --git a/src/core/common/frame_builder.hpp b/src/core/common/frame_builder.hpp index 42385ac88..bbbb73154 100644 --- a/src/core/common/frame_builder.hpp +++ b/src/core/common/frame_builder.hpp @@ -37,10 +37,11 @@ #include "openthread-core-config.h" #include "common/error.hpp" -#include "common/message.hpp" #include "common/type_traits.hpp" +#include "mac/mac_types.hpp" namespace ot { +class Message; /** * The `FrameBuilder` can be used to construct frame content in a given data buffer. @@ -182,6 +183,18 @@ public: */ Error AppendBytes(const void *aBuffer, uint16_t aLength); + /** + * This method appends a given `Mac::Address` to the `FrameBuilder`. + * + * @param[in] aMacAddress A `Mac::Address` to append. + * + * @retval kErrorNone Successfully appended the address. + * @retval kErrorNoBufs Insufficient available buffers. + * + */ + Error AppendMacAddress(const Mac::Address &aMacAddress); + +#if OPENTHREAD_FTD || OPENTHREAD_MTD /** * This method appends bytes read from a given message to the `FrameBuilder`. * @@ -195,6 +208,7 @@ public: * */ Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength); +#endif /** * This method appends an object to the `FrameBuilder`. diff --git a/src/core/mac/data_poll_sender.cpp b/src/core/mac/data_poll_sender.cpp index c42bba579..84486ffd2 100644 --- a/src/core/mac/data_poll_sender.cpp +++ b/src/core/mac/data_poll_sender.cpp @@ -563,66 +563,41 @@ uint32_t DataPollSender::GetDefaultPollPeriod(void) const Mac::TxFrame *DataPollSender::PrepareDataRequest(Mac::TxFrames &aTxFrames) { - Mac::TxFrame *frame = nullptr; - Mac::Address src, dst; - uint16_t fcf; - bool iePresent; + Mac::TxFrame *frame = nullptr; + Mac::Addresses addresses; + Mac::PanIds panIds; #if OPENTHREAD_CONFIG_MULTI_RADIO Mac::RadioType radio; - SuccessOrExit(GetPollDestinationAddress(dst, radio)); + SuccessOrExit(GetPollDestinationAddress(addresses.mDestination, radio)); frame = &aTxFrames.GetTxFrame(radio); #else - SuccessOrExit(GetPollDestinationAddress(dst)); + SuccessOrExit(GetPollDestinationAddress(addresses.mDestination)); frame = &aTxFrames.GetTxFrame(); #endif - fcf = Mac::Frame::kFcfFrameMacCmd | Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfAckRequest | - Mac::Frame::kFcfSecurityEnabled; - - iePresent = Get().CalcIePresent(nullptr); - - if (iePresent) + if (addresses.mDestination.IsExtended()) { - fcf |= Mac::Frame::kFcfIePresent; - } - - fcf |= Get().CalcFrameVersion(Get().FindNeighbor(dst), iePresent); - - if (dst.IsExtended()) - { - fcf |= Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrExt; - src.SetExtended(Get().GetExtAddress()); + addresses.mSource.SetExtended(Get().GetExtAddress()); } else { - fcf |= Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort; - src.SetShort(Get().GetShortAddress()); + addresses.mSource.SetShort(Get().GetShortAddress()); } - frame->InitMacHeader(fcf, Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32); + panIds.mSource = Get().GetPanId(); + panIds.mDestination = Get().GetPanId(); - if (frame->IsDstPanIdPresent()) - { - frame->SetDstPanId(Get().GetPanId()); - } + Get().PrepareMacHeaders(*frame, Mac::Frame::kTypeMacCmd, addresses, panIds, + Mac::Frame::kSecurityEncMic32, Mac::Frame::kKeyIdMode1, nullptr); - frame->SetSrcAddr(src); - frame->SetDstAddr(dst); -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - if (iePresent) - { - Get().AppendHeaderIe(nullptr, *frame); - } - -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE if (frame->GetHeaderIe(Mac::CslIe::kHeaderIeId) != nullptr) { // Disable frame retransmission when the data poll has CSL IE included aTxFrames.SetMaxFrameRetries(0); } -#endif #endif IgnoreError(frame->SetCommandId(Mac::Frame::kMacCmdDataRequest)); diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 7e7480a7e..27731ad14 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -224,7 +224,7 @@ Error Mac::ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveSc VerifyOrExit(aBeaconFrame != nullptr, error = kErrorInvalidArgs); - VerifyOrExit(aBeaconFrame->GetType() == Frame::kFcfFrameBeacon, error = kErrorParse); + VerifyOrExit(aBeaconFrame->GetType() == Frame::kTypeBeacon, error = kErrorParse); SuccessOrExit(error = aBeaconFrame->GetSrcAddr(address)); VerifyOrExit(address.IsExtended(), error = kErrorParse); aResult.mExtAddress = address.GetExtended(); @@ -719,12 +719,16 @@ void Mac::FinishOperation(void) TxFrame *Mac::PrepareBeaconRequest(void) { - TxFrame &frame = mLinks.GetTxFrames().GetBroadcastTxFrame(); - uint16_t fcf = Frame::kFcfFrameMacCmd | Frame::kFcfDstAddrShort | Frame::kFcfSrcAddrNone; + TxFrame &frame = mLinks.GetTxFrames().GetBroadcastTxFrame(); + Addresses addrs; + PanIds panIds; + + addrs.mSource.SetNone(); + addrs.mDestination.SetShort(kShortAddrBroadcast); + panIds.mDestination = kShortAddrBroadcast; + + frame.InitMacHeader(Frame::kTypeMacCmd, Frame::kVersion2003, addrs, panIds, Frame::kSecurityNone); - frame.InitMacHeader(fcf, Frame::kSecNone); - frame.SetDstPanId(kShortAddrBroadcast); - frame.SetDstAddr(kShortAddrBroadcast); IgnoreError(frame.SetCommandId(Frame::kMacCmdBeaconRequest)); LogInfo("Sending Beacon Request"); @@ -734,9 +738,10 @@ TxFrame *Mac::PrepareBeaconRequest(void) TxFrame *Mac::PrepareBeacon(void) { - TxFrame *frame; - uint16_t fcf; - Beacon *beacon = nullptr; + TxFrame *frame; + Beacon *beacon = nullptr; + Addresses addrs; + PanIds panIds; #if OPENTHREAD_CONFIG_MAC_OUTGOING_BEACON_PAYLOAD_ENABLE uint8_t beaconLength; BeaconPayload *beaconPayload = nullptr; @@ -750,10 +755,11 @@ TxFrame *Mac::PrepareBeacon(void) frame = &mLinks.GetTxFrames().GetBroadcastTxFrame(); #endif - fcf = Frame::kFcfFrameBeacon | Frame::kFcfDstAddrNone | Frame::kFcfSrcAddrExt; - frame->InitMacHeader(fcf, Frame::kSecNone); - IgnoreError(frame->SetSrcPanId(mPanId)); - frame->SetSrcAddr(GetExtAddress()); + addrs.mSource.SetExtended(GetExtAddress()); + panIds.mSource = mPanId; + addrs.mDestination.SetNone(); + + frame->InitMacHeader(Frame::kTypeBeacon, Frame::kVersion2003, addrs, panIds, Frame::kSecurityNone); beacon = reinterpret_cast(frame->GetPayload()); beacon->Init(); @@ -1198,7 +1204,7 @@ void Mac::RecordFrameTransmitStatus(const TxFrame &aFrame, ProcessEnhAckProbing(*aAckFrame, *neighbor); #endif #if OPENTHREAD_FTD - if (aAckFrame->GetVersion() == Frame::kFcfFrameVersion2015) + if (aAckFrame->GetVersion() == Frame::kVersion2015) { #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE ProcessCsl(*aAckFrame, dstAddr); @@ -1500,7 +1506,7 @@ Error Mac::ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neig VerifyOrExit(aFrame.GetSecurityEnabled(), error = kErrorNone); IgnoreError(aFrame.GetSecurityLevel(securityLevel)); - VerifyOrExit(securityLevel == Frame::kSecEncMic32); + VerifyOrExit(securityLevel == Frame::kSecurityEncMic32); IgnoreError(aFrame.GetFrameCounter(frameCounter)); LogDebg("Rx security - frame counter %lu", ToUlong(frameCounter)); @@ -1638,7 +1644,7 @@ Error Mac::ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame) VerifyOrExit(aAckFrame.IsVersion2015()); IgnoreError(aAckFrame.GetSecurityLevel(securityLevel)); - VerifyOrExit(securityLevel == Frame::kSecEncMic32); + VerifyOrExit(securityLevel == Frame::kSecurityEncMic32); IgnoreError(aAckFrame.GetKeyIdMode(keyIdMode)); VerifyOrExit(keyIdMode == Frame::kKeyIdMode1, error = kErrorNone); @@ -1837,7 +1843,7 @@ void Mac::HandleReceivedFrame(RxFrame *aFrame, Error aError) } #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - if (aFrame->GetVersion() == Frame::kFcfFrameVersion2015) + if (aFrame->GetVersion() == Frame::kVersion2015) { ProcessCsl(*aFrame, srcaddr); } @@ -1878,7 +1884,7 @@ void Mac::HandleReceivedFrame(RxFrame *aFrame, Error aError) #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 && OPENTHREAD_FTD // From Thread 1.2, MAC Data Frame can also act as keep-alive message if child supports - if (aFrame->GetType() == Frame::kFcfFrameData && !neighbor->IsRxOnWhenIdle() && + if (aFrame->GetType() == Frame::kTypeData && !neighbor->IsRxOnWhenIdle() && neighbor->IsEnhancedKeepAliveSupported()) { neighbor->SetLastHeard(TimerMilli::GetNow()); @@ -1896,7 +1902,7 @@ void Mac::HandleReceivedFrame(RxFrame *aFrame, Error aError) { case kOperationActiveScan: - if (aFrame->GetType() == Frame::kFcfFrameBeacon) + if (aFrame->GetType() == Frame::kTypeBeacon) { mCounters.mRxBeacon++; ReportActiveScanResult(aFrame); @@ -1941,7 +1947,7 @@ void Mac::HandleReceivedFrame(RxFrame *aFrame, Error aError) switch (aFrame->GetType()) { - case Frame::kFcfFrameMacCmd: + case Frame::kTypeMacCmd: if (HandleMacCommand(*aFrame)) // returns `true` when handled { ExitNow(error = kErrorNone); @@ -1949,11 +1955,11 @@ void Mac::HandleReceivedFrame(RxFrame *aFrame, Error aError) break; - case Frame::kFcfFrameBeacon: + case Frame::kTypeBeacon: mCounters.mRxBeacon++; break; - case Frame::kFcfFrameData: + case Frame::kTypeData: mCounters.mRxData++; break; diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp index 27e404bb4..a31350b19 100644 --- a/src/core/mac/mac_frame.cpp +++ b/src/core/mac/mac_frame.cpp @@ -37,6 +37,7 @@ #include "common/code_utils.hpp" #include "common/debug.hpp" +#include "common/frame_builder.hpp" #include "common/log.hpp" #include "radio/trel_link.hpp" #if !OPENTHREAD_RADIO || OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE @@ -58,23 +59,106 @@ void HeaderIe::Init(uint16_t aId, uint8_t aLen) SetLength(aLen); } -void Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl) +void Frame::InitMacHeader(Type aType, + Version aVersion, + const Addresses &aAddrs, + const PanIds &aPanIds, + SecurityLevel aSecurityLevel, + KeyIdMode aKeyIdMode) { - mLength = CalculateAddrFieldSize(aFcf); + uint16_t fcf; + FrameBuilder builder; - OT_ASSERT(mLength != kInvalidSize); + fcf = static_cast(aType) | static_cast(aVersion); - WriteUint16(aFcf, mPsdu); - - if (aFcf & kFcfSecurityEnabled) + switch (aAddrs.mSource.GetType()) { - mPsdu[mLength] = aSecurityControl; - - mLength += CalculateSecurityHeaderSize(aSecurityControl); - mLength += CalculateMicSize(aSecurityControl); + case Address::kTypeNone: + fcf |= kFcfSrcAddrNone; + break; + case Address::kTypeShort: + fcf |= kFcfSrcAddrShort; + break; + case Address::kTypeExtended: + fcf |= kFcfSrcAddrExt; + break; } - if ((aFcf & kFcfFrameTypeMask) == kFcfFrameMacCmd) + switch (aAddrs.mDestination.GetType()) + { + case Address::kTypeNone: + fcf |= kFcfDstAddrNone; + break; + case Address::kTypeShort: + fcf |= kFcfDstAddrShort; + fcf |= ((aAddrs.mDestination.GetShort() == kShortAddrBroadcast) ? 0 : kFcfAckRequest); + break; + case Address::kTypeExtended: + fcf |= (kFcfDstAddrExt | kFcfAckRequest); + break; + } + + fcf |= (aSecurityLevel != kSecurityNone) ? kFcfSecurityEnabled : 0; + + // When we have both source and destination addresses we check PAN + // IDs to determine whether to include `kFcfPanidCompression`. + + if (!aAddrs.mSource.IsNone() && !aAddrs.mDestination.IsNone() && (aPanIds.mSource == aPanIds.mDestination)) + { + switch (aVersion) + { + case kVersion2015: + // Special case for a IEEE 802.15.4-2015 frame: When both + // addresses are extended, the PAN ID compression is set + // to one to indicate that no PAN ID is in the frame, + // while setting the PAN ID Compression to zero indicates + // the presence of the destination PAN ID in the frame. + + if (aAddrs.mSource.IsExtended() && aAddrs.mDestination.IsExtended()) + { + break; + } + + OT_FALL_THROUGH; + + case kVersion2003: + case kVersion2006: + fcf |= kFcfPanidCompression; + break; + } + } + + builder.Init(mPsdu, GetMtu()); + IgnoreError(builder.AppendLittleEndianUint16(fcf)); + IgnoreError(builder.AppendUint8(0)); // Seq number + + if (IsDstPanIdPresent(fcf)) + { + IgnoreError(builder.AppendLittleEndianUint16(aPanIds.mDestination)); + } + + IgnoreError(builder.AppendMacAddress(aAddrs.mDestination)); + + if (IsSrcPanIdPresent(fcf)) + { + IgnoreError(builder.AppendLittleEndianUint16(aPanIds.mSource)); + } + + IgnoreError(builder.AppendMacAddress(aAddrs.mSource)); + + mLength = builder.GetLength(); + + if (aSecurityLevel != kSecurityNone) + { + uint8_t secCtl = static_cast(aSecurityLevel) | static_cast(aKeyIdMode); + + IgnoreError(builder.AppendUint8(secCtl)); + + mLength += CalculateSecurityHeaderSize(secCtl); + mLength += CalculateMicSize(secCtl); + } + + if (aType == kTypeMacCmd) { mLength += kCommandIdSize; } @@ -136,7 +220,6 @@ bool Frame::IsDstPanIdPresent(uint16_t aFcf) { bool present = true; -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT if (IsVersion2015(aFcf)) { switch (aFcf & (kFcfDstAddrMask | kFcfSrcAddrMask | kFcfPanidCompression)) @@ -156,7 +239,6 @@ bool Frame::IsDstPanIdPresent(uint16_t aFcf) } } else -#endif { present = IsDstAddrPresent(aFcf); } @@ -277,26 +359,21 @@ exit: bool Frame::IsSrcPanIdPresent(uint16_t aFcf) { - bool srcPanIdPresent = false; + bool present = IsSrcAddrPresent(aFcf) && ((aFcf & kFcfPanidCompression) == 0); - if ((aFcf & kFcfSrcAddrMask) != kFcfSrcAddrNone && (aFcf & kFcfPanidCompression) == 0) + // Special case for a IEEE 802.15.4-2015 frame: When both + // addresses are extended, then the source PAN iD is not present + // independent of PAN ID Compression. In this case, if the PAN ID + // compression is set, it indicates that no PAN ID is in the + // frame, while if the PAN ID Compression is zero, it indicates + // the presence of the destination PAN ID in the frame. + + if (IsVersion2015(aFcf) && ((aFcf & (kFcfDstAddrMask | kFcfSrcAddrMask)) == (kFcfDstAddrExt | kFcfSrcAddrExt))) { -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - // Handle a special case in IEEE 802.15.4-2015, when Pan ID Compression is 0, but Src Pan ID is not present: - // Dest Address: Extended - // Source Address: Extended - // Dest Pan ID: Present - // Src Pan ID: Not Present - // Pan ID Compression: 0 - if (!IsVersion2015(aFcf) || (aFcf & kFcfDstAddrMask) != kFcfDstAddrExt || - (aFcf & kFcfSrcAddrMask) != kFcfSrcAddrExt) -#endif - { - srcPanIdPresent = true; - } + present = false; } - return srcPanIdPresent; + return present; } Error Frame::GetSrcPanId(PanId &aPanId) const @@ -619,7 +696,7 @@ bool Frame::IsDataRequestCommand(void) const bool isDataRequest = false; uint8_t commandId; - VerifyOrExit(GetType() == kFcfFrameMacCmd); + VerifyOrExit(GetType() == kTypeMacCmd); SuccessOrExit(GetCommandId(commandId)); isDataRequest = (commandId == kMacCmdDataRequest); @@ -647,23 +724,23 @@ uint8_t Frame::CalculateMicSize(uint8_t aSecurityControl) switch (aSecurityControl & kSecLevelMask) { - case kSecNone: - case kSecEnc: + case kSecurityNone: + case kSecurityEnc: micSize = kMic0Size; break; - case kSecMic32: - case kSecEncMic32: + case kSecurityMic32: + case kSecurityEncMic32: micSize = kMic32Size; break; - case kSecMic64: - case kSecEncMic64: + case kSecurityMic64: + case kSecurityEncMic64: micSize = kMic64Size; break; - case kSecMic128: - case kSecEncMic128: + case kSecurityMic128: + case kSecurityEncMic128: micSize = kMic128Size; break; } @@ -707,7 +784,7 @@ uint8_t Frame::CalculateSecurityHeaderSize(uint8_t aSecurityControl) { uint8_t size = kSecurityControlSize + kFrameCounterSize; - VerifyOrExit((aSecurityControl & kSecLevelMask) != kSecNone, size = kInvalidSize); + VerifyOrExit((aSecurityControl & kSecLevelMask) != kSecurityNone, size = kInvalidSize); switch (aSecurityControl & kKeyIdModeMask) { @@ -845,7 +922,7 @@ uint8_t Frame::FindPayloadIndex(void) const } #endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - if (!IsVersion2015() && (GetFrameControlField() & kFcfFrameTypeMask) == kFcfFrameMacCmd) + if (!IsVersion2015() && (GetFrameControlField() & kFcfFrameTypeMask) == kTypeMacCmd) { index += kCommandIdSize; } @@ -898,6 +975,8 @@ Error Frame::InitIeHeaderAt(uint8_t &aIndex, uint8_t ieId, uint8_t ieContentSize { Error error = kErrorNone; + WriteUint16(GetFrameControlField() | kFcfIePresent, mPsdu); + if (aIndex == 0) { aIndex = FindHeaderIeIndex(); @@ -1175,7 +1254,7 @@ exit: void TxFrame::GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending) { - uint16_t fcf = kFcfFrameAck | aFrame.GetVersion(); + uint16_t fcf = static_cast(kTypeAck) | aFrame.GetVersion(); mChannel = aFrame.mChannel; memset(&mInfo.mTxInfo, 0, sizeof(mInfo.mTxInfo)); @@ -1196,13 +1275,15 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const { Error error = kErrorNone; - uint16_t fcf = kFcfFrameAck | kFcfFrameVersion2015 | kFcfSrcAddrNone; + uint16_t fcf; Address address; PanId panId; uint8_t footerLength; uint8_t securityControlField; uint8_t keyId; + fcf = static_cast(kTypeAck) | static_cast(kVersion2015) | kFcfSrcAddrNone; + mChannel = aFrame.mChannel; memset(&mInfo.mTxInfo, 0, sizeof(mInfo.mTxInfo)); @@ -1366,19 +1447,19 @@ Frame::InfoString Frame::ToInfoString(void) const switch (type) { - case kFcfFrameBeacon: + case kTypeBeacon: string.Append("Beacon"); break; - case kFcfFrameData: + case kTypeData: string.Append("Data"); break; - case kFcfFrameAck: + case kTypeAck: string.Append("Ack"); break; - case kFcfFrameMacCmd: + case kTypeMacCmd: if (GetCommandId(commandId) != kErrorNone) { commandId = 0xff; diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp index 9ffe2d57c..edfb1a0da 100644 --- a/src/core/mac/mac_frame.hpp +++ b/src/core/mac/mac_frame.hpp @@ -275,75 +275,81 @@ public: class Frame : public otRadioFrame { public: - static constexpr uint8_t kFcfSize = sizeof(uint16_t); - static constexpr uint8_t kDsnSize = sizeof(uint8_t); - static constexpr uint8_t kSecurityControlSize = sizeof(uint8_t); - static constexpr uint8_t kFrameCounterSize = sizeof(uint32_t); - static constexpr uint8_t kCommandIdSize = sizeof(uint8_t); - static constexpr uint8_t k154FcsSize = sizeof(uint16_t); + /** + * This enumeration represents the MAC frame type. + * + * Values match the Frame Type field in Frame Control Field (FCF) as an `uint16_t`. + * + */ + enum Type : uint16_t + { + kTypeBeacon = 0, ///< Beacon Frame Type. + kTypeData = 1, ///< Data Frame Type. + kTypeAck = 2, ///< Ack Frame Type. + kTypeMacCmd = 3, ///< MAC Command Frame Type. + }; - static constexpr uint16_t kFcfFrameBeacon = 0 << 0; - static constexpr uint16_t kFcfFrameData = 1 << 0; - static constexpr uint16_t kFcfFrameAck = 2 << 0; - static constexpr uint16_t kFcfFrameMacCmd = 3 << 0; - static constexpr uint16_t kFcfFrameTypeMask = 7 << 0; - static constexpr uint16_t kFcfSecurityEnabled = 1 << 3; - static constexpr uint16_t kFcfFramePending = 1 << 4; - static constexpr uint16_t kFcfAckRequest = 1 << 5; - static constexpr uint16_t kFcfPanidCompression = 1 << 6; - static constexpr uint16_t kFcfIePresent = 1 << 9; - static constexpr uint16_t kFcfDstAddrNone = 0 << 10; - static constexpr uint16_t kFcfDstAddrShort = 2 << 10; - static constexpr uint16_t kFcfDstAddrExt = 3 << 10; - static constexpr uint16_t kFcfDstAddrMask = 3 << 10; - static constexpr uint16_t kFcfFrameVersion2006 = 1 << 12; - static constexpr uint16_t kFcfFrameVersion2015 = 2 << 12; - static constexpr uint16_t kFcfFrameVersionMask = 3 << 12; - static constexpr uint16_t kFcfSrcAddrNone = 0 << 14; - static constexpr uint16_t kFcfSrcAddrShort = 2 << 14; - static constexpr uint16_t kFcfSrcAddrExt = 3 << 14; - static constexpr uint16_t kFcfSrcAddrMask = 3 << 14; + /** + * This enumeration represents the MAC frame version. + * + * Values match the Version field in Frame Control Field (FCF) as an `uint16_t`. + * + */ + enum Version : uint16_t + { + kVersion2003 = 0 << 12, ///< 2003 Frame Version. + kVersion2006 = 1 << 12, ///< 2006 Frame Version. + kVersion2015 = 2 << 12, ///< 2015 Frame Version. + }; - static constexpr uint8_t kSecNone = 0 << 0; - static constexpr uint8_t kSecMic32 = 1 << 0; - static constexpr uint8_t kSecMic64 = 2 << 0; - static constexpr uint8_t kSecMic128 = 3 << 0; - static constexpr uint8_t kSecEnc = 4 << 0; - static constexpr uint8_t kSecEncMic32 = 5 << 0; - static constexpr uint8_t kSecEncMic64 = 6 << 0; - static constexpr uint8_t kSecEncMic128 = 7 << 0; - static constexpr uint8_t kSecLevelMask = 7 << 0; + /** + * This enumeration represents the MAC frame security level. + * + * Values match the Security Level field in Security Control Field as an `uint8_t`. + * + */ + enum SecurityLevel : uint8_t + { + kSecurityNone = 0, ///< No security. + kSecurityMic32 = 1, ///< No encryption, MIC-32 authentication. + kSecurityMic64 = 2, ///< No encryption, MIC-64 authentication. + kSecurityMic128 = 3, ///< No encryption, MIC-128 authentication. + kSecurityEnc = 4, ///< Encryption, no authentication + kSecurityEncMic32 = 5, ///< Encryption with MIC-32 authentication. + kSecurityEncMic64 = 6, ///< Encryption with MIC-64 authentication. + kSecurityEncMic128 = 7, ///< Encryption with MIC-128 authentication. + }; - static constexpr uint8_t kMic0Size = 0; - static constexpr uint8_t kMic32Size = 32 / CHAR_BIT; - static constexpr uint8_t kMic64Size = 64 / CHAR_BIT; - static constexpr uint8_t kMic128Size = 128 / CHAR_BIT; - static constexpr uint8_t kMaxMicSize = kMic128Size; + /** + * This enumeration represents the MAC frame security key identifier mode. + * + * Values match the Key Identifier Mode field in Security Control Field as an `uint8_t`. + * + */ + enum KeyIdMode : uint8_t + { + kKeyIdMode0 = 0 << 3, ///< Key ID Mode 0 - Key is determined implicitly. + kKeyIdMode1 = 1 << 3, ///< Key ID Mode 1 - Key is determined from Key Index field. + kKeyIdMode2 = 2 << 3, ///< Key ID Mode 2 - Key is determined from 4-bytes Key Source and Index fields. + kKeyIdMode3 = 3 << 3, ///< Key ID Mode 3 - Key is determined from 8-bytes Key Source and Index fields. + }; - static constexpr uint8_t kKeyIdMode0 = 0 << 3; - static constexpr uint8_t kKeyIdMode1 = 1 << 3; - static constexpr uint8_t kKeyIdMode2 = 2 << 3; - static constexpr uint8_t kKeyIdMode3 = 3 << 3; - static constexpr uint8_t kKeyIdModeMask = 3 << 3; - - static constexpr uint8_t kKeySourceSizeMode0 = 0; - static constexpr uint8_t kKeySourceSizeMode1 = 0; - static constexpr uint8_t kKeySourceSizeMode2 = 4; - static constexpr uint8_t kKeySourceSizeMode3 = 8; - - static constexpr uint8_t kKeyIndexSize = sizeof(uint8_t); - - static constexpr uint8_t kMacCmdAssociationRequest = 1; - static constexpr uint8_t kMacCmdAssociationResponse = 2; - static constexpr uint8_t kMacCmdDisassociationNotification = 3; - static constexpr uint8_t kMacCmdDataRequest = 4; - static constexpr uint8_t kMacCmdPanidConflictNotification = 5; - static constexpr uint8_t kMacCmdOrphanNotification = 6; - static constexpr uint8_t kMacCmdBeaconRequest = 7; - static constexpr uint8_t kMacCmdCoordinatorRealignment = 8; - static constexpr uint8_t kMacCmdGtsRequest = 9; - - static constexpr uint8_t kImmAckLength = kFcfSize + kDsnSize + k154FcsSize; + /** + * This enumeration represents a subset of MAC Command Identifiers. + * + */ + enum CommandId : uint8_t + { + kMacCmdAssociationRequest = 1, + kMacCmdAssociationResponse = 2, + kMacCmdDisassociationNotification = 3, + kMacCmdDataRequest = 4, + kMacCmdPanidConflictNotification = 5, + kMacCmdOrphanNotification = 6, + kMacCmdBeaconRequest = 7, + kMacCmdCoordinatorRealignment = 8, + kMacCmdGtsRequest = 9, + }; static constexpr uint16_t kInfoStringSize = 128; ///< Max chars for `InfoString` (ToInfoString()). @@ -365,11 +371,26 @@ public: /** * This method initializes the MAC header. * - * @param[in] aFcf The Frame Control field. - * @param[in] aSecurityControl The Security Control field. + * This method 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. The Frame Pending and IE + * Present bits are not set. + * + * @param[in] aType Frame type. + * @param[in] aVerion 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] aSeucirtyLevel Frame security level. + * @param[in] aKeyIdMode Frame security key ID mode. * */ - void InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl); + void InitMacHeader(Type aType, + Version aVersion, + const Addresses &aAddrs, + const PanIds &aPanIds, + SecurityLevel aSecurityLevel, + KeyIdMode aKeyIdMode = kKeyIdMode0); /** * This method validates the frame. @@ -395,7 +416,7 @@ public: * @retval FALSE If this is not an Ack. * */ - bool IsAck(void) const { return GetType() == kFcfFrameAck; } + bool IsAck(void) const { return GetType() == kTypeAck; } /** * This method returns the IEEE 802.15.4 Frame Version. @@ -918,6 +939,8 @@ public: /** * This template method appends an Header IE at specified index in this frame. * + * This method also sets the IE present bit in the Frame Control Field (FCF). + * * @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 @@ -1066,6 +1089,46 @@ public: uint16_t GetFrameControlField(void) const; protected: + static constexpr uint8_t kFcfSize = sizeof(uint16_t); + static constexpr uint8_t kDsnSize = sizeof(uint8_t); + static constexpr uint8_t kSecurityControlSize = sizeof(uint8_t); + static constexpr uint8_t kFrameCounterSize = sizeof(uint32_t); + static constexpr uint8_t kCommandIdSize = sizeof(uint8_t); + static constexpr uint8_t k154FcsSize = sizeof(uint16_t); + static constexpr uint8_t kKeyIndexSize = sizeof(uint8_t); + + static constexpr uint16_t kFcfFrameTypeMask = 7 << 0; + static constexpr uint16_t kFcfSecurityEnabled = 1 << 3; + static constexpr uint16_t kFcfFramePending = 1 << 4; + static constexpr uint16_t kFcfAckRequest = 1 << 5; + static constexpr uint16_t kFcfPanidCompression = 1 << 6; + static constexpr uint16_t kFcfIePresent = 1 << 9; + static constexpr uint16_t kFcfDstAddrNone = 0 << 10; + static constexpr uint16_t kFcfDstAddrShort = 2 << 10; + static constexpr uint16_t kFcfDstAddrExt = 3 << 10; + static constexpr uint16_t kFcfDstAddrMask = 3 << 10; + static constexpr uint16_t kFcfFrameVersionMask = 3 << 12; + static constexpr uint16_t kFcfSrcAddrNone = 0 << 14; + static constexpr uint16_t kFcfSrcAddrShort = 2 << 14; + static constexpr uint16_t kFcfSrcAddrExt = 3 << 14; + static constexpr uint16_t kFcfSrcAddrMask = 3 << 14; + + static constexpr uint8_t kSecLevelMask = 7 << 0; + static constexpr uint8_t kKeyIdModeMask = 3 << 3; + + static constexpr uint8_t kMic0Size = 0; + static constexpr uint8_t kMic32Size = 32 / CHAR_BIT; + static constexpr uint8_t kMic64Size = 64 / CHAR_BIT; + static constexpr uint8_t kMic128Size = 128 / CHAR_BIT; + static constexpr uint8_t kMaxMicSize = kMic128Size; + + static constexpr uint8_t kKeySourceSizeMode0 = 0; + static constexpr uint8_t kKeySourceSizeMode1 = 0; + static constexpr uint8_t kKeySourceSizeMode2 = 4; + static constexpr uint8_t kKeySourceSizeMode3 = 8; + + static constexpr uint8_t kImmAckLength = kFcfSize + kDsnSize + k154FcsSize; + static constexpr uint8_t kInvalidIndex = 0xff; static constexpr uint8_t kInvalidSize = kInvalidIndex; static constexpr uint8_t kMaxPsduSize = kInvalidSize - 1; @@ -1092,7 +1155,7 @@ protected: static bool IsDstPanIdPresent(uint16_t aFcf); static bool IsSrcAddrPresent(uint16_t aFcf) { return (aFcf & kFcfSrcAddrMask) != kFcfSrcAddrNone; } static bool IsSrcPanIdPresent(uint16_t aFcf); - static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kFcfFrameVersion2015; } + static bool IsVersion2015(uint16_t aFcf) { return (aFcf & kFcfFrameVersionMask) == kVersion2015; } static uint8_t CalculateAddrFieldSize(uint16_t aFcf); static uint8_t CalculateSecurityHeaderSize(uint8_t aSecurityControl); diff --git a/src/core/mac/mac_types.hpp b/src/core/mac/mac_types.hpp index 3e03c75cb..9ee73986c 100644 --- a/src/core/mac/mac_types.hpp +++ b/src/core/mac/mac_types.hpp @@ -421,6 +421,16 @@ struct Addresses Address mDestination; ///< Destination address. }; +/** + * This structure represents two PAN IDs corresponding to source and destination. + * + */ +struct PanIds +{ + PanId mSource; ///< Source PAN ID. + PanId mDestination; ///< Destination PAN ID. +}; + /** * This class represents a MAC key. * diff --git a/src/core/radio/trel_link.cpp b/src/core/radio/trel_link.cpp index 9a12a9b37..f5635012d 100644 --- a/src/core/radio/trel_link.cpp +++ b/src/core/radio/trel_link.cpp @@ -216,11 +216,11 @@ void Link::BeginTransmit(void) if (mTxFrame.GetAckRequest()) { - uint16_t fcf = Mac::Frame::kFcfFrameAck; + uint16_t fcf = Mac::Frame::kTypeAck; if (!Get().IsRxOnWhenIdle()) { - fcf |= Mac::Frame::kFcfFramePending; + fcf |= kFcfFramePending; } // Prepare the ack frame (FCF followed by sequence number) diff --git a/src/core/radio/trel_link.hpp b/src/core/radio/trel_link.hpp index 1aa95b9ca..f19b0bbae 100644 --- a/src/core/radio/trel_link.hpp +++ b/src/core/radio/trel_link.hpp @@ -153,6 +153,7 @@ private: static constexpr uint16_t k154AckFrameSize = 3 + kFcsSize; static constexpr int8_t kRxRssi = -20; // The RSSI value used for received frames on TREL radio link. static constexpr uint32_t kAckWaitWindow = 750; // (in msec) + static constexpr uint16_t kFcfFramePending = 1 << 4; enum State : uint8_t { diff --git a/src/core/thread/link_metrics_types.cpp b/src/core/thread/link_metrics_types.cpp index 146393692..cd5872176 100644 --- a/src/core/thread/link_metrics_types.cpp +++ b/src/core/thread/link_metrics_types.cpp @@ -137,13 +137,13 @@ bool SeriesInfo::IsFrameTypeMatch(uint8_t aFrameType) const VerifyOrExit(!mSeriesFlags.IsMacDataFlagSet()); // Ignore this when Mac Data is accounted match = mSeriesFlags.IsLinkProbeFlagSet(); break; - case Mac::Frame::kFcfFrameData: + case Mac::Frame::kTypeData: match = mSeriesFlags.IsMacDataFlagSet(); break; - case Mac::Frame::kFcfFrameMacCmd: + case Mac::Frame::kTypeMacCmd: match = mSeriesFlags.IsMacDataRequestFlagSet(); break; - case Mac::Frame::kFcfFrameAck: + case Mac::Frame::kTypeAck: match = mSeriesFlags.IsMacAckFlagSet(); break; default: diff --git a/src/core/thread/link_metrics_types.hpp b/src/core/thread/link_metrics_types.hpp index ce92d7b71..f0d564a3f 100644 --- a/src/core/thread/link_metrics_types.hpp +++ b/src/core/thread/link_metrics_types.hpp @@ -273,8 +273,8 @@ class SeriesInfo : public LinkedListEntry public: /** * This constant represents Link Probe when filtering frames to be accounted using Series Flag. There's - * already `kFcfFrameData`, `kFcfFrameAck` and `kFcfFrameMacCmd`. This item is added so that we can - * filter a Link Probe for series in the same way as other frames. + * already `Mac::Frame::kTypeData`, `Mac::Frame::kTypeAck` and `Mac::Frame::kTypeMacCmd`. This item is + * added so that we can filter a Link Probe for series in the same way as other frames. * */ static constexpr uint8_t kSeriesTypeLinkProbe = 0; diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 877528e6f..2d8b6db52 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -164,51 +164,24 @@ exit: void MeshForwarder::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest) { - uint16_t fcf = 0; - bool iePresent = CalcIePresent(nullptr); + Mac::Addresses addresses; + Mac::PanIds panIds; - Mac::Address macSource; - macSource.SetShort(Get().GetShortAddress()); + addresses.mSource.SetShort(Get().GetShortAddress()); - if (macSource.IsShortAddrInvalid() || aMacDest.IsExtended()) + if (addresses.mSource.IsShortAddrInvalid() || aMacDest.IsExtended()) { - macSource.SetExtended(Get().GetExtAddress()); + addresses.mSource.SetExtended(Get().GetExtAddress()); } - fcf = Mac::Frame::kFcfFrameData | Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfSecurityEnabled; + addresses.mDestination = aMacDest; + panIds.mSource = Get().GetPanId(); + panIds.mDestination = Get().GetPanId(); - if (iePresent) - { - fcf |= Mac::Frame::kFcfIePresent; - } + PrepareMacHeaders(aFrame, Mac::Frame::kTypeData, addresses, panIds, Mac::Frame::kSecurityEncMic32, + Mac::Frame::kKeyIdMode1, nullptr); - fcf |= CalcFrameVersion(Get().FindNeighbor(aMacDest), iePresent); - - if (aAckRequest) - { - fcf |= Mac::Frame::kFcfAckRequest; - } - - fcf |= (aMacDest.IsShort()) ? Mac::Frame::kFcfDstAddrShort : Mac::Frame::kFcfDstAddrExt; - fcf |= (macSource.IsShort()) ? Mac::Frame::kFcfSrcAddrShort : Mac::Frame::kFcfSrcAddrExt; - - aFrame.InitMacHeader(fcf, Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32); - - if (aFrame.IsDstPanIdPresent()) - { - aFrame.SetDstPanId(Get().GetPanId()); - } - IgnoreError(aFrame.SetSrcPanId(Get().GetPanId())); - - aFrame.SetDstAddr(aMacDest); - aFrame.SetSrcAddr(macSource); - aFrame.SetFramePending(false); -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - if (iePresent) - { - AppendHeaderIe(nullptr, aFrame); - } -#endif + aFrame.SetAckRequest(aAckRequest); aFrame.SetPayloadLength(0); } @@ -819,6 +792,30 @@ exit: 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) +{ + bool iePresent; + Mac::Frame::Version version; + + iePresent = CalcIePresent(aMessage); + version = CalcFrameVersion(Get().FindNeighbor(aMacAddrs.mDestination), iePresent); + + aFrame.InitMacHeader(aFrameType, version, aMacAddrs, aPanIds, aSecurityLevel, aKeyIdMode); + +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT + if (iePresent) + { + AppendHeaderIe(aMessage, aFrame); + } +#endif +} + // This method constructs a MAC data from from a given IPv6 message. // // This method handles generation of MAC header, mesh header (if @@ -838,125 +835,59 @@ uint16_t MeshForwarder::PrepareDataFrame(Mac::TxFrame &aFrame, uint16_t aMeshDest, bool aAddFragHeader) { - uint16_t fcf; - uint16_t payloadLength; - uint16_t dstpan; - uint8_t secCtl; - uint16_t origMsgOffset; - uint16_t nextOffset; - FrameBuilder frameBuilder; - bool iePresent = CalcIePresent(&aMessage); + Mac::Frame::SecurityLevel securityLevel; + Mac::Frame::KeyIdMode keyIdMode; + Mac::PanIds panIds; + uint16_t payloadLength; + uint16_t origMsgOffset; + uint16_t nextOffset; + FrameBuilder frameBuilder; start: - // Initialize MAC header - fcf = Mac::Frame::kFcfFrameData; - - fcf |= (aMacAddrs.mDestination.IsShort()) ? Mac::Frame::kFcfDstAddrShort : Mac::Frame::kFcfDstAddrExt; - fcf |= (aMacAddrs.mSource.IsShort()) ? Mac::Frame::kFcfSrcAddrShort : Mac::Frame::kFcfSrcAddrExt; - - if (iePresent) - { - fcf |= Mac::Frame::kFcfIePresent; - } - - fcf |= CalcFrameVersion(Get().FindNeighbor(aMacAddrs.mDestination), iePresent); - - // All unicast frames request ACK - if (aMacAddrs.mDestination.IsExtended() || !aMacAddrs.mDestination.IsBroadcast()) - { - fcf |= Mac::Frame::kFcfAckRequest; - } + securityLevel = Mac::Frame::kSecurityNone; + keyIdMode = Mac::Frame::kKeyIdMode1; if (aMessage.IsLinkSecurityEnabled()) { - fcf |= Mac::Frame::kFcfSecurityEnabled; + securityLevel = Mac::Frame::kSecurityEncMic32; switch (aMessage.GetSubType()) { case Message::kSubTypeJoinerEntrust: - secCtl = static_cast(Mac::Frame::kKeyIdMode0); + keyIdMode = Mac::Frame::kKeyIdMode0; break; case Message::kSubTypeMleAnnounce: - secCtl = static_cast(Mac::Frame::kKeyIdMode2); + keyIdMode = Mac::Frame::kKeyIdMode2; break; default: - secCtl = static_cast(Mac::Frame::kKeyIdMode1); + // Use the `kKeyIdMode1` break; } - - secCtl |= Mac::Frame::kSecEncMic32; - } - else - { - secCtl = Mac::Frame::kSecNone; } - dstpan = Get().GetPanId(); + panIds.mSource = Get().GetPanId(); + panIds.mDestination = Get().GetPanId(); switch (aMessage.GetSubType()) { case Message::kSubTypeMleAnnounce: aFrame.SetChannel(aMessage.GetChannel()); - dstpan = Mac::kPanIdBroadcast; + panIds.mDestination = Mac::kPanIdBroadcast; break; case Message::kSubTypeMleDiscoverRequest: case Message::kSubTypeMleDiscoverResponse: - dstpan = aMessage.GetPanId(); + panIds.mDestination = aMessage.GetPanId(); break; default: break; } - // Handle special case in 15.4-2015: - // Dest Address: Extended - // Source Address: Extended - // Dest PanId: Present - // Src Panid: Not Present - // Pan ID Compression: 0 - if (dstpan == Get().GetPanId() && - ((fcf & Mac::Frame::kFcfFrameVersionMask) == Mac::Frame::kFcfFrameVersion2006 || - (fcf & Mac::Frame::kFcfDstAddrMask) != Mac::Frame::kFcfDstAddrExt || - (fcf & Mac::Frame::kFcfSrcAddrMask) != Mac::Frame::kFcfSrcAddrExt)) - { -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - // Handle a special case in IEEE 802.15.4-2015, when Pan ID Compression is 0, but Src Pan ID is not present: - // Dest Address: Extended - // Src Address: Extended - // Dest Pan ID: Present - // Src Pan ID: Not Present - // Pan ID Compression: 0 - - if ((fcf & Mac::Frame::kFcfFrameVersionMask) != Mac::Frame::kFcfFrameVersion2015 || - (fcf & Mac::Frame::kFcfDstAddrMask) != Mac::Frame::kFcfDstAddrExt || - (fcf & Mac::Frame::kFcfSrcAddrMask) != Mac::Frame::kFcfSrcAddrExt) -#endif - { - fcf |= Mac::Frame::kFcfPanidCompression; - } - } - - aFrame.InitMacHeader(fcf, secCtl); - - if (aFrame.IsDstPanIdPresent()) - { - aFrame.SetDstPanId(dstpan); - } - - IgnoreError(aFrame.SetSrcPanId(Get().GetPanId())); - aFrame.SetDstAddr(aMacAddrs.mDestination); - aFrame.SetSrcAddr(aMacAddrs.mSource); - -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - if (iePresent) - { - AppendHeaderIe(&aMessage, aFrame); - } -#endif + PrepareMacHeaders(aFrame, Mac::Frame::kTypeData, aMacAddrs, panIds, securityLevel, keyIdMode, &aMessage); frameBuilder.Init(aFrame.GetPayload(), aFrame.GetMaxPayloadLength()); @@ -1376,7 +1307,7 @@ void MeshForwarder::HandleReceivedFrame(Mac::RxFrame &aFrame) switch (aFrame.GetType()) { - case Mac::Frame::kFcfFrameData: + case Mac::Frame::kTypeData: if (Lowpan::MeshHeader::IsMeshHeader(frameData)) { #if OPENTHREAD_FTD @@ -1400,7 +1331,7 @@ void MeshForwarder::HandleReceivedFrame(Mac::RxFrame &aFrame) break; - case Mac::Frame::kFcfFrameBeacon: + case Mac::Frame::kTypeBeacon: break; default: @@ -1756,7 +1687,7 @@ void MeshForwarder::AppendHeaderIe(const Message *aMessage, Mac::TxFrame &aFrame uint8_t index = 0; bool iePresent = false; bool payloadPresent = - (aFrame.GetType() == Mac::Frame::kFcfFrameMacCmd) || (aMessage != nullptr && aMessage->GetLength() != 0); + (aFrame.GetType() == Mac::Frame::kTypeMacCmd) || (aMessage != nullptr && aMessage->GetLength() != 0); #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE if (aMessage != nullptr && aMessage->IsTimeSync()) @@ -1786,26 +1717,26 @@ void MeshForwarder::AppendHeaderIe(const Message *aMessage, Mac::TxFrame &aFrame } #endif -uint16_t MeshForwarder::CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent) +Mac::Frame::Version MeshForwarder::CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent) const { - uint16_t version = Mac::Frame::kFcfFrameVersion2006; + Mac::Frame::Version version = Mac::Frame::kVersion2006; OT_UNUSED_VARIABLE(aNeighbor); if (aIePresent) { - version = Mac::Frame::kFcfFrameVersion2015; + version = Mac::Frame::kVersion2015; } #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE else if ((aNeighbor != nullptr) && Get().Contains(*aNeighbor) && static_cast(aNeighbor)->IsCslSynchronized()) { - version = Mac::Frame::kFcfFrameVersion2015; + version = Mac::Frame::kVersion2015; } #endif #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE else if (aNeighbor != nullptr && aNeighbor->IsEnhAckProbingActive()) { - version = Mac::Frame::kFcfFrameVersion2015; ///< Set version to 2015 to fetch Link Metrics data in Enh-ACK. + version = Mac::Frame::kVersion2015; ///< Set version to 2015 to fetch Link Metrics data in Enh-ACK. } #endif diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index e836e027f..9ee160b5c 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -445,6 +445,15 @@ private: void HandleMesh(FrameData &aFrameData, const Mac::Address &aMacSource, const ThreadLinkInfo &aLinkInfo); void HandleFragment(FrameData &aFrameData, const Mac::Addresses &aMacAddrs, const ThreadLinkInfo &aLinkInfo); void HandleLowpanHC(const FrameData &aFrameData, const Mac::Addresses &aMacAddrs, const ThreadLinkInfo &aLinkInfo); + + 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); + uint16_t PrepareDataFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs, @@ -504,8 +513,8 @@ private: const Mac::Addresses &aMeshAddrs, Message::Priority &aPriority); - bool CalcIePresent(const Message *aMessage); - uint16_t CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent); + bool CalcIePresent(const Message *aMessage); + Mac::Frame::Version CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent) const; #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT void AppendHeaderIe(const Message *aMessage, Mac::TxFrame &aFrame); #endif diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 0e5bd0ad1..589a60f3d 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -349,31 +349,13 @@ void MeshForwarder::RemoveDataResponseMessages(void) void MeshForwarder::SendMesh(Message &aMessage, Mac::TxFrame &aFrame) { - uint16_t fcf; - bool iePresent = CalcIePresent(&aMessage); + Mac::PanIds panIds; - // initialize MAC header - fcf = Mac::Frame::kFcfFrameData | Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfDstAddrShort | - Mac::Frame::kFcfSrcAddrShort | Mac::Frame::kFcfAckRequest | Mac::Frame::kFcfSecurityEnabled; + panIds.mSource = Get().GetPanId(); + panIds.mDestination = Get().GetPanId(); - if (iePresent) - { - fcf |= Mac::Frame::kFcfIePresent; - } - - fcf |= CalcFrameVersion(Get().FindNeighbor(mMacAddrs.mDestination), iePresent); - - aFrame.InitMacHeader(fcf, Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32); - aFrame.SetDstPanId(Get().GetPanId()); - aFrame.SetDstAddr(mMacAddrs.mDestination.GetShort()); - aFrame.SetSrcAddr(mMacAddrs.mSource); - -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - if (iePresent) - { - AppendHeaderIe(&aMessage, aFrame); - } -#endif + PrepareMacHeaders(aFrame, Mac::Frame::kTypeData, mMacAddrs, panIds, Mac::Frame::kSecurityEncMic32, + Mac::Frame::kKeyIdMode1, &aMessage); // write payload OT_ASSERT(aMessage.GetLength() <= aFrame.GetMaxPayloadLength()); diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 132b6f6ea..c840a517f 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -2328,7 +2328,7 @@ Error Mle::ProcessMessageSecurity(Crypto::AesCcm::Mode aMode, } senderAddress->GetIid().ConvertToExtAddress(extAddress); - Crypto::AesCcm::GenerateNonce(extAddress, aHeader.GetFrameCounter(), Mac::Frame::kSecEncMic32, nonce); + Crypto::AesCcm::GenerateNonce(extAddress, aHeader.GetFrameCounter(), Mac::Frame::kSecurityEncMic32, nonce); keySequence = aHeader.GetKeyId(); diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index f5a246274..dafbac82f 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1836,7 +1836,8 @@ private: } private: - static constexpr uint8_t kKeyIdMode2Mic32 = (Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecEncMic32); + static constexpr uint8_t kKeyIdMode2Mic32 = + static_cast(Mac::Frame::kKeyIdMode2) | static_cast(Mac::Frame::kSecurityEncMic32); uint8_t mSecurityControl; uint32_t mFrameCounter; diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp index 846c6373e..7966b70e9 100644 --- a/tests/unit/test_mac_frame.cpp +++ b/tests/unit/test_mac_frame.cpp @@ -53,6 +53,30 @@ bool CompareReversed(const uint8_t *aFirst, const uint8_t *aSecond, uint16_t aLe return matches; } +bool CompareAddresses(const Mac::Address &aFirst, const Mac::Address &aSecond) +{ + bool matches = false; + + VerifyOrExit(aFirst.GetType() == aSecond.GetType()); + + switch (aFirst.GetType()) + { + case Mac::Address::kTypeNone: + break; + case Mac::Address::kTypeShort: + VerifyOrExit(aFirst.GetShort() == aSecond.GetShort()); + break; + case Mac::Address::kTypeExtended: + VerifyOrExit(aFirst.GetExtended() == aSecond.GetExtended()); + break; + } + + matches = true; + +exit: + return matches; +} + void TestMacAddress(void) { const uint8_t kExtAddr[OT_EXT_ADDRESS_SIZE] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; @@ -156,57 +180,186 @@ void TestMacAddress(void) void TestMacHeader(void) { - static const struct + enum AddrType : uint8_t { - uint16_t fcf; - uint8_t secCtl; - uint8_t headerLength; - uint8_t footerLength; - } tests[] = { - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrNone | Mac::Frame::kFcfSrcAddrNone, 0, 3, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrNone | Mac::Frame::kFcfSrcAddrShort, 0, 7, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrNone | Mac::Frame::kFcfSrcAddrExt, 0, 13, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrNone, 0, 7, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrNone, 0, 13, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort, 0, 11, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrExt, 0, 17, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrShort, 0, 17, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrExt, 0, 23, 2}, - - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort | - Mac::Frame::kFcfPanidCompression, - 0, 9, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrExt | - Mac::Frame::kFcfPanidCompression, - 0, 15, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrShort | - Mac::Frame::kFcfPanidCompression, - 0, 15, 2}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrExt | - Mac::Frame::kFcfPanidCompression, - 0, 21, 2}, - - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort | - Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfSecurityEnabled, - Mac::Frame::kSecMic32 | Mac::Frame::kKeyIdMode1, 15, 6}, - {Mac::Frame::kFcfFrameVersion2006 | Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort | - Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfSecurityEnabled, - Mac::Frame::kSecMic32 | Mac::Frame::kKeyIdMode2, 19, 6}, + kNoneAddr, + kShrtAddr, + kExtdAddr, }; - for (const auto &test : tests) + enum PanIdMode { - uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE]; - Mac::TxFrame frame; + kSamePanIds, + kDiffPanIds, + }; + + struct TestCase + { + Mac::Frame::Version mVersion; + AddrType mSrcAddrType; + AddrType mDstAddrType; + PanIdMode mPanIdMode; + Mac::Frame::SecurityLevel mSecurity; + Mac::Frame::KeyIdMode mKeyIdMode; + uint8_t mHeaderLength; + uint8_t mFooterLength; + }; + + static constexpr Mac::Frame::Version kVer2006 = Mac::Frame::kVersion2006; + static constexpr Mac::Frame::Version kVer2015 = Mac::Frame::kVersion2015; + + static constexpr Mac::Frame::SecurityLevel kNoSec = Mac::Frame::kSecurityNone; + static constexpr Mac::Frame::SecurityLevel kMic32 = Mac::Frame::kSecurityMic32; + + static constexpr Mac::Frame::KeyIdMode kModeId1 = Mac::Frame::kKeyIdMode1; + static constexpr Mac::Frame::KeyIdMode kModeId2 = Mac::Frame::kKeyIdMode2; + + static constexpr TestCase kTestCases[] = { + {kVer2006, kNoneAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 3, 2}, + {kVer2006, kShrtAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 7, 2}, + {kVer2006, kExtdAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 13, 2}, + {kVer2006, kNoneAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 7, 2}, + {kVer2006, kNoneAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 13, 2}, + {kVer2006, kShrtAddr, kShrtAddr, kDiffPanIds, kNoSec, kModeId1, 11, 2}, + {kVer2006, kShrtAddr, kExtdAddr, kDiffPanIds, kNoSec, kModeId1, 17, 2}, + {kVer2006, kExtdAddr, kShrtAddr, kDiffPanIds, kNoSec, kModeId1, 17, 2}, + {kVer2006, kExtdAddr, kExtdAddr, kDiffPanIds, kNoSec, kModeId1, 23, 2}, + {kVer2006, kShrtAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 9, 2}, + {kVer2006, kShrtAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 15, 2}, + {kVer2006, kExtdAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 15, 2}, + {kVer2006, kExtdAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 21, 2}, + {kVer2006, kShrtAddr, kShrtAddr, kSamePanIds, kMic32, kModeId1, 15, 6}, + {kVer2006, kShrtAddr, kShrtAddr, kSamePanIds, kMic32, kModeId2, 19, 6}, + + {kVer2015, kNoneAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 3, 2}, + {kVer2015, kShrtAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 7, 2}, + {kVer2015, kExtdAddr, kNoneAddr, kSamePanIds, kNoSec, kModeId1, 13, 2}, + {kVer2015, kNoneAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 7, 2}, + {kVer2015, kNoneAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 13, 2}, + {kVer2015, kShrtAddr, kShrtAddr, kDiffPanIds, kNoSec, kModeId1, 11, 2}, + {kVer2015, kShrtAddr, kExtdAddr, kDiffPanIds, kNoSec, kModeId1, 17, 2}, + {kVer2015, kExtdAddr, kShrtAddr, kDiffPanIds, kNoSec, kModeId1, 17, 2}, + {kVer2015, kShrtAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 9, 2}, + {kVer2015, kShrtAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 15, 2}, + {kVer2015, kExtdAddr, kShrtAddr, kSamePanIds, kNoSec, kModeId1, 15, 2}, + {kVer2015, kExtdAddr, kExtdAddr, kSamePanIds, kNoSec, kModeId1, 21, 2}, + {kVer2015, kShrtAddr, kShrtAddr, kSamePanIds, kMic32, kModeId1, 15, 6}, + {kVer2015, kShrtAddr, kShrtAddr, kSamePanIds, kMic32, kModeId2, 19, 6}, + }; + + const uint16_t kPanId1 = 0xbaba; + const uint16_t kPanId2 = 0xdede; + const uint16_t kShortAddr1 = 0x1234; + const uint16_t kShortAddr2 = 0x5678; + const uint8_t kExtAddr1[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0}; + const uint8_t kExtAddr2[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; + + Mac::ExtAddress extAddr1; + Mac::ExtAddress extAddr2; + + extAddr1.Set(kExtAddr1); + extAddr2.Set(kExtAddr2); + + printf("TestMacHeader\n"); + + for (const TestCase &testCase : kTestCases) + { + uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE]; + Mac::TxFrame frame; + Mac::Addresses addresses; + Mac::Address address; + Mac::PanIds panIds; + Mac::PanId panId; frame.mPsdu = psdu; frame.mLength = 0; frame.mRadioType = 0; - frame.InitMacHeader(test.fcf, test.secCtl); - VerifyOrQuit(frame.GetHeaderLength() == test.headerLength); - VerifyOrQuit(frame.GetFooterLength() == test.footerLength); - VerifyOrQuit(frame.GetLength() == test.headerLength + test.footerLength); + switch (testCase.mSrcAddrType) + { + case kNoneAddr: + addresses.mSource.SetNone(); + break; + case kShrtAddr: + addresses.mSource.SetShort(kShortAddr1); + break; + case kExtdAddr: + addresses.mSource.SetExtended(extAddr1); + break; + } + + switch (testCase.mDstAddrType) + { + case kNoneAddr: + addresses.mDestination.SetNone(); + break; + case kShrtAddr: + addresses.mDestination.SetShort(kShortAddr2); + break; + case kExtdAddr: + addresses.mDestination.SetExtended(extAddr2); + break; + } + + switch (testCase.mPanIdMode) + { + case kSamePanIds: + panIds.mSource = panIds.mDestination = kPanId1; + break; + case kDiffPanIds: + panIds.mSource = kPanId1; + panIds.mDestination = kPanId2; + break; + } + + frame.InitMacHeader(Mac::Frame::kTypeData, testCase.mVersion, addresses, panIds, testCase.mSecurity, + testCase.mKeyIdMode); + + VerifyOrQuit(frame.GetHeaderLength() == testCase.mHeaderLength); + VerifyOrQuit(frame.GetFooterLength() == testCase.mFooterLength); + VerifyOrQuit(frame.GetLength() == testCase.mHeaderLength + testCase.mFooterLength); + + VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeData); + VerifyOrQuit(!frame.IsAck()); + VerifyOrQuit(frame.GetVersion() == testCase.mVersion); + VerifyOrQuit(frame.GetSecurityEnabled() == (testCase.mSecurity != kNoSec)); + VerifyOrQuit(!frame.GetFramePending()); + VerifyOrQuit(!frame.IsIePresent()); + VerifyOrQuit(frame.GetAckRequest() == (testCase.mDstAddrType != kNoneAddr)); + + VerifyOrQuit(frame.IsSrcAddrPresent() == (testCase.mSrcAddrType != kNoneAddr)); + SuccessOrQuit(frame.GetSrcAddr(address)); + VerifyOrQuit(CompareAddresses(address, addresses.mSource)); + VerifyOrQuit(frame.IsDstAddrPresent() == (testCase.mDstAddrType != kNoneAddr)); + SuccessOrQuit(frame.GetDstAddr(address)); + VerifyOrQuit(CompareAddresses(address, addresses.mDestination)); + + if (testCase.mDstAddrType != kNoneAddr) + { + VerifyOrQuit(frame.IsDstPanIdPresent()); + SuccessOrQuit(frame.GetDstPanId(panId)); + VerifyOrQuit(panId == panIds.mDestination); + } + + if (frame.IsSrcPanIdPresent()) + { + SuccessOrQuit(frame.GetSrcPanId(panId)); + VerifyOrQuit(panId == panIds.mSource); + } + + if (frame.GetSecurityEnabled()) + { + uint8_t security; + uint8_t keyIdMode; + + SuccessOrQuit(frame.GetSecurityLevel(security)); + VerifyOrQuit(security == testCase.mSecurity); + + SuccessOrQuit(frame.GetKeyIdMode(keyIdMode)); + VerifyOrQuit(keyIdMode == testCase.mKeyIdMode); + } + + printf(" %d, %d\n", testCase.mHeaderLength, testCase.mFooterLength); } } @@ -381,14 +534,14 @@ void TestMacFrameApi(void) // FCS: 0x9bd2 (Correct) frame.mPsdu = ack_psdu1; frame.mLength = sizeof(ack_psdu1); - VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameAck); + VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeAck); VerifyOrQuit(!frame.GetSecurityEnabled()); VerifyOrQuit(!frame.GetFramePending()); VerifyOrQuit(!frame.GetAckRequest()); VerifyOrQuit(!frame.IsIePresent()); VerifyOrQuit(!frame.IsDstPanIdPresent()); VerifyOrQuit(!frame.IsDstAddrPresent()); - VerifyOrQuit(frame.GetVersion() == Mac::Frame::kFcfFrameVersion2006); + VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2006); VerifyOrQuit(!frame.IsSrcAddrPresent()); VerifyOrQuit(frame.GetSequence() == 94); @@ -420,8 +573,8 @@ void TestMacFrameApi(void) frame.mPsdu = mac_cmd_psdu1; frame.mLength = sizeof(mac_cmd_psdu1); VerifyOrQuit(frame.GetSequence() == 133); - VerifyOrQuit(frame.GetVersion() == Mac::Frame::kFcfFrameVersion2006); - VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameMacCmd); + VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2006); + VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeMacCmd); SuccessOrQuit(frame.GetCommandId(commandId)); VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest); SuccessOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdBeaconRequest)); @@ -439,7 +592,7 @@ void TestMacFrameApi(void) frame.mLength = sizeof(mac_cmd_psdu2); VerifyOrQuit(frame.GetSequence() == 141); VerifyOrQuit(frame.IsVersion2015()); - VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameMacCmd); + VerifyOrQuit(frame.GetType() == Mac::Frame::kTypeMacCmd); SuccessOrQuit(frame.GetCommandId(commandId)); VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest); printf("commandId:%d\n", commandId); @@ -452,6 +605,8 @@ void TestMacFrameApi(void) void TestMacFrameAckGeneration(void) { + constexpr uint8_t kImmAckLength = 5; + Mac::RxFrame receivedFrame; Mac::TxFrame ackFrame; uint8_t ackFrameBuffer[100]; @@ -487,8 +642,8 @@ void TestMacFrameAckGeneration(void) receivedFrame.mLength = sizeof(data_psdu1); ackFrame.GenerateImmAck(receivedFrame, false); - VerifyOrQuit(ackFrame.mLength == Mac::Frame::kImmAckLength); - VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kFcfFrameAck); + VerifyOrQuit(ackFrame.mLength == kImmAckLength); + VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kTypeAck); VerifyOrQuit(!ackFrame.GetSecurityEnabled()); VerifyOrQuit(!ackFrame.GetFramePending()); @@ -497,7 +652,7 @@ void TestMacFrameAckGeneration(void) VerifyOrQuit(!ackFrame.IsDstPanIdPresent()); VerifyOrQuit(!ackFrame.IsDstAddrPresent()); VerifyOrQuit(!ackFrame.IsSrcAddrPresent()); - VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kFcfFrameVersion2006); + VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kVersion2006); VerifyOrQuit(ackFrame.GetSequence() == 189); #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) @@ -548,13 +703,13 @@ void TestMacFrameAckGeneration(void) IgnoreError(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data))); csl = reinterpret_cast(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe)); VerifyOrQuit(ackFrame.mLength == 23); - VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kFcfFrameAck); + VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kTypeAck); VerifyOrQuit(ackFrame.GetSecurityEnabled()); VerifyOrQuit(ackFrame.IsIePresent()); VerifyOrQuit(!ackFrame.IsDstPanIdPresent()); VerifyOrQuit(ackFrame.IsDstAddrPresent()); VerifyOrQuit(!ackFrame.IsSrcAddrPresent()); - VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kFcfFrameVersion2015); + VerifyOrQuit(ackFrame.GetVersion() == Mac::Frame::kVersion2015); VerifyOrQuit(ackFrame.GetSequence() == 142); VerifyOrQuit(csl->GetPeriod() == 3125 && csl->GetPhase() == 3105);