mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 09:27:47 +00:00
[mac] simplify and enhance Header IE processing (#13261)
This commit refactors `Mac::HeaderIe` generation and parsing to improve code readability, type safety, and bounds checking. Key changes include: - Adds `HeaderIe::GetSize()` and `HeaderIe::GetContent()` to encapsulate pointer arithmetic inside the class and eliminate ad-hoc pointer offset math across `Mac` modules. - Updates `Frame::FindPayloadIndex()`, `Frame::GetHeaderIe()`, `Frame::GetThreadIe()`, and `Frame::GetTimeIe()` to utilize the new helper methods, simplifying boundary checks. - Simplifies `HeaderIe::Init()` by replacing the union with a clearer `mLenIdType` field and updating the internal bitwise operations to use `bit_utils.hpp` helper methods.
This commit is contained in:
@@ -264,8 +264,7 @@ uint8_t otMacFrameGenerateCslIeTemplate(uint8_t *aDest)
|
||||
{
|
||||
assert(aDest != nullptr);
|
||||
|
||||
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::CslIe::kHeaderIeId);
|
||||
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(sizeof(Mac::CslIe));
|
||||
reinterpret_cast<Mac::HeaderIe *>(aDest)->Init(Mac::CslIe::kHeaderIeId, sizeof(Mac::CslIe));
|
||||
|
||||
return sizeof(Mac::HeaderIe) + sizeof(Mac::CslIe);
|
||||
}
|
||||
@@ -278,8 +277,7 @@ uint8_t otMacFrameGenerateEnhAckProbingIe(uint8_t *aDest, const uint8_t *aIeData
|
||||
|
||||
assert(aDest != nullptr);
|
||||
|
||||
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::ThreadIe::kHeaderIeId);
|
||||
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(len);
|
||||
reinterpret_cast<Mac::HeaderIe *>(aDest)->Init(Mac::ThreadIe::kHeaderIeId, len);
|
||||
|
||||
aDest += sizeof(Mac::HeaderIe);
|
||||
|
||||
|
||||
+12
-11
@@ -1081,12 +1081,13 @@ uint8_t Frame::FindPayloadIndex(void) const
|
||||
|
||||
do
|
||||
{
|
||||
const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
|
||||
const HeaderIe *ie;
|
||||
|
||||
index += sizeof(HeaderIe);
|
||||
VerifyOrExit(index + footerLength <= mLength, index = kInvalidIndex);
|
||||
VerifyOrExit(index + footerLength + sizeof(HeaderIe) <= mLength, index = kInvalidIndex);
|
||||
|
||||
ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
|
||||
index += ie->GetSize();
|
||||
|
||||
index += ie->GetLength();
|
||||
VerifyOrExit(index + footerLength <= mLength, index = kInvalidIndex);
|
||||
|
||||
if (ie->GetId() == Termination2Ie::kHeaderIeId)
|
||||
@@ -1173,7 +1174,7 @@ const uint8_t *Frame::GetHeaderIe(uint8_t aIeId) const
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
index += sizeof(HeaderIe) + ie->GetLength();
|
||||
index += ie->GetSize();
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -1198,8 +1199,8 @@ const uint8_t *Frame::GetThreadIe(uint8_t aSubType) const
|
||||
|
||||
if ((ie->GetId() == VendorIeHeader::kHeaderIeId) && (ie->GetLength() >= VendorIeHeader::kIeContentSize))
|
||||
{
|
||||
const VendorIeHeader *vendorIe =
|
||||
reinterpret_cast<const VendorIeHeader *>(reinterpret_cast<const uint8_t *>(ie) + sizeof(HeaderIe));
|
||||
const VendorIeHeader *vendorIe = reinterpret_cast<const VendorIeHeader *>(ie->GetContent());
|
||||
|
||||
if (vendorIe->GetVendorOui() == ThreadIe::kVendorOuiThreadCompanyId && vendorIe->GetSubType() == aSubType)
|
||||
{
|
||||
header = &mPsdu[index];
|
||||
@@ -1207,7 +1208,7 @@ const uint8_t *Frame::GetThreadIe(uint8_t aSubType) const
|
||||
}
|
||||
}
|
||||
|
||||
index += sizeof(HeaderIe) + ie->GetLength();
|
||||
index += ie->GetSize();
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -1278,8 +1279,8 @@ const TimeIe *Frame::GetTimeIe(void) const
|
||||
|
||||
if ((ie->GetId() == VendorIeHeader::kHeaderIeId) && (ie->GetLength() >= TimeIe::kIeContentSize))
|
||||
{
|
||||
const TimeIe *vendorIe =
|
||||
reinterpret_cast<const TimeIe *>(reinterpret_cast<const uint8_t *>(ie) + sizeof(HeaderIe));
|
||||
const TimeIe *vendorIe = reinterpret_cast<const TimeIe *>(ie->GetContent());
|
||||
|
||||
if (vendorIe->GetVendorOui() == TimeIe::kVendorOuiNest && vendorIe->GetSubType() == TimeIe::kVendorIeTime)
|
||||
{
|
||||
timeIe = vendorIe;
|
||||
@@ -1287,7 +1288,7 @@ const TimeIe *Frame::GetTimeIe(void) const
|
||||
}
|
||||
}
|
||||
|
||||
index += sizeof(HeaderIe) + ie->GetLength();
|
||||
index += ie->GetSize();
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
@@ -36,11 +36,11 @@
|
||||
namespace ot {
|
||||
namespace Mac {
|
||||
|
||||
void HeaderIe::Init(uint16_t aId, uint8_t aLen)
|
||||
void HeaderIe::Init(uint8_t aId, uint8_t aLen)
|
||||
{
|
||||
Init();
|
||||
SetId(aId);
|
||||
mLenIdType = 0;
|
||||
SetLength(aLen);
|
||||
SetId(aId);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/bit_utils.hpp"
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/numeric_limits.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
@@ -52,73 +53,73 @@ namespace Mac {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements IEEE 802.15.4 IE (Information Element) header generation and parsing.
|
||||
* Implements IEEE 802.15.4 IE (Information Element) generation and parsing.
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class HeaderIe
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes the Header IE.
|
||||
*/
|
||||
void Init(void) { mFields.m16 = 0; }
|
||||
|
||||
/**
|
||||
* Initializes the Header IE with Id and Length.
|
||||
* Initializes the Header IE with a given ID and Length.
|
||||
*
|
||||
* @param[in] aId The IE Element Id.
|
||||
* @param[in] aId The IE Element ID.
|
||||
* @param[in] aLen The IE content length.
|
||||
*/
|
||||
void Init(uint16_t aId, uint8_t aLen);
|
||||
void Init(uint8_t aId, uint8_t aLen);
|
||||
|
||||
/**
|
||||
* Returns the IE Element Id.
|
||||
* Returns the IE Element ID.
|
||||
*
|
||||
* @returns the IE Element Id.
|
||||
* @returns the IE Element ID.
|
||||
*/
|
||||
uint16_t GetId(void) const { return ReadBitsLittleEndian<uint16_t, kIdMask>(mFields.m16); }
|
||||
|
||||
/**
|
||||
* Sets the IE Element Id.
|
||||
*
|
||||
* @param[in] aId The IE Element Id.
|
||||
*/
|
||||
void SetId(uint16_t aId) { mFields.m16 = UpdateBitsLittleEndian<uint16_t, kIdMask>(mFields.m16, aId); }
|
||||
uint8_t GetId(void) const { return static_cast<uint8_t>(ReadBitsLittleEndian<uint16_t, kIdMask>(mLenIdType)); }
|
||||
|
||||
/**
|
||||
* Returns the IE content length.
|
||||
*
|
||||
* @returns the IE content length.
|
||||
*/
|
||||
uint8_t GetLength(void) const { return ReadBits<uint8_t, kLengthMask>(mFields.m8[0]); }
|
||||
uint8_t GetLength(void) const { return static_cast<uint8_t>(ReadBitsLittleEndian<uint16_t, kLenMask>(mLenIdType)); }
|
||||
|
||||
/**
|
||||
* Sets the IE content length.
|
||||
* Returns the total size of the Header IE (descriptor header plus content length) in bytes.
|
||||
*
|
||||
* @param[in] aLength The IE content length.
|
||||
* @note The total size fits in a `uint8_t` since the content length is limited to 7 bits (max 127 bytes).
|
||||
*
|
||||
* @returns The total size of the Header IE in bytes.
|
||||
*/
|
||||
void SetLength(uint8_t aLength) { WriteBits<uint8_t, kLengthMask>(mFields.m8[0], aLength); }
|
||||
uint8_t GetSize(void) const { return GetLength() + sizeof(HeaderIe); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the IE content bytes.
|
||||
*
|
||||
* @returns A pointer to the IE content bytes.
|
||||
*/
|
||||
const uint8_t *GetContent(void) const { return GetBytes() + sizeof(HeaderIe); }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the IE content bytes.
|
||||
*
|
||||
* @returns A pointer to the IE content bytes.
|
||||
*/
|
||||
uint8_t *GetContent(void) { return AsNonConst(AsConst(this)->GetContent()); }
|
||||
|
||||
private:
|
||||
// Header IE format:
|
||||
// IEEE 802.15.4 Header IE descriptor (2 bytes, little-endian):
|
||||
//
|
||||
// +-----------+------------+--------+
|
||||
// | Bits: 0-6 | 7-14 | 15 |
|
||||
// +-----------+------------+--------+
|
||||
// | Length | Element ID | Type=0 |
|
||||
// +-----------+------------+--------+
|
||||
// Bits 0-6 (7 bits) : Length of IE content in bytes (max 127).
|
||||
// Bits 7-14 (8 bits) : Element ID.
|
||||
// Bit 15 (1 bit) : Type (0 for Header IE).
|
||||
|
||||
static constexpr uint8_t kSize = 2;
|
||||
static constexpr uint8_t kIdOffset = 7;
|
||||
static constexpr uint8_t kLengthMask = 0x7f;
|
||||
static constexpr uint16_t kIdMask = 0x00ff << kIdOffset;
|
||||
static constexpr uint16_t kLenMask = 0x007f << 0;
|
||||
static constexpr uint16_t kIdMask = 0x00ff << 7;
|
||||
|
||||
union OT_TOOL_PACKED_FIELD
|
||||
{
|
||||
uint8_t m8[kSize];
|
||||
uint16_t m16;
|
||||
} mFields;
|
||||
void SetId(uint8_t aId) { mLenIdType = UpdateBitsLittleEndian<uint16_t, kIdMask>(mLenIdType, aId); }
|
||||
void SetLength(uint8_t aLength) { mLenIdType = UpdateBitsLittleEndian<uint16_t, kLenMask>(mLenIdType, aLength); }
|
||||
|
||||
const uint8_t *GetBytes(void) const { return reinterpret_cast<const uint8_t *>(this); }
|
||||
|
||||
uint16_t mLenIdType;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user