network, wifi: Allow more it_present words in radiotap header

Provided bit 31 of the it_present field is not set, the data for fields specified in the it_present bitmask immediately follow the radiotap header. If it is set, then more it_present words follow and the radiotap data follows after the it_present word that has bit 31 unset.
This commit is contained in:
Sébastien Deronne
2025-05-31 12:37:21 +02:00
committed by Sébastien Deronne
parent 222eaa14fb
commit cabd04fad3
4 changed files with 167 additions and 189 deletions

View File

@@ -56,13 +56,13 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
{
NS_LOG_FUNCTION(this << &start);
start.WriteU8(0); // major version of radiotap header
start.WriteU8(0); // pad field
start.WriteU16(m_length); // entire length of radiotap data + header
start.WriteU32(m_present); // bits describing which fields follow header
if (m_presentExt)
start.WriteU8(0); // major version of radiotap header
start.WriteU8(0); // pad field
start.WriteU16(m_length); // entire length of radiotap data + header
NS_ASSERT(!m_present.empty());
for (const auto present : m_present)
{
start.WriteU32(*m_presentExt); // extended bitmasks
start.WriteU32(present); // bits describing which fields follow header
}
//
@@ -70,7 +70,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// arrived at the MAC)
// Reference: https://www.radiotap.org/fields/TSFT.html
//
if (m_present & RADIOTAP_TSFT) // bit 0
if (m_present.at(0) & RADIOTAP_TSFT) // bit 0
{
SerializeTsft(start);
}
@@ -79,7 +79,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// Properties of transmitted and received frames.
// Reference: https://www.radiotap.org/fields/Flags.html
//
if (m_present & RADIOTAP_FLAGS) // bit 1
if (m_present.at(0) & RADIOTAP_FLAGS) // bit 1
{
start.WriteU8(m_flags);
}
@@ -88,7 +88,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// TX/RX data rate in units of 500 kbps
// Reference: https://www.radiotap.org/fields/Rate.html
//
if (m_present & RADIOTAP_RATE) // bit 2
if (m_present.at(0) & RADIOTAP_RATE) // bit 2
{
start.WriteU8(m_rate);
}
@@ -97,7 +97,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// Tx/Rx frequency in MHz, followed by flags.
// Reference: https://www.radiotap.org/fields/Channel.html
//
if (m_present & RADIOTAP_CHANNEL) // bit 3
if (m_present.at(0) & RADIOTAP_CHANNEL) // bit 3
{
SerializeChannel(start);
}
@@ -107,7 +107,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// still need to account for it.
// Reference: https://www.radiotap.org/fields/FHSS.html
//
if (m_present & RADIOTAP_FHSS) // bit 4
if (m_present.at(0) & RADIOTAP_FHSS) // bit 4
{
NS_ASSERT(false); // not yet implemented
}
@@ -117,7 +117,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// reference.
// Reference: https://www.radiotap.org/fields/Antenna%20signal.html
//
if (m_present & RADIOTAP_DBM_ANTSIGNAL) // bit 5
if (m_present.at(0) & RADIOTAP_DBM_ANTSIGNAL) // bit 5
{
start.WriteU8(m_antennaSignal);
}
@@ -127,7 +127,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// reference.
// Reference: https://www.radiotap.org/fields/Antenna%20noise.html
//
if (m_present & RADIOTAP_DBM_ANTNOISE) // bit 6
if (m_present.at(0) & RADIOTAP_DBM_ANTNOISE) // bit 6
{
start.WriteU8(m_antennaNoise);
}
@@ -136,7 +136,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// Quality of Barker code lock.
// Reference: https://www.radiotap.org/fields/Lock%20quality.html
//
if (m_present & RADIOTAP_LOCK_QUALITY) // bit 7
if (m_present.at(0) & RADIOTAP_LOCK_QUALITY) // bit 7
{
NS_ASSERT(false); // not yet implemented
}
@@ -146,7 +146,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// set at factory calibration (0 is max power).
// Reference: https://www.radiotap.org/fields/TX%20attenuation.html
//
if (m_present & RADIOTAP_TX_ATTENUATION) // bit 8
if (m_present.at(0) & RADIOTAP_TX_ATTENUATION) // bit 8
{
NS_ASSERT(false); // not yet implemented
}
@@ -156,7 +156,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// set at factory calibration (0 is max power).
// Reference: https://www.radiotap.org/fields/dB%20TX%20attenuation.html
//
if (m_present & RADIOTAP_DB_TX_ATTENUATION) // bit 9
if (m_present.at(0) & RADIOTAP_DB_TX_ATTENUATION) // bit 9
{
NS_ASSERT(false); // not yet implemented
}
@@ -166,7 +166,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// This is the absolute power level measured at the antenna port.
// Reference: https://www.radiotap.org/fields/dBm%20TX%20power.html
//
if (m_present & RADIOTAP_DBM_TX_POWER) // bit 10
if (m_present.at(0) & RADIOTAP_DBM_TX_POWER) // bit 10
{
NS_ASSERT(false); // not yet implemented
}
@@ -176,7 +176,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// The first antenna is antenna 0.
// Reference: https://www.radiotap.org/fields/Antenna.html
//
if (m_present & RADIOTAP_ANTENNA) // bit 11
if (m_present.at(0) & RADIOTAP_ANTENNA) // bit 11
{
NS_ASSERT(false); // not yet implemented
}
@@ -185,7 +185,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
// Reference: https://www.radiotap.org/fields/dB%20antenna%20signal.html
//
if (m_present & RADIOTAP_DB_ANTSIGNAL) // bit 12
if (m_present.at(0) & RADIOTAP_DB_ANTSIGNAL) // bit 12
{
NS_ASSERT(false); // not yet implemented
}
@@ -194,7 +194,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
// Reference: https://www.radiotap.org/fields/dB%20antenna%20noise.html
//
if (m_present & RADIOTAP_DB_ANTNOISE) // bit 13
if (m_present.at(0) & RADIOTAP_DB_ANTNOISE) // bit 13
{
NS_ASSERT(false); // not yet implemented
}
@@ -203,7 +203,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// Properties of received frames.
// Reference: https://www.radiotap.org/fields/RX%20flags.html
//
if (m_present & RADIOTAP_RX_FLAGS) // bit 14
if (m_present.at(0) & RADIOTAP_RX_FLAGS) // bit 14
{
NS_ASSERT(false); // not yet implemented
}
@@ -212,7 +212,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// MCS field.
// Reference: https://www.radiotap.org/fields/MCS.html
//
if (m_present & RADIOTAP_MCS) // bit 19
if (m_present.at(0) & RADIOTAP_MCS) // bit 19
{
SerializeMcs(start);
}
@@ -221,7 +221,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// A-MPDU Status, information about the received or transmitted A-MPDU.
// Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
//
if (m_present & RADIOTAP_AMPDU_STATUS) // bit 20
if (m_present.at(0) & RADIOTAP_AMPDU_STATUS) // bit 20
{
SerializeAmpduStatus(start);
}
@@ -230,7 +230,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// Information about the received or transmitted VHT frame.
// Reference: https://www.radiotap.org/fields/VHT.html
//
if (m_present & RADIOTAP_VHT) // bit 21
if (m_present.at(0) & RADIOTAP_VHT) // bit 21
{
SerializeVht(start);
}
@@ -239,7 +239,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// HE field.
// Reference: https://www.radiotap.org/fields/HE.html
//
if (m_present & RADIOTAP_HE) // bit 23
if (m_present.at(0) & RADIOTAP_HE) // bit 23
{
SerializeHe(start);
}
@@ -248,7 +248,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// HE MU field.
// Reference: https://www.radiotap.org/fields/HE-MU.html
//
if (m_present & RADIOTAP_HE_MU) // bit 24
if (m_present.at(0) & RADIOTAP_HE_MU) // bit 24
{
SerializeHeMu(start);
}
@@ -257,7 +257,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// HE MU other user field.
// Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
//
if (m_present & RADIOTAP_HE_MU_OTHER_USER) // bit 25
if (m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER) // bit 25
{
SerializeHeMuOtherUser(start);
}
@@ -266,7 +266,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// U-SIG field.
// Reference: https://www.radiotap.org/fields/U-SIG.html
//
if (m_presentExt && (*m_presentExt & RADIOTAP_USIG)) // bit 33
if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG) // bit 33
{
SerializeUsig(start);
}
@@ -275,7 +275,7 @@ RadiotapHeader::Serialize(Buffer::Iterator start) const
// EHT field.
// Reference: https://www.radiotap.org/fields/EHT.html
//
if (m_presentExt && (*m_presentExt & RADIOTAP_EHT_SIG)) // bit 34
if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT_SIG) // bit 34
{
SerializeEht(start);
}
@@ -290,14 +290,15 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
NS_ASSERT_MSG(tmp == 0x00, "RadiotapHeader::Deserialize(): Unexpected major version");
start.ReadU8(); // pad field
m_length = start.ReadU16(); // entire length of radiotap data + header
m_present = start.ReadU32(); // bits describing which fields follow header
uint32_t bytesRead = 8;
m_length = start.ReadU16(); // entire length of radiotap data + header
m_present.emplace_back(start.ReadU32()); // bits describing which fields follow header
uint32_t bytesRead = MIN_HEADER_SIZE;
if (m_present & RADIOTAP_EXT)
std::size_t index{0};
while (m_present.at(index++) & RADIOTAP_EXT)
{
// If bit 31 of the it_present field is set, an extended it_present bitmask is present.
m_presentExt = start.ReadU32();
// If bit 31 of the it_present field is set, another it_present bitmask is present.
m_present.emplace_back(start.ReadU32());
bytesRead += 4;
}
@@ -305,7 +306,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// Time Synchronization Function Timer (when the first bit of the MPDU arrived at the MAC)
// Reference: https://www.radiotap.org/fields/TSFT.html
//
if (m_present & RADIOTAP_TSFT) // bit 0
if (m_present.at(0) & RADIOTAP_TSFT) // bit 0
{
bytesRead += DeserializeTsft(start, bytesRead);
}
@@ -314,7 +315,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// Properties of transmitted and received frames.
// Reference: https://www.radiotap.org/fields/Flags.html
//
if (m_present & RADIOTAP_FLAGS) // bit 1
if (m_present.at(0) & RADIOTAP_FLAGS) // bit 1
{
m_flags = start.ReadU8();
++bytesRead;
@@ -324,7 +325,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// TX/RX data rate in units of 500 kbps
// Reference: https://www.radiotap.org/fields/Rate.html
//
if (m_present & RADIOTAP_RATE) // bit 2
if (m_present.at(0) & RADIOTAP_RATE) // bit 2
{
m_rate = start.ReadU8();
++bytesRead;
@@ -334,7 +335,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// Tx/Rx frequency in MHz, followed by flags.
// Reference: https://www.radiotap.org/fields/Channel.html
//
if (m_present & RADIOTAP_CHANNEL) // bit 3
if (m_present.at(0) & RADIOTAP_CHANNEL) // bit 3
{
bytesRead += DeserializeChannel(start, bytesRead);
}
@@ -344,7 +345,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// still need to account for it.
// Reference: https://www.radiotap.org/fields/FHSS.html
//
if (m_present & RADIOTAP_FHSS) // bit 4
if (m_present.at(0) & RADIOTAP_FHSS) // bit 4
{
NS_ASSERT(false); // not yet implemented
}
@@ -354,7 +355,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// reference.
// Reference: https://www.radiotap.org/fields/Antenna%20signal.html
//
if (m_present & RADIOTAP_DBM_ANTSIGNAL) // bit 5
if (m_present.at(0) & RADIOTAP_DBM_ANTSIGNAL) // bit 5
{
m_antennaSignal = start.ReadU8();
++bytesRead;
@@ -365,7 +366,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// reference.
// Reference: https://www.radiotap.org/fields/Antenna%20noise.html
//
if (m_present & RADIOTAP_DBM_ANTNOISE) // bit 6
if (m_present.at(0) & RADIOTAP_DBM_ANTNOISE) // bit 6
{
m_antennaNoise = start.ReadU8();
++bytesRead;
@@ -375,7 +376,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// Quality of Barker code lock.
// Reference: https://www.radiotap.org/fields/Lock%20quality.html
//
if (m_present & RADIOTAP_LOCK_QUALITY) // bit 7
if (m_present.at(0) & RADIOTAP_LOCK_QUALITY) // bit 7
{
NS_ASSERT(false); // not yet implemented
}
@@ -385,7 +386,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// set at factory calibration (0 is max power).
// Reference: https://www.radiotap.org/fields/TX%20attenuation.html
//
if (m_present & RADIOTAP_TX_ATTENUATION) // bit 8
if (m_present.at(0) & RADIOTAP_TX_ATTENUATION) // bit 8
{
NS_ASSERT(false); // not yet implemented
}
@@ -395,7 +396,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// set at factory calibration (0 is max power).
// Reference: https://www.radiotap.org/fields/dB%20TX%20attenuation.html
//
if (m_present & RADIOTAP_DB_TX_ATTENUATION) // bit 9
if (m_present.at(0) & RADIOTAP_DB_TX_ATTENUATION) // bit 9
{
NS_ASSERT(false); // not yet implemented
}
@@ -405,7 +406,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// This is the absolute power level measured at the antenna port.
// Reference: https://www.radiotap.org/fields/dBm%20TX%20power.html
//
if (m_present & RADIOTAP_DBM_TX_POWER) // bit 10
if (m_present.at(0) & RADIOTAP_DBM_TX_POWER) // bit 10
{
NS_ASSERT(false); // not yet implemented
}
@@ -415,7 +416,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// The first antenna is antenna 0.
// Reference: https://www.radiotap.org/fields/Antenna.html
//
if (m_present & RADIOTAP_ANTENNA) // bit 11
if (m_present.at(0) & RADIOTAP_ANTENNA) // bit 11
{
NS_ASSERT(false); // not yet implemented
}
@@ -424,7 +425,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
// Reference: https://www.radiotap.org/fields/dB%20antenna%20signal.html
//
if (m_present & RADIOTAP_DB_ANTSIGNAL) // bit 12
if (m_present.at(0) & RADIOTAP_DB_ANTSIGNAL) // bit 12
{
NS_ASSERT(false); // not yet implemented
}
@@ -433,7 +434,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
// Reference: https://www.radiotap.org/fields/dB%20antenna%20noise.html
//
if (m_present & RADIOTAP_DB_ANTNOISE) // bit 13
if (m_present.at(0) & RADIOTAP_DB_ANTNOISE) // bit 13
{
NS_ASSERT(false); // not yet implemented
}
@@ -442,7 +443,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// Properties of received frames.
// Reference: https://www.radiotap.org/fields/RX%20flags.html
//
if (m_present & RADIOTAP_RX_FLAGS) // bit 14
if (m_present.at(0) & RADIOTAP_RX_FLAGS) // bit 14
{
NS_ASSERT(false); // not yet implemented
}
@@ -451,7 +452,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// MCS field.
// Reference: https://www.radiotap.org/fields/MCS.html
//
if (m_present & RADIOTAP_MCS) // bit 19
if (m_present.at(0) & RADIOTAP_MCS) // bit 19
{
bytesRead += DeserializeMcs(start, bytesRead);
}
@@ -460,7 +461,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// A-MPDU Status, information about the received or transmitted A-MPDU.
// Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
//
if (m_present & RADIOTAP_AMPDU_STATUS)
if (m_present.at(0) & RADIOTAP_AMPDU_STATUS)
{
bytesRead += DeserializeAmpduStatus(start, bytesRead);
}
@@ -469,7 +470,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// Information about the received or transmitted VHT frame.
// Reference: https://www.radiotap.org/fields/VHT.html
//
if (m_present & RADIOTAP_VHT) // bit 21
if (m_present.at(0) & RADIOTAP_VHT) // bit 21
{
bytesRead += DeserializeVht(start, bytesRead);
}
@@ -478,7 +479,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// HE field.
// Reference: https://www.radiotap.org/fields/HE.html
//
if (m_present & RADIOTAP_HE) // bit 23
if (m_present.at(0) & RADIOTAP_HE) // bit 23
{
bytesRead += DeserializeHe(start, bytesRead);
}
@@ -487,7 +488,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// HE MU field.
// Reference: https://www.radiotap.org/fields/HE-MU.html
//
if (m_present & RADIOTAP_HE_MU) // bit 24
if (m_present.at(0) & RADIOTAP_HE_MU) // bit 24
{
bytesRead += DeserializeHeMu(start, bytesRead);
}
@@ -496,7 +497,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// HE MU other user field.
// Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
//
if (m_present & RADIOTAP_HE_MU_OTHER_USER) // bit 25
if (m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER) // bit 25
{
bytesRead += DeserializeHeMuOtherUser(start, bytesRead);
}
@@ -505,7 +506,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// U-SIG field.
// Reference: https://www.radiotap.org/fields/U-SIG.html
//
if (m_presentExt && (*m_presentExt & RADIOTAP_USIG)) // bit 33
if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG) // bit 33
{
bytesRead += DeserializeUsig(start, bytesRead);
}
@@ -514,7 +515,7 @@ RadiotapHeader::Deserialize(Buffer::Iterator start)
// EHT field.
// Reference: https://www.radiotap.org/fields/EHT.html
//
if (m_presentExt && (*m_presentExt & RADIOTAP_EHT_SIG)) // bit 34
if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT_SIG) // bit 34
{
bytesRead += DeserializeEht(start, bytesRead);
}
@@ -529,55 +530,58 @@ RadiotapHeader::Print(std::ostream& os) const
{
NS_LOG_FUNCTION(this << &os);
os << " tsft=" << m_tsft << " flags=" << std::hex << m_flags << std::dec << " rate=" << +m_rate;
if (m_present & RADIOTAP_CHANNEL)
if (m_present.at(0) & RADIOTAP_CHANNEL)
{
PrintChannel(os);
}
os << std::dec << " signal=" << +m_antennaSignal << " noise=" << +m_antennaNoise;
if (m_present & RADIOTAP_MCS)
if (m_present.at(0) & RADIOTAP_MCS)
{
PrintMcs(os);
}
if (m_present & RADIOTAP_AMPDU_STATUS)
if (m_present.at(0) & RADIOTAP_AMPDU_STATUS)
{
PrintAmpduStatus(os);
}
if (m_present & RADIOTAP_VHT)
if (m_present.at(0) & RADIOTAP_VHT)
{
PrintVht(os);
}
if (m_present & RADIOTAP_HE)
if (m_present.at(0) & RADIOTAP_HE)
{
PrintHe(os);
}
if (m_present & RADIOTAP_HE_MU)
if (m_present.at(0) & RADIOTAP_HE_MU)
{
PrintHeMu(os);
}
if (m_present & RADIOTAP_HE_MU_OTHER_USER)
if (m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER)
{
PrintHeMuOtherUser(os);
}
if (m_presentExt && (*m_presentExt & RADIOTAP_USIG))
if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG)
{
PrintUsig(os);
}
if (m_presentExt && (*m_presentExt & RADIOTAP_EHT_SIG))
if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT_SIG)
{
PrintEht(os);
}
}
void
RadiotapHeader::SetWifiHeader(bool extended)
RadiotapHeader::SetWifiHeader(std::size_t numPresentWords)
{
NS_LOG_FUNCTION(this << extended);
NS_LOG_FUNCTION(this << numPresentWords);
NS_ASSERT_MSG(numPresentWords > 0,
"RadiotapHeader::SetWifiHeader() requires at least one it_present word");
NS_ASSERT_MSG(m_length == MIN_HEADER_SIZE,
"RadiotapHeader::SetWifiHeader() should be called before any other Set* method");
if (extended)
NS_ASSERT_MSG(m_present.size() == 1, "RadiotapHeader::SetWifiHeader() should be called once");
for (std::size_t i = 0; i < (numPresentWords - 1); ++i)
{
m_present |= RADIOTAP_EXT;
m_presentExt = 0;
m_present.at(i) |= RADIOTAP_EXT;
m_present.emplace_back(0);
m_length += sizeof(RadiotapExtFlags);
}
}
@@ -587,13 +591,13 @@ RadiotapHeader::SetTsft(uint64_t value)
{
NS_LOG_FUNCTION(this << value);
NS_ASSERT_MSG(!(m_present & RADIOTAP_TSFT), "TSFT radiotap field already present");
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_TSFT), "TSFT radiotap field already present");
m_tsftPad = ((8 - m_length % 8) % 8);
m_present |= RADIOTAP_TSFT;
m_present.at(0) |= RADIOTAP_TSFT;
m_length += 8 + m_tsftPad;
m_tsft = value;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -618,12 +622,12 @@ RadiotapHeader::SetFrameFlags(uint8_t flags)
{
NS_LOG_FUNCTION(this << +flags);
NS_ASSERT_MSG(!(m_present & RADIOTAP_FLAGS), "Flags radiotap field already present");
m_present |= RADIOTAP_FLAGS;
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_FLAGS), "Flags radiotap field already present");
m_present.at(0) |= RADIOTAP_FLAGS;
m_length += 1;
m_flags = flags;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -632,12 +636,12 @@ RadiotapHeader::SetRate(uint8_t rate)
{
NS_LOG_FUNCTION(this << +rate);
NS_ASSERT_MSG(!(m_present & RADIOTAP_RATE), "Rate radiotap field already present");
m_present |= RADIOTAP_RATE;
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_RATE), "Rate radiotap field already present");
m_present.at(0) |= RADIOTAP_RATE;
m_length += 1;
m_rate = rate;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -646,13 +650,13 @@ RadiotapHeader::SetChannelFields(const ChannelFields& channelFields)
{
NS_LOG_FUNCTION(this << channelFields.frequency << channelFields.flags);
NS_ASSERT_MSG(!(m_present & RADIOTAP_CHANNEL), "Channel radiotap field already present");
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_CHANNEL), "Channel radiotap field already present");
m_channelPad = ((2 - m_length % 2) % 2);
m_present |= RADIOTAP_CHANNEL;
m_present.at(0) |= RADIOTAP_CHANNEL;
m_length += (sizeof(ChannelFields) + m_channelPad);
m_channelFields = channelFields;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -686,9 +690,9 @@ RadiotapHeader::SetAntennaSignalPower(double signal)
{
NS_LOG_FUNCTION(this << signal);
NS_ASSERT_MSG(!(m_present & RADIOTAP_DBM_ANTSIGNAL),
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_DBM_ANTSIGNAL),
"Antenna signal radiotap field already present");
m_present |= RADIOTAP_DBM_ANTSIGNAL;
m_present.at(0) |= RADIOTAP_DBM_ANTSIGNAL;
m_length += 1;
if (signal > 127)
@@ -704,7 +708,7 @@ RadiotapHeader::SetAntennaSignalPower(double signal)
m_antennaSignal = static_cast<int8_t>(floor(signal + 0.5));
}
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -713,9 +717,9 @@ RadiotapHeader::SetAntennaNoisePower(double noise)
{
NS_LOG_FUNCTION(this << noise);
NS_ASSERT_MSG(!(m_present & RADIOTAP_DBM_ANTNOISE),
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_DBM_ANTNOISE),
"Antenna noise radiotap field already present");
m_present |= RADIOTAP_DBM_ANTNOISE;
m_present.at(0) |= RADIOTAP_DBM_ANTNOISE;
m_length += 1;
if (noise > 127.0)
@@ -731,7 +735,7 @@ RadiotapHeader::SetAntennaNoisePower(double noise)
m_antennaNoise = static_cast<int8_t>(floor(noise + 0.5));
}
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -740,12 +744,12 @@ RadiotapHeader::SetMcsFields(const McsFields& mcsFields)
{
NS_LOG_FUNCTION(this << +mcsFields.known << +mcsFields.flags << +mcsFields.mcs);
NS_ASSERT_MSG(!(m_present & RADIOTAP_MCS), "MCS radiotap field already present");
m_present |= RADIOTAP_MCS;
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_MCS), "MCS radiotap field already present");
m_present.at(0) |= RADIOTAP_MCS;
m_length += sizeof(McsFields);
m_mcsFields = mcsFields;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -778,14 +782,14 @@ RadiotapHeader::SetAmpduStatus(const AmpduStatusFields& ampduStatusFields)
{
NS_LOG_FUNCTION(this << ampduStatusFields.referenceNumber << ampduStatusFields.flags);
NS_ASSERT_MSG(!(m_present & RADIOTAP_AMPDU_STATUS),
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_AMPDU_STATUS),
"A-MPDU status radiotap field already present");
m_ampduStatusPad = ((4 - m_length % 4) % 4);
m_present |= RADIOTAP_AMPDU_STATUS;
m_present.at(0) |= RADIOTAP_AMPDU_STATUS;
m_length += (sizeof(ampduStatusFields) + m_ampduStatusPad);
m_ampduStatusFields = ampduStatusFields;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -825,13 +829,13 @@ RadiotapHeader::SetVhtFields(const VhtFields& vhtFields)
<< +vhtFields.mcsNss.at(3) << +vhtFields.coding << +vhtFields.groupId
<< +vhtFields.partialAid);
NS_ASSERT_MSG(!(m_present & RADIOTAP_VHT), "VHT radiotap field already present");
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_VHT), "VHT radiotap field already present");
m_vhtPad = ((2 - m_length % 2) % 2);
m_present |= RADIOTAP_VHT;
m_present.at(0) |= RADIOTAP_VHT;
m_length += (sizeof(VhtFields) + m_vhtPad);
m_vhtFields = vhtFields;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -887,13 +891,13 @@ RadiotapHeader::SetHeFields(const HeFields& heFields)
NS_LOG_FUNCTION(this << heFields.data1 << heFields.data2 << heFields.data3 << heFields.data4
<< heFields.data5 << heFields.data6);
NS_ASSERT_MSG(!(m_present & RADIOTAP_HE), "HE radiotap field already present");
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_HE), "HE radiotap field already present");
m_hePad = ((2 - m_length % 2) % 2);
m_present |= RADIOTAP_HE;
m_present.at(0) |= RADIOTAP_HE;
m_length += (sizeof(heFields) + m_hePad);
m_heFields = heFields;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -937,13 +941,13 @@ RadiotapHeader::SetHeMuFields(const HeMuFields& heMuFields)
{
NS_LOG_FUNCTION(this << heMuFields.flags1 << heMuFields.flags2);
NS_ASSERT_MSG(!(m_present & RADIOTAP_HE_MU), "HE-MU radiotap field already present");
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_HE_MU), "HE-MU radiotap field already present");
m_heMuPad = ((2 - m_length % 2) % 2);
m_present |= RADIOTAP_HE_MU;
m_present.at(0) |= RADIOTAP_HE_MU;
m_length += (sizeof(heMuFields) + m_heMuPad);
m_heMuFields = heMuFields;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -995,14 +999,14 @@ RadiotapHeader::SetHeMuOtherUserFields(const HeMuOtherUserFields& heMuOtherUserF
<< +heMuOtherUserFields.perUserPosition
<< +heMuOtherUserFields.perUserKnown);
NS_ASSERT_MSG(!(m_present & RADIOTAP_HE_MU_OTHER_USER),
NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER),
"HE-MU-other-user radiotap field already present");
m_heMuOtherUserPad = ((2 - m_length % 2) % 2);
m_present |= RADIOTAP_HE_MU_OTHER_USER;
m_present.at(0) |= RADIOTAP_HE_MU_OTHER_USER;
m_length += (sizeof(HeMuOtherUserFields) + m_heMuOtherUserPad);
m_heMuOtherUserFields = heMuOtherUserFields;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
<< std::dec);
}
@@ -1042,11 +1046,12 @@ void
RadiotapHeader::SetUsigFields(const UsigFields& usigFields)
{
NS_LOG_FUNCTION(this << usigFields.common << usigFields.mask << usigFields.value);
NS_ASSERT_MSG(m_presentExt, "Number of it_present words is incorrect");
m_present |= RADIOTAP_TLV;
NS_ASSERT_MSG(m_present.size() >= 2,
"Number of it_present words (" << m_present.size() << ") is incorrect");
m_present.at(0) |= RADIOTAP_TLV;
NS_ASSERT_MSG(!(*m_presentExt & RADIOTAP_USIG), "U-SIG radiotap field already present");
*m_presentExt |= RADIOTAP_USIG;
NS_ASSERT_MSG(!(m_present.at(1) & RADIOTAP_USIG), "U-SIG radiotap field already present");
m_present.at(1) |= RADIOTAP_USIG;
m_usigTlvPad = ((8 - m_length % 8) % 8);
m_usigTlv.type = 32 + std::countr_zero<uint16_t>(RADIOTAP_USIG);
@@ -1057,8 +1062,8 @@ RadiotapHeader::SetUsigFields(const UsigFields& usigFields)
m_usigFields = usigFields;
m_length += m_usigTlv.length + m_usigPad;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
<< " m_presentExt=0x" << *m_presentExt << std::dec);
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present[0]=0x" << std::hex
<< m_present.at(0) << " m_present[1]=0x" << m_present.at(1) << std::dec);
}
void
@@ -1104,11 +1109,12 @@ void
RadiotapHeader::SetEhtFields(const EhtFields& ehtFields)
{
NS_LOG_FUNCTION(this << ehtFields.known);
NS_ASSERT_MSG(m_presentExt, "Number of it_present words is incorrect");
m_present |= RADIOTAP_TLV;
NS_ASSERT_MSG(m_present.size() >= 2,
"Number of it_present words (" << m_present.size() << ") is incorrect");
m_present.at(0) |= RADIOTAP_TLV;
NS_ASSERT_MSG(!(*m_presentExt & RADIOTAP_EHT_SIG), "EHT radiotap field already present");
*m_presentExt |= RADIOTAP_EHT_SIG;
NS_ASSERT_MSG(!(m_present.at(1) & RADIOTAP_EHT_SIG), "EHT radiotap field already present");
m_present.at(1) |= RADIOTAP_EHT_SIG;
m_ehtTlvPad = ((8 - m_length % 8) % 8);
m_ehtTlv.type = 32 + std::countr_zero<uint16_t>(RADIOTAP_EHT_SIG);
@@ -1119,8 +1125,8 @@ RadiotapHeader::SetEhtFields(const EhtFields& ehtFields)
m_ehtFields = ehtFields;
m_length += m_ehtTlv.length + m_ehtPad;
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present
<< " m_presentExt=0x" << *m_presentExt << std::dec);
NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present[0]=0x" << std::hex
<< m_present.at(0) << " m_present[1]=0x" << m_present.at(1) << std::dec);
}
void

