Skip to content

Commit

Permalink
[mac-frame] update InitMacFrame() (openthread#9337)
Browse files Browse the repository at this point in the history
This commit updates the `InitMacFrame()` method to allow the caller to
specify whether the source or destination PAN IDs are present or not.
It also handles all cases related to PAN ID compression as defined by
IEEE 802.15.4-2015. While these cases are not used by the Thread
stack itself, adding them to `InitMacFrame()` makes it more capable
allowing future use-cases of this method such as generating enhanced
ACKs based on a received frame.

The `test_mac_frame` unit test has been updated to cover the newly
added cases.
  • Loading branch information
abtink authored Aug 14, 2023
1 parent b03022b commit 4639dc6
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 89 deletions.
3 changes: 1 addition & 2 deletions src/core/mac/data_poll_sender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,8 +577,7 @@ Mac::TxFrame *DataPollSender::PrepareDataRequest(Mac::TxFrames &aTxFrames)
addresses.mSource.SetShort(Get<Mac::Mac>().GetShortAddress());
}

panIds.mSource = Get<Mac::Mac>().GetPanId();
panIds.mDestination = Get<Mac::Mac>().GetPanId();
panIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());

Get<MeshForwarder>().PrepareMacHeaders(*frame, Mac::Frame::kTypeMacCmd, addresses, panIds,
Mac::Frame::kSecurityEncMic32, Mac::Frame::kKeyIdMode1, nullptr);
Expand Down
4 changes: 2 additions & 2 deletions src/core/mac/mac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ TxFrame *Mac::PrepareBeaconRequest(void)

addrs.mSource.SetNone();
addrs.mDestination.SetShort(kShortAddrBroadcast);
panIds.mDestination = kShortAddrBroadcast;
panIds.SetDestination(kShortAddrBroadcast);

frame.InitMacHeader(Frame::kTypeMacCmd, Frame::kVersion2003, addrs, panIds, Frame::kSecurityNone);

Expand Down Expand Up @@ -769,7 +769,7 @@ TxFrame *Mac::PrepareBeacon(void)
#endif

addrs.mSource.SetExtended(GetExtAddress());
panIds.mSource = mPanId;
panIds.SetSource(mPanId);
addrs.mDestination.SetNone();

frame->InitMacHeader(Frame::kTypeBeacon, Frame::kVersion2003, addrs, panIds, Frame::kSecurityNone);
Expand Down
169 changes: 142 additions & 27 deletions src/core/mac/mac_frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,34 +98,105 @@ void Frame::InitMacHeader(Type aType,
break;
}

if (aType == kTypeAck)
{
fcf &= ~kFcfAckRequest;
}

fcf |= (aSecurityLevel != kSecurityNone) ? kFcfSecurityEnabled : 0;

// When we have both source and destination addresses we check PAN
// IDs to determine whether to include `kFcfPanidCompression`.
// PAN ID compression

if (!aAddrs.mSource.IsNone() && !aAddrs.mDestination.IsNone() && (aPanIds.mSource == aPanIds.mDestination))
switch (aVersion)
{
switch (aVersion)
case kVersion2003:
case kVersion2006:

// For 2003-2006 versions:
//
// - If only either the destination or the source addressing information is present,
// the PAN ID Compression field shall be set to zero, and the PAN ID field of the
// single address shall be included in the transmitted frame.
// - If both destination and source addressing information is present, the MAC shall
// compare the destination and source PAN identifiers. If the PAN IDs are identical,
// the PAN ID Compression field shall be set to one, and the Source PAN ID field
// shall be omitted from the transmitted frame. If the PAN IDs are different, the
// PAN ID Compression field shall be set to zero, and both Destination PAN ID
// field and Source PAN ID fields shall be included in the transmitted frame.

if (!aAddrs.mSource.IsNone() && !aAddrs.mDestination.IsNone() &&
(aPanIds.GetSource() == aPanIds.GetDestination()))
{
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())
fcf |= kFcfPanidCompression;
}
break;

