[mac-frame] parse and store unpacked FCF/SCF fields in ParseInfo (#13534)

This commit refactors `Frame::ParseInfo` by replacing the raw `mFcf`
and `mSecCtl` control field members with parsed, typed fields and
boolean bit-flags, `mType`, `mVersion`, `mIsSecurityEnabled`,
`mIsFramePending`, etc.

This simplifies callers by allowing direct access to the parsed
properties without repeatedly calling static FCF decoding helper
functions.
This commit is contained in:
Abtin Keshavarzian
2026-08-20 19:03:10 -07:00
committed by GitHub
parent 7aeb1b18d3
commit a93706fde1
2 changed files with 58 additions and 41 deletions
+50 -38
View File
@@ -274,8 +274,9 @@ Error Frame::ParseInfo::ParseFrom(const Frame &aFrame, ParseMode aMode)
Error error = kErrorParse; Error error = kErrorParse;
FrameData frameData; FrameData frameData;
uint16_t value; uint16_t fcf;
uint8_t size; PanId panId;
uint8_t value;
VerifyOrExit(aFrame.GetPsdu() != nullptr); VerifyOrExit(aFrame.GetPsdu() != nullptr);
@@ -284,36 +285,47 @@ Error Frame::ParseInfo::ParseFrom(const Frame &aFrame, ParseMode aMode)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Address Fields // Address Fields
SuccessOrExit(frameData.ReadUint<kLittleEndian>(mFcf)); SuccessOrExit(frameData.ReadUint<kLittleEndian>(fcf));
// Only accept standard frame types (Beacon, Data, Ack, MAC Command). // Only accept standard frame types (Beacon, Data, Ack, MAC Command).
// Other types (e.g., Multipurpose) use a different FCF/header layout. // Other types (e.g., Multipurpose) use a different FCF/header layout.
// Also restrict frame version to 2003, 2006, 2015. Future frame // Also restrict frame version to 2003, 2006, 2015. Future frame
// versions can alter the MAC header layout. // versions can alter the MAC header layout.
VerifyOrExit(ReadType(mFcf) <= kTypeMacCmd); value = ReadType(fcf);
VerifyOrExit(ReadVersion(mFcf) <= kVersion2015); VerifyOrExit(value <= kTypeMacCmd);
mType = static_cast<Type>(value);
if (IsSeqPresent(mFcf)) value = ReadVersion(fcf);
VerifyOrExit(value <= kVersion2015);
mVersion = static_cast<Version>(value);
mIsSecurityEnabled = IsSecurityEnabled(fcf);
mIsFramePending = IsFramePending(fcf);
mIsAckRequest = IsAckRequest(fcf);
mIsSeqNumPresent = IsSeqPresent(fcf);
mIsIePresent = IsIePresent(fcf);
if (mIsSeqNumPresent)
{ {
SuccessOrExit(frameData.ReadUint8(mSequenceNum)); SuccessOrExit(frameData.ReadUint8(mSequenceNum));
} }
if (IsDstPanIdPresent(mFcf)) if (IsDstPanIdPresent(fcf))
{ {
SuccessOrExit(frameData.ReadUint<kLittleEndian>(value)); SuccessOrExit(frameData.ReadUint<kLittleEndian>(panId));
mPanIds.SetDestination(value); mPanIds.SetDestination(panId);
} }
SuccessOrExit(ParseAddress(frameData, ReadDstAddrMode(mFcf), mAddrs.mDestination)); SuccessOrExit(ParseAddress(frameData, ReadDstAddrMode(fcf), mAddrs.mDestination));
if (IsSrcPanIdPresent(mFcf)) if (IsSrcPanIdPresent(fcf))
{ {
SuccessOrExit(frameData.ReadUint<kLittleEndian>(value)); SuccessOrExit(frameData.ReadUint<kLittleEndian>(panId));
mPanIds.SetSource(value); mPanIds.SetSource(panId);
} }
SuccessOrExit(ParseAddress(frameData, ReadSrcAddrMode(mFcf), mAddrs.mSource)); SuccessOrExit(ParseAddress(frameData, ReadSrcAddrMode(fcf), mAddrs.mSource));
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// FCS // FCS
@@ -328,12 +340,15 @@ Error Frame::ParseInfo::ParseFrom(const Frame &aFrame, ParseMode aMode)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Aux Security Header // Aux Security Header
if (IsSecurityEnabled(mFcf)) if (mIsSecurityEnabled)
{ {
SuccessOrExit(frameData.ReadUint8(mSecCtl)); uint8_t scf;
uint8_t size;
mSecurityLevel = ReadSecurityLevel(mSecCtl); SuccessOrExit(frameData.ReadUint8(scf));
mKeyIdMode = ReadKeyIdMode(mSecCtl);
mSecurityLevel = ReadSecurityLevel(scf);
mKeyIdMode = ReadKeyIdMode(scf);
VerifyOrExit(mSecurityLevel != kSecurityNone); VerifyOrExit(mSecurityLevel != kSecurityNone);
@@ -358,14 +373,14 @@ Error Frame::ParseInfo::ParseFrom(const Frame &aFrame, ParseMode aMode)
if (aMode == kParseSecurityHeader) if (aMode == kParseSecurityHeader)
{ {
VerifyOrExit(IsSecurityEnabled(mFcf), error = kErrorNotFound); VerifyOrExit(mIsSecurityEnabled, error = kErrorNotFound);
ExitNow(error = kErrorNone); ExitNow(error = kErrorNone);
} }
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Header IE // Header IE
if (IsIePresent(mFcf)) if (mIsIePresent)
{ {
#if !OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT #if !OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
ExitNow(); ExitNow();
@@ -404,7 +419,7 @@ Error Frame::ParseInfo::ParseFrom(const Frame &aFrame, ParseMode aMode)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// MAC Command // MAC Command
if (ReadType(mFcf) == kTypeMacCmd) if (mType == kTypeMacCmd)
{ {
VerifyOrExit(frameData.CanRead(sizeof(mCommandId))); VerifyOrExit(frameData.CanRead(sizeof(mCommandId)));
@@ -415,7 +430,7 @@ Error Frame::ParseInfo::ParseFrom(const Frame &aFrame, ParseMode aMode)
// encrypted payload, while in earlier versions, it is part of // encrypted payload, while in earlier versions, it is part of
// the MAC header. // the MAC header.
if (!IsVersion2015(mFcf)) if (mVersion != kVersion2015)
{ {
frameData.SkipOver(sizeof(mCommandId)); frameData.SkipOver(sizeof(mCommandId));
} }
@@ -789,7 +804,7 @@ Error Frame::GetCommandId(uint8_t &aCommandId) const
ParseInfo info; ParseInfo info;
SuccessOrExit(error = info.ParseFrom(*this, kParseFully)); SuccessOrExit(error = info.ParseFrom(*this, kParseFully));
VerifyOrExit(ReadType(info.mFcf) == kTypeMacCmd, error = kErrorNotFound); VerifyOrExit(info.mType == kTypeMacCmd, error = kErrorNotFound);
aCommandId = info.mCommandId; aCommandId = info.mCommandId;
exit: exit:
@@ -901,7 +916,7 @@ const HeaderIe *Frame::FindHeaderIe(HeaderIeMatcher aMatcher) const
SuccessOrExit(info.ParseFrom(*this, kParseFully)); SuccessOrExit(info.ParseFrom(*this, kParseFully));
VerifyOrExit(IsIePresent(info.mFcf)); VerifyOrExit(info.mIsIePresent);
// `ParseFrom()` already validates that Header IE(s) are // `ParseFrom()` already validates that Header IE(s) are
// well-formed and contained within the frame. Here we // well-formed and contained within the frame. Here we
@@ -1098,9 +1113,9 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, con
SuccessOrExit(rxInfo.ParseFrom(aRxFrame, kParseFully)); SuccessOrExit(rxInfo.ParseFrom(aRxFrame, kParseFully));
VerifyOrExit(IsVersion2015(rxInfo.mFcf)); VerifyOrExit(rxInfo.mVersion == kVersion2015);
VerifyOrExit(IsAckRequest(rxInfo.mFcf)); VerifyOrExit(rxInfo.mIsAckRequest);
VerifyOrExit(IsSeqPresent(rxInfo.mFcf)); VerifyOrExit(rxInfo.mIsSeqNumPresent);
// Check `aRxFrame` has a valid destination address. The ack frame // Check `aRxFrame` has a valid destination address. The ack frame
// will not use this as its source though and will always use no // will not use this as its source though and will always use no
@@ -1114,7 +1129,7 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, con
buildInfo.mAddrs.mDestination = rxInfo.mAddrs.mSource; buildInfo.mAddrs.mDestination = rxInfo.mAddrs.mSource;
VerifyOrExit(!buildInfo.mAddrs.mDestination.IsNone()); VerifyOrExit(!buildInfo.mAddrs.mDestination.IsNone());
if (IsSecurityEnabled(rxInfo.mFcf)) if (rxInfo.mIsSecurityEnabled)
{ {
VerifyOrExit(rxInfo.mSecurityLevel == kSecurityEncMic32); VerifyOrExit(rxInfo.mSecurityLevel == kSecurityEncMic32);
VerifyOrExit(rxInfo.mKeyIdMode == kKeyIdMode1); VerifyOrExit(rxInfo.mKeyIdMode == kKeyIdMode1);
@@ -1144,7 +1159,7 @@ Error TxFrame::GenerateEnhAck(const RxFrame &aRxFrame, bool aIsFramePending, con
SetFramePending(aIsFramePending); SetFramePending(aIsFramePending);
SetSequence(rxInfo.mSequenceNum); SetSequence(rxInfo.mSequenceNum);
if (IsSecurityEnabled(rxInfo.mFcf)) if (rxInfo.mIsSecurityEnabled)
{ {
SetKeyIndex(rxInfo.mKeyIndex); SetKeyIndex(rxInfo.mKeyIndex);
} }
@@ -1233,7 +1248,6 @@ Frame::InfoString Frame::ToInfoString(void) const
{ {
InfoString string; InfoString string;
ParseInfo info; ParseInfo info;
uint8_t type;
string.Append("len:%u", mLength); string.Append("len:%u", mLength);
@@ -1243,16 +1257,14 @@ Frame::InfoString Frame::ToInfoString(void) const
ExitNow(); ExitNow();
} }
if (IsSeqPresent(info.mFcf)) if (info.mIsSeqNumPresent)
{ {
string.Append(", seqnum:%u", info.mSequenceNum); string.Append(", seqnum:%u", info.mSequenceNum);
} }
string.Append(", type:"); string.Append(", type:");
type = ReadType(info.mFcf); switch (info.mType)
switch (type)
{ {
case kTypeBeacon: case kTypeBeacon:
string.Append("Beacon"); string.Append("Beacon");
@@ -1285,15 +1297,15 @@ Frame::InfoString Frame::ToInfoString(void) const
break; break;
default: default:
string.Append("%u", type); string.Append("%u", info.mType);
break; break;
} }
string.Append(", src:%s, dst:%s, sec:%s, ackreq:%s", info.mAddrs.mSource.ToString().AsCString(), string.Append(", src:%s, dst:%s, sec:%s, ackreq:%s", info.mAddrs.mSource.ToString().AsCString(),
info.mAddrs.mDestination.ToString().AsCString(), ToYesNo(IsSecurityEnabled(info.mFcf)), info.mAddrs.mDestination.ToString().AsCString(), ToYesNo(info.mIsSecurityEnabled),
ToYesNo(IsAckRequest(info.mFcf))); ToYesNo(info.mIsAckRequest));
if (IsSecurityEnabled(info.mFcf)) if (info.mIsSecurityEnabled)
{ {
string.Append(", fc:%lu", ToUlong(info.mFrameCounter)); string.Append(", fc:%lu", ToUlong(info.mFrameCounter));
} }
+8 -3
View File
@@ -624,14 +624,19 @@ protected:
public: public:
// - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - -
// Mac Header Address Info // Mac Header Address Info
uint16_t mFcf; Type mType;
Version mVersion;
bool mIsSecurityEnabled : 1;
bool mIsFramePending : 1;
bool mIsAckRequest : 1;
bool mIsSeqNumPresent : 1;
bool mIsIePresent : 1;
uint8_t mSequenceNum;
PanIds mPanIds; PanIds mPanIds;
Addresses mAddrs; Addresses mAddrs;
uint8_t mSequenceNum;
// - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - -
// Aux Security Header // Aux Security Header
uint8_t mSecCtl;
SecurityLevel mSecurityLevel; SecurityLevel mSecurityLevel;
KeyIdMode mKeyIdMode; KeyIdMode mKeyIdMode;
uint8_t mKeyIndex; uint8_t mKeyIndex;