From 26d1a35b8605f7b388ed4d51fc29bbd0a97b3aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20L=C3=B3pez?= Date: Fri, 11 Sep 2026 06:05:46 +0200 Subject: [PATCH] ieee80211: preserve all 12 bits of the A-MPDU delimiter length The MPDU subframe decoder discarded the high length nibble and overwrote the length with its low byte, decoding 0xABC as 0xBC. Combine both parts before setting the field to restore symmetry with the encoder. Add registered-serializer round trips at 0, 255, 256, 0xABC, and 4095 plus a fixed-byte decoding case. Assert decoded fields using fresh byte-backed packets so cached serialized bytes cannot mask the defect. --- .../mac/Ieee80211MacHeaderSerializer.cc | 7 +++- ...ee80211MpduSubframeHeaderSerializer_1.test | 42 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/unit/Ieee80211MpduSubframeHeaderSerializer_1.test diff --git a/src/inet/linklayer/ieee80211/mac/Ieee80211MacHeaderSerializer.cc b/src/inet/linklayer/ieee80211/mac/Ieee80211MacHeaderSerializer.cc index d6c90abeb3c..fab687ca125 100644 --- a/src/inet/linklayer/ieee80211/mac/Ieee80211MacHeaderSerializer.cc +++ b/src/inet/linklayer/ieee80211/mac/Ieee80211MacHeaderSerializer.cc @@ -137,8 +137,11 @@ const Ptr Ieee80211MpduSubframeHeaderSerializer::deserializeFields(Memory { auto mpduSubframe = makeShared(); stream.readUint4(); - mpduSubframe->setLength(stream.readUint4() >> 8); - mpduSubframe->setLength(stream.readUint8()); + // IEEE Std 802.11-2024, 9.7.1, Table 9-659 and Figure 9-1330: + // in an HT PPDU, MPDU Length Low is 12 bits and MPDU Length High is reserved. + int length = stream.readUint4() << 8; + length |= stream.readUint8(); + mpduSubframe->setLength(length); stream.readByte(); stream.readByte(); return mpduSubframe; diff --git a/tests/unit/Ieee80211MpduSubframeHeaderSerializer_1.test b/tests/unit/Ieee80211MpduSubframeHeaderSerializer_1.test new file mode 100644 index 00000000000..601e4c45f3d --- /dev/null +++ b/tests/unit/Ieee80211MpduSubframeHeaderSerializer_1.test @@ -0,0 +1,42 @@ +%description: +The MPDU subframe header decoder preserves all 12 length bits emitted by the encoder. +Check decoded fields through the registered serializer using fresh byte-backed packets, +so cached serialized bytes cannot hide an incorrect decoded length. + +%includes: +#include + +#include "inet/common/packet/Packet.h" +#include "inet/common/packet/chunk/BytesChunk.h" +#include "inet/linklayer/ieee80211/mac/Ieee80211Frame_m.h" + +using namespace inet; +using namespace inet::ieee80211; + +%global: +static void checkDecodedLength(const std::vector& bytes, int expectedLength) +{ + Packet input("input", makeShared(bytes)); + auto header = input.popAtFront(B(4)); + ASSERT(header->getLength() == expectedLength); + ASSERT(header->getChunkLength() == B(4)); + ASSERT(input.getDataLength() == B(0)); +} + +%activity: +for (int length : {0, 255, 256, 0xABC, 4095}) { + auto header = makeShared(); + header->setLength(length); + Packet output("output", header); + auto bytes = output.peekAllAsBytes()->getBytes(); + ASSERT(bytes.size() == 4); + checkDecodedLength(bytes, length); +} + +// Fixed input in the existing encoder's format, independent of the round trip. +checkDecodedLength({0x0A, 0xBC, 0x00, 0x4E}, 0xABC); + +EV << "MPDU subframe lengths preserved across the 8-bit boundary.\n"; + +%contains: stdout +MPDU subframe lengths preserved across the 8-bit boundary.