[mac] check frame version for sequence number suppression (#13388)

In IEEE 802.15.4-2015, bit 8 of the Frame Control Field (FCF) was
introduced as the Sequence Number Suppression bit. In legacy frame
versions (IEEE 802.15.4-2003 and IEEE 802.15.4-2006), this bit was
reserved and has no defined meaning.

Previously, IsSequencePresent() checked whether bit 8 was cleared
without inspecting the frame version field. Consequently, if a legacy
frame was received with reserved bit 8 set to 1, it would be
incorrectly processed as having its sequence number suppressed,
leading to improper MAC frame parsing and handling.

This commit introduces IsSequenceSuppressed() to verify that the frame
version is IEEE 802.15.4-2015 before evaluating the Sequence Number
Suppression bit. For 2003 and 2006 frame versions, sequence suppression
is ignored and IsSequencePresent() unconditionally returns true. Unit
tests are also added to verify correct detection across all frame
versions.
This commit is contained in:
Jonathan Hui
2026-07-23 11:23:57 -07:00
committed by GitHub
parent 81ae4a4966
commit 3be32b5597
3 changed files with 38 additions and 5 deletions
+3 -3
View File
@@ -183,7 +183,7 @@ void TxFrame::BuildInfo::PrepareHeadersIn(TxFrame &aTxFrame) const
builder.Init(aTxFrame.mPsdu, aTxFrame.GetMtu());
IgnoreError(builder.AppendUint<kLittleEndian>(fcf));
if (IsSequencePresent(fcf))
if (!IsSequenceSuppressed(fcf))
{
builder.Append<uint8_t>(); // Place holder for seq number
}
@@ -305,7 +305,7 @@ uint8_t Frame::SkipSequenceIndex(void) const
uint16_t fcf = GetFrameControlField();
uint8_t index = kFcfSize;
if (IsSequencePresent(fcf))
if (!IsSequenceSuppressed(fcf))
{
index += kDsnSize;
}
@@ -906,7 +906,7 @@ exit:
uint8_t Frame::CalculateAddrFieldSize(uint16_t aFcf)
{
uint8_t size = kFcfSize + (IsSequencePresent(aFcf) ? kDsnSize : 0);
uint8_t size = kFcfSize + (IsSequenceSuppressed(aFcf) ? 0 : kDsnSize);
// This static method calculates the size (number of bytes) of
// Address header field for a given Frame Control `aFcf` value.
+5 -2
View File
@@ -281,7 +281,7 @@ public:
*
* @returns TRUE if the Sequence Number is present, FALSE otherwise.
*/
uint8_t IsSequencePresent(void) const { return IsSequencePresent(GetFrameControlField()); }
uint8_t IsSequencePresent(void) const { return !IsSequenceSuppressed(GetFrameControlField()); }
/**
* Indicates whether or not the Destination PAN ID is present.
@@ -677,7 +677,10 @@ protected:
static uint16_t GetFcfDstAddr(uint16_t aFcf) { return ReadBits<uint16_t, kFcfDstAddrMask>(aFcf); }
static uint16_t GetFcfSrcAddr(uint16_t aFcf) { return ReadBits<uint16_t, kFcfSrcAddrMask>(aFcf); }
static bool IsSequencePresent(uint16_t aFcf) { return (aFcf & kFcfSequenceSuppression) == 0; }
static bool IsSequenceSuppressed(uint16_t aFcf)
{
return IsVersion2015(aFcf) && ((aFcf & kFcfSequenceSuppression) != 0);
}
static bool IsDstAddrPresent(uint16_t aFcf) { return (aFcf & kFcfDstAddrMask) != 0; }
static bool IsSrcAddrPresent(uint16_t aFcf) { return (aFcf & kFcfSrcAddrMask) != 0; }
static bool IsSecurityEnabled(uint16_t aFcf) { return (aFcf & kFcfSecurityEnabled) != 0; }
+30
View File
@@ -752,6 +752,36 @@ void TestMacFrameApi(void)
printf("commandId:%d\n", commandId);
#endif
{
uint8_t psdu2003WithBit8[] = {0x00, 0x01, 0x11};
uint8_t psdu2006WithBit8[] = {0x00, 0x11, 0x22};
uint8_t psdu2015WithBit8[] = {0x00, 0x21, 0x33};
uint8_t psdu2015NoBit8[] = {0x00, 0x20, 0x44};
frame.mPsdu = psdu2003WithBit8;
frame.mLength = sizeof(psdu2003WithBit8);
VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2003);
VerifyOrQuit(frame.IsSequencePresent());
VerifyOrQuit(frame.GetSequence() == 0x11);
frame.mPsdu = psdu2006WithBit8;
frame.mLength = sizeof(psdu2006WithBit8);
VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2006);
VerifyOrQuit(frame.IsSequencePresent());
VerifyOrQuit(frame.GetSequence() == 0x22);
frame.mPsdu = psdu2015WithBit8;
frame.mLength = sizeof(psdu2015WithBit8);
VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2015);
VerifyOrQuit(!frame.IsSequencePresent());
frame.mPsdu = psdu2015NoBit8;
frame.mLength = sizeof(psdu2015NoBit8);
VerifyOrQuit(frame.GetVersion() == Mac::Frame::kVersion2015);
VerifyOrQuit(frame.IsSequencePresent());
VerifyOrQuit(frame.GetSequence() == 0x44);
}
}
void TestMacFrameAckGeneration(void)