Skip to content

Commit 4394c09

Browse files
authored
[mac] simplify and enhance Header IE processing (openthread#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.
1 parent 5f9fe67 commit 4394c09

4 files changed

Lines changed: 54 additions & 54 deletions

File tree

examples/platforms/utils/mac_frame.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,7 @@ uint8_t otMacFrameGenerateCslIeTemplate(uint8_t *aDest)
264264
{
265265
assert(aDest != nullptr);
266266

267-
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::CslIe::kHeaderIeId);
268-
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(sizeof(Mac::CslIe));
267+
reinterpret_cast<Mac::HeaderIe *>(aDest)->Init(Mac::CslIe::kHeaderIeId, sizeof(Mac::CslIe));
269268

270269
return sizeof(Mac::HeaderIe) + sizeof(Mac::CslIe);
271270
}
@@ -278,8 +277,7 @@ uint8_t otMacFrameGenerateEnhAckProbingIe(uint8_t *aDest, const uint8_t *aIeData
278277

279278
assert(aDest != nullptr);
280279

281-
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::ThreadIe::kHeaderIeId);
282-
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(len);
280+
reinterpret_cast<Mac::HeaderIe *>(aDest)->Init(Mac::ThreadIe::kHeaderIeId, len);
283281

284282
aDest += sizeof(Mac::HeaderIe);
285283

src/core/mac/mac_frame.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,12 +1081,13 @@ uint8_t Frame::FindPayloadIndex(void) const
10811081

10821082
do
10831083
{
1084-
const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
1084+
const HeaderIe *ie;
10851085

1086-
index += sizeof(HeaderIe);
1087-
VerifyOrExit(index + footerLength <= mLength, index = kInvalidIndex);
1086+
VerifyOrExit(index + footerLength + sizeof(HeaderIe) <= mLength, index = kInvalidIndex);
1087+
1088+
ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
1089+
index += ie->GetSize();
10881090

1089-
index += ie->GetLength();
10901091
VerifyOrExit(index + footerLength <= mLength, index = kInvalidIndex);
10911092

10921093
if (ie->GetId() == Termination2Ie::kHeaderIeId)
@@ -1173,7 +1174,7 @@ const uint8_t *Frame::GetHeaderIe(uint8_t aIeId) const
11731174
ExitNow();
11741175
}
11751176

1176-
index += sizeof(HeaderIe) + ie->GetLength();
1177+
index += ie->GetSize();
11771178
}
11781179

11791180
exit:
@@ -1198,16 +1199,16 @@ const uint8_t *Frame::GetThreadIe(uint8_t aSubType) const
11981199

11991200
if ((ie->GetId() == VendorIeHeader::kHeaderIeId) && (ie->GetLength() >= VendorIeHeader::kIeContentSize))
12001201
{
1201-
const VendorIeHeader *vendorIe =
1202-
reinterpret_cast<const VendorIeHeader *>(reinterpret_cast<const uint8_t *>(ie) + sizeof(HeaderIe));
1202+
const VendorIeHeader *vendorIe = reinterpret_cast<const VendorIeHeader *>(ie->GetContent());
1203+
12031204
if (vendorIe->GetVendorOui() == ThreadIe::kVendorOuiThreadCompanyId && vendorIe->GetSubType() == aSubType)
12041205
{
12051206
header = &mPsdu[index];
12061207
ExitNow();
12071208
}
12081209
}
12091210

1210-
index += sizeof(HeaderIe) + ie->GetLength();
1211+
index += ie->GetSize();
12111212
}
12121213

12131214
exit:
@@ -1278,16 +1279,16 @@ const TimeIe *Frame::GetTimeIe(void) const
12781279

12791280
if ((ie->GetId() == VendorIeHeader::kHeaderIeId) && (ie->GetLength() >= TimeIe::kIeContentSize))
12801281
{
1281-
const TimeIe *vendorIe =
1282-
reinterpret_cast<const TimeIe *>(reinterpret_cast<const uint8_t *>(ie) + sizeof(HeaderIe));
1282+
const TimeIe *vendorIe = reinterpret_cast<const TimeIe *>(ie->GetContent());
1283+
12831284
if (vendorIe->GetVendorOui() == TimeIe::kVendorOuiNest && vendorIe->GetSubType() == TimeIe::kVendorIeTime)
12841285
{
12851286
timeIe = vendorIe;
12861287
ExitNow();
12871288
}
12881289
}
12891290

1290-
index += sizeof(HeaderIe) + ie->GetLength();
1291+
index += ie->GetSize();
12911292
}
12921293

12931294
exit:

