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.