wifi: Move some HE-SIG-B related functions to HePpdu

This commit is contained in:
Sébastien Deronne
2022-10-10 18:42:06 +02:00
committed by Sebastien Deronne
parent 13083552c0
commit 24669e3f58
11 changed files with 204 additions and 134 deletions

View File

@@ -129,6 +129,18 @@ EhtPhy::GetDuration(WifiPpduField field, const WifiTxVector& txVector) const
}
}
uint32_t
EhtPhy::GetSigBSize(const WifiTxVector& txVector) const
{
if (ns3::IsDlMu(txVector.GetPreambleType()) && ns3::IsEht(txVector.GetPreambleType()))
{
return EhtPpdu::GetEhtSigFieldSize(txVector.GetChannelWidth(),
txVector.GetRuAllocation(),
txVector.GetEhtPpduType());
}
return HePhy::GetSigBSize(txVector);
}
Time
EhtPhy::CalculateNonOfdmaDurationForHeTb(const WifiTxVector& txVector) const
{

View File

@@ -262,6 +262,7 @@ class EhtPhy : public HePhy
WifiPhyRxfailureReason GetFailureReason(WifiPpduField field) const override;
Time CalculateNonOfdmaDurationForHeTb(const WifiTxVector& txVector) const override;
Time CalculateNonOfdmaDurationForHeMu(const WifiTxVector& txVector) const override;
uint32_t GetSigBSize(const WifiTxVector& txVector) const override;
/**
* Create and return the EHT MCS corresponding to

View File

@@ -52,6 +52,7 @@ EhtPpdu::EhtPpdu(const WifiConstPsduMap& psdus,
m_ehtSuMcs = txVector.GetMode().GetMcsValue();
m_ehtSuNStreams = txVector.GetNss();
}
m_ehtPpduType = txVector.GetEhtPpduType();
}
WifiPpduType
@@ -97,10 +98,7 @@ EhtPpdu::SetTxVectorFromPhyHeaders(WifiTxVector& txVector,
txVector.SetBssColor(heSig.GetBssColor());
txVector.SetLength(lSig.GetLength());
txVector.SetAggregation(m_psdus.size() > 1 || m_psdus.begin()->second->IsAggregate());
if (!m_muUserInfos.empty())
{
txVector.SetEhtPpduType(0); // FIXME set to 2 for DL MU-MIMO (non-OFDMA) transmission
}
txVector.SetEhtPpduType(m_ehtPpduType); // FIXME: PPDU type should be read from U-SIG
for (const auto& muUserInfo : m_muUserInfos)
{
txVector.SetHeMuUserInfo(muUserInfo.first, muUserInfo.second);
@@ -112,6 +110,51 @@ EhtPpdu::SetTxVectorFromPhyHeaders(WifiTxVector& txVector,
}
}
std::pair<std::size_t, std::size_t>
EhtPpdu::GetNumRusPerEhtSigBContentChannel(uint16_t channelWidth,
uint8_t ehtPpduType,
const std::vector<uint8_t>& ruAllocation)
{
if (ehtPpduType == 1)
{
return {1, 0};
}
return HePpdu::GetNumRusPerHeSigBContentChannel(channelWidth, ruAllocation);
}
uint32_t
EhtPpdu::GetEhtSigFieldSize(uint16_t channelWidth,
const RuAllocation& ruAllocation,
uint8_t ehtPpduType)
{
// FIXME: EHT-SIG is not implemented yet, hence this is a copy of HE-SIG-B
auto commonFieldSize = 4 /* CRC */ + 6 /* tail */;
if (channelWidth <= 40)
{
commonFieldSize += 8; // only one allocation subfield
}
else
{
commonFieldSize +=
8 * (channelWidth / 40) /* one allocation field per 40 MHz */ + 1 /* center RU */;
}
auto numStaPerContentChannel =
GetNumRusPerEhtSigBContentChannel(channelWidth, ehtPpduType, ruAllocation);
auto maxNumStaPerContentChannel =
std::max(numStaPerContentChannel.first, numStaPerContentChannel.second);
auto maxNumUserBlockFields = maxNumStaPerContentChannel /
2; // handle last user block with single user, if any, further down
std::size_t userSpecificFieldSize =
maxNumUserBlockFields * (2 * 21 /* user fields (2 users) */ + 4 /* tail */ + 6 /* CRC */);
if (maxNumStaPerContentChannel % 2 != 0)
{
userSpecificFieldSize += 21 /* last user field */ + 4 /* CRC */ + 6 /* tail */;
}
return commonFieldSize + userSpecificFieldSize;
}
Ptr<WifiPpdu>
EhtPpdu::Copy() const
{

View File

@@ -62,6 +62,32 @@ class EhtPpdu : public HePpdu
WifiPpduType GetType() const override;
Ptr<WifiPpdu> Copy() const override;
/**
* Get the number of RUs per EHT-SIG-B content channel.
* This function will be used once EHT PHY headers are implemented.
*
* \param channelWidth the channel width occupied by the PPDU (in MHz)
* \param ehtPpduType the EHT_PPDU_TYPE used by the PPDU
* \param ruAllocation 8 bit RU_ALLOCATION per 20 MHz
* \return a pair containing the number of RUs in each EHT-SIG-B content channel (resp. 1 and 2)
*/
static std::pair<std::size_t, std::size_t> GetNumRusPerEhtSigBContentChannel(
uint16_t channelWidth,
uint8_t ehtPpduType,
const std::vector<uint8_t>& ruAllocation);
/**
* Get variable length EHT-SIG field size
* \param channelWidth the channel width occupied by the PPDU (in MHz)
* \param ruAllocation 8 bit RU_ALLOCATION per 20 MHz
* \param ehtPpduType the EHT_PPDU_TYPE used by the PPDU
* \return field size in bytes
*/
static uint32_t GetEhtSigFieldSize(uint16_t channelWidth,
const std::vector<uint8_t>& ruAllocation,
uint8_t ehtPpduType);
private:
bool IsDlMu() const override;
bool IsUlMu() const override;
@@ -71,6 +97,8 @@ class EhtPpdu : public HePpdu
uint8_t m_ehtSuMcs{0}; //!< EHT-MCS for EHT SU transmissions
uint8_t m_ehtSuNStreams{1}; //!< Number of streams for EHT SU transmissions
uint8_t m_ehtPpduType{1}; /**< EHT_PPDU_TYPE per Table 36-1 IEEE 802.11be D2.3.
To be removed once EHT PHY headers are supported. */
}; // class EhtPpdu
} // namespace ns3