case kVersion2015:
// +----+--------------+--------------+--------------+--------------+--------------+
// | No | Dest Addr | Src Addr | Dst PAN ID | Src PAN ID | PAN ID Comp |
// +----+--------------+--------------+--------------+--------------+--------------+
// | 1 | Not Present | Not Present | Not Present | Not Present | 0 |
// | 2 | Not Present | Not Present | Present | Not Present | 1 |
// | 3 | Present | Not Present | Present | Not Present | 0 |
// | 4 | Present | Not Present | Not Present | Not Present | 1 |
// | 5 | Not Present | Present | Not Present | Present | 0 |
// | 6 | Not Present | Present | Not Present | Not Present | 1 |
// +----+--------------+--------------+--------------+--------------+--------------+
// | 7 | Extended | Extended | Present | Not Present | 0 |
// | 8 | Extended | Extended | Not Present | Not Present | 1 |
// |----+--------------+--------------+--------------+--------------+--------------+
// | 9 | Short | Short | Present | Present | 0 |
// | 10 | Short | Extended | Present | Present | 0 |
// | 11 | Extended | Short | Present | Present | 0 |
// | 12 | Short | Extended | Present | Not Present | 1 |
// | 13 | Extended | Short | Present | Not Present | 1 |
// | 14 | Short | Short | Present | Not Present | 1 |
// +----+--------------+--------------+--------------+--------------+--------------+

if (aAddrs.mDestination.IsNone())
{
// Dst addr not present - rows 1,2,5,6.

if ((aAddrs.mSource.IsNone() && aPanIds.IsDestinationPresent()) || // Row 2.
(!aAddrs.mSource.IsNone() && !aPanIds.IsDestinationPresent() && !aPanIds.IsSourcePresent())) // Row 6.
{
break;
fcf |= kFcfPanidCompression;
}

OT_FALL_THROUGH;
break;
}

if (aAddrs.mSource.IsNone())
{
// Dst addr present, Src addr not present - rows 3,4.

if (!aPanIds.IsDestinationPresent()) // Row 4.
{
fcf |= kFcfPanidCompression;
}

case kVersion2003:
case kVersion2006:
fcf |= kFcfPanidCompression;
break;
}

// Both addresses are present - rows 7 to 14.

if (aAddrs.mSource.IsExtended() && aAddrs.mDestination.IsExtended())
{
// Both addresses are extended - rows 7,8.

if (aPanIds.IsDestinationPresent()) // Row 7.
{
break;
}
}
else if (aPanIds.GetSource() != aPanIds.GetDestination()) // Rows 9-14.
{
break;
}

fcf |= kFcfPanidCompression;

break;
}

