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