wifi: Cleanup PHY headers serialization and deserialization
This commit is contained in:
committed by
Sebastien Deronne
parent
bce3ec21e5
commit
e09443d148
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user