src/core/mac/mac_header_ie.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@
3636
namespace ot {
3737
namespace Mac {
3838

39-
void HeaderIe::Init(uint16_t aId, uint8_t aLen)
39+
void HeaderIe::Init(uint8_t aId, uint8_t aLen)
4040
{
41-
Init();
42-
SetId(aId);
41+
mLenIdType = 0;
4342
SetLength(aLen);
43+
SetId(aId);
4444
}
4545

4646
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE

src/core/mac/mac_header_ie.hpp

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
#include "common/as_core_type.hpp"
4040
#include "common/bit_utils.hpp"
41+
#include "common/const_cast.hpp"
4142
#include "common/encoding.hpp"
4243
#include "common/numeric_limits.hpp"
4344
#include "mac/mac_types.hpp"
@@ -52,73 +53,73 @@ namespace Mac {
5253
*/
5354

5455
/**
55-
* Implements IEEE 802.15.4 IE (Information Element) header generation and parsing.
56+
* Implements IEEE 802.15.4 IE (Information Element) generation and parsing.
5657
*/
5758
OT_TOOL_PACKED_BEGIN
5859
class HeaderIe
5960
{
6061
public:
6162
/**
62-
* Initializes the Header IE.
63+
* Initializes the Header IE with a given ID and Length.
64+
*
65+
* @param[in] aId The IE Element ID.
66+
* @param[in] aLen The IE content length.
6367
*/
64-
void Init(void) { mFields.m16 = 0; }
68+
void Init(uint8_t aId, uint8_t aLen);
6569

6670
/**
67-
* Initializes the Header IE with Id and Length.
71+
* Returns the IE Element ID.
6872
*
69-
* @param[in] aId The IE Element Id.
70-
* @param[in] aLen The IE content length.
73+
* @returns the IE Element ID.
7174
*/
72-
void Init(uint16_t aId, uint8_t aLen);
75+
uint8_t GetId(void) const { return static_cast<uint8_t>(ReadBitsLittleEndian<uint16_t, kIdMask>(mLenIdType)); }
7376

7477
/**
75-
* Returns the IE Element Id.
78+
* Returns the IE content length.
7679
*
77-
* @returns the IE Element Id.
80+
* @returns the IE content length.
7881
*/
79-
uint16_t GetId(void) const { return ReadBitsLittleEndian<uint16_t, kIdMask>(mFields.m16); }
82+
uint8_t GetLength(void) const { return static_cast<uint8_t>(ReadBitsLittleEndian<uint16_t, kLenMask>(mLenIdType)); }
8083

8184
/**
82-
* Sets the IE Element Id.
85+
* Returns the total size of the Header IE (descriptor header plus content length) in bytes.
86+
*
87+
* @note The total size fits in a `uint8_t` since the content length is limited to 7 bits (max 127 bytes).
8388
*
84-
* @param[in] aId The IE Element Id.
89+
* @returns The total size of the Header IE in bytes.
8590
*/
86-
void SetId(uint16_t aId) { mFields.m16 = UpdateBitsLittleEndian<uint16_t, kIdMask>(mFields.m16, aId); }
91+
uint8_t GetSize(void) const { return GetLength() + sizeof(HeaderIe); }
8792

8893
/**
89-
* Returns the IE content length.
94+
* Returns a pointer to the IE content bytes.
9095
*
91-
* @returns the IE content length.
96+
* @returns A pointer to the IE content bytes.
9297
*/
93-
uint8_t GetLength(void) const { return ReadBits<uint8_t, kLengthMask>(mFields.m8[0]); }
98+
const uint8_t *GetContent(void) const { return GetBytes() + sizeof(HeaderIe); }
9499

95100
/**
96-
* Sets the IE content length.
101+
* Returns a pointer to the IE content bytes.
97102
*
98-
* @param[in] aLength The IE content length.
103+
* @returns A pointer to the IE content bytes.
99104
*/
100-
void SetLength(uint8_t aLength) { WriteBits<uint8_t, kLengthMask>(mFields.m8[0], aLength); }
105+
uint8_t *GetContent(void) { return AsNonConst(AsConst(this)->GetContent()); }
101106

102107
private:
103-
// Header IE format:
108+
// IEEE 802.15.4 Header IE descriptor (2 bytes, little-endian):
104109
//
105-
// +-----------+------------+--------+
106-
// | Bits: 0-6 | 7-14 | 15 |
107-
// +-----------+------------+--------+
108-
// | Length | Element ID | Type=0 |
109-
// +-----------+------------+--------+
110-
111-
static constexpr uint8_t kSize = 2;
112-
static constexpr uint8_t kIdOffset = 7;
113-
static constexpr uint8_t kLengthMask = 0x7f;
114-
static constexpr uint16_t kIdMask = 0x00ff << kIdOffset;
115-
116-
union OT_TOOL_PACKED_FIELD
117-
{
118-
uint8_t m8[kSize];
119-
uint16_t m16;
120-
} mFields;
110+
// Bits 0-6 (7 bits) : Length of IE content in bytes (max 127).
111+
// Bits 7-14 (8 bits) : Element ID.
112+
// Bit 15 (1 bit) : Type (0 for Header IE).
113+
114+
static constexpr uint16_t kLenMask = 0x007f << 0;
115+
static constexpr uint16_t kIdMask = 0x00ff << 7;
116+
117+
void SetId(uint8_t aId) { mLenIdType = UpdateBitsLittleEndian<uint16_t, kIdMask>(mLenIdType, aId); }
118+
void SetLength(uint8_t aLength) { mLenIdType = UpdateBitsLittleEndian<uint16_t, kLenMask>(mLenIdType, aLength); }
119+
120+
const uint8_t *GetBytes(void) const { return reinterpret_cast<const uint8_t *>(this); }
121121

122+
uint16_t mLenIdType;
122123
} OT_TOOL_PACKED_END;
123124

124125
/**

0 commit comments

Comments
 (0)