wifi: Add initial support for HE MU and HE MU Other User fields in radiotap header

This commit is contained in:
Sébastien Deronne
2019-09-08 15:02:11 +02:00
committed by Sebastien Deronne
parent 2e22c3da6b
commit ed83b8fa3b
3 changed files with 202 additions and 4 deletions

View File

@@ -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<uint8_t, 4> &/*ruChannel1*/, const std::array<uint8_t, 4> &/*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

View File

@@ -22,7 +22,6 @@
#ifndef RADIOTAP_HEADER_H
#define RADIOTAP_HEADER_H
#include <ns3/header.h>
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<uint8_t, 4> &ruChannel1, const std::array<uint8_t, 4> &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

View File

@@ -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<uint8_t, 4> ruChannel1, ruChannel2;
header.SetHeMuFields (0, 0, ruChannel1, ruChannel2);
header.SetHeMuPerUserFields (0, 0, 0, 0);
}
}
void