builder.Init(mPsdu, GetMtu());
Expand All @@ -134,14 +205,14 @@ void Frame::InitMacHeader(Type aType,

if (IsDstPanIdPresent(fcf))
{
IgnoreError(builder.AppendLittleEndianUint16(aPanIds.mDestination));
IgnoreError(builder.AppendLittleEndianUint16(aPanIds.GetDestination()));
}

IgnoreError(builder.AppendMacAddress(aAddrs.mDestination));

if (IsSrcPanIdPresent(fcf))
{
IgnoreError(builder.AppendLittleEndianUint16(aPanIds.mSource));
IgnoreError(builder.AppendLittleEndianUint16(aPanIds.GetSource()));
}

IgnoreError(builder.AppendMacAddress(aAddrs.mSource));
Expand Down Expand Up @@ -222,16 +293,39 @@ bool Frame::IsDstPanIdPresent(uint16_t aFcf)

if (IsVersion2015(aFcf))
{
// Original table at `InitMacHeader()`
//
// +----+--------------+--------------+--------------++--------------+
// | No | Dest Addr | Src Addr | PAN ID Comp || Dst PAN ID |
// +----+--------------+--------------+--------------++--------------+
// | 1 | Not Present | Not Present | 0 || Not Present |
// | 2 | Not Present | Not Present | 1 || Present |
// | 3 | Present | Not Present | 0 || Present |
// | 4 | Present | Not Present | 1 || Not Present |
// | 5 | Not Present | Present | 0 || Not Present |
// | 6 | Not Present | Present | 1 || Not Present |
// +----+--------------+--------------+--------------++--------------+
// | 7 | Extended | Extended | 0 || Present |
// | 8 | Extended | Extended | 1 || Not Present |
// |----+--------------+--------------+--------------++--------------+
// | 9 | Short | Short | 0 || Present |
// | 10 | Short | Extended | 0 || Present |
// | 11 | Extended | Short | 0 || Present |
// | 12 | Short | Extended | 1 || Present |
// | 13 | Extended | Short | 1 || Present |
// | 14 | Short | Short | 1 || Present |
// +----+--------------+--------------+--------------++--------------+

switch (aFcf & (kFcfDstAddrMask | kFcfSrcAddrMask | kFcfPanidCompression))
{
case (kFcfDstAddrNone | kFcfSrcAddrNone):
case (kFcfDstAddrExt | kFcfSrcAddrNone | kFcfPanidCompression):
case (kFcfDstAddrShort | kFcfSrcAddrNone | kFcfPanidCompression):
case (kFcfDstAddrNone | kFcfSrcAddrExt):
case (kFcfDstAddrNone | kFcfSrcAddrShort):
case (kFcfDstAddrNone | kFcfSrcAddrExt | kFcfPanidCompression):
case (kFcfDstAddrNone | kFcfSrcAddrShort | kFcfPanidCompression):
case (kFcfDstAddrExt | kFcfSrcAddrExt | kFcfPanidCompression):
case (kFcfDstAddrNone | kFcfSrcAddrNone): // 1
case (kFcfDstAddrShort | kFcfSrcAddrNone | kFcfPanidCompression): // 4 (short dst)
case (kFcfDstAddrExt | kFcfSrcAddrNone | kFcfPanidCompression): // 4 (ext dst)
case (kFcfDstAddrNone | kFcfSrcAddrShort): // 5 (short src)
case (kFcfDstAddrNone | kFcfSrcAddrExt): // 5 (ext src)
case (kFcfDstAddrNone | kFcfSrcAddrShort | kFcfPanidCompression): // 6 (short src)
case (kFcfDstAddrNone | kFcfSrcAddrExt | kFcfPanidCompression): // 6 (ext src)
case (kFcfDstAddrExt | kFcfSrcAddrExt | kFcfPanidCompression): // 8
present = false;
break;
default:
Expand Down Expand Up @@ -367,6 +461,27 @@ bool Frame::IsSrcPanIdPresent(uint16_t aFcf)
// 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.
//
// +----+--------------+--------------+--------------++--------------+
// | No | Dest Addr | Src Addr | PAN ID Comp || Src PAN ID |
// +----+--------------+--------------+--------------++--------------+
// | 1 | Not Present | Not Present | 0 || Not Present |
// | 2 | Not Present | Not Present | 1 || Not Present |
// | 3 | Present | Not Present | 0 || Not Present |
// | 4 | Present | Not Present | 1 || Not Present |
// | 5 | Not Present | Present | 0 || Present |
// | 6 | Not Present | Present | 1 || Not Present |
// +----+--------------+--------------+--------------++--------------+
// | 7 | Extended | Extended | 0 || Not Present |
// | 8 | Extended | Extended | 1 || Not Present |
// |----+--------------+--------------+--------------++--------------+
// | 9 | Short | Short | 0 || Present |
// | 10 | Short | Extended | 0 || Present |
// | 11 | Extended | Short | 0 || Present |
// | 12 | Short | Extended | 1 || Not Present |
// | 13 | Extended | Short | 1 || Not Present |
// | 14 | Short | Short | 1 || Not Present |
// +----+--------------+--------------+--------------++--------------+

if (IsVersion2015(aFcf) && ((aFcf & (kFcfDstAddrMask | kFcfSrcAddrMask)) == (kFcfDstAddrExt | kFcfSrcAddrExt)))
{
Expand Down
4 changes: 2 additions & 2 deletions src/core/mac/mac_frame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,8 @@ class Frame : public otRadioFrame
* 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.
* The Ack Request bit in FCF is set if there is destination and it is not broadcast and frame type @p aType is not
* ACK. The Frame Pending and IE Present bits are not set.
*
* @param[in] aType Frame type.
* @param[in] aVerion Frame version.
Expand Down
18 changes: 18 additions & 0 deletions src/core/mac/mac_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,24 @@ Address::InfoString Address::ToString(void) const
return string;
}

void PanIds::SetSource(PanId aPanId)
{
mSource = aPanId;
mIsSourcePresent = true;
}

void PanIds::SetDestination(PanId aPanId)
{
mDestination = aPanId;
mIsDestinationPresent = true;
}

void PanIds::SetBothSourceDestination(PanId aPanId)
{
SetSource(aPanId);
SetDestination(aPanId);
}

#if OPENTHREAD_CONFIG_MULTI_RADIO

const RadioType RadioTypes::kAllRadioTypes[kNumRadioTypes] = {
Expand Down
74 changes: 71 additions & 3 deletions src/core/mac/mac_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,78 @@ struct Addresses
* Represents two PAN IDs corresponding to source and destination.
*
*/
struct PanIds
class PanIds : public Clearable<PanIds>
{
PanId mSource; ///< Source PAN ID.
PanId mDestination; ///< Destination PAN ID.
public:
/**
* Initializes PAN IDs as empty (no source or destination PAN ID).
*
*/
PanIds(void) { Clear(); }

/**
* Indicates whether or not source PAN ID is present.
*
* @retval TRUE The source PAN ID is present.
* @retval FALSE The source PAN ID is not present.
*
*/
bool IsSourcePresent(void) const { return mIsSourcePresent; }

/**
* Gets the source PAN ID when it is present.
*
* @returns The source PAN ID.
*
*/
PanId GetSource(void) const { return mSource; }

/**
* Indicates whether or not destination PAN ID is present.
*
* @retval TRUE The destination PAN ID is present.
* @retval FALSE The destination PAN ID is not present.
*
*/
bool IsDestinationPresent(void) const { return mIsDestinationPresent; }

/**
* Gets the destination PAN ID when it is present.
*
* @returns The destination PAN ID.
*
*/
PanId GetDestination(void) const { return mDestination; }

/**
* Sets the source PAN ID.
*
* @param[in] aPanId The source PAN ID.
*
*/
void SetSource(PanId aPanId);

/**
* Sets the destination PAN ID.
*
* @param[in] aPanId The source PAN ID.
*
*/
void SetDestination(PanId aPanId);

/**
* Sets both source and destination PAN IDs to the same value.
*
* @param[in] aPanId The PAN ID.
*
*/
void SetBothSourceDestination(PanId aPanId);

private:
PanId mSource;
PanId mDestination;
bool mIsSourcePresent;
bool mIsDestinationPresent;
};

/**
Expand Down
10 changes: 4 additions & 6 deletions src/core/thread/mesh_forwarder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,7 @@ void MeshForwarder::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &
}

addresses.mDestination = aMacDest;
panIds.mSource = Get<Mac::Mac>().GetPanId();
panIds.mDestination = Get<Mac::Mac>().GetPanId();
panIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());

PrepareMacHeaders(aFrame, Mac::Frame::kTypeData, addresses, panIds, Mac::Frame::kSecurityEncMic32,
Mac::Frame::kKeyIdMode1, nullptr);
Expand Down Expand Up @@ -926,20 +925,19 @@ uint16_t MeshForwarder::PrepareDataFrame(Mac::TxFrame &aFrame,
}
}

panIds.mSource = Get<Mac::Mac>().GetPanId();
panIds.mDestination = Get<Mac::Mac>().GetPanId();
panIds.SetBothSourceDestination(Get<Mac::Mac>().GetPanId());

switch (aMessage.GetSubType())
{
case Message::kSubTypeMleAnnounce:
aFrame.SetChannel(aMessage.GetChannel());
aFrame.SetRxChannelAfterTxDone(Get<Mac::Mac>().GetPanChannel());
panIds.mDestination = Mac::kPanIdBroadcast;
panIds.SetDestination(Mac::kPanIdBroadcast);
break;

case Message::kSubTypeMleDiscoverRequest:
case Message::kSubTypeMleDiscoverResponse:
panIds.mDestination = aMessage.GetPanId();
panIds.SetDestination(aMessage.GetPanId());
break;

default:
Expand Down
Loading

0 comments on commit 4639dc6

Please sign in to comment.