wifi: Fix amount of users per content channel and user infos in reconstructed TXVECTOR for HE/EHT MU PPDUs

This commit is contained in:
Sébastien Deronne
2024-12-04 11:20:50 +01:00
parent 75040e5666
commit 75d42725ae
8 changed files with 529 additions and 279 deletions

View File

@@ -151,6 +151,7 @@ EhtPpdu::SetTxVectorFromPhyHeaders(WifiTxVector& txVector) const
: 0;
SetHeMuUserInfos(txVector,
ruAllocation.value(),
std::nullopt,
ehtPhyHeader->m_contentChannels,
ehtPhyHeader->m_ppduType == 2,
muMimoUsers);
@@ -195,6 +196,7 @@ EhtPpdu::GetNumRusPerEhtSigBContentChannel(MHz_u channelWidth,
}
return HePpdu::GetNumRusPerHeSigBContentChannel(channelWidth,
ruAllocation,
std::nullopt,
compression,
numMuMimoUsers);
}

View File

@@ -218,6 +218,7 @@ HePhy::GetSigBSize(const WifiTxVector& txVector) const
txVector.GetChannelWidth(),
txVector.GetRuAllocation(
m_wifiPhy ? m_wifiPhy->GetOperatingChannel().GetPrimaryChannelIndex(MHz_u{20}) : 0),
txVector.GetCenter26ToneRuIndication(),
txVector.IsSigBCompression(),
txVector.IsSigBCompression() ? txVector.GetHeMuUserInfoMap().size() : 0);
}

View File

