diff --git a/src/network/utils/radiotap-header.cc b/src/network/utils/radiotap-header.cc index 7daa4ef97..085084906 100644 --- a/src/network/utils/radiotap-header.cc +++ b/src/network/utils/radiotap-header.cc @@ -49,7 +49,12 @@ RadiotapHeader::RadiotapHeader () m_vhtBandwidth (0), m_vhtCoding (0), m_vhtGroupId (0), - m_vhtPartialAid (0) + m_vhtPartialAid (0), + m_hePad (0), + m_heData1 (0), + m_heData2 (0), + m_heData3 (0), + m_heData5 (0) { NS_LOG_FUNCTION (this); } @@ -257,6 +262,20 @@ RadiotapHeader::Serialize (Buffer::Iterator start) const start.WriteU8 (m_vhtGroupId); start.WriteU16 (m_vhtPartialAid); } + + // + // HE field. + // + if (m_present & RADIOTAP_HE) // bit 23 + { + start.WriteU8 (0, m_hePad); + start.WriteU16 (m_heData1); + start.WriteU16 (m_heData2); + start.WriteU16 (m_heData3); + start.WriteU16 (0); //HE data4 field + start.WriteU16 (m_heData5); + start.WriteU16 (0); //HE data6 field + } } uint32_t @@ -472,6 +491,22 @@ RadiotapHeader::Deserialize (Buffer::Iterator start) bytesRead += (12 + m_vhtPad); } + // + // HE field. + // + if (m_present & RADIOTAP_HE) // bit 23 + { + m_hePad = ((2 - bytesRead % 2) % 2); + start.Next (m_hePad); + m_heData1 = start.ReadU16 (); + m_heData2 = start.ReadU16 (); + m_heData3 = start.ReadU16 (); + start.ReadU16 (); //HE data4 field + m_heData5 = start.ReadU16 (); + start.ReadU16 (); //HE data6 field + bytesRead += (12 + m_hePad); + } + NS_ASSERT_MSG (m_length == bytesRead, "RadiotapHeader::Deserialize(): expected and actual lengths inconsistent"); return bytesRead; } @@ -482,15 +517,15 @@ RadiotapHeader::Print (std::ostream &os) const NS_LOG_FUNCTION (this << &os); os << " tsft=" << m_tsft << " flags=" << std::hex << m_flags << std::dec - << " rate=" << (uint16_t) m_rate + << " rate=" << +m_rate << " freq=" << m_channelFreq - << " chflags=" << std::hex << (uint32_t)m_channelFlags << std::dec - << " signal=" << (int16_t) m_antennaSignal - << " noise=" << (int16_t) m_antennaNoise + << " chflags=" << std::hex << +m_channelFlags << std::dec + << " signal=" << +m_antennaSignal + << " noise=" << +m_antennaNoise << " mcsKnown=" << m_mcsKnown << " mcsFlags=" << m_mcsFlags << " mcsRate=" << m_mcsRate - << " ampduStatusFlags=" << (int16_t) m_ampduStatusFlags + << " ampduStatusFlags=" << +m_ampduStatusFlags << " vhtKnown=" << m_vhtKnown << " vhtFlags=" << m_vhtFlags << " vhtBandwidth=" << m_vhtBandwidth @@ -500,7 +535,11 @@ RadiotapHeader::Print (std::ostream &os) const << " vhtMcsNss for user 4=" << m_vhtMcsNss[3] << " vhtCoding=" << m_vhtCoding << " vhtGroupId=" << m_vhtGroupId - << " vhtPartialAid=" << m_vhtPartialAid; + << " vhtPartialAid=" << m_vhtPartialAid + << " heData1=" << m_heData1 + << " heData2=" << m_heData2 + << " heData3=" << m_heData3 + << " heData5=" << m_heData5; } void @@ -521,7 +560,7 @@ RadiotapHeader::SetTsft (uint64_t value) void RadiotapHeader::SetFrameFlags (uint8_t flags) { - NS_LOG_FUNCTION (this << static_cast (flags)); + NS_LOG_FUNCTION (this << +flags); m_flags = flags; if (!(m_present & RADIOTAP_FLAGS)) @@ -536,7 +575,7 @@ RadiotapHeader::SetFrameFlags (uint8_t flags) void RadiotapHeader::SetRate (uint8_t rate) { - NS_LOG_FUNCTION (this << static_cast (rate)); + NS_LOG_FUNCTION (this << +rate); m_rate = rate; if (!(m_present & RADIOTAP_RATE)) @@ -620,7 +659,7 @@ RadiotapHeader::SetAntennaNoisePower (double noise) void RadiotapHeader::SetMcsFields (uint8_t known, uint8_t flags, uint8_t mcs) { - NS_LOG_FUNCTION (this << known << flags << mcs); + NS_LOG_FUNCTION (this << known << +flags << +mcs); m_mcsKnown = known; m_mcsFlags = flags; m_mcsRate = mcs; @@ -653,7 +692,7 @@ RadiotapHeader::SetAmpduStatus (uint32_t referenceNumber, uint16_t flags, uint8_ void RadiotapHeader::SetVhtFields (uint16_t known, uint8_t flags, uint8_t bandwidth, uint8_t mcs_nss[4], uint8_t coding, uint8_t group_id, uint16_t partial_aid) { - NS_LOG_FUNCTION (this << known << flags << mcs_nss[0] << mcs_nss[1] << mcs_nss[2] << mcs_nss[3] << coding << group_id << partial_aid); + NS_LOG_FUNCTION (this << known << flags << +mcs_nss[0] << +mcs_nss[1] << +mcs_nss[2] << +mcs_nss[3] << +coding << +group_id << +partial_aid); m_vhtKnown = known; m_vhtFlags = flags; m_vhtBandwidth = bandwidth; @@ -674,4 +713,22 @@ RadiotapHeader::SetVhtFields (uint16_t known, uint8_t flags, uint8_t bandwidth, NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec); } +void +RadiotapHeader::SetHeFields (uint16_t data1, uint16_t data2, uint16_t data3, uint16_t data5) +{ + NS_LOG_FUNCTION (this << data1 << data2 << data3 << data5); + m_heData1 = data1; + m_heData2 = data2; + m_heData3 = data3; + m_heData5 = data5; + if (!(m_present & RADIOTAP_HE)) + { + m_hePad = ((2 - m_length % 2) % 2); + m_present |= RADIOTAP_HE; + m_length += 12; + } + + NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec); +} + } // namespace ns3 diff --git a/src/network/utils/radiotap-header.h b/src/network/utils/radiotap-header.h index fdafc481a..de45165e7 100644 --- a/src/network/utils/radiotap-header.h +++ b/src/network/utils/radiotap-header.h @@ -282,6 +282,97 @@ public: uint8_t coding, uint8_t group_id, uint16_t partial_aid); + /** + * @brief HE data1. + */ + enum HeData1 + { + HE_DATA1_FORMAT_EXT_SU = 0x0001, /**< HE EXT SU PPDU format */ + HE_DATA1_FORMAT_MU = 0x0002, /**< HE MU PPDU format */ + HE_DATA1_FORMAT_TRIG = 0x0003, /**< HE TRIG PPDU format */ + HE_DATA1_BSS_COLOR_KNOWN = 0x0004, /**< BSS Color known */ + HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008, /**< Beam Change known */ + HE_DATA1_UL_DL_KNOWN = 0x0010, /**< UL/DL known */ + HE_DATA1_DATA_MCS_KNOWN = 0x0020, /**< data MCS known */ + HE_DATA1_DATA_DCM_KNOWN = 0x0040, /**< data DCM known */ + HE_DATA1_CODING_KNOWN = 0x0080, /**< Coding known */ + HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100, /**< LDPC extra symbol segment known */ + HE_DATA1_STBC_KNOWN = 0x0200, /**< STBC known */ + HE_DATA1_SPTL_REUSE_KNOWN = 0x0400, /**< Spatial Reuse known (Spatial Reuse 1 for HE TRIG PPDU format) */ + HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800, /**< Spatial Reuse 2 known (HE TRIG PPDU format), STA-ID known (HE MU PPDU format) */ + HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000, /**< Spatial Reuse 3 known (HE TRIG PPDU format) */ + HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000, /**< Spatial Reuse 4 known (HE TRIG PPDU format) */ + HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000, /**< data BW/RU allocation known */ + HE_DATA1_DOPPLER_KNOWN = 0x8000, /**< Doppler known */ + }; + + /** + * @brief HE data2. + */ + enum HeData2 + { + HE_DATA2_PRISEC_80_KNOWN = 0x0001, /**< pri/sec 80 MHz known */ + HE_DATA2_GI_KNOWN = 0x0002, /**< GI known */ + HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004, /**< number of LTF symbols known */ + HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008, /**< Pre-FEC Padding Factor known */ + HE_DATA2_TXBF_KNOWN = 0x0010, /**< TxBF known */ + HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020, /**< PE Disambiguity known */ + HE_DATA2_TXOP_KNOWN = 0x0040, /**< TXOP known */ + HE_DATA2_MIDAMBLE_KNOWN = 0x0080, /**< midamble periodicity known */ + HE_DATA2_RU_OFFSET = 0x3f00, /**< RU allocation offset */ + HE_DATA2_RU_OFFSET_KNOWN = 0x4000, /**< RU allocation offset known */ + HE_DATA2_PRISEC_80_SEC = 0x8000, /**< pri/sec 80 MHz */ + }; + + /** + * @brief HE data3. + */ + enum HeData3 + { + HE_DATA3_BSS_COLOR = 0x003f, /**< BSS Color */ + HE_DATA3_BEAM_CHANGE = 0x0040, /**< Beam Change */ + HE_DATA3_UL_DL = 0x0080, /**< UL/DL */ + HE_DATA3_DATA_MCS = 0x0f00, /**< data MCS */ + HE_DATA3_DATA_DCM = 0x1000, /**< data DCM */ + HE_DATA3_CODING = 0x2000, /**< Coding */ + HE_DATA3_LDPC_XSYMSEG = 0x4000, /**< LDPC extra symbol segment */ + HE_DATA3_STBC = 0x8000, /**< STBC */ + }; + + /** + * @brief HE data5. + */ + enum HeData5 + { + HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 0x0001, /**< 40 MHz data Bandwidth */ + HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 0x0002, /**< 80 MHz data Bandwidth */ + HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 0x0003, /**< 160 MHz data Bandwidth */ + HE_DATA5_DATA_BW_RU_ALLOC_26T = 0x0004, /**< 26-tone RU allocation */ + HE_DATA5_DATA_BW_RU_ALLOC_52T = 0x0005, /**< 52-tone RU allocation */ + HE_DATA5_DATA_BW_RU_ALLOC_106T = 0x0006, /**< 106-tone RU allocation */ + HE_DATA5_DATA_BW_RU_ALLOC_242T = 0x0007, /**< 242-tone RU allocation */ + HE_DATA5_DATA_BW_RU_ALLOC_484T = 0x0008, /**< 484-tone RU allocation */ + HE_DATA5_DATA_BW_RU_ALLOC_996T = 0x0009, /**< 996-tone RU allocation */ + HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 0x000a, /**< 2x996-tone RU allocation */ + HE_DATA5_GI_1_6 = 0x0010, /**< 1.6us GI */ + HE_DATA5_GI_3_2 = 0x0020, /**< 3.2us GI */ + HE_DATA5_LTF_SYM_SIZE = 0x00c0, /**< LTF symbol size */ + HE_DATA5_NUM_LTF_SYMS = 0x0700, /**< number of LTF symbols */ + HE_DATA5_PRE_FEC_PAD = 0x3000, /**< Pre-FEC Padding Factor */ + HE_DATA5_TXBF = 0x4000, /**< TxBF */ + HE_DATA5_PE_DISAMBIG = 0x8000, /**< PE Disambiguity */ + }; + + /** + * @brief Set the HE fields + * + * @param data1 The data1 field. + * @param data2 The data2 field. + * @param data3 The data3 field. + * @param data5 The data5 field. + */ + void SetHeFields (uint16_t data1, uint16_t data2, uint16_t data3, uint16_t data5); + private: /** * @brief Radiotap flags. @@ -306,6 +397,7 @@ private: RADIOTAP_MCS = 0x00080000, RADIOTAP_AMPDU_STATUS = 0x00100000, RADIOTAP_VHT = 0x00200000, + RADIOTAP_HE = 0x00800000, RADIOTAP_EXT = 0x10000000 }; @@ -338,6 +430,12 @@ private: uint8_t m_vhtCoding; //!< VHT coding field. uint8_t m_vhtGroupId; //!< VHT group_id field. uint16_t m_vhtPartialAid; //!< VHT partial_aid field. + + uint8_t m_hePad; //!< HE padding. + uint16_t m_heData1; //!< HE data1 field. + uint16_t m_heData2; //!< HE data2 field. + uint16_t m_heData3; //!< HE data3 field. + uint16_t m_heData5; //!< HE data5 field. }; } // namespace ns3 diff --git a/src/wifi/helper/wifi-helper.cc b/src/wifi/helper/wifi-helper.cc index 450b2d4e7..6a6d44fad 100644 --- a/src/wifi/helper/wifi-helper.cc +++ b/src/wifi/helper/wifi-helper.cc @@ -396,6 +396,56 @@ WifiPhyHelper::GetRadiotapHeader ( header.SetVhtFields (vhtKnown, vhtFlags, vhtBandwidth, vhtMcsNss, vhtCoding, vhtGroupId, vhtPartialAid); } + + if (txVector.GetMode ().GetModulationClass () == WIFI_MOD_CLASS_HE) + { + uint16_t data1 = RadiotapHeader::HE_DATA1_STBC_KNOWN | RadiotapHeader::HE_DATA1_DATA_MCS_KNOWN; + if (preamble == WIFI_PREAMBLE_HE_ER_SU) + { + data1 |= RadiotapHeader::HE_DATA1_FORMAT_EXT_SU; + } + else if (preamble == WIFI_PREAMBLE_HE_MU) + { + data1 |= RadiotapHeader::HE_DATA1_FORMAT_MU; + } + else if (preamble == WIFI_PREAMBLE_HE_TB) + { + data1 |= RadiotapHeader::HE_DATA1_FORMAT_TRIG; + } + + uint16_t data2 = RadiotapHeader::HE_DATA2_NUM_LTF_SYMS_KNOWN | RadiotapHeader::HE_DATA2_GI_KNOWN; + + uint16_t data3 = 0; + if (txVector.IsStbc ()) + { + data3 |= RadiotapHeader::HE_DATA3_STBC; + } + + uint16_t data5 = 0; + if (txVector.GetChannelWidth () == 40) + { + data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_40MHZ; + } + else if (txVector.GetChannelWidth () == 80) + { + data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_80MHZ; + } + else if (txVector.GetChannelWidth () == 160) + { + data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_160MHZ; + } + if (txVector.GetGuardInterval () == 1600) + { + data5 |= RadiotapHeader::HE_DATA5_GI_1_6; + } + else if (txVector.GetGuardInterval () == 3200) + { + data5 |= RadiotapHeader::HE_DATA5_GI_3_2; + } + + header.SetHeFields (data1, data2, data3, data5); + } + return header; }