View File

@@ -86,9 +86,9 @@ class RadiotapHeader : public Header
* @brief Set the ieee80211_radiotap_header. This method must be called
* before any other Set* method.
*
* @param extended If true, one more it_present word follows the it_present bitmask.
* @param numPresentWords Number of it_present words in the radiotap header.
*/
void SetWifiHeader(bool extended);
void SetWifiHeader(std::size_t numPresentWords);
/**
* @brief Set the Time Synchronization Function Timer (TSFT) value. Valid for
@@ -1058,9 +1058,8 @@ class RadiotapHeader : public Header
RADIOTAP_EHT_SIG = 0x00000004
};
uint16_t m_length{MIN_HEADER_SIZE}; //!< entire length of radiotap data + header
uint32_t m_present{0}; //!< bits describing which fields follow header
std::optional<uint32_t> m_presentExt{}; //!< optional extended present bitmask
uint16_t m_length{MIN_HEADER_SIZE}; //!< entire length of radiotap data + header
std::vector<uint32_t> m_present{0}; //!< bits describing which fields follow header
uint8_t m_tsftPad{0}; //!< TSFT padding.
uint64_t m_tsft{0}; //!< Time Synchronization Function Timer (when the first bit of the MPDU

View File

@@ -275,14 +275,12 @@ WifiPhyHelper::PcapSniffTxEvent(const std::shared_ptr<PcapFilesInfo>& info,
}
case PcapHelper::DLT_IEEE802_11_RADIO: {
Ptr<Packet> p = packet->Copy();
RadiotapHeader header;
GetRadiotapHeader(header,
p,
channelFreqMhz,
info->device->GetPhy(phyId)->GetPrimary20Index(),
txVector,
aMpdu,
staId);
const auto header = GetRadiotapHeader(p,
channelFreqMhz,
info->device->GetPhy(phyId)->GetPrimary20Index(),
txVector,
aMpdu,
staId);
p->AddHeader(header);
file->Write(Simulator::Now(), p);
return;
@@ -318,15 +316,13 @@ WifiPhyHelper::PcapSniffRxEvent(const std::shared_ptr<PcapFilesInfo>& info,
}
case PcapHelper::DLT_IEEE802_11_RADIO: {
Ptr<Packet> p = packet->Copy();
RadiotapHeader header;
GetRadiotapHeader(header,
p,
channelFreqMhz,
info->device->GetPhy(phyId)->GetPrimary20Index(),
txVector,
aMpdu,
staId,
signalNoise);
const auto header = GetRadiotapHeader(p,
channelFreqMhz,
info->device->GetPhy(phyId)->GetPrimary20Index(),
txVector,
aMpdu,
staId,
signalNoise);
p->AddHeader(header);
file->Write(Simulator::Now(), p);
return;
@@ -336,36 +332,29 @@ WifiPhyHelper::PcapSniffRxEvent(const std::shared_ptr<PcapFilesInfo>& info,
}
}
void
WifiPhyHelper::GetRadiotapHeader(RadiotapHeader& header,
Ptr<Packet> packet,
RadiotapHeader
WifiPhyHelper::GetRadiotapHeader(Ptr<Packet> packet,
uint16_t channelFreqMhz,
uint8_t p20Index,
const WifiTxVector& txVector,
MpduInfo aMpdu,
uint16_t staId,
SignalNoiseDbm signalNoise)
std::optional<SignalNoiseDbm> signalNoise)
{
GetRadiotapHeader(header, packet, channelFreqMhz, p20Index, txVector, aMpdu, staId);
header.SetAntennaSignalPower(signalNoise.signal);
header.SetAntennaNoisePower(signalNoise.noise);
}
RadiotapHeader header;
void
WifiPhyHelper::GetRadiotapHeader(RadiotapHeader& header,
Ptr<Packet> packet,
uint16_t channelFreqMhz,
uint8_t p20Index,
const WifiTxVector& txVector,
MpduInfo aMpdu,
uint16_t staId)
{
const auto preamble = txVector.GetPreambleType();
const auto modClass = txVector.GetModulationClass();
const auto channelWidth = txVector.GetChannelWidth();
const auto gi = txVector.GetGuardInterval();
header.SetWifiHeader(IsEht(preamble));
header.SetWifiHeader(IsEht(preamble) ? 2 : 1);
if (signalNoise)
{
header.SetAntennaSignalPower(signalNoise->signal);
header.SetAntennaNoisePower(signalNoise->noise);
}
header.SetTsft(Simulator::Now().GetMicroSeconds());
@@ -817,6 +806,8 @@ WifiPhyHelper::GetRadiotapHeader(RadiotapHeader& header,
ehtFields.userInfo.push_back(userInfo);
header.SetEhtFields(ehtFields);
}
return header;
}
void

View File

@@ -20,6 +20,7 @@
#include <functional>
#include <map>
#include <optional>
#include <vector>
namespace ns3
@@ -309,45 +310,26 @@ class WifiPhyHelper : public PcapHelperForDevice, public AsciiTraceHelperForDevi
static Ptr<PcapFileWrapper> GetOrCreatePcapFile(const std::shared_ptr<PcapFilesInfo>& info,
uint8_t phyId);
/**
* Get the Radiotap header for a transmitted packet.
*
* @param header the radiotap header to be filled in
* @param packet the packet
* @param channelFreqMhz the channel frequency
* @param p20Index the index of the primary20 channel
* @param txVector the TXVECTOR
* @param aMpdu the A-MPDU information
* @param staId the STA-ID
*/
static void GetRadiotapHeader(RadiotapHeader& header,
Ptr<Packet> packet,
uint16_t channelFreqMhz,
uint8_t p20Index,
const WifiTxVector& txVector,
MpduInfo aMpdu,
uint16_t staId);
/**
* Get the Radiotap header for a received packet.
*
* @param header the radiotap header to be filled in
* @param packet the packet
* @param channelFreqMhz the channel frequency
* @param p20Index the index of the primary20 channel
* @param txVector the TXVECTOR
* @param aMpdu the A-MPDU information
* @param staId the STA-ID
* @param signalNoise the rx signal and noise information
* @param signalNoise the rx signal and noise information (for receiver only)
* @return the radiotap header
*/
static void GetRadiotapHeader(RadiotapHeader& header,
Ptr<Packet> packet,
uint16_t channelFreqMhz,
uint8_t p20Index,
const WifiTxVector& txVector,
MpduInfo aMpdu,
uint16_t staId,
SignalNoiseDbm signalNoise);
static RadiotapHeader GetRadiotapHeader(
Ptr<Packet> packet,
uint16_t channelFreqMhz,
uint8_t p20Index,
const WifiTxVector& txVector,
MpduInfo aMpdu,
uint16_t staId,
std::optional<SignalNoiseDbm> signalNoise = std::nullopt);
/**
* @brief Enable pcap output the indicated net device.