@@ -19,6 +19,7 @@
#include "ns3/wifi-utils.h"
#include <algorithm>
#include <numeric>
namespace ns3
{
@@ -192,6 +193,7 @@ HePpdu::SetTxVectorFromPhyHeaders(WifiTxVector& txVector) const
txVector.SetBssColor(heSigHeader->m_bssColor);
SetHeMuUserInfos(txVector,
heSigHeader->m_ruAllocation,
heSigHeader->m_center26ToneRuIndication,
heSigHeader->m_contentChannels,
heSigHeader->m_sigBCompression,
GetMuMimoUsersFromEncoding(heSigHeader->m_muMimoUsers));
@@ -210,33 +212,107 @@ HePpdu::SetTxVectorFromPhyHeaders(WifiTxVector& txVector) const
}
}
HeRu::RuSpec
HePpdu::GetRuSpec(std::size_t ruAllocIndex,
const std::vector<HeRu::RuSpec>& ruSpecs,
HeRu::RuType ruType,
std::size_t ruIndex,
MHz_u bw) const
{
const auto ruBw = HeRu::GetBandwidth(ruType);
const uint8_t num20MhzSubchannelsInRu = (ruBw < MHz_u{20}) ? 1 : Count20MHzSubchannels(ruBw);
const std::size_t numRus = (ruBw > MHz_u{20}) ? 1 : HeRu::GetNRus(MHz_u{20}, ruType);
const std::size_t ruIndexOffset =
(ruBw < MHz_u{20}) ? (numRus * ruAllocIndex) : (ruAllocIndex / num20MhzSubchannelsInRu);
std::size_t index = ruSpecs.at(ruIndex).GetIndex() + ruIndexOffset;
auto isPrimary80 = true;
if (bw > MHz_u{80})
{
const auto isLow80 = ruAllocIndex < 4;
const auto p20Index = m_operatingChannel.GetPrimaryChannelIndex(MHz_u{20});
const auto primary80IsLower80 = (p20Index < bw / MHz_u{40});
if (!isLow80)
{
const auto numRusP80 = HeRu::GetRusOfType(MHz_u{80}, ruType).size();
index -= (ruType == HeRu::RU_26_TONE) ? (numRusP80 - 1) : numRusP80;
}
isPrimary80 = ((primary80IsLower80 && isLow80) || (!primary80IsLower80 && !isLow80));
}
if ((ruType == HeRu::RU_26_TONE) && (ruAllocIndex >= 2) && (index >= 19))
{
index++;
}
return {ruType, index, isPrimary80};
}
void
HePpdu::SetHeMuUserInfos(WifiTxVector& txVector,
const RuAllocation& ruAllocation,
std::optional<Center26ToneRuIndication> center26ToneRuIndication,
const HeSigBContentChannels& contentChannels,
bool sigBcompression,
uint8_t numMuMimoUsers) const
{
NS_ASSERT(ruAllocation.size() == Count20MHzSubchannels(txVector.GetChannelWidth()));
std::vector<uint8_t> remainingRuAllocIndices(ruAllocation.size());
std::iota(remainingRuAllocIndices.begin(), remainingRuAllocIndices.end(), 0);
std::size_t contentChannelIndex = 0;
std::size_t ruAllocIndex = 0;
for (const auto& contentChannel : contentChannels)
{
std::size_t numRusLeft = 0;
std::size_t numUsersLeft = 0;
std::size_t ruAllocIndex = contentChannelIndex;
ruAllocIndex = remainingRuAllocIndices.front();
std::size_t numUsersLeftInCc = contentChannel.size();
if (contentChannel.empty())
{
const auto pos = std::find(remainingRuAllocIndices.cbegin(),
remainingRuAllocIndices.cend(),
ruAllocIndex);
remainingRuAllocIndices.erase(pos);
++contentChannelIndex;
continue;
}
for (const auto& userInfo : contentChannel)
{
if (userInfo.staId == NO_USER_STA_ID)
if (*center26ToneRuIndication && (numUsersLeftInCc == 1))
{
continue;
}
if (ruAllocIndex >= ruAllocation.size())
{
break;
// handle central 26 tones
if ((contentChannelIndex == 0) &&
((*center26ToneRuIndication ==
Center26ToneRuIndication::CENTER_26_TONE_RU_LOW_80_MHZ_ALLOCATED) ||
(*center26ToneRuIndication ==
Center26ToneRuIndication::CENTER_26_TONE_RU_LOW_AND_HIGH_80_MHZ_ALLOCATED)))
{
txVector.SetHeMuUserInfo(
userInfo.staId,
{HeRu::RuSpec{HeRu::RU_26_TONE, 19, true}, userInfo.mcs, userInfo.nss});
continue;
}
else if ((contentChannelIndex == 1) &&
((*center26ToneRuIndication ==
Center26ToneRuIndication::CENTER_26_TONE_RU_HIGH_80_MHZ_ALLOCATED) ||
(*center26ToneRuIndication ==
Center26ToneRuIndication::
CENTER_26_TONE_RU_LOW_AND_HIGH_80_MHZ_ALLOCATED)))
{
txVector.SetHeMuUserInfo(
userInfo.staId,
{HeRu::RuSpec{HeRu::RU_26_TONE, 19, false}, userInfo.mcs, userInfo.nss});
continue;
}
}
NS_ASSERT(ruAllocIndex < ruAllocation.size());
auto ruSpecs = HeRu::GetRuSpecs(ruAllocation.at(ruAllocIndex));
if (ruSpecs.empty())
while (ruSpecs.empty() && (ruAllocIndex < ruAllocation.size()))
{
continue;
const auto pos = std::find(remainingRuAllocIndices.cbegin(),
remainingRuAllocIndices.cend(),
ruAllocIndex);
remainingRuAllocIndices.erase(pos);
ruAllocIndex += 2;
NS_ASSERT(ruAllocIndex < ruAllocation.size());
ruSpecs = HeRu::GetRuSpecs(ruAllocation.at(ruAllocIndex));
}
if (numRusLeft == 0)
{
@@ -255,44 +331,35 @@ HePpdu::SetHeMuUserInfos(WifiTxVector& txVector,
}
}
auto ruIndex = (ruSpecs.size() - numRusLeft);
auto ruSpec = ruSpecs.at(ruIndex);
const auto ruSpec = ruSpecs.at(ruIndex);
auto ruType = ruSpec.GetRuType();
if ((ruAllocation.size() == 8) && (ruType == HeRu::RU_996_TONE) &&
(((txVector.GetChannelWidth() == MHz_u{160}) && sigBcompression) ||
std::all_of(
contentChannel.cbegin(),
contentChannel.cend(),
[&userInfo](const auto& item) { return userInfo.staId == item.staId; })))
if (sigBcompression)
{
ruType = HeRu::RU_2x996_TONE;
ruType = HeRu::GetRuType(ruAllocation.size() * MHz_u{20});
}
const auto ruBw = HeRu::GetBandwidth(ruType);
auto primary80 = ruAllocIndex < 4;
const uint8_t num20MhzSubchannelsInRu =
(ruBw < MHz_u{20}) ? 1 : Count20MHzSubchannels(ruBw);
auto numRuAllocsInContentChannel = std::max(1, num20MhzSubchannelsInRu / 2);
auto ruIndexOffset = (ruBw < MHz_u{20}) ? (ruSpecs.size() * ruAllocIndex)
: (ruAllocIndex / num20MhzSubchannelsInRu);
if (!primary80)
if (userInfo.staId != NO_USER_STA_ID)
{
ruIndexOffset -= HeRu::GetRusOfType(MHz_u{80}, ruType).size();
}
if (!txVector.IsAllocated(userInfo.staId))
{
txVector.SetHeMuUserInfo(userInfo.staId,
{{ruType, ruSpec.GetIndex() + ruIndexOffset, primary80},
userInfo.mcs,
userInfo.nss});
}
if ((ruType == HeRu::RU_2x996_TONE) && !sigBcompression)
{
return;
const auto ru{
GetRuSpec(ruAllocIndex, ruSpecs, ruType, ruIndex, txVector.GetChannelWidth())};
txVector.SetHeMuUserInfo(userInfo.staId, {ru, userInfo.mcs, userInfo.nss});
}
numRusLeft--;
numUsersLeft--;
numUsersLeftInCc--;
if (numRusLeft == 0 && numUsersLeft == 0)
{
ruAllocIndex += (2 * numRuAllocsInContentChannel);
const auto ruBw = HeRu::GetBandwidth(ruType);
const uint8_t num20MhzSubchannelsInRu =
(ruBw < MHz_u{20}) ? 1 : Count20MHzSubchannels(ruBw);
const auto pos = std::find(remainingRuAllocIndices.cbegin(),
remainingRuAllocIndices.cend(),
ruAllocIndex);
remainingRuAllocIndices.erase(pos);
ruAllocIndex += num20MhzSubchannelsInRu;
if (ruAllocIndex % 2 != contentChannelIndex)
{
++ruAllocIndex;
}
}
}
contentChannelIndex++;
@@ -473,10 +540,12 @@ HePpdu::UpdateTxVectorForUlMu(const std::optional<WifiTxVector>& trigVector) con
}
std::pair<std::size_t, std::size_t>
HePpdu::GetNumRusPerHeSigBContentChannel(MHz_u channelWidth,
const RuAllocation& ruAllocation,
bool sigBCompression,
uint8_t numMuMimoUsers)
HePpdu::GetNumRusPerHeSigBContentChannel(
MHz_u channelWidth,
const RuAllocation& ruAllocation,
std::optional<Center26ToneRuIndication> center26ToneRuIndication,
bool sigBCompression,
uint8_t numMuMimoUsers)
{
std::pair<std::size_t /* number of RUs in content channel 1 */,
std::size_t /* number of RUs in content channel 2 */>
@@ -515,28 +584,64 @@ HePpdu::GetNumRusPerHeSigBContentChannel(MHz_u channelWidth,
default:
for (std::size_t n = 0; n < Count20MHzSubchannels(channelWidth);)
{
chSize.first += HeRu::GetRuSpecs(ruAllocation[n]).size();
if (ruAllocation[n] >= 208)
std::size_t ccIndex;
const auto ruAlloc = ruAllocation.at(n);
const auto ruSpecs = HeRu::GetRuSpecs(ruAlloc);
if (ruSpecs.empty())
{
// 996 tone RU occupies 80 MHz
n += 4;
++n;
continue;
}
n += 2;
}
for (std::size_t n = 0; n < Count20MHzSubchannels(channelWidth);)
{
chSize.second += HeRu::GetRuSpecs(ruAllocation[n + 1]).size();
if (ruAllocation[n + 1] >= 208)
if (ruSpecs.front().GetRuType() >= HeRu::RU_484_TONE)
{
// 996 tone RU occupies 80 MHz
n += 4;
continue;
ccIndex = (chSize.first <= chSize.second) ? 0 : 1;
}
else
{
ccIndex = (n % 2 == 0) ? 0 : 1;
}
const auto nRuSpecs = HeRu::GetRuSpecs(ruAlloc).size();
if (ccIndex == 0)
{
chSize.first += nRuSpecs;
}
else
{
chSize.second += nRuSpecs;
}
const auto ruBw = HeRu::GetBandwidth(ruSpecs.at(0).GetRuType());
if (ruBw <= MHz_u{20})
{
++n;
}
else
{
const auto num20MHz = Count20MHzSubchannels(ruBw);
const auto skipNumIndices = (ccIndex == 0) ? num20MHz : num20MHz - 1;
n += skipNumIndices;
}
n += 2;
}
break;
}
if (center26ToneRuIndication)
{
switch (*center26ToneRuIndication)
{
case Center26ToneRuIndication::CENTER_26_TONE_RU_LOW_80_MHZ_ALLOCATED:
chSize.first++;
break;
case Center26ToneRuIndication::CENTER_26_TONE_RU_HIGH_80_MHZ_ALLOCATED:
chSize.second++;
break;
case Center26ToneRuIndication::CENTER_26_TONE_RU_LOW_AND_HIGH_80_MHZ_ALLOCATED:
chSize.first++;
chSize.second++;
break;
case Center26ToneRuIndication::CENTER_26_TONE_RU_UNALLOCATED:
default:
break;
}
}
return chSize;
}
@@ -551,21 +656,48 @@ HePpdu::GetHeSigBContentChannels(const WifiTxVector& txVector, uint8_t p20Index)
contentChannels.emplace_back();
}
std::optional<HeSigBUserSpecificField> cc1Central26ToneRu;
std::optional<HeSigBUserSpecificField> cc2Central26ToneRu;
const auto& orderedMap = txVector.GetUserInfoMapOrderedByRus(p20Index);
std::optional<HeRu::RuType> prevRuType;
std::size_t prevRuIndex{0};
std::size_t prevCcIndex{0};
for (const auto& [ru, staIds] : orderedMap)
{
const auto ruType = ru.GetRuType();
if ((ruType > HeRu::RU_242_TONE) && !txVector.IsSigBCompression())
if ((ruType == HeRu::RU_26_TONE) && (ru.GetIndex() == 19))
{
for (auto i = 0; i < ((ruType == HeRu::RU_2x996_TONE) ? 2 : 1); ++i)
const auto staId = *staIds.cbegin();
const auto& userInfo = txVector.GetHeMuUserInfo(staId);
if (ru.GetPrimary80MHz())
{
for (auto staId : staIds)
{
const auto& userInfo = txVector.GetHeMuUserInfo(staId);
NS_ASSERT(ru == userInfo.ru);
contentChannels[0].push_back({staId, userInfo.nss, userInfo.mcs});
contentChannels[1].push_back({staId, userInfo.nss, userInfo.mcs});
}
NS_ASSERT(!cc1Central26ToneRu);
cc1Central26ToneRu = HeSigBUserSpecificField{staId, userInfo.nss, userInfo.mcs};
}
else
{
NS_ASSERT(!cc2Central26ToneRu);
cc2Central26ToneRu = HeSigBUserSpecificField{staId, userInfo.nss, userInfo.mcs};
}
continue;
}
const auto ruIndex = ru.GetPhyIndex(channelWidth, p20Index);
if (prevRuType && (*prevRuType != ruType))
{
prevRuIndex *= HeRu::GetBandwidth(*prevRuType) / HeRu::GetBandwidth(ruType);
}
if (ruType >= HeRu::RU_484_TONE)
{
for (auto staId : staIds)
{
// equal split
const auto ccIndex =
(contentChannels.at(0).size() <= contentChannels.at(1).size()) ? 0 : 1;
const auto& userInfo = txVector.GetHeMuUserInfo(staId);
NS_ASSERT(ru == userInfo.ru);
contentChannels[ccIndex].push_back({staId, userInfo.nss, userInfo.mcs});
}
continue;
}
@@ -573,7 +705,40 @@ HePpdu::GetHeSigBContentChannels(const WifiTxVector& txVector, uint8_t p20Index)
std::size_t numRus = (ruType >= HeRu::RU_242_TONE)
? 1
: HeRu::m_heRuSubcarrierGroups.at({MHz_u{20}, ruType}).size();
const auto ruIdx = ru.GetIndex();
auto ruIdx = ru.GetIndex();
while (prevRuIndex < ruIndex - 1)
{
std::size_t ccIndex{0};
if (channelWidth < MHz_u{40})
{
// only one content channel
ccIndex = 0;
}
else if (txVector.IsSigBCompression())
{
// equal split
ccIndex = (contentChannels.at(0).size() <= contentChannels.at(1).size()) ? 0 : 1;
}
else
{
ccIndex = ((prevRuIndex / numRus) % 2 == 0) ? 0 : 1;
}
const auto central26TonesRus = HeRu::GetCentral26TonesRus(channelWidth, *prevRuType);
if (ruType < HeRu::RuType::RU_242_TONE && (prevCcIndex == ccIndex) &&
((ruType != HeRu::RuType::RU_26_TONE) ||
std::none_of(central26TonesRus.cbegin(),
central26TonesRus.cend(),
[ruIndex, channelWidth, p20Index](const auto& ruSpec) {
return ruSpec.GetPhyIndex(channelWidth, p20Index) == ruIndex;
})))
{
contentChannels[ccIndex].push_back({NO_USER_STA_ID, 0, 0});
}
++prevRuIndex;
prevCcIndex = ccIndex;
}
prevRuIndex = ruIndex;
prevRuType = ruType;
for (auto staId : staIds)
{
const auto& userInfo = txVector.GetHeMuUserInfo(staId);
@@ -586,17 +751,32 @@ HePpdu::GetHeSigBContentChannels(const WifiTxVector& txVector, uint8_t p20Index)
}
else if (txVector.IsSigBCompression())
{
// equal split
// MU-MIMO: equal split
ccIndex = (contentChannels.at(0).size() <= contentChannels.at(1).size()) ? 0 : 1;
}
else // MU-MIMO
else
{
if (ruType == HeRu::RU_26_TONE && ruIdx > 19)
{
// "ignore" the center 26-tone RUs in 80 MHz channels
ruIdx--;
}
ccIndex = (((ruIdx - 1) / numRus) % 2 == 0) ? 0 : 1;
}
contentChannels.at(ccIndex).push_back({staId, userInfo.nss, userInfo.mcs});
prevCcIndex = ccIndex;
}
}
if (cc1Central26ToneRu)
{
contentChannels.at(0).push_back(*cc1Central26ToneRu);
}
if (cc2Central26ToneRu)
{
contentChannels.at(1).push_back(*cc2Central26ToneRu);
}
const auto isSigBCompression = txVector.IsSigBCompression();
if (!isSigBCompression)
{
@@ -604,6 +784,7 @@ HePpdu::GetHeSigBContentChannels(const WifiTxVector& txVector, uint8_t p20Index)
auto numNumRusPerHeSigBContentChannel = GetNumRusPerHeSigBContentChannel(
channelWidth,
txVector.GetRuAllocation(p20Index),
txVector.GetCenter26ToneRuIndication(),
isSigBCompression,
isSigBCompression ? txVector.GetHeMuUserInfoMap().size() : 0);
std::size_t contentChannelIndex = 1;
@@ -628,6 +809,7 @@ HePpdu::GetHeSigBContentChannels(const WifiTxVector& txVector, uint8_t p20Index)
uint32_t
HePpdu::GetSigBFieldSize(MHz_u channelWidth,
const RuAllocation& ruAllocation,
std::optional<Center26ToneRuIndication> center26ToneRuIndication,
bool sigBCompression,
std::size_t numMuMimoUsers)
{
@@ -650,6 +832,7 @@ HePpdu::GetSigBFieldSize(MHz_u channelWidth,
auto numRusPerContentChannel = GetNumRusPerHeSigBContentChannel(channelWidth,
ruAllocation,
center26ToneRuIndication,
sigBCompression,
numMuMimoUsers);
auto maxNumRusPerContentChannel =

View File

@@ -184,6 +184,7 @@ class HePpdu : public OfdmPpdu
*
* @param channelWidth the channel width occupied by the PPDU
* @param ruAllocation 8 bit RU_ALLOCATION per 20 MHz
* @param center26ToneRuIndication the center 26 tone RU indication
* @param sigBCompression flag whether SIG-B compression is used by the PPDU
* @param numMuMimoUsers the number of MU-MIMO users addressed by the PPDU
* @return a pair containing the number of RUs in each HE-SIG-B content channel (resp. 1 and 2)
@@ -191,6 +192,7 @@ class HePpdu : public OfdmPpdu
static std::pair<std::size_t, std::size_t> GetNumRusPerHeSigBContentChannel(
MHz_u channelWidth,
const RuAllocation& ruAllocation,
std::optional<Center26ToneRuIndication> center26ToneRuIndication,
bool sigBCompression,
uint8_t numMuMimoUsers);
@@ -209,14 +211,17 @@ class HePpdu : public OfdmPpdu
* Get variable length HE SIG-B field size
* @param channelWidth the channel width occupied by the PPDU
* @param ruAllocation 8 bit RU_ALLOCATION per 20 MHz
* @param center26ToneRuIndication the center 26 tone RU indication
* @param sigBCompression flag whether SIG-B compression is used by the PPDU
* @param numMuMimoUsers the number of MU-MIMO users addressed by the PPDU
* @return field size in bytes
*/
static uint32_t GetSigBFieldSize(MHz_u channelWidth,
const RuAllocation& ruAllocation,
bool sigBCompression,
std::size_t numMuMimoUsers);
static uint32_t GetSigBFieldSize(
MHz_u channelWidth,
const RuAllocation& ruAllocation,
std::optional<Center26ToneRuIndication> center26ToneRuIndication,
bool sigBCompression,
std::size_t numMuMimoUsers);
protected:
/**
@@ -231,16 +236,34 @@ class HePpdu : public OfdmPpdu
*
* @param txVector the TXVECTOR to set its HeMuUserInfoMap
* @param ruAllocation the RU_ALLOCATION per 20 MHz
* @param center26ToneRuIndication the center 26 tone RU indication
* @param contentChannels the HE-SIG-B content channels
* @param sigBCompression flag whether SIG-B compression is used by the PPDU
* @param numMuMimoUsers the number of MU-MIMO users addressed by the PPDU
*/
void SetHeMuUserInfos(WifiTxVector& txVector,
const RuAllocation& ruAllocation,
std::optional<Center26ToneRuIndication> center26ToneRuIndication,
const HeSigBContentChannels& contentChannels,
bool sigBCompression,
uint8_t numMuMimoUsers) const;
/**
* Get the RU specification that has been assigned a given user.
*
* @param ruAllocIndex the index of the RU allocation
* @param ruSpecs RU specs deduced from the RU allocation
* @param ruType RU type of the user to be assigned
* @param ruIndex RU index of the user to be assigned
* @param bw the total bandwidth used for the transmission
* @return the value used to encode the bandwidth field in HE-SIG-A
*/
virtual HeRu::RuSpec GetRuSpec(std::size_t ruAllocIndex,
const std::vector<HeRu::RuSpec>& ruSpecs,
HeRu::RuType ruType,
std::size_t ruIndex,
MHz_u bw) const;
/**
* Convert channel width expressed in MHz to bandwidth field encoding in HE-SIG-A.
*

View File

@@ -595,12 +595,6 @@ WifiTxVector::GetNumStasInRu(const HeRu::RuSpec& ru) const
[&ru](const auto& info) -> bool { return (ru == info.second.ru); });
}
bool
WifiTxVector::IsAllocated(uint16_t staId) const
{
return m_muUserInfos.contains(staId);
}
HeRu::RuSpec
WifiTxVector::GetRu(uint16_t staId) const
{
@@ -798,30 +792,39 @@ WifiTxVector::DeriveRuAllocation(uint8_t p20Index) const
std::vector<HeRu::RuType> ruTypes{};
ruTypes.resize(ruAllocations.size());
const auto& orderedMap = GetUserInfoMapOrderedByRus(p20Index);
std::pair<std::size_t /* number of RUs in content channel 1 */,
std::size_t /* number of RUs in content channel 2 */>
ccSizes{0, 0};
for (const auto& [ru, staIds] : orderedMap)
{
if ((ru.GetRuType() == HeRu::RU_26_TONE) && (ru.GetIndex() == 19))
{
continue;
}
const auto ruType = ru.GetRuType();
const auto ruBw = HeRu::GetBandwidth(ruType);
const auto isPrimary80MHz = ru.GetPrimary80MHz();
const auto rusPerSubchannel =
HeRu::GetRusOfType(ruBw > MHz_u{20} ? ruBw : MHz_u{20}, ruType);
auto ruIndex = ru.GetIndex();
if ((m_channelWidth >= MHz_u{80}) && (ruIndex > 19))
{
// take into account the center 26-tone RU in the primary 80 MHz
// take into account the center 26-tone RU in the low 80 MHz
ruIndex--;
}
if ((!isPrimary80MHz) && (ruIndex > 19))
const auto isPrimary80MHz = ru.GetPrimary80MHz();
const auto primary80IsLower80 = (p20Index < m_channelWidth / MHz_u{40});
const auto isLow80 =
(primary80IsLower80 && isPrimary80MHz) || (!primary80IsLower80 && !isPrimary80MHz);
if ((m_channelWidth > MHz_u{80}) && !isLow80 && (ruIndex > 19))
{
// take into account the center 26-tone RU in the secondary 80 MHz
// take into account the center 26-tone RU in the high 80 MHz
ruIndex--;
}
if (!isPrimary80MHz && (ruType != HeRu::RU_2x996_TONE))
if ((m_channelWidth > MHz_u{80}) && !isLow80 && (ruType != HeRu::GetRuType(m_channelWidth)))
{
NS_ASSERT(m_channelWidth > MHz_u{80});
// adjust RU index for the secondary 80 MHz: in that case index is restarting at 1,
// adjust RU index for the high 80 MHz: in that case index is restarting at 1,
// hence we need to add an offset corresponding to the number of RUs of the same type in
// the primary 80 MHz
// the low 80 MHz
ruIndex += HeRu::GetRusOfType(MHz_u{80}, ruType).size();
}
const auto numSubchannelsForRu = (ruBw < MHz_u{20}) ? 1 : Count20MHzSubchannels(ruBw);
@@ -848,10 +851,29 @@ WifiTxVector::DeriveRuAllocation(uint8_t p20Index) const
NS_ASSERT_MSG(false, "unsupported RU combination");
}
}
std::size_t ccIndex;
if (ruType >= HeRu::RU_484_TONE)
{
ccIndex = (ccSizes.first <= ccSizes.second) ? 0 : 1;
}
else
{
ccIndex = (index % 2 == 0) ? 0 : 1;
}
if (ccIndex == 0)
{
ccSizes.first += staIds.size();
}
else
{
ccSizes.second += staIds.size();
}
for (std::size_t i = 0; i < numSubchannelsForRu; ++i)
{
auto ruAllocNoUsers = HeRu::GetEqualizedRuAllocation(ruType, false, false);
ruTypes.at(index + i) = ruType;
ruAllocations.at(index + i) = ruAlloc;
ruAllocations.at(index + i) =
(IsSigBCompression() || ((index + i) % 2) == ccIndex) ? ruAlloc : ruAllocNoUsers;
}
}
return ruAllocations;

View File

@@ -380,12 +380,6 @@ class WifiTxVector
* @return true if this TX vector is used for a downlink multi-user transmission using MU-MIMO
*/
bool IsDlMuMimo() const;
/**
* Check if STA ID is allocated
* @param staId STA ID
* @return true if allocated, false otherwise
*/
bool IsAllocated(uint16_t staId) const;
/**
* Get the RU specification for the STA-ID.
* This is applicable only for MU.

View File

@@ -1550,6 +1550,7 @@ HeSigBDurationTest::DoRun()
const auto& numUsersPerCc = HePpdu::GetNumRusPerHeSigBContentChannel(
txVector.GetChannelWidth(),
txVector.GetRuAllocation(0),
txVector.GetCenter26ToneRuIndication(),
txVector.IsSigBCompression(),
txVector.IsSigBCompression() ? txVector.GetHeMuUserInfoMap().size() : 0);
const auto contentChannels = HePpdu::GetHeSigBContentChannels(txVector, 0);
@@ -1957,12 +1958,12 @@ TxDurationTestSuite::TxDurationTestSuite()
// 40 MHz band, HeSigBDurationTest::OFDMA, even number of users per HE-SIG-B content channel
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
{{HeRu::RU_106_TONE, 2, true}, 10, 4},
{{HeRu::RU_52_TONE, 5, true}, 4, 1},
{{HeRu::RU_52_TONE, 6, true}, 6, 2},
{{HeRu::RU_52_TONE, 7, true}, 5, 3},
{{HeRu::RU_52_TONE, 8, true}, 6, 2}},
new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1}, // CC1
{{HeRu::RU_106_TONE, 2, true}, 10, 4}, // CC1
{{HeRu::RU_52_TONE, 5, true}, 4, 1}, // CC2
{{HeRu::RU_52_TONE, 6, true}, 6, 2}, // CC2
{{HeRu::RU_52_TONE, 7, true}, 5, 3}, // CC2
{{HeRu::RU_52_TONE, 8, true}, 6, 2}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{40},
HeSigBDurationTest::OFDMA,
@@ -1974,13 +1975,13 @@ TxDurationTestSuite::TxDurationTestSuite()
// 40 MHz band, HeSigBDurationTest::OFDMA, odd number of users per HE-SIG-B content channel
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
{{HeRu::RU_106_TONE, 2, true}, 10, 4},
{{HeRu::RU_52_TONE, 5, true}, 4, 1},
{{HeRu::RU_52_TONE, 6, true}, 6, 2},
{{HeRu::RU_52_TONE, 7, true}, 5, 3},
{{HeRu::RU_52_TONE, 8, true}, 6, 2},
{{HeRu::RU_26_TONE, 14, true}, 3, 1}},
new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1}, // CC1
{{HeRu::RU_106_TONE, 2, true}, 10, 4}, // CC1
{{HeRu::RU_52_TONE, 5, true}, 4, 1}, // CC2
{{HeRu::RU_52_TONE, 6, true}, 6, 2}, // CC2
{{HeRu::RU_52_TONE, 7, true}, 5, 3}, // CC2
{{HeRu::RU_52_TONE, 8, true}, 6, 2}, // CC2
{{HeRu::RU_26_TONE, 14, true}, 3, 1}}, // CC2
VhtPhy::GetVhtMcs3(),
MHz_u{40},
HeSigBDurationTest::OFDMA,
@@ -1992,15 +1993,15 @@ TxDurationTestSuite::TxDurationTestSuite()
// 80 MHz band, OFDMA
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
{{HeRu::RU_106_TONE, 2, true}, 10, 4},
{{HeRu::RU_52_TONE, 5, true}, 4, 1},
{{HeRu::RU_52_TONE, 6, true}, 6, 2},
{{HeRu::RU_52_TONE, 7, true}, 5, 3},
{{HeRu::RU_52_TONE, 8, true}, 6, 2},
{{HeRu::RU_26_TONE, 14, true}, 3, 1},
{{HeRu::RU_242_TONE, 3, true}, 1, 1},
{{HeRu::RU_242_TONE, 4, true}, 4, 1}},
new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1}, // CC1
{{HeRu::RU_106_TONE, 2, true}, 10, 4}, // CC1
{{HeRu::RU_52_TONE, 5, true}, 4, 1}, // CC2
{{HeRu::RU_52_TONE, 6, true}, 6, 2}, // CC2
{{HeRu::RU_52_TONE, 7, true}, 5, 3}, // CC2
{{HeRu::RU_52_TONE, 8, true}, 6, 2}, // CC2
{{HeRu::RU_26_TONE, 14, true}, 3, 1}, // CC2
{{HeRu::RU_242_TONE, 3, true}, 1, 1}, // CC1
{{HeRu::RU_242_TONE, 4, true}, 4, 1}}, // CC2
VhtPhy::GetVhtMcs1(),
MHz_u{80},
HeSigBDurationTest::OFDMA,
@@ -2011,91 +2012,98 @@ TxDurationTestSuite::TxDurationTestSuite()
TestCase::Duration::QUICK);
// 160 MHz band, OFDMA
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
{{HeRu::RU_106_TONE, 2, true}, 10, 4},
{{HeRu::RU_52_TONE, 5, true}, 4, 1},
{{HeRu::RU_52_TONE, 6, true}, 6, 2},
{{HeRu::RU_52_TONE, 7, true}, 5, 3},
{{HeRu::RU_52_TONE, 8, true}, 6, 2},
{{HeRu::RU_26_TONE, 14, true}, 3, 1},
{{HeRu::RU_242_TONE, 3, true}, 1, 1},
{{HeRu::RU_242_TONE, 4, true}, 4, 1},
{{HeRu::RU_996_TONE, 1, false}, 1, 1}},
VhtPhy::GetVhtMcs1(),
MHz_u{160},
HeSigBDurationTest::OFDMA,
{96, 15, 192, 192, 208, 208, 208, 208},
std::make_pair(4, 7), // four users in HE-SIG-B content channel 1 and
// seven users in HE-SIG-B content channel 2
MicroSeconds(20)), // five OFDM symbols
TestCase::Duration::QUICK);
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_106_TONE, 1, true}, 11, 1}, // CC1
{{HeRu::RU_106_TONE, 2, true}, 10, 4}, // CC1
{{HeRu::RU_52_TONE, 5, true}, 4, 1}, // CC2
{{HeRu::RU_52_TONE, 6, true}, 6, 2}, // CC2
{{HeRu::RU_52_TONE, 7, true}, 5, 3}, // CC2
{{HeRu::RU_52_TONE, 8, true}, 6, 2}, // CC2
{{HeRu::RU_26_TONE, 14, true}, 3, 1}, // CC2
{{HeRu::RU_242_TONE, 3, true}, 1, 1}, // CC1
{{HeRu::RU_242_TONE, 4, true}, 4, 1}, // CC2
{{HeRu::RU_996_TONE, 1, false}, 1, 1}}, // CC1 or CC2 => CC1 for better split
VhtPhy::GetVhtMcs1(),
MHz_u{160},
HeSigBDurationTest::OFDMA,
{96, 15, 192, 192, 208, 115, 208, 115},
std::make_pair(4, 6), // four users in HE-SIG-B content channel 1 and
// seven users in HE-SIG-B content channel 2
MicroSeconds(16)), // four OFDM symbols
TestCase::Duration::QUICK);
// 20 MHz band, HeSigBDurationTest::OFDMA, one unallocated RU at the middle
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_26_TONE, 1, true}, 11, 1},
{{HeRu::RU_26_TONE, 2, true}, 11, 1},
{{HeRu::RU_26_TONE, 3, true}, 11, 1},
{{HeRu::RU_26_TONE, 4, true}, 11, 1},
{{HeRu::RU_26_TONE, 6, true}, 11, 1},
{{HeRu::RU_26_TONE, 7, true}, 11, 1},
{{HeRu::RU_26_TONE, 8, true}, 11, 1},
{{HeRu::RU_26_TONE, 9, true}, 11, 1}},
VhtPhy::GetVhtMcs5(),
MHz_u{20},
HeSigBDurationTest::OFDMA,
{0},
std::make_pair(9, 0), // 9 users in HE-SIG-B content channel 1
MicroSeconds(8)), // two OFDM symbols
new HeSigBDurationTest(
{{{HeRu::RU_26_TONE, 1, true}, 11, 1}, // CC1
{{HeRu::RU_26_TONE, 2, true}, 11, 1}, // CC1
{{HeRu::RU_26_TONE, 3, true}, 11, 1}, // CC1
{{HeRu::RU_26_TONE, 4, true}, 11, 1}, // CC1
{{HeRu::RU_26_TONE, 6, true}, 11, 1}, // CC1
{{HeRu::RU_26_TONE, 7, true}, 11, 1}, // CC1
{{HeRu::RU_26_TONE, 8, true}, 11, 1}, // CC1
{{HeRu::RU_26_TONE, 9, true}, 11, 1}}, // CC1
VhtPhy::GetVhtMcs5(),
MHz_u{20},
HeSigBDurationTest::OFDMA,
{0},
std::make_pair(9, 0), // 9 users (8 users + 1 empty user) in HE-SIG-B content channel 1
MicroSeconds(8)), // two OFDM symbols
TestCase::Duration::QUICK);
// 40 MHz band, HeSigBDurationTest::OFDMA, unallocated RUs at the begin and at the end of the
// first 20 MHz subband and in the middle of the second 20 MHz subband
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_52_TONE, 2, true}, 10, 1},
{{HeRu::RU_52_TONE, 3, true}, 10, 2},
{{HeRu::RU_52_TONE, 5, true}, 11, 1},
{{HeRu::RU_52_TONE, 8, true}, 11, 2}},
VhtPhy::GetVhtMcs5(),
MHz_u{40},
HeSigBDurationTest::OFDMA,
{112, 112},
std::make_pair(4, 4), // 4 users in both HE-SIG-B content channels
MicroSeconds(4)), // two OFDM symbols
new HeSigBDurationTest(
{{{HeRu::RU_52_TONE, 2, true}, 10, 1}, // CC1
{{HeRu::RU_52_TONE, 3, true}, 10, 2}, // CC1
{{HeRu::RU_52_TONE, 5, true}, 11, 1}, // CC2
{{HeRu::RU_52_TONE, 8, true}, 11, 2}}, // CC2
VhtPhy::GetVhtMcs5(),
MHz_u{40},
HeSigBDurationTest::OFDMA,
{112, 112},
std::make_pair(4,
4), // 4 users (2 users + 2 empty users) in each HE-SIG-B content channel
MicroSeconds(4)), // one OFDM symbol
TestCase::Duration::QUICK);
// 40 MHz band, HeSigBDurationTest::OFDMA, one unallocated RUs in the first 20 MHz subband and
// two unallocated RUs in second 20 MHz subband
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_52_TONE, 1, true}, 10, 1},
{{HeRu::RU_52_TONE, 2, true}, 10, 2},
{{HeRu::RU_52_TONE, 3, true}, 11, 1},
{{HeRu::RU_52_TONE, 5, true}, 11, 2},
{{HeRu::RU_52_TONE, 6, true}, 11, 3}},
VhtPhy::GetVhtMcs5(),
MHz_u{40},
HeSigBDurationTest::OFDMA,
{112, 112},
std::make_pair(4, 4), // 4 users in both HE-SIG-B content channels
MicroSeconds(4)), // two OFDM symbols
new HeSigBDurationTest(
{{{HeRu::RU_52_TONE, 1, true}, 10, 1}, // CC1
{{HeRu::RU_52_TONE, 2, true}, 10, 2}, // CC1
{{HeRu::RU_52_TONE, 3, true}, 11, 1}, // CC1
{{HeRu::RU_52_TONE, 5, true}, 11, 2}, // CC2
{{HeRu::RU_52_TONE, 6, true}, 11, 3}}, // CC2
VhtPhy::GetVhtMcs5(),
MHz_u{40},
HeSigBDurationTest::OFDMA,
{112, 112},
std::make_pair(4,
4), // 4 users (3 users + 1 empty user) in HE-SIG-B content channel 1 and
// 4 users (2 users + 2 empty users) in HE-SIG-B content channel 2
MicroSeconds(4)), // one OFDM symbol
TestCase::Duration::QUICK);
// 20 MHz band, MU-MIMO, 2 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_242_TONE, 1, true}, 11, 1}, {{HeRu::RU_242_TONE, 1, true}, 10, 4}},
VhtPhy::GetVhtMcs5(),
MHz_u{20},
HeSigBDurationTest::MU_MIMO,
{192},
std::make_pair(2, 0), // both users in HE-SIG-B content channel 1
MicroSeconds(4)), // one OFDM symbol
TestCase::Duration::QUICK);
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 11, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 10, 4}}, // CC1
VhtPhy::GetVhtMcs5(),
MHz_u{20},
HeSigBDurationTest::MU_MIMO,
{192},
std::make_pair(2, 0), // both users in HE-SIG-B content channel 1
MicroSeconds(4)), // one OFDM symbol
TestCase::Duration::QUICK);
// 20 MHz band, MU-MIMO, 3 users
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 3},
{{HeRu::RU_242_TONE, 1, true}, 5, 2},
{{HeRu::RU_242_TONE, 1, true}, 6, 1}},
new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 3}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 5, 2}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 6, 1}}, // CC1
VhtPhy::GetVhtMcs4(),
MHz_u{20},
HeSigBDurationTest::MU_MIMO,
@@ -2106,10 +2114,10 @@ TxDurationTestSuite::TxDurationTestSuite()
// 20 MHz band, MU-MIMO, 4 users
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1},
{{HeRu::RU_242_TONE, 1, true}, 5, 2},
{{HeRu::RU_242_TONE, 1, true}, 6, 3},
{{HeRu::RU_242_TONE, 1, true}, 7, 2}},
new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 5, 2}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 6, 3}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 7, 2}}, // CC1
VhtPhy::GetVhtMcs4(),
MHz_u{20},
HeSigBDurationTest::MU_MIMO,
@@ -2120,12 +2128,12 @@ TxDurationTestSuite::TxDurationTestSuite()
// 20 MHz band, MU-MIMO, 6 users
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1},
{{HeRu::RU_242_TONE, 1, true}, 5, 1},
{{HeRu::RU_242_TONE, 1, true}, 6, 2},
{{HeRu::RU_242_TONE, 1, true}, 7, 2},
{{HeRu::RU_242_TONE, 1, true}, 8, 1},
{{HeRu::RU_242_TONE, 1, true}, 9, 1}},
new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 5, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 6, 2}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 7, 2}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 8, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 9, 1}}, // CC1
VhtPhy::GetVhtMcs4(),
MHz_u{20},
HeSigBDurationTest::MU_MIMO,
@@ -2136,14 +2144,14 @@ TxDurationTestSuite::TxDurationTestSuite()
// 20 MHz band, MU-MIMO, 8 users
AddTestCase(
new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1},
{{HeRu::RU_242_TONE, 1, true}, 5, 1},
{{HeRu::RU_242_TONE, 1, true}, 6, 1},
{{HeRu::RU_242_TONE, 1, true}, 7, 1},
{{HeRu::RU_242_TONE, 1, true}, 8, 1},
{{HeRu::RU_242_TONE, 1, true}, 9, 1},
{{HeRu::RU_242_TONE, 1, true}, 10, 1},
{{HeRu::RU_242_TONE, 1, true}, 11, 1}},
new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 5, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 6, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 7, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 8, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 9, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 10, 1}, // CC1
{{HeRu::RU_242_TONE, 1, true}, 11, 1}}, // CC1
VhtPhy::GetVhtMcs4(),
MHz_u{20},
HeSigBDurationTest::MU_MIMO,
@@ -2154,7 +2162,8 @@ TxDurationTestSuite::TxDurationTestSuite()
// 40 MHz band, MU-MIMO, 2 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_484_TONE, 1, true}, 11, 1}, {{HeRu::RU_484_TONE, 1, true}, 10, 4}},
{{{HeRu::RU_484_TONE, 1, true}, 11, 1}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 10, 4}}, // CC2
VhtPhy::GetVhtMcs5(),
MHz_u{40},
HeSigBDurationTest::MU_MIMO,
@@ -2166,9 +2175,9 @@ TxDurationTestSuite::TxDurationTestSuite()
// 40 MHz band, MU-MIMO, 3 users
AddTestCase(
new HeSigBDurationTest(
{{{HeRu::RU_484_TONE, 1, true}, 4, 3},
{{HeRu::RU_484_TONE, 1, true}, 5, 2},
{{HeRu::RU_484_TONE, 1, true}, 6, 1}},
{{{HeRu::RU_484_TONE, 1, true}, 4, 3}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 5, 2}, // CC2
{{HeRu::RU_484_TONE, 1, true}, 6, 1}}, // CC1
VhtPhy::GetVhtMcs4(),
MHz_u{40},
HeSigBDurationTest::MU_MIMO,
@@ -2179,10 +2188,10 @@ TxDurationTestSuite::TxDurationTestSuite()
// 40 MHz band, MU-MIMO, 4 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_484_TONE, 1, true}, 4, 1},
{{HeRu::RU_484_TONE, 1, true}, 5, 2},
{{HeRu::RU_484_TONE, 1, true}, 6, 3},
{{HeRu::RU_484_TONE, 1, true}, 7, 2}},
{{{HeRu::RU_484_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 5, 2}, // CC2
{{HeRu::RU_484_TONE, 1, true}, 6, 3}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 7, 2}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{40},
HeSigBDurationTest::MU_MIMO,
@@ -2193,12 +2202,12 @@ TxDurationTestSuite::TxDurationTestSuite()
// 40 MHz band, MU-MIMO, 6 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_484_TONE, 1, true}, 4, 1},
{{HeRu::RU_484_TONE, 1, true}, 5, 1},
{{HeRu::RU_484_TONE, 1, true}, 6, 2},
{{HeRu::RU_484_TONE, 1, true}, 7, 2},
{{HeRu::RU_484_TONE, 1, true}, 8, 1},
{{HeRu::RU_484_TONE, 1, true}, 9, 1}},
{{{HeRu::RU_484_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 5, 1}, // CC2
{{HeRu::RU_484_TONE, 1, true}, 6, 2}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 7, 2}, // CC2
{{HeRu::RU_484_TONE, 1, true}, 8, 1}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 9, 1}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{40},
HeSigBDurationTest::MU_MIMO,
@@ -2209,14 +2218,14 @@ TxDurationTestSuite::TxDurationTestSuite()
// 40 MHz band, MU-MIMO, 8 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_484_TONE, 1, true}, 4, 1},
{{HeRu::RU_484_TONE, 1, true}, 5, 1},
{{HeRu::RU_484_TONE, 1, true}, 6, 1},
{{HeRu::RU_484_TONE, 1, true}, 7, 1},
{{HeRu::RU_484_TONE, 1, true}, 8, 1},
{{HeRu::RU_484_TONE, 1, true}, 9, 1},
{{HeRu::RU_484_TONE, 1, true}, 10, 1},
{{HeRu::RU_484_TONE, 1, true}, 11, 1}},
{{{HeRu::RU_484_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 5, 1}, // CC2
{{HeRu::RU_484_TONE, 1, true}, 6, 1}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 7, 1}, // CC2
{{HeRu::RU_484_TONE, 1, true}, 8, 1}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 9, 1}, // CC2
{{HeRu::RU_484_TONE, 1, true}, 10, 1}, // CC1
{{HeRu::RU_484_TONE, 1, true}, 11, 1}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{40},
HeSigBDurationTest::MU_MIMO,
@@ -2227,7 +2236,8 @@ TxDurationTestSuite::TxDurationTestSuite()
// 80 MHz band, MU-MIMO, 2 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_996_TONE, 1, true}, 11, 1}, {{HeRu::RU_996_TONE, 1, true}, 10, 4}},
{{{HeRu::RU_996_TONE, 1, true}, 11, 1}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 10, 4}}, // CC2
VhtPhy::GetVhtMcs5(),
MHz_u{80},
HeSigBDurationTest::MU_MIMO,
@@ -2239,9 +2249,9 @@ TxDurationTestSuite::TxDurationTestSuite()
// 80 MHz band, MU-MIMO, 3 users
AddTestCase(
new HeSigBDurationTest(
{{{HeRu::RU_996_TONE, 1, true}, 4, 3},
{{HeRu::RU_996_TONE, 1, true}, 5, 2},
{{HeRu::RU_996_TONE, 1, true}, 6, 1}},
{{{HeRu::RU_996_TONE, 1, true}, 4, 3}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 5, 2}, // CC2
{{HeRu::RU_996_TONE, 1, true}, 6, 1}}, // CC1
VhtPhy::GetVhtMcs4(),
MHz_u{80},
HeSigBDurationTest::MU_MIMO,
@@ -2252,10 +2262,10 @@ TxDurationTestSuite::TxDurationTestSuite()
// 80 MHz band, MU-MIMO, 4 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_996_TONE, 1, true}, 4, 1},
{{HeRu::RU_996_TONE, 1, true}, 5, 2},
{{HeRu::RU_996_TONE, 1, true}, 6, 3},
{{HeRu::RU_996_TONE, 1, true}, 7, 2}},
{{{HeRu::RU_996_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 5, 2}, // CC2
{{HeRu::RU_996_TONE, 1, true}, 6, 3}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 7, 2}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{80},
HeSigBDurationTest::MU_MIMO,
@@ -2266,12 +2276,12 @@ TxDurationTestSuite::TxDurationTestSuite()
// 80 MHz band, MU-MIMO, 6 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_996_TONE, 1, true}, 4, 1},
{{HeRu::RU_996_TONE, 1, true}, 5, 1},
{{HeRu::RU_996_TONE, 1, true}, 6, 2},
{{HeRu::RU_996_TONE, 1, true}, 7, 2},
{{HeRu::RU_996_TONE, 1, true}, 8, 1},
{{HeRu::RU_996_TONE, 1, true}, 9, 1}},
{{{HeRu::RU_996_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 5, 1}, // CC2
{{HeRu::RU_996_TONE, 1, true}, 6, 2}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 7, 2}, // CC2
{{HeRu::RU_996_TONE, 1, true}, 8, 1}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 9, 1}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{80},
HeSigBDurationTest::MU_MIMO,
@@ -2282,14 +2292,14 @@ TxDurationTestSuite::TxDurationTestSuite()
// 80 MHz band, MU-MIMO, 8 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_996_TONE, 1, true}, 4, 1},
{{HeRu::RU_996_TONE, 1, true}, 5, 1},
{{HeRu::RU_996_TONE, 1, true}, 6, 1},
{{HeRu::RU_996_TONE, 1, true}, 7, 1},
{{HeRu::RU_996_TONE, 1, true}, 8, 1},
{{HeRu::RU_996_TONE, 1, true}, 9, 1},
{{HeRu::RU_996_TONE, 1, true}, 10, 1},
{{HeRu::RU_996_TONE, 1, true}, 11, 1}},
{{{HeRu::RU_996_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 5, 1}, // CC2
{{HeRu::RU_996_TONE, 1, true}, 6, 1}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 7, 1}, // CC2
{{HeRu::RU_996_TONE, 1, true}, 8, 1}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 9, 1}, // CC2
{{HeRu::RU_996_TONE, 1, true}, 10, 1}, // CC1
{{HeRu::RU_996_TONE, 1, true}, 11, 1}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{80},
HeSigBDurationTest::MU_MIMO,
@@ -2299,23 +2309,23 @@ TxDurationTestSuite::TxDurationTestSuite()
TestCase::Duration::QUICK);
// 160 MHz band, MU-MIMO, 2 users
AddTestCase(
new HeSigBDurationTest(
{{{HeRu::RU_2x996_TONE, 1, true}, 11, 1}, {{HeRu::RU_2x996_TONE, 1, true}, 10, 4}},
VhtPhy::GetVhtMcs5(),
MHz_u{160},
HeSigBDurationTest::MU_MIMO,
{208, 208, 208, 208, 208, 208, 208, 208},
std::make_pair(1, 1), // users equally split between the two content channels
MicroSeconds(4)), // one OFDM symbol
TestCase::Duration::QUICK);
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_2x996_TONE, 1, true}, 11, 1}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 10, 4}}, // CC2
VhtPhy::GetVhtMcs5(),
MHz_u{160},
HeSigBDurationTest::MU_MIMO,
{208, 208, 208, 208, 208, 208, 208, 208},
std::make_pair(1, 1), // users equally split between the two content channels
MicroSeconds(4)), // one OFDM symbol
TestCase::Duration::QUICK);
// 160 MHz band, MU-MIMO, 3 users
AddTestCase(
new HeSigBDurationTest(
{{{HeRu::RU_2x996_TONE, 1, true}, 4, 3},
{{HeRu::RU_2x996_TONE, 1, true}, 5, 2},
{{HeRu::RU_2x996_TONE, 1, true}, 6, 1}},
{{{HeRu::RU_2x996_TONE, 1, true}, 4, 3}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 5, 2}, // CC2
{{HeRu::RU_2x996_TONE, 1, true}, 6, 1}}, // CC1
VhtPhy::GetVhtMcs4(),
MHz_u{160},
HeSigBDurationTest::MU_MIMO,
@@ -2326,10 +2336,10 @@ TxDurationTestSuite::TxDurationTestSuite()
// 160 MHz band, MU-MIMO, 4 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_2x996_TONE, 1, true}, 4, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 5, 2},
{{HeRu::RU_2x996_TONE, 1, true}, 6, 3},
{{HeRu::RU_2x996_TONE, 1, true}, 7, 2}},
{{{HeRu::RU_2x996_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 5, 2}, // CC2
{{HeRu::RU_2x996_TONE, 1, true}, 6, 3}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 7, 2}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{160},
HeSigBDurationTest::MU_MIMO,
@@ -2340,12 +2350,12 @@ TxDurationTestSuite::TxDurationTestSuite()
// 160 MHz band, MU-MIMO, 6 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_2x996_TONE, 1, true}, 4, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 5, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 6, 2},
{{HeRu::RU_2x996_TONE, 1, true}, 7, 2},
{{HeRu::RU_2x996_TONE, 1, true}, 8, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 9, 1}},
{{{HeRu::RU_2x996_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 5, 1}, // CC2
{{HeRu::RU_2x996_TONE, 1, true}, 6, 2}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 7, 2}, // CC2
{{HeRu::RU_2x996_TONE, 1, true}, 8, 1}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 9, 1}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{160},
HeSigBDurationTest::MU_MIMO,
@@ -2356,14 +2366,14 @@ TxDurationTestSuite::TxDurationTestSuite()
// 160 MHz band, MU-MIMO, 8 users
AddTestCase(new HeSigBDurationTest(
{{{HeRu::RU_2x996_TONE, 1, true}, 4, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 5, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 6, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 7, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 8, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 9, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 10, 1},
{{HeRu::RU_2x996_TONE, 1, true}, 11, 1}},
{{{HeRu::RU_2x996_TONE, 1, true}, 4, 1}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 5, 1}, // CC2
{{HeRu::RU_2x996_TONE, 1, true}, 6, 1}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 7, 1}, // CC2
{{HeRu::RU_2x996_TONE, 1, true}, 8, 1}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 9, 1}, // CC2
{{HeRu::RU_2x996_TONE, 1, true}, 10, 1}, // CC1
{{HeRu::RU_2x996_TONE, 1, true}, 11, 1}}, // CC2
VhtPhy::GetVhtMcs4(),
MHz_u{160},
HeSigBDurationTest::MU_MIMO,

View File

@@ -549,12 +549,24 @@ TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
else if (m_channelWidth == MHz_u{80})
{
ruType = HeRu::RU_484_TONE;
txVector.SetRuAllocation({200, 200, 200, 200}, 0);
const uint16_t ruAllocUser = 200;
const uint16_t ruAllocNoUser = 114;
txVector.SetRuAllocation({ruAllocUser, ruAllocNoUser, ruAllocNoUser, ruAllocUser}, 0);
}
else if (m_channelWidth == MHz_u{160})
{
ruType = HeRu::RU_996_TONE;
txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208}, 0);
const uint16_t ruAllocUser = 208;
const uint16_t ruAllocNoUser = 115;
txVector.SetRuAllocation({ruAllocUser,
ruAllocNoUser,
ruAllocUser,
ruAllocNoUser,
ruAllocNoUser,
ruAllocUser,
ruAllocNoUser,
ruAllocUser},
0);
}
else
{
@@ -1436,14 +1448,17 @@ TestDlOfdmaPhyPuncturing::SendMuPpdu(uint16_t rxStaId1,
RuAllocation ruAlloc;
if (puncturedSubchannels.empty())
{
std::fill_n(std::back_inserter(ruAlloc), 4, 200);
ruAlloc.push_back(200);
ruAlloc.push_back(114);
ruAlloc.push_back(114);
ruAlloc.push_back(200);
}
else
{
ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 114);
ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
: (puncturedSubchannels.at(3) ? 192 : 200));
: (puncturedSubchannels.at(3) ? 192 : 114));
ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
: (puncturedSubchannels.at(3) ? 113 : 200));
}