Skip to content

Commit

Permalink
[mac-frame] update InitMacHeader() (#8660)
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
abtink authored Jan 18, 2023
1 parent 57733ea commit fe1cf3a
Show file tree
Hide file tree
Showing 21 changed files with 662 additions and 394 deletions.
6 changes: 3 additions & 3 deletions examples/platforms/utils/mac_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ bool otMacFrameDoesAddrMatch(const otRadioFrame *aFrame,

bool otMacFrameIsAck(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kFcfFrameAck;
return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kTypeAck;
}

bool otMacFrameIsData(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kFcfFrameData;
return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kTypeData;
}

bool otMacFrameIsCommand(const otRadioFrame *aFrame)
{
return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kFcfFrameMacCmd;
return static_cast<const Mac::Frame *>(aFrame)->GetType() == Mac::Frame::kTypeMacCmd;
}

bool otMacFrameIsDataRequest(const otRadioFrame *aFrame)
Expand Down
2 changes: 2 additions & 0 deletions src/core/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/core/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
36 changes: 36 additions & 0 deletions src/core/common/frame_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@

#include "frame_builder.hpp"

#include <string.h>

#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)
Expand Down Expand Up @@ -76,6 +86,31 @@ Error FrameBuilder::AppendBytes(const void *aBuffer, uint16_t aLength)
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;
Expand All @@ -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)
{
Expand Down
16 changes: 15 additions & 1 deletion src/core/common/frame_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -182,6 +183,18 @@ class FrameBuilder
*/
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`.
*
Expand All @@ -195,6 +208,7 @@ class FrameBuilder
*
*/
Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
#endif

/**
* This method appends an object to the `FrameBuilder`.
Expand Down
51 changes: 13 additions & 38 deletions src/core/mac/data_poll_sender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<MeshForwarder>().CalcIePresent(nullptr);

if (iePresent)
if (addresses.mDestination.IsExtended())
{
fcf |= Mac::Frame::kFcfIePresent;
}

fcf |= Get<MeshForwarder>().CalcFrameVersion(Get<NeighborTable>().FindNeighbor(dst), iePresent);

if (dst.IsExtended())
{
fcf |= Mac::Frame::kFcfDstAddrExt | Mac::Frame::kFcfSrcAddrExt;
src.SetExtended(Get<Mac::Mac>().GetExtAddress());
addresses.mSource.SetExtended(Get<Mac::Mac>().GetExtAddress());
}
else
{
fcf |= Mac::Frame::kFcfDstAddrShort | Mac::Frame::kFcfSrcAddrShort;
src.SetShort(Get<Mac::Mac>().GetShortAddress());
addresses.mSource.SetShort(Get<Mac::Mac>().GetShortAddress());
}

frame->InitMacHeader(fcf, Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32);
panIds.mSource = Get<Mac::Mac>().GetPanId();
panIds.mDestination = Get<Mac::Mac>().GetPanId();

if (frame->IsDstPanIdPresent())
{
frame->SetDstPanId(Get<Mac::Mac>().GetPanId());
}

frame->SetSrcAddr(src);
frame->SetDstAddr(dst);
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
if (iePresent)
{
Get<MeshForwarder>().AppendHeaderIe(nullptr, *frame);
}
Get<MeshForwarder>().PrepareMacHeaders(*frame, Mac::Frame::kTypeMacCmd, addresses, panIds,
Mac::Frame::kSecurityEncMic32, Mac::Frame::kKeyIdMode1, nullptr);

#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));
Expand Down
50 changes: 28 additions & 22 deletions src/core/mac/mac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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");
Expand All @@ -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;
Expand All @@ -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<Beacon *>(frame->GetPayload());
beacon->Init();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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());
Expand All @@ -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);
Expand Down Expand Up @@ -1941,19 +1947,19 @@ 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);
}

break;

case Frame::kFcfFrameBeacon:
case Frame::kTypeBeacon:
mCounters.mRxBeacon++;
break;

case Frame::kFcfFrameData:
case Frame::kTypeData:
mCounters.mRxData++;
break;

Expand Down
Loading

0 comments on commit fe1cf3a

Please sign in to comment.