wifi: Cleanup PHY headers serialization and deserialization

This commit is contained in:
Sébastien Deronne
2023-04-26 20:48:00 +02:00
committed by Sebastien Deronne
parent bce3ec21e5
commit e09443d148
10 changed files with 11 additions and 772 deletions

View File

@@ -544,65 +544,6 @@ HePpdu::HeSigHeader::HeSigHeader(bool heSigBPresent)
{
}
TypeId
HePpdu::HeSigHeader::GetTypeId()
{
static TypeId tid = TypeId("ns3::HeSigHeader")
.SetParent<Header>()
.SetGroupName("Wifi")
.AddConstructor<HeSigHeader>();
return tid;
}
TypeId
HePpdu::HeSigHeader::GetInstanceTypeId() const
{
return GetTypeId();
}
void
HePpdu::HeSigHeader::Print(std::ostream& os) const
{
os << "MCS=" << +m_mcs << " CHANNEL_WIDTH=" << GetChannelWidth() << " GI=" << GetGuardInterval()
<< " NSTS=" << +m_nsts << " BSSColor=" << +m_bssColor;
if (m_heSigBPresent)
{
os << " SIG-B_MCS=" << +m_sigBMcs << " RU_ALLOCATION=";
for (auto alloc : m_ruAllocation)
{
os << +alloc << " ";
}
if (m_center26ToneRuIndication.has_value())
{
os << "CENTER_26_TONE_RU=" << +m_center26ToneRuIndication.value();
}
auto contentChannelIdx = 1;
for (const auto& contentChannel : m_contentChannels)
{
os << " CONTENT_CHANNEL_" << contentChannelIdx++ << ": {";
for (const auto& userInfo : contentChannel)
{
os << "STA_ID=" << userInfo.staId << " MCS=" << +userInfo.mcs
<< " NSS=" << +userInfo.nss << ", ";
}
os << "}";
}
}
}
uint32_t
HePpdu::HeSigHeader::GetSerializedSize() const
{
uint32_t size = 0;
size += 4; // HE-SIG-A1
size += 4; // HE-SIG-A2
if (m_heSigBPresent)
{
size += GetSigBSize(); // HE-SIG-B
}
return size;
}
void
HePpdu::HeSigHeader::SetHeSigBPresent(bool heSigBPresent)
{
@@ -795,367 +736,4 @@ HePpdu::HeSigHeader::GetCenter26ToneRuIndication() const
return m_center26ToneRuIndication;
}
void
HePpdu::HeSigHeader::SerializeSigBContentChannel(
Buffer::Iterator& start,
uint8_t contentChannelId,
const std::vector<uint32_t>& userBlockFieldsContentChannel) const
{
NS_ASSERT(contentChannelId <= WIFI_MAX_NUM_HE_SIGB_CONTENT_CHANNELS);
NS_ASSERT(!userBlockFieldsContentChannel.empty());
// Common field
const auto bw = GetChannelWidth();
switch (bw)
{
case 20:
NS_ASSERT(contentChannelId == 1);
NS_ASSERT(m_ruAllocation.size() == 1);
start.WriteU8(m_ruAllocation.at(0));
break;
case 40:
NS_ASSERT(m_ruAllocation.size() == 2);
start.WriteU8(m_ruAllocation.at(contentChannelId - 1));
break;
case 80:
NS_ASSERT(m_ruAllocation.size() == 4);
start.WriteU8(m_ruAllocation.at(contentChannelId - 1));
start.WriteU8(m_ruAllocation.at(contentChannelId + 1));
break;
case 160:
NS_ASSERT(m_ruAllocation.size() == 8);
start.WriteU8(m_ruAllocation.at(contentChannelId - 1));
start.WriteU8(m_ruAllocation.at(contentChannelId + 1));
start.WriteU8(m_ruAllocation.at(contentChannelId + 3));
start.WriteU8(m_ruAllocation.at(contentChannelId + 5));
break;
default:
NS_FATAL_ERROR("Invalid channel width: " << bw << " MHz");
}
uint8_t byte = 0;
uint8_t offset = 0;
if (m_center26ToneRuIndication.has_value())
{
NS_ASSERT(bw >= 80);
if ((m_center26ToneRuIndication.value() ==
CENTER_26_TONE_RU_LOW_AND_HIGH_80_MHZ_ALLOCATED) ||
((contentChannelId == 1) &&
(m_center26ToneRuIndication.value() == CENTER_26_TONE_RU_LOW_80_MHZ_ALLOCATED)) ||
((contentChannelId == 2) &&
(m_center26ToneRuIndication.value() == CENTER_26_TONE_RU_HIGH_80_MHZ_ALLOCATED)))
{
byte |= 0x01;
}
offset++;
}
// CRC and tail (set to 0 for simplification)
offset += 10;
start.WriteU8(byte);
byte = 0;
offset -= 8;
// User fields
for (auto userField : userBlockFieldsContentChannel)
{
std::size_t nBits = 0;
const uint8_t bitsPerUserField = 21 + 4 /* CRC */ + 6 /* tail */;
while (nBits < bitsPerUserField)
{
NS_ASSERT(offset < 8);
const uint8_t nBitsLeftToWrite = bitsPerUserField - nBits;
const uint8_t bitsLeft = (8 - offset);
if (nBitsLeftToWrite >= 8)
{
const uint8_t bitMask = (0x01 << bitsLeft) - 0x01;
byte |= ((userField >> nBits) & bitMask) << offset;
start.WriteU8(byte);
nBits += bitsLeft;
byte = 0;
offset = 0;
}
else
{
// less than one byte to write, set bits to be used by next user field
const uint8_t bitMask = (0x01 << (8 - offset)) - 0x01;
byte |= (userField & (bitMask << nBits)) << offset;
offset = nBitsLeftToWrite;
nBits = bitsPerUserField;
}
}
}
}
uint16_t
HePpdu::HeSigHeader::DeserializeSigBContentChannel(
Buffer::Iterator start,
uint8_t contentChannelId,
std::vector<uint32_t>& userBlockFieldsContentChannel)
{
NS_ASSERT(contentChannelId <= WIFI_MAX_NUM_HE_SIGB_CONTENT_CHANNELS);
Buffer::Iterator i = start;
uint16_t count = 0;
// Common field
const auto bw = GetChannelWidth();
switch (bw)
{
case 20:
NS_ASSERT(contentChannelId == 1);
NS_ASSERT(m_ruAllocation.size() == 1);
m_ruAllocation.at(0) = i.ReadU8();
count += 1;
break;
case 40:
NS_ASSERT(m_ruAllocation.size() == 2);
m_ruAllocation.at(contentChannelId - 1) = i.ReadU8();
count += 1;
break;
case 80:
NS_ASSERT(m_ruAllocation.size() == 4);
m_ruAllocation.at(contentChannelId - 1) = i.ReadU8();
m_ruAllocation.at(contentChannelId + 1) = i.ReadU8();
count += 2;
break;
case 160:
NS_ASSERT(m_ruAllocation.size() == 8);
m_ruAllocation.at(contentChannelId - 1) = i.ReadU8();
m_ruAllocation.at(contentChannelId + 1) = i.ReadU8();
m_ruAllocation.at(contentChannelId + 3) = i.ReadU8();
m_ruAllocation.at(contentChannelId + 5) = i.ReadU8();
count += 4;
break;
default:
NS_FATAL_ERROR("Invalid channel width: " << bw << " MHz");
}
uint8_t offset = 0;
uint8_t byte = i.ReadU8();
count += 1;
if (bw >= 80)
{
NS_ASSERT(m_center26ToneRuIndication.has_value());
auto val = static_cast<uint8_t>(m_center26ToneRuIndication.value());
val |= (byte & 0x01) << (contentChannelId - 1);
m_center26ToneRuIndication = static_cast<Center26ToneRuIndication>(val);
offset++;
}
// CRC and tail
offset += 10;
byte = i.ReadU8();
count += 1;
offset -= 8;
// User fields
const auto numRusPerHeSigBContentChannel = GetNumRusPerHeSigBContentChannel(bw, m_ruAllocation);
std::size_t nUserFields = (contentChannelId == 1) ? numRusPerHeSigBContentChannel.first
: numRusPerHeSigBContentChannel.second;
userBlockFieldsContentChannel.reserve(nUserFields);
for (std::size_t field = 0; field < nUserFields; ++field)
{
uint8_t nBits = 0;
uint32_t userField = 0;
const uint8_t bitsPerUserField = 21 + 4 /* CRC */ + 6 /* tail */;
while (nBits < bitsPerUserField)
{
NS_ASSERT(offset < 8);
const uint8_t bitsLeft = std::min(8 - offset, bitsPerUserField - nBits);
const uint8_t bitMask = (0x01 << bitsLeft) - 0x01;
userField |= ((byte >> offset) & bitMask) << nBits;
offset += bitsLeft;
nBits += bitsLeft;
if ((bitsPerUserField - nBits < 8) && (field == nUserFields - 1))
{
// reached padding, can stop deserializing user fields
break;
}
if (offset == 8)
{
// reached end of byte, read next one
byte = i.ReadU8();
count += 1;
offset = 0;
}
}
userBlockFieldsContentChannel.push_back(userField);
}
return count;
}
void
HePpdu::HeSigHeader::Serialize(Buffer::Iterator start) const
{
// HE-SIG-A1
uint32_t sigA1 = 0;
if (!m_heSigBPresent)
{
sigA1 |= m_format & 0x01;
if (m_format == 1) // HE SU or HE ER SU PPDU
{
sigA1 |= ((m_mcs & 0x0f) << 3);
sigA1 |= ((m_bssColor & 0x3f) << 8);
sigA1 |= (0x01 << 14); // Reserved set to 1
sigA1 |= ((m_bandwidth & 0x03) << 19);
sigA1 |= ((m_gi_ltf_size & 0x03) << 21);
sigA1 |= ((m_nsts & 0x07) << 23);
}
else
{
// HE TB PPDU
sigA1 |= ((m_bssColor & 0x3f) << 1);
sigA1 |= (0x01 << 23); // Reserved set to 1
sigA1 |= ((m_bandwidth & 0x03) << 24);
}
}
else
{
// HE MU PPDU
sigA1 |= ((m_sigBMcs & 0x07) << 1);
sigA1 |= ((m_bssColor & 0x3f) << 5);
sigA1 |= ((m_bandwidth & 0x03) << 15);
sigA1 |= ((m_gi_ltf_size & 0x03) << 23);
}
start.WriteU32(sigA1);
// HE-SIG-A2
uint32_t sigA2 = 0;
if (!m_heSigBPresent && (m_format == 1))
{
// HE SU or HE ER SU PPDU
sigA2 |= (0x01 << 14); // Set Reserved bit #14 to 1
}
start.WriteU32(sigA2);
if (m_heSigBPresent)
{
// HE-SIG-B
std::vector<uint32_t> userBlockFieldsContentChannel1;
std::vector<uint32_t> userBlockFieldsContentChannel2;
for (const auto& userInfo : m_contentChannels.at(0))
{
uint32_t userField = userInfo.staId;
userField |= ((userInfo.nss & 0x07) << 11);
userField |= ((userInfo.mcs & 0x0f) << 15);
// CRC and tail set to 0 for simplification
userBlockFieldsContentChannel1.push_back(userField);
}
SerializeSigBContentChannel(start, 1, userBlockFieldsContentChannel1);
if (m_contentChannels.size() > 1)
{
NS_ASSERT(GetChannelWidth() > 20);
for (const auto& userInfo : m_contentChannels.at(1))
{
uint32_t userField = userInfo.staId;
userField |= ((userInfo.nss & 0x07) << 11);
userField |= ((userInfo.mcs & 0x0f) << 15);
// CRC and tail set to 0 for simplification
userBlockFieldsContentChannel2.push_back(userField);
}
SerializeSigBContentChannel(start, 2, userBlockFieldsContentChannel2);
}
}
}
uint32_t
HePpdu::HeSigHeader::Deserialize(Buffer::Iterator start)
{
Buffer::Iterator i = start;
// HE-SIG-A1
uint32_t sigA1 = i.ReadU32();
if (!m_heSigBPresent)
{
m_format = (sigA1 & 0x01);
if (m_format == 1)
{
// HE SU or HE ER SU PPDU
m_mcs = ((sigA1 >> 3) & 0x0f);
m_bssColor = ((sigA1 >> 8) & 0x3f);
m_bandwidth = ((sigA1 >> 19) & 0x03);
m_gi_ltf_size = ((sigA1 >> 21) & 0x03);
m_nsts = ((sigA1 >> 23) & 0x07);
}
else
{
// HE TB PPDU
m_bssColor = ((sigA1 >> 1) & 0x3f);
m_bandwidth = ((sigA1 >> 24) & 0x03);
}
}
else
{
// HE MU PPDU
m_sigBMcs = ((sigA1 >> 1) & 0x07);
m_bssColor = ((sigA1 >> 5) & 0x3f);
m_bandwidth = ((sigA1 >> 15) & 0x03);
m_gi_ltf_size = ((sigA1 >> 23) & 0x03);
}
// HE-SIG-A2
i.ReadU32();
if (m_heSigBPresent)
{
// HE-SIG-B
m_ruAllocation.clear();
m_contentChannels.clear();
std::size_t ruAllocationSize = 0;
const auto bw = GetChannelWidth();
switch (bw)
{
case 20:
ruAllocationSize = 1;
break;
case 40:
ruAllocationSize = 2;
break;
case 80:
ruAllocationSize = 4;
break;
case 160:
ruAllocationSize = 8;
break;
default:
NS_FATAL_ERROR("Invalid channel width: " << bw << " MHz");
}
m_ruAllocation.resize(ruAllocationSize);
std::vector<uint32_t> userBlockFieldsContentChannel1;
std::vector<uint32_t> userBlockFieldsContentChannel2;
if (bw < 80)
{
m_center26ToneRuIndication = std::nullopt;
}
else
{
m_center26ToneRuIndication = CENTER_26_TONE_RU_UNALLOCATED;
}
uint16_t nBytes = DeserializeSigBContentChannel(i, 1, userBlockFieldsContentChannel1);
i.Next(nBytes);
m_contentChannels.emplace_back();
for (auto userField : userBlockFieldsContentChannel1)
{
uint16_t staId = (userField & 0x07ff);
uint8_t nss = (userField >> 11) & 0x07;
uint8_t mcs = (userField >> 15) & 0x0f;
m_contentChannels.at(0).push_back({staId, nss, mcs});
}
if (bw >= 40)
{
nBytes = DeserializeSigBContentChannel(i, 2, userBlockFieldsContentChannel2);
i.Next(nBytes);
m_contentChannels.emplace_back();
for (auto userField : userBlockFieldsContentChannel2)
{
uint16_t staId = (userField & 0x07ff);
uint8_t nss = (userField >> 11) & 0x07;
uint8_t mcs = (userField >> 15) & 0x0f;
m_contentChannels.at(1).push_back({staId, nss, mcs});
}
}
}
return i.GetDistanceFrom(start);
}
} // namespace ns3

