From ed83b8fa3b16d4d701b07474433d00e27aa5d43f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Sun, 8 Sep 2019 15:02:11 +0200 Subject: [PATCH] wifi: Add initial support for HE MU and HE MU Other User fields in radiotap header --- src/network/utils/radiotap-header.cc | 114 ++++++++++++++++++++++++++- src/network/utils/radiotap-header.h | 84 +++++++++++++++++++- src/wifi/helper/wifi-helper.cc | 8 ++ 3 files changed, 202 insertions(+), 4 deletions(-) diff --git a/src/network/utils/radiotap-header.cc b/src/network/utils/radiotap-header.cc index b7e35a175..0a2abd00d 100644 --- a/src/network/utils/radiotap-header.cc +++ b/src/network/utils/radiotap-header.cc @@ -56,7 +56,15 @@ RadiotapHeader::RadiotapHeader () m_heData3 (0), m_heData4 (0), m_heData5 (0), - m_heData6 (0) + m_heData6 (0), + m_heMuPad (0), + m_heMuFlags1 (0), + m_heMuFlags2 (0), + m_heMuOtherUserPad (0), + m_heMuPerUser1 (0), + m_heMuPerUser2 (0), + m_heMuPerUserPosition (0), + m_heMuPerUserKnown (0) { NS_LOG_FUNCTION (this); } @@ -278,6 +286,36 @@ RadiotapHeader::Serialize (Buffer::Iterator start) const start.WriteU16 (m_heData5); start.WriteU16 (m_heData6); } + + // + // HE MU field. + // + if (m_present & RADIOTAP_HE_MU) // bit 24 + { + start.WriteU8 (0, m_heMuPad); + start.WriteU16 (m_heMuFlags1); + start.WriteU16 (m_heMuFlags2); + start.WriteU8 (0); + start.WriteU8 (0); + start.WriteU8 (0); + start.WriteU8 (0); + start.WriteU8 (0); + start.WriteU8 (0); + start.WriteU8 (0); + start.WriteU8 (0); + } + + // + // HE MU other user field. + // + if (m_present & RADIOTAP_HE_MU_OTHER_USER) // bit 25 + { + start.WriteU8 (0, m_heMuOtherUserPad); + start.WriteU16 (m_heMuPerUser1); + start.WriteU16 (m_heMuPerUser2); + start.WriteU8 (m_heMuPerUserPosition); + start.WriteU8 (m_heMuPerUserKnown); + } } uint32_t @@ -509,6 +547,38 @@ RadiotapHeader::Deserialize (Buffer::Iterator start) bytesRead += (12 + m_hePad); } + // + // HE MU field. + // + if (m_present & RADIOTAP_HE_MU) // bit 24 + { + m_heMuPad = ((2 - bytesRead % 2) % 2); + m_heMuFlags1 = start.ReadU16 (); + m_heMuFlags2 = start.ReadU16 (); + start.ReadU8 (); + start.ReadU8 (); + start.ReadU8 (); + start.ReadU8 (); + start.ReadU8 (); + start.ReadU8 (); + start.ReadU8 (); + start.ReadU8 (); + bytesRead += (12 + m_heMuPad); + } + + // + // HE MU other user field. + // + if (m_present & RADIOTAP_HE_MU_OTHER_USER) // bit 25 + { + m_heMuOtherUserPad = ((2 - bytesRead % 2) % 2); + m_heMuPerUser1 = start.ReadU16 (); + m_heMuPerUser2 = start.ReadU16 (); + m_heMuPerUserPosition = start.ReadU8 (); + m_heMuPerUserKnown = start.ReadU8 (); + bytesRead += (6 + m_heMuOtherUserPad); + } + NS_ASSERT_MSG (m_length == bytesRead, "RadiotapHeader::Deserialize(): expected and actual lengths inconsistent"); return bytesRead; } @@ -543,7 +613,13 @@ RadiotapHeader::Print (std::ostream &os) const << " heData3=" << m_heData3 << " heData4=" << m_heData4 << " heData5=" << m_heData5 - << " heData6=" << m_heData6; + << " heData6=" << m_heData6 + << " heMuFlags1=" << m_heMuFlags1 + << " heMuFlags2=" << m_heMuFlags2 + << " heMuPerUser1=" << m_heMuPerUser1 + << " heMuPerUser2=" << m_heMuPerUser2 + << " heMuPerUserPosition=" << +m_heMuPerUserPosition + << " heMuPerUserKnown=" << +m_heMuPerUserKnown; } void @@ -737,4 +813,38 @@ RadiotapHeader::SetHeFields (uint16_t data1, uint16_t data2, uint16_t data3, uin NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec); } +void +RadiotapHeader::SetHeMuFields (uint16_t flags1, uint16_t flags2, const std::array &/*ruChannel1*/, const std::array &/*ruChannel2*/) +{ + NS_LOG_FUNCTION (this << flags1 << flags2); + m_heMuFlags1 = flags1; + m_heMuFlags2 = flags2; + if (!(m_present & RADIOTAP_HE_MU)) + { + m_heMuPad = ((2 - m_length % 2) % 2); + m_present |= RADIOTAP_HE_MU; + m_length += (12 + m_heMuPad); + } + + NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec); +} + +void +RadiotapHeader::SetHeMuPerUserFields (uint16_t per_user_1, uint16_t per_user_2, uint8_t perUserPosition, uint8_t perUserKnown) +{ + NS_LOG_FUNCTION (this << per_user_1 << per_user_2 << +perUserPosition << +perUserKnown); + m_heMuPerUser1 = per_user_1; + m_heMuPerUser2 = per_user_2; + m_heMuPerUserPosition = perUserPosition; + m_heMuPerUserKnown = perUserKnown; + if (!(m_present & RADIOTAP_HE_MU_OTHER_USER)) + { + m_heMuOtherUserPad = ((2 - m_length % 2) % 2); + m_present |= RADIOTAP_HE_MU_OTHER_USER; + m_length += (6 + m_heMuOtherUserPad); + } + + 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 fc671a55b..12f1c6b85 100644 --- a/src/network/utils/radiotap-header.h +++ b/src/network/utils/radiotap-header.h @@ -22,7 +22,6 @@ #ifndef RADIOTAP_HEADER_H #define RADIOTAP_HEADER_H - #include namespace ns3 { @@ -365,6 +364,73 @@ public: uint16_t data5, uint16_t data6); + /** + * @brief HE MU flags1. + */ + enum HeMuFlags1 + { + HE_MU_FLAGS1_SIGB_MCS = 0x000f, /**< SIG-B MCS (from SIG-A) */ + HE_MU_FLAGS1_SIGB_MCS_KNOWN = 0x0010, /**< SIG-B MCS known */ + HE_MU_FLAGS1_SIGB_DCM = 0x0020, /**< SIG-B DCM (from SIG-A) */ + HE_MU_FLAGS1_SIGB_DCM_KNOWN = 0x0040, /**< SIG-B DCM known */ + HE_MU_FLAGS1_CH2_CENTER_26T_RU_KNOWN = 0x0080, /**< (Channel 2) Center 26-tone RU bit known */ + HE_MU_FLAGS1_CH1_RUS_KNOWN = 0x0100, /**< Channel 1 RUs known (which depends on BW) */ + HE_MU_FLAGS1_CH2_RUS_KNOWN = 0x0200, /**< Channel 2 RUs known (which depends on BW) */ + HE_MU_FLAGS1_CH1_CENTER_26T_RU_KNOWN = 0x1000, /**< (Channel 1) Center 26-tone RU bit known */ + HE_MU_FLAGS1_CH1_CENTER_26T_RU = 0x2000, /**< (Channel 1) Center 26-tone RU value */ + HE_MU_FLAGS1_SIGB_COMPRESSION_KNOWN = 0x4000, /**< SIG-B Compression known */ + HE_MU_FLAGS1_NUM_SIGB_SYMBOLS_KNOWN = 0x8000, /**< # of HE-SIG-B Symbols/MU-MIMO Users known */ + }; + + /** + * @brief HE MU flags2. + */ + enum HeMuFlags2 + { + HE_MU_FLAGS2_BW_FROM_SIGA = 0x0003, /**< Bandwidth from Bandwidth field in HE-SIG-A */ + HE_MU_FLAGS2_BW_FROM_SIGA_KNOWN = 0x0004, /**< Bandwidth from Bandwidth field in HE-SIG-A known */ + HE_MU_FLAGS2_SIGB_COMPRESSION_FROM_SIGA = 0x0008, /**< SIG-B compression from SIG-A */ + HE_MU_FLAGS2_NUM_SIGB_SYMBOLS_FROM_SIGA = 0x00f0, /**< # of HE-SIG-B Symbols - 1 or # of MU-MIMO Users - 1 from SIG-A */ + HE_MU_FLAGS2_PREAMBLE_PUNCTURING_FROM_SIGA_BW_FIELD = 0x0300, /**< Preamble puncturing from Bandwidth field in HE-SIG-A */ + HE_MU_FLAGS2_PREAMBLE_PUNCTURING_FROM_SIGA_BW_FIELD_KNOWN = 0x0400, /**< Preamble puncturing from Bandwidth field in HE-SIG-A known */ + HE_MU_FLAGS2_CH2_CENTER_26T_RU = 0x0800, /**< (Channel 2) Center 26-tone RU value */ + }; + + /** + * @brief Set the HE MU fields + * + * @param flags1 The flags1 field. + * @param flags2 The flags2 field. + * @param ruChannel1 The RU_channel1 field. + * @param ruChannel2 The RU_channel2 field. + */ + void SetHeMuFields (uint16_t flags1, uint16_t flags2, const std::array &ruChannel1, const std::array &ruChannel2); + + /** + * @brief HE MU per_user_known. + */ + enum HeMuPerUserKnown + { + HE_MU_PER_USER_POSITION_KNOWN = 0x01, /**< User field position known */ + HE_MU_PER_USER_STA_ID_KNOWN = 0x02, /**< STA-ID known */ + HE_MU_PER_USER_NSTS_KNOWN = 0x04, /**< NSTS known */ + HE_MU_PER_USER_TX_BF_KNOWN = 0x08, /**< Tx Beamforming known */ + HE_MU_PER_USER_SPATIAL_CONFIGURATION_KNOWN = 0x10, /**< Spatial Configuration known */ + HE_MU_PER_USER_MCS_KNOWN = 0x20, /**< MCS known */ + HE_MU_PER_USER_DCM_KNOWN = 0x40, /**< DCM known */ + HE_MU_PER_USER_CODING_KNOWN = 0x80, /**< Coding known */ + }; + + /** + * @brief Set the HE MU per user fields + * + * @param perUser1 The per_user_1 field. + * @param perUser2 The per_user_2 field. + * @param perUserPosition The per_user_position field. + * @param perUserKnown The per_user_known field. + */ + void SetHeMuPerUserFields (uint16_t per_user_1, uint16_t per_user_2, uint8_t perUserPosition, uint8_t perUserKnown); + private: /** * @brief Radiotap flags. @@ -390,7 +456,11 @@ private: RADIOTAP_AMPDU_STATUS = 0x00100000, RADIOTAP_VHT = 0x00200000, RADIOTAP_HE = 0x00800000, - RADIOTAP_EXT = 0x10000000 + RADIOTAP_HE_MU = 0x01000000, + RADIOTAP_HE_MU_OTHER_USER = 0x02000000, + RADIOTAP_ZERO_LEN_PSDU = 0x04000000, + RADIOTAP_LSIG = 0x08000000, + RADIOTAP_EXT = 0x80000000 }; uint16_t m_length; //!< entire length of radiotap data + header @@ -430,6 +500,16 @@ private: uint16_t m_heData4; //!< HE data4 field. uint16_t m_heData5; //!< HE data5 field. uint16_t m_heData6; //!< HE data6 field. + + uint8_t m_heMuPad; //!< HE MU padding. + uint16_t m_heMuFlags1; //!< HE MU flags1 field. + uint16_t m_heMuFlags2; //!< HE MU flags2 field. + + uint8_t m_heMuOtherUserPad; //!< HE MU other user padding. + uint16_t m_heMuPerUser1; //!< HE MU per_user_1 field. + uint16_t m_heMuPerUser2; //!< HE MU per_user_2 field. + uint8_t m_heMuPerUserPosition; //!< HE MU per_user_position field. + uint8_t m_heMuPerUserKnown; //!< HE MU per_user_known field. }; } // namespace ns3 diff --git a/src/wifi/helper/wifi-helper.cc b/src/wifi/helper/wifi-helper.cc index 388f7bae3..2396b8ca2 100644 --- a/src/wifi/helper/wifi-helper.cc +++ b/src/wifi/helper/wifi-helper.cc @@ -566,6 +566,14 @@ WifiPhyHelper::GetRadiotapHeader ( header.SetHeFields (data1, data2, data3, data4, data5, 0); } + + if (preamble == WIFI_PREAMBLE_HE_MU) + { + //TODO: fill in fields (everything is set to 0 so far) + std::array ruChannel1, ruChannel2; + header.SetHeMuFields (0, 0, ruChannel1, ruChannel2); + header.SetHeMuPerUserFields (0, 0, 0, 0); + } } void