View File

@@ -216,14 +216,22 @@ HePhy::GetSigADuration(WifiPreamble preamble) const
: MicroSeconds(8); // HE-SIG-A (first and second symbol)
}
uint32_t
HePhy::GetSigBSize(const WifiTxVector& txVector) const
{
if (ns3::IsDlMu(txVector.GetPreambleType()))
{
NS_ASSERT(txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE);
return HePpdu::GetSigBFieldSize(txVector.GetChannelWidth(), txVector.GetRuAllocation());
}
return 0;
}
Time
HePhy::GetSigBDuration(const WifiTxVector& txVector) const
{
if (ns3::IsDlMu(txVector.GetPreambleType())) // See section 27.3.11.8 of IEEE 802.11ax-2021
if (auto sigBSize = GetSigBSize(txVector); sigBSize > 0)
{
NS_ASSERT(txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE);
auto sigBSize = GetSigBFieldSize(txVector);
auto symbolDuration = MicroSeconds(4);
// Number of data bits per symbol
auto ndbps =
@@ -1779,41 +1787,6 @@ HePhy::GetMaxPsduSize() const
return 6500631;
}
uint32_t
HePhy::GetSigBFieldSize(const WifiTxVector& txVector)
{
NS_ASSERT(txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE);
NS_ASSERT(ns3::IsDlMu(txVector.GetPreambleType()));
// Compute the number of bits used by common field.
// Assume that compression bit in HE-SIG-A is not set (i.e. not
// full band MU-MIMO); the field is present.
auto bw = txVector.GetChannelWidth();
auto commonFieldSize = 4 /* CRC */ + 6 /* tail */;
if (bw <= 40)
{
commonFieldSize += 8; // only one allocation subfield
}
else
{
commonFieldSize += 8 * (bw / 40) /* one allocation field per 40 MHz */ + 1 /* center RU */;
}
auto numStaPerContentChannel = txVector.GetNumRusPerHeSigBContentChannel();
auto maxNumStaPerContentChannel =
std::max(numStaPerContentChannel.first, numStaPerContentChannel.second);
auto maxNumUserBlockFields = maxNumStaPerContentChannel /
2; // handle last user block with single user, if any, further down
std::size_t userSpecificFieldSize =
maxNumUserBlockFields * (2 * 21 /* user fields (2 users) */ + 4 /* tail */ + 6 /* CRC */);
if (maxNumStaPerContentChannel % 2 != 0)
{
userSpecificFieldSize += 21 /* last user field */ + 4 /* CRC */ + 6 /* tail */;
}
return commonFieldSize + userSpecificFieldSize;
}
bool
HePhy::CanStartRx(Ptr<const WifiPpdu> ppdu, uint16_t txChannelWidth) const
{

View File

@@ -423,13 +423,6 @@ class HePhy : public VhtPhy
*/
static bool IsAllowed(const WifiTxVector& txVector);
/**
* Get variable length HE SIG-B field size based on TX Vector
* \param txVector WiFi TX Vector
* \return field size in bytes
*/
static uint32_t GetSigBFieldSize(const WifiTxVector& txVector);
protected:
PhyFieldRxStatus ProcessSig(Ptr<Event> event,
PhyFieldRxStatus status,
@@ -479,6 +472,12 @@ class HePhy : public VhtPhy
*/
virtual PhyFieldRxStatus ProcessSigB(Ptr<Event> event, PhyFieldRxStatus status);
/**
* \param txVector the transmission parameters
* \return the number of bits of the HE-SIG-B
*/
virtual uint32_t GetSigBSize(const WifiTxVector& txVector) const;
/**
* Start receiving the PSDU (i.e. the first symbol of the PSDU has arrived) of an OFDMA
* transmission. This function is called upon the RX event corresponding to the OFDMA part of

View File

@@ -425,19 +425,75 @@ HePpdu::UpdateTxVectorForUlMu(const std::optional<WifiTxVector>& trigVector) con
}
}
bool
HePpdu::IsAllocated(uint16_t staId) const
std::pair<std::size_t, std::size_t>
HePpdu::GetNumRusPerHeSigBContentChannel(uint16_t channelWidth,
const std::vector<uint8_t>& ruAllocation)
{
return (m_muUserInfos.find(staId) != m_muUserInfos.cend());
// MU-MIMO is not handled for now, i.e. one station per RU
NS_ASSERT_MSG(!ruAllocation.empty(), "RU allocation is not set");
NS_ASSERT_MSG(ruAllocation.size() == channelWidth / 20,
"RU allocation is not consistent with packet bandwidth");
std::pair<std::size_t /* number of RUs in content channel 1 */,
std::size_t /* number of RUs in content channel 2 */>
chSize{0, 0};
switch (channelWidth)
{
case 40:
chSize.second += HeRu::GetRuSpecs(ruAllocation[1]).size();
[[fallthrough]];
case 20:
chSize.first += HeRu::GetRuSpecs(ruAllocation[0]).size();
break;
default:
for (auto n = 0; n < channelWidth / 20;)
{
chSize.first += HeRu::GetRuSpecs(ruAllocation[n]).size();
chSize.second += HeRu::GetRuSpecs(ruAllocation[n + 1]).size();
if (ruAllocation[n] >= 208)
{
// 996 tone RU occupies 80 MHz
n += 4;
continue;
}
n += 2;
}
break;
}
return chSize;
}
bool
HePpdu::IsStaInContentChannel(uint16_t staId, std::size_t channelId) const
uint32_t
HePpdu::GetSigBFieldSize(uint16_t channelWidth, const RuAllocation& ruAllocation)
{
NS_ASSERT_MSG(channelId < m_contentChannelAlloc.size(),
"Invalid content channel ID " << channelId);
const auto& channelAlloc = m_contentChannelAlloc.at(channelId);
return (std::find(channelAlloc.cbegin(), channelAlloc.cend(), staId) != channelAlloc.cend());
// Compute the number of bits used by common field.
// Assume that compression bit in HE-SIG-A is not set (i.e. not
// full band MU-MIMO); the field is present.
auto commonFieldSize = 4 /* CRC */ + 6 /* tail */;
if (channelWidth <= 40)
{
commonFieldSize += 8; // only one allocation subfield
}
else
{
commonFieldSize +=
8 * (channelWidth / 40) /* one allocation field per 40 MHz */ + 1 /* center RU */;
}
auto numStaPerContentChannel = GetNumRusPerHeSigBContentChannel(channelWidth, ruAllocation);
auto maxNumStaPerContentChannel =
std::max(numStaPerContentChannel.first, numStaPerContentChannel.second);
auto maxNumUserBlockFields = maxNumStaPerContentChannel /
2; // handle last user block with single user, if any, further down
std::size_t userSpecificFieldSize =
maxNumUserBlockFields * (2 * 21 /* user fields (2 users) */ + 4 /* tail */ + 6 /* CRC */);
if (maxNumStaPerContentChannel % 2 != 0)
{
userSpecificFieldSize += 21 /* last user field */ + 4 /* CRC */ + 6 /* tail */;
}
return commonFieldSize + userSpecificFieldSize;
}
std::string

View File

@@ -33,6 +33,9 @@
namespace ns3
{
/// HE SIG-B Content Channels
constexpr size_t WIFI_MAX_NUM_HE_SIGB_CONTENT_CHANNELS = 2;
class WifiPsdu;
/**
@@ -249,19 +252,27 @@ class HePpdu : public OfdmPpdu
void UpdateTxVectorForUlMu(const std::optional<WifiTxVector>& trigVector) const;
/**
* Check if STA ID is in HE SIG-B Content Channel ID
* \param staId STA ID
* \param channelId Content Channel ID
* \return true if STA ID in content channel ID, false otherwise
* Get the number of RUs per HE-SIG-B content channel.
* This is applicable only for MU. MU-MIMO (i.e. multiple stations
* per RU) is not supported yet.
* See section 27.3.10.8.3 of IEEE 802.11ax draft 4.0.
*
* \param channelWidth the channel width occupied by the PPDU (in MHz)
* \param ruAllocation 8 bit RU_ALLOCATION per 20 MHz
* \return a pair containing the number of RUs in each HE-SIG-B content channel (resp. 1 and 2)
*/
bool IsStaInContentChannel(uint16_t staId, size_t channelId) const;
static std::pair<std::size_t, std::size_t> GetNumRusPerHeSigBContentChannel(
uint16_t channelWidth,
const std::vector<uint8_t>& ruAllocation);
/**
* Check if STA ID is allocated
* \param staId STA ID
* \return true if allocated, false otherwise
* Get variable length HE SIG-B field size
* \param channelWidth the channel width occupied by the PPDU (in MHz)
* \param ruAllocation 8 bit RU_ALLOCATION per 20 MHz
* \return field size in bytes
*/
bool IsAllocated(uint16_t staId) const;
static uint32_t GetSigBFieldSize(uint16_t channelWidth,
const std::vector<uint8_t>& ruAllocation);
protected:
/**

View File

@@ -530,54 +530,6 @@ WifiTxVector::GetHeMuUserInfoMap()
return m_muUserInfos;
}
std::pair<std::size_t, std::size_t>
WifiTxVector::GetNumRusPerHeSigBContentChannel() const
{
if (m_preamble == WIFI_PREAMBLE_EHT_MU && m_ehtPpduType == 1)
{
return {1, 0};
}
// MU-MIMO is not handled for now, i.e. one station per RU
auto ruAllocation = GetRuAllocation();
NS_ASSERT_MSG(!ruAllocation.empty(), "RU allocation is not set");
if (ruAllocation.size() != m_channelWidth / 20)
{
ruAllocation = DeriveRuAllocation();
}
NS_ASSERT_MSG(ruAllocation.size() == m_channelWidth / 20,
"RU allocation is not consistent with packet bandwidth");
std::pair<std::size_t /* number of RUs in content channel 1 */,
std::size_t /* number of RUs in content channel 2 */>
chSize{0, 0};
switch (GetChannelWidth())
{
case 40:
chSize.second += HeRu::GetRuSpecs(ruAllocation[1]).size();
[[fallthrough]];
case 20:
chSize.first += HeRu::GetRuSpecs(ruAllocation[0]).size();
break;
default:
for (auto n = 0; n < m_channelWidth / 20;)
{
chSize.first += HeRu::GetRuSpecs(ruAllocation[n]).size();
chSize.second += HeRu::GetRuSpecs(ruAllocation[n + 1]).size();
if (ruAllocation[n] >= 208)
{
// 996 tone RU occupies 80 MHz
n += 4;
continue;
}
n += 2;
}
break;
}
return chSize;
}
void
WifiTxVector::SetInactiveSubchannels(const std::vector<bool>& inactiveSubchannels)
{

View File

@@ -59,9 +59,6 @@ struct HeMuUserInfo
/// A vector of subcarrier group
using SubcarrierGroups = std::vector<HeRu::SubcarrierGroup>;
/// Maximum number of HE-SIG-B content channels
constexpr size_t WIFI_MAX_NUM_HE_SIGB_CONTENT_CHANNELS = 2;
/// HE SIG-B Content Channels STA ID Allocation
using ContentChannelAllocation = std::vector<std::vector<uint16_t>>;
@@ -422,15 +419,6 @@ class WifiTxVector
* \return a reference to the map of HE MU user-specific information indexed by STA-ID
*/
HeMuUserInfoMap& GetHeMuUserInfoMap();
/**
* Get the number of RUs per HE-SIG-B content channel.
* This is applicable only for MU. MU-MIMO (i.e. multiple stations
* per RU) is not supported yet.
* See section 27.3.10.8.3 of IEEE 802.11ax draft 4.0.
*
* \return a pair containing the number of RUs in each HE-SIG-B content channel (resp. 1 and 2)
*/
std::pair<std::size_t, std::size_t> GetNumRusPerHeSigBContentChannel() const;
/**
* Set the 20 MHz subchannels that are punctured.

View File

@@ -19,7 +19,8 @@
*/
#include "ns3/dsss-phy.h"
#include "ns3/eht-phy.h" //includes OFDM, HT, VHT and HE
#include "ns3/eht-phy.h" //includes OFDM, HT, VHT and HE
#include "ns3/eht-ppdu.h" //includes OFDM, HT, VHT and HE
#include "ns3/erp-ofdm-phy.h"
#include "ns3/he-ru.h"
#include "ns3/log.h"
@@ -1361,7 +1362,9 @@ HeSigBDurationTest::DoRun()
NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
VhtPhy::GetVhtMcs5(),
"HE-SIG-B should be sent at MCS 5");
std::pair<std::size_t, std::size_t> numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
std::pair<std::size_t, std::size_t> numUsersPerCc =
HePpdu::GetNumRusPerHeSigBContentChannel(txVector.GetChannelWidth(),
txVector.GetRuAllocation());
NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
2,
"Both users should be on HE-SIG-B content channel 1");
@@ -1383,7 +1386,8 @@ HeSigBDurationTest::DoRun()
NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
VhtPhy::GetVhtMcs4(),
"HE-SIG-B should be sent at MCS 4");
numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
numUsersPerCc = HePpdu::GetNumRusPerHeSigBContentChannel(txVector.GetChannelWidth(),
txVector.GetRuAllocation());
NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
2,
"Two users should be on HE-SIG-B content channel 1");
@@ -1402,7 +1406,8 @@ HeSigBDurationTest::DoRun()
NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
VhtPhy::GetVhtMcs3(),
"HE-SIG-B should be sent at MCS 3");
numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
numUsersPerCc = HePpdu::GetNumRusPerHeSigBContentChannel(txVector.GetChannelWidth(),
txVector.GetRuAllocation());
NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
2,
"Two users should be on HE-SIG-B content channel 1");
@@ -1422,7 +1427,8 @@ HeSigBDurationTest::DoRun()
NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
VhtPhy::GetVhtMcs1(),
"HE-SIG-B should be sent at MCS 1");
numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
numUsersPerCc = HePpdu::GetNumRusPerHeSigBContentChannel(txVector.GetChannelWidth(),
txVector.GetRuAllocation());
NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
3,
"Three users should be on HE-SIG-B content channel 1");
@@ -1441,7 +1447,8 @@ HeSigBDurationTest::DoRun()
NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
VhtPhy::GetVhtMcs1(),
"HE-SIG-B should be sent at MCS 1");
numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
numUsersPerCc = HePpdu::GetNumRusPerHeSigBContentChannel(txVector.GetChannelWidth(),
txVector.GetRuAllocation());
NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
4,
"Four users should be on HE-SIG-B content channel 1");