View File

@@ -50,7 +50,7 @@ class HePpdu : public OfdmPpdu
/**
* HE-SIG PHY header (HE-SIG-A1/A2/B)
*/
class HeSigHeader : public Header
class HeSigHeader
{
public:
HeSigHeader();
@@ -61,18 +61,6 @@ class HePpdu : public OfdmPpdu
*/
HeSigHeader(bool heSigBPresent);
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId();
TypeId GetInstanceTypeId() const override;
void Print(std::ostream& os) const override;
uint32_t GetSerializedSize() const override;
void Serialize(Buffer::Iterator start) const override;
uint32_t Deserialize(Buffer::Iterator start) override;
/**
* Set whether HE-SIG-B fields are present or not.
*
@@ -208,32 +196,6 @@ class HePpdu : public OfdmPpdu
* \return the size of HE-SIG-B in bytes
*/
uint32_t GetSigBSize() const;
/**
* Serialize one user field content channel.
*
* \param start an iterator which points to where the user field content channel should be
* written
* \param contentChannelId the ID of the content channel (either 1 or 2)
* \param userBlockFieldsContentChannel the user block fields contained in the content
* channel to write
*/
void SerializeSigBContentChannel(
Buffer::Iterator& start,
uint8_t contentChannelId,
const std::vector<uint32_t>& userBlockFieldsContentChannel) const;
/**
* Deserialize one user field content channel.
*
* \param start an iterator which points to where the user field
* content channel should be read
* \param contentChannelId the ID of the content channel (either 1 or 2)
* \param userBlockFieldsContentChannel the user block fields to fill in
* \return the number of bytes read
*/
uint16_t DeserializeSigBContentChannel(
Buffer::Iterator start,
uint8_t contentChannelId,
std::vector<uint32_t>& userBlockFieldsContentChannel);
// HE-SIG-A1 fields
uint8_t m_format; ///< Format bit
@@ -378,7 +340,7 @@ class HePpdu : public OfdmPpdu
*/
void SetHeMuUserInfos(WifiTxVector& txVector, const HeSigHeader& heSig) const;
HeSigHeader m_heSig; //!< the HE-SIG PHY header
HeSigHeader m_heSig; //!< the HE-SIG PHY header
mutable TxPsdFlag m_txPsdFlag; //!< the transmit power spectral density flag
private:

View File

@@ -130,35 +130,6 @@ HtPpdu::HtSigHeader::HtSigHeader()
{
}
TypeId
HtPpdu::HtSigHeader::GetTypeId()
{
static TypeId tid = TypeId("ns3::HtSigHeader")
.SetParent<Header>()
.SetGroupName("Wifi")
.AddConstructor<HtSigHeader>();
return tid;
}
TypeId
HtPpdu::HtSigHeader::GetInstanceTypeId() const
{
return GetTypeId();
}
void
HtPpdu::HtSigHeader::Print(std::ostream& os) const
{
os << "MCS=" << +m_mcs << " HT_LENGTH=" << m_htLength << " CHANNEL_WIDTH=" << GetChannelWidth()
<< " SGI=" << +m_sgi << " AGGREGATION=" << +m_aggregation;
}
uint32_t
HtPpdu::HtSigHeader::GetSerializedSize() const
{
return 6;
}
void
HtPpdu::HtSigHeader::SetMcs(uint8_t mcs)
{
@@ -220,33 +191,4 @@ HtPpdu::HtSigHeader::GetShortGuardInterval() const
return m_sgi;
}
void
HtPpdu::HtSigHeader::Serialize(Buffer::Iterator start) const
{
uint8_t byte = m_mcs;
byte |= ((m_cbw20_40 & 0x01) << 7);
start.WriteU8(byte);
start.WriteU16(m_htLength);
byte = (0x01 << 2); // Set Reserved bit #2 to 1
byte |= ((m_aggregation & 0x01) << 3);
byte |= ((m_sgi & 0x01) << 7);
start.WriteU8(byte);
start.WriteU16(0);
}
uint32_t
HtPpdu::HtSigHeader::Deserialize(Buffer::Iterator start)
{
Buffer::Iterator i = start;
uint8_t byte = i.ReadU8();
m_mcs = byte & 0x7f;
m_cbw20_40 = ((byte >> 7) & 0x01);
m_htLength = i.ReadU16();
byte = i.ReadU8();
m_aggregation = ((byte >> 3) & 0x01);
m_sgi = ((byte >> 7) & 0x01);
i.ReadU16();
return i.GetDistanceFrom(start);
}
} // namespace ns3

