diff --git a/src/wifi/model/eht/eht-ppdu.cc b/src/wifi/model/eht/eht-ppdu.cc index 7b8d5803c..8653e15ad 100644 --- a/src/wifi/model/eht/eht-ppdu.cc +++ b/src/wifi/model/eht/eht-ppdu.cc @@ -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); } diff --git a/src/wifi/model/he/he-phy.cc b/src/wifi/model/he/he-phy.cc index 8ef403b56..9f69e66bf 100644 --- a/src/wifi/model/he/he-phy.cc +++ b/src/wifi/model/he/he-phy.cc @@ -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); } diff --git a/src/wifi/model/he/he-ppdu.cc b/src/wifi/model/he/he-ppdu.cc index 24127b426..f76b3405f 100644 --- a/src/wifi/model/he/he-ppdu.cc +++ b/src/wifi/model/he/he-ppdu.cc @@ -19,6 +19,7 @@ #include "ns3/wifi-utils.h" #include +#include 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& 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, const HeSigBContentChannels& contentChannels, bool sigBcompression, uint8_t numMuMimoUsers) const { + NS_ASSERT(ruAllocation.size() == Count20MHzSubchannels(txVector.GetChannelWidth())); + std::vector 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& trigVector) con } std::pair -HePpdu::GetNumRusPerHeSigBContentChannel(MHz_u channelWidth, - const RuAllocation& ruAllocation, - bool sigBCompression, - uint8_t numMuMimoUsers) +HePpdu::GetNumRusPerHeSigBContentChannel( + MHz_u channelWidth, + const RuAllocation& ruAllocation, + std::optional center26ToneRuIndication, + bool sigBCompression, + uint8_t numMuMimoUsers) { std::pair @@ -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 cc1Central26ToneRu; + std::optional cc2Central26ToneRu; + const auto& orderedMap = txVector.GetUserInfoMapOrderedByRus(p20Index); + std::optional 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, 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 = diff --git a/src/wifi/model/he/he-ppdu.h b/src/wifi/model/he/he-ppdu.h index 538495034..e09403ef8 100644 --- a/src/wifi/model/he/he-ppdu.h +++ b/src/wifi/model/he/he-ppdu.h @@ -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 GetNumRusPerHeSigBContentChannel( MHz_u channelWidth, const RuAllocation& ruAllocation, + std::optional 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, + 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, 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& 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. * diff --git a/src/wifi/model/wifi-tx-vector.cc b/src/wifi/model/wifi-tx-vector.cc index 82cc0ba97..a2f58d5d1 100644 --- a/src/wifi/model/wifi-tx-vector.cc +++ b/src/wifi/model/wifi-tx-vector.cc @@ -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 ruTypes{}; ruTypes.resize(ruAllocations.size()); const auto& orderedMap = GetUserInfoMapOrderedByRus(p20Index); + std::pair + 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; diff --git a/src/wifi/model/wifi-tx-vector.h b/src/wifi/model/wifi-tx-vector.h index 6fac08b94..37ef4ea06 100644 --- a/src/wifi/model/wifi-tx-vector.h +++ b/src/wifi/model/wifi-tx-vector.h @@ -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. diff --git a/src/wifi/test/tx-duration-test.cc b/src/wifi/test/tx-duration-test.cc index 5ed23a35a..8fe72101f 100644 --- a/src/wifi/test/tx-duration-test.cc +++ b/src/wifi/test/tx-duration-test.cc @@ -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, diff --git a/src/wifi/test/wifi-phy-ofdma-test.cc b/src/wifi/test/wifi-phy-ofdma-test.cc index 096d9228c..cb7cb53b9 100644 --- a/src/wifi/test/wifi-phy-ofdma-test.cc +++ b/src/wifi/test/wifi-phy-ofdma-test.cc @@ -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)); }