wifi: Add initial support for HE MU and HE MU Other User fields in radiotap header
This commit is contained in:
committed by
Sebastien Deronne
parent
2e22c3da6b
commit
ed83b8fa3b
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user