View File

@@ -48,23 +48,11 @@ class HtPpdu : public OfdmPpdu
* HT PHY header (HT-SIG1/2).
* See section 19.3.9 in IEEE 802.11-2016.
*/
class HtSigHeader : public Header
class HtSigHeader
{
public:
HtSigHeader();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId();
TypeId GetInstanceTypeId() const override;
void Print(std::ostream& os) const override;
uint32_t GetSerializedSize() const override;
void Serialize(Buffer::Iterator start) const override;
uint32_t Deserialize(Buffer::Iterator start) override;
/**
* Fill the MCS field of HT-SIG.
*
@@ -195,7 +183,7 @@ class HtPpdu : public OfdmPpdu
const HtSigHeader& htSig) const;
HtSigHeader m_htSig; //!< the HT-SIG PHY header
}; // class HtPpdu
}; // class HtPpdu
} // namespace ns3

View File

@@ -97,34 +97,6 @@ DsssPpdu::DsssSigHeader::DsssSigHeader()
{
}
TypeId
DsssPpdu::DsssSigHeader::GetTypeId()
{
static TypeId tid = TypeId("ns3::DsssSigHeader")
.SetParent<Header>()
.SetGroupName("Wifi")
.AddConstructor<DsssSigHeader>();
return tid;
}
TypeId
DsssPpdu::DsssSigHeader::GetInstanceTypeId() const
{
return GetTypeId();
}
void
DsssPpdu::DsssSigHeader::Print(std::ostream& os) const
{
os << "SIGNAL=" << GetRate() << " LENGTH=" << m_length;
}
uint32_t
DsssPpdu::DsssSigHeader::GetSerializedSize() const
{
return 6;
}
void
DsssPpdu::DsssSigHeader::SetRate(uint64_t rate)
{
@@ -191,24 +163,4 @@ DsssPpdu::DsssSigHeader::GetLength() const
return m_length;
}
void
DsssPpdu::DsssSigHeader::Serialize(Buffer::Iterator start) const
{
start.WriteU8(m_rate);
start.WriteU8(0); /* SERVICE */
start.WriteU16(m_length);
start.WriteU16(0); /* CRC */
}
uint32_t
DsssPpdu::DsssSigHeader::Deserialize(Buffer::Iterator start)
{
Buffer::Iterator i = start;
m_rate = i.ReadU8();
i.ReadU8(); /* SERVICE */
m_length = i.ReadU16();
i.ReadU16(); /* CRC */
return i.GetDistanceFrom(start);
}
} // namespace ns3

View File

@@ -22,7 +22,6 @@
#ifndef DSSS_PPDU_H
#define DSSS_PPDU_H
#include "ns3/header.h"
#include "ns3/wifi-ppdu.h"
/**
@@ -49,23 +48,11 @@ class DsssPpdu : public WifiPpdu
* DSSS SIG PHY header.
* See section 16.2.2 in IEEE 802.11-2016.
*/
class DsssSigHeader : public Header
class DsssSigHeader
{
public:
DsssSigHeader();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId();
TypeId GetInstanceTypeId() const override;
void Print(std::ostream& os) const override;
uint32_t GetSerializedSize() const override;
void Serialize(Buffer::Iterator start) const override;
uint32_t Deserialize(Buffer::Iterator start) override;
/**
* Fill the RATE field of L-SIG (in bit/s).
*
@@ -146,7 +133,7 @@ class DsssPpdu : public WifiPpdu
const DsssSigHeader& dsssSig) const;
DsssSigHeader m_dsssSig; //!< the DSSS SIG PHY header
}; // class DsssPpdu
}; // class DsssPpdu
} // namespace ns3

View File

@@ -101,34 +101,6 @@ OfdmPpdu::LSigHeader::LSigHeader()
{
}
TypeId
OfdmPpdu::LSigHeader::GetTypeId()
{
static TypeId tid = TypeId("ns3::LSigHeader")
.SetParent<Header>()
.SetGroupName("Wifi")
.AddConstructor<LSigHeader>();
return tid;
}
TypeId
OfdmPpdu::LSigHeader::GetInstanceTypeId() const
{
return GetTypeId();
}
void
OfdmPpdu::LSigHeader::Print(std::ostream& os) const
{
os << "SIGNAL=" << GetRate() << " LENGTH=" << m_length;
}
uint32_t
OfdmPpdu::LSigHeader::GetSerializedSize() const
{
return 3;
}
void
OfdmPpdu::LSigHeader::SetRate(uint64_t rate, uint16_t channelWidth)
{
@@ -240,33 +212,4 @@ OfdmPpdu::LSigHeader::GetLength() const
return m_length;
}
void
OfdmPpdu::LSigHeader::Serialize(Buffer::Iterator start) const
{
uint8_t byte = 0;
uint16_t bytes = 0;
byte |= m_rate;
byte |= (m_length & 0x07) << 5;
start.WriteU8(byte);
bytes |= (m_length & 0x0ff8) >> 3;
start.WriteU16(bytes);
}
uint32_t
OfdmPpdu::LSigHeader::Deserialize(Buffer::Iterator start)
{
Buffer::Iterator i = start;
uint8_t byte = i.ReadU8();
m_rate = byte & 0x0f;
m_length = (byte >> 5) & 0x07;
uint16_t bytes = i.ReadU16();
m_length |= (bytes << 3) & 0x0ff8;
return i.GetDistanceFrom(start);
}
} // namespace ns3

View File

@@ -22,7 +22,6 @@
#ifndef OFDM_PPDU_H
#define OFDM_PPDU_H
#include "ns3/header.h"
#include "ns3/wifi-phy-band.h"
#include "ns3/wifi-ppdu.h"
@@ -51,23 +50,11 @@ class OfdmPpdu : public WifiPpdu
* OFDM and ERP OFDM L-SIG PHY header.
* See section 17.3.4 in IEEE 802.11-2016.
*/
class LSigHeader : public Header
class LSigHeader
{
public:
LSigHeader();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId();
TypeId GetInstanceTypeId() const override;
void Print(std::ostream& os) const override;
uint32_t GetSerializedSize() const override;
void Serialize(Buffer::Iterator start) const override;
uint32_t Deserialize(Buffer::Iterator start) override;
/**
* Fill the RATE field of L-SIG (in bit/s).
*

View File

@@ -117,7 +117,8 @@ VhtPpdu::GetTxDuration() const
const auto sgiDisambiguation = m_vhtSig.GetShortGuardIntervalDisambiguation();
const auto tSymbol = NanoSeconds(3200 + txVector.GetGuardInterval());
const auto preambleDuration = WifiPhy::CalculatePhyPreambleAndHeaderDuration(txVector);
const auto calculatedDuration = MicroSeconds(((ceil(static_cast<double>(length + 3) / 3)) * 4) + 20);
const auto calculatedDuration =
MicroSeconds(((ceil(static_cast<double>(length + 3) / 3)) * 4) + 20);
uint32_t nSymbols =
floor(static_cast<double>((calculatedDuration - preambleDuration).GetNanoSeconds()) /
tSymbol.GetNanoSeconds());
@@ -150,42 +151,6 @@ VhtPpdu::VhtSigHeader::VhtSigHeader()
{
}
TypeId
VhtPpdu::VhtSigHeader::GetTypeId()
{
static TypeId tid = TypeId("ns3::VhtSigHeader")
.SetParent<Header>()
.SetGroupName("Wifi")
.AddConstructor<VhtSigHeader>();
return tid;
}
TypeId
VhtPpdu::VhtSigHeader::GetInstanceTypeId() const
{
return GetTypeId();
}
void
VhtPpdu::VhtSigHeader::Print(std::ostream& os) const
{
os << "SU_MCS=" << +m_suMcs << " CHANNEL_WIDTH=" << GetChannelWidth() << " SGI=" << +m_sgi
<< " NSTS=" << +m_nsts << " MU=" << +m_mu;
}
uint32_t
VhtPpdu::VhtSigHeader::GetSerializedSize() const
{
uint32_t size = 0;
size += 3; // VHT-SIG-A1
size += 3; // VHT-SIG-A2
if (m_mu)
{
size += 4; // VHT-SIG-B
}
return size;
}
void
VhtPpdu::VhtSigHeader::SetMuFlag(bool mu)
{
@@ -284,57 +249,4 @@ VhtPpdu::VhtSigHeader::GetSuMcs() const
return m_suMcs;
}
void
VhtPpdu::VhtSigHeader::Serialize(Buffer::Iterator start) const
{
// VHT-SIG-A1
uint8_t byte = m_bw;
byte |= (0x01 << 2); // Set Reserved bit #2 to 1
start.WriteU8(byte);
uint16_t bytes = (m_nsts & 0x07) << 2;
bytes |= (0x01 << (23 - 8)); // Set Reserved bit #23 to 1
start.WriteU16(bytes);
// VHT-SIG-A2
byte = m_sgi & 0x01;
byte |= ((m_sgi_disambiguation & 0x01) << 1);
byte |= ((m_suMcs & 0x0f) << 4);
start.WriteU8(byte);
bytes = (0x01 << (9 - 8)); // Set Reserved bit #9 to 1
start.WriteU16(bytes);
if (m_mu)
{
// VHT-SIG-B
start.WriteU32(0);
}
}
uint32_t
VhtPpdu::VhtSigHeader::Deserialize(Buffer::Iterator start)
{
Buffer::Iterator i = start;
// VHT-SIG-A1
uint8_t byte = i.ReadU8();
m_bw = byte & 0x03;
uint16_t bytes = i.ReadU16();
m_nsts = ((bytes >> 2) & 0x07);
// VHT-SIG-A2
byte = i.ReadU8();
m_sgi = byte & 0x01;
m_sgi_disambiguation = ((byte >> 1) & 0x01);
m_suMcs = ((byte >> 4) & 0x0f);
i.ReadU16();
if (m_mu)
{
// VHT-SIG-B
i.ReadU32();
}
return i.GetDistanceFrom(start);
}
} // namespace ns3

View File

@@ -49,23 +49,11 @@ class VhtPpdu : public OfdmPpdu
* VHT PHY header (VHT-SIG-A1/A2/B).
* See section 21.3.8 in IEEE 802.11-2016.
*/
class VhtSigHeader : public Header
class VhtSigHeader
{
public:
VhtSigHeader();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId();
TypeId GetInstanceTypeId() const override;
void Print(std::ostream& os) const override;
uint32_t GetSerializedSize() const override;
void Serialize(Buffer::Iterator start) const override;
uint32_t Deserialize(Buffer::Iterator start) override;
/**
* Set the Multi-User (MU) flag.
*
@@ -210,7 +198,7 @@ class VhtPpdu : public OfdmPpdu
const VhtSigHeader& vhtSig) const;
VhtSigHeader m_vhtSig; //!< the VHT-SIG PHY header
}; // class VhtPpdu
}; // class VhtPpdu
} // namespace ns3