From 0ad40e64bcbabb216d75077cebd10430757dbda8 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Tue, 1 Jun 2021 12:40:42 +0200 Subject: [PATCH] wifi: Make use of RU PHY indices --- src/wifi/model/he/he-phy.cc | 10 ++++--- src/wifi/model/he/he-ru.cc | 41 ++++++++++++++++++---------- src/wifi/model/he/he-ru.h | 10 +++---- src/wifi/model/spectrum-wifi-phy.cc | 18 +++++++++--- src/wifi/model/wifi-tx-vector.cc | 6 ++++ src/wifi/test/wifi-phy-ofdma-test.cc | 16 +++++------ 6 files changed, 65 insertions(+), 36 deletions(-) diff --git a/src/wifi/model/he/he-phy.cc b/src/wifi/model/he/he-phy.cc index 8d4625d3c..7830c6b37 100644 --- a/src/wifi/model/he/he-phy.cc +++ b/src/wifi/model/he/he-phy.cc @@ -732,7 +732,7 @@ HePhy::GetRuBandForTx (const WifiTxVector& txVector, uint16_t staId) const HeRu::RuSpec ru = txVector.GetRu (staId); uint16_t channelWidth = txVector.GetChannelWidth (); NS_ASSERT (channelWidth <= m_wifiPhy->GetChannelWidth ()); - HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup (channelWidth, ru.GetRuType (), ru.GetIndex ()); + HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup (channelWidth, ru.GetRuType (), ru.GetPhyIndex ()); HeRu::SubcarrierRange range = std::make_pair (group.front ().first, group.back ().second); // for a TX spectrum, the guard bandwidth is a function of the transmission channel width // and the spectrum width equals the transmission channel width (hence bandIndex equals 0) @@ -749,7 +749,7 @@ HePhy::GetRuBandForRx (const WifiTxVector& txVector, uint16_t staId) const HeRu::RuSpec ru = txVector.GetRu (staId); uint16_t channelWidth = txVector.GetChannelWidth (); NS_ASSERT (channelWidth <= m_wifiPhy->GetChannelWidth ()); - HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup (channelWidth, ru.GetRuType (), ru.GetIndex ()); + HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup (channelWidth, ru.GetRuType (), ru.GetPhyIndex ()); HeRu::SubcarrierRange range = std::make_pair (group.front ().first, group.back ().second); // for an RX spectrum, the guard bandwidth is a function of the operating channel width // and the spectrum width equals the operating channel width @@ -770,8 +770,9 @@ HePhy::GetNonOfdmaBand (const WifiTxVector& txVector, uint16_t staId) const // Find the RU that encompasses the non-OFDMA part of the HE TB PPDU for the STA-ID HeRu::RuSpec nonOfdmaRu = HeRu::FindOverlappingRu (channelWidth, ru, HeRu::GetRuType (nonOfdmaWidth)); + nonOfdmaRu.SetPhyIndex (channelWidth, m_wifiPhy->GetOperatingChannel ().GetPrimaryChannelIndex (20)); - HeRu::SubcarrierGroup groupPreamble = HeRu::GetSubcarrierGroup (channelWidth, nonOfdmaRu.GetRuType (), nonOfdmaRu.GetIndex ()); + HeRu::SubcarrierGroup groupPreamble = HeRu::GetSubcarrierGroup (channelWidth, nonOfdmaRu.GetRuType (), nonOfdmaRu.GetPhyIndex ()); HeRu::SubcarrierRange range = std::make_pair (groupPreamble.front ().first, groupPreamble.back ().second); return m_wifiPhy->ConvertHeRuSubcarriers (channelWidth, GetGuardBandwidth (m_wifiPhy->GetChannelWidth ()), range, m_wifiPhy->GetOperatingChannel ().GetPrimaryChannelIndex (channelWidth)); @@ -879,9 +880,10 @@ HePhy::GetCenterFrequencyForNonOfdmaPart (const WifiTxVector& txVector, uint16_t { //Obtain the index of the non-OFDMA portion HeRu::RuSpec nonOfdmaRu = HeRu::FindOverlappingRu (currentWidth, ru, HeRu::GetRuType (nonOfdmaWidth)); + nonOfdmaRu.SetPhyIndex (currentWidth, m_wifiPhy->GetOperatingChannel ().GetPrimaryChannelIndex (20)); uint16_t startingFrequency = centerFrequency - (currentWidth / 2); - centerFrequency = startingFrequency + nonOfdmaWidth * (nonOfdmaRu.GetIndex () - 1) + nonOfdmaWidth / 2; + centerFrequency = startingFrequency + nonOfdmaWidth * (nonOfdmaRu.GetPhyIndex () - 1) + nonOfdmaWidth / 2; } return centerFrequency; } diff --git a/src/wifi/model/he/he-ru.cc b/src/wifi/model/he/he-ru.cc index 740468c19..e34402bae 100644 --- a/src/wifi/model/he/he-ru.cc +++ b/src/wifi/model/he/he-ru.cc @@ -310,7 +310,7 @@ HeRu::GetCentral26TonesRus (uint16_t bw, HeRu::RuType ruType) } HeRu::SubcarrierGroup -HeRu::GetSubcarrierGroup (uint16_t bw, RuType ruType, std::size_t index) +HeRu::GetSubcarrierGroup (uint16_t bw, RuType ruType, std::size_t phyIndex) { if (ruType == HeRu::RU_2x996_TONE) //handle special case of RU covering 160 MHz channel { @@ -319,24 +319,24 @@ HeRu::GetSubcarrierGroup (uint16_t bw, RuType ruType, std::size_t index) } // Determine the shift to apply to tone indices for 160 MHz channel (i.e. -1012 to 1012), since - // m_heRuSubcarrierGroups contains indices for primary 80 MHz subchannel (i.e. from -500 to 500). - // The index is used to that aim. - std::size_t indexInPrimary80MHz = index; + // m_heRuSubcarrierGroups contains indices for lower 80 MHz subchannel (i.e. from -500 to 500). + // The phyIndex is used to that aim. + std::size_t indexInLower80MHz = phyIndex; std::size_t numRus = GetNRus (bw, ruType); int16_t shift = (bw == 160) ? -512 : 0; - if (bw == 160 && index > (numRus / 2)) + if (bw == 160 && phyIndex > (numRus / 2)) { - // The provided index is that of the secondary 80 MHz subchannel - indexInPrimary80MHz = index - (numRus / 2); + // The provided index is that of the upper 80 MHz subchannel + indexInLower80MHz = phyIndex - (numRus / 2); shift = 512; } auto it = m_heRuSubcarrierGroups.find ({(bw == 160 ? 80 : bw), ruType}); NS_ABORT_MSG_IF (it == m_heRuSubcarrierGroups.end (), "RU not found"); - NS_ABORT_MSG_IF (!indexInPrimary80MHz || indexInPrimary80MHz > it->second.size (), "RU index not available"); + NS_ABORT_MSG_IF (indexInLower80MHz > it->second.size (), "RU index not available"); - SubcarrierGroup group = it->second.at (indexInPrimary80MHz - 1); + SubcarrierGroup group = it->second.at (indexInLower80MHz - 1); if (bw == 160) { for (auto & range : group) @@ -357,7 +357,11 @@ HeRu::DoesOverlap (uint16_t bw, RuSpec ru, const std::vector &v) return true; } - SubcarrierGroup groups = GetSubcarrierGroup (bw, ru.GetRuType (), ru.GetIndex ()); + // This function may be called by the MAC layer, hence the PHY index may have + // not been set yet. Hence, we pass the "MAC" index to GetSubcarrierGroup instead + // of the PHY index. This is fine because we compare the primary 80 MHz bands of + // the two RUs below. + SubcarrierGroup rangesRu = GetSubcarrierGroup (bw, ru.GetRuType (), ru.GetIndex ()); for (auto& p : v) { if (ru.GetPrimary80MHz () != p.GetPrimary80MHz ()) @@ -365,9 +369,16 @@ HeRu::DoesOverlap (uint16_t bw, RuSpec ru, const std::vector &v) // the two RUs are located in distinct 80MHz bands continue; } - if (DoesOverlap (bw, p, groups)) + for (const auto& rangeRu : rangesRu) { - return true; + SubcarrierGroup rangesP = GetSubcarrierGroup (bw, p.GetRuType (), p.GetIndex ()); + for (auto& rangeP : rangesP) + { + if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first) + { + return true; + } + } } } return false; @@ -383,7 +394,7 @@ HeRu::DoesOverlap (uint16_t bw, RuSpec ru, const SubcarrierGroup &toneRanges) return true; } - SubcarrierGroup rangesRu = GetSubcarrierGroup (bw, ru.GetRuType (), ru.GetIndex ()); + SubcarrierGroup rangesRu = GetSubcarrierGroup (bw, ru.GetRuType (), ru.GetPhyIndex ()); for (auto& r : rangesRu) { if (range.second >= r.first && r.second >= range.first) @@ -406,7 +417,7 @@ HeRu::FindOverlappingRu (uint16_t bw, RuSpec referenceRu, RuType searchedRuType) { primary80MhzFlags.push_back (true); primary80MhzFlags.push_back (false); - numRusPer80Mhz = numRus / 2; + numRusPer80Mhz = (searchedRuType == HeRu::RU_2x996_TONE ? 1 : numRus / 2); } else { @@ -414,9 +425,9 @@ HeRu::FindOverlappingRu (uint16_t bw, RuSpec referenceRu, RuType searchedRuType) numRusPer80Mhz = numRus; } - std::size_t index = 1; for (const auto primary80MHz : primary80MhzFlags) { + std::size_t index = 1; for (std::size_t indexPer80Mhz = 1; indexPer80Mhz <= numRusPer80Mhz; ++indexPer80Mhz, ++index) { RuSpec searchedRu (searchedRuType, index, primary80MHz); diff --git a/src/wifi/model/he/he-ru.h b/src/wifi/model/he/he-ru.h index d853ae2b9..1e51da21c 100644 --- a/src/wifi/model/he/he-ru.h +++ b/src/wifi/model/he/he-ru.h @@ -161,20 +161,20 @@ public: static std::vector GetCentral26TonesRus (uint16_t bw, HeRu::RuType ruType); /** - * Get the subcarrier group of the RU having the given index among all the + * Get the subcarrier group of the RU having the given PHY index among all the * RUs of the given type (number of tones) available in a HE PPDU of the * given bandwidth. A subcarrier group is defined as one or more pairs * indicating the lowest frequency index and the highest frequency index. * Note that for channel width of 160 MHz the returned range is relative to - * the 160 MHz channel (i.e. -1012 to 1012). The index parameter is used to - * distinguish between primary and secondary 80 MHz subchannels. + * the 160 MHz channel (i.e. -1012 to 1012). The PHY index parameter is used to + * distinguish between lower and higher 80 MHz subchannels. * * \param bw the bandwidth (MHz) of the HE PPDU (20, 40, 80, 160) * \param ruType the RU type (number of tones) - * \param index the index (starting at 1) of the RU + * \param phyIndex the PHY index (starting at 1) of the RU * \return the subcarrier range of the specified RU */ - static SubcarrierGroup GetSubcarrierGroup (uint16_t bw, RuType ruType, std::size_t index); + static SubcarrierGroup GetSubcarrierGroup (uint16_t bw, RuType ruType, std::size_t phyIndex); /** * Check whether the given RU overlaps with the given set of RUs. diff --git a/src/wifi/model/spectrum-wifi-phy.cc b/src/wifi/model/spectrum-wifi-phy.cc index b6ee22ee5..8f3e353d5 100644 --- a/src/wifi/model/spectrum-wifi-phy.cc +++ b/src/wifi/model/spectrum-wifi-phy.cc @@ -179,14 +179,24 @@ SpectrumWifiPhy::UpdateInterferenceHelperBands (void) { HeRu::RuType ruType = static_cast (type); std::size_t nRus = HeRu::GetNRus (bw, ruType); - for (std::size_t index = 1; index <= nRus; index++) + for (std::size_t phyIndex = 1; phyIndex <= nRus; phyIndex++) { - HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup (bw, ruType, index); + HeRu::SubcarrierGroup group = HeRu::GetSubcarrierGroup (bw, ruType, phyIndex); HeRu::SubcarrierRange range = std::make_pair (group.front ().first, group.back ().second); WifiSpectrumBand band = ConvertHeRuSubcarriers (bw, GetGuardBandwidth (channelWidth), range, i); - bool primary80 = (channelWidth < 160 || index <= nRus / 2); - m_ruBands[channelWidth].insert ({band, HeRu::RuSpec (ruType, index, primary80)}); + std::size_t index = (bw == 160 && phyIndex > nRus / 2 + ? phyIndex - nRus / 2 : phyIndex); + bool primary80IsLower80 = (GetOperatingChannel ().GetPrimaryChannelIndex (20) + < bw / 40); + bool primary80 = (bw < 160 + || ruType == HeRu::RU_2x996_TONE + || (primary80IsLower80 && phyIndex <= nRus / 2) + || (!primary80IsLower80 && phyIndex > nRus / 2)); + HeRu::RuSpec ru (ruType, index, primary80); + ru.SetPhyIndex (bw, GetOperatingChannel ().GetPrimaryChannelIndex (20)); + NS_ABORT_IF (ru.GetPhyIndex () != phyIndex); + m_ruBands[channelWidth].insert ({band, ru}); } } } diff --git a/src/wifi/model/wifi-tx-vector.cc b/src/wifi/model/wifi-tx-vector.cc index 0a6fe76db..7c1022ef7 100644 --- a/src/wifi/model/wifi-tx-vector.cc +++ b/src/wifi/model/wifi-tx-vector.cc @@ -480,6 +480,12 @@ WifiTxVector::GetNumRusPerHeSigBContentChannel (void) const for (auto & userInfo : m_muUserInfos) { HeRu::RuSpec ru = userInfo.second.ru; + if (!ru.IsPhyIndexSet ()) + { + // this method can be called when calculating the TX duration of a frame + // and at that time the RU PHY index may have not been set yet + ru.SetPhyIndex (m_channelWidth, 0); + } if (HeRu::DoesOverlap (m_channelWidth, ru, toneRangesContentChannel1)) { numRusContentChannel1++; diff --git a/src/wifi/test/wifi-phy-ofdma-test.cc b/src/wifi/test/wifi-phy-ofdma-test.cc index e6a561a03..45f8588c9 100644 --- a/src/wifi/test/wifi-phy-ofdma-test.cc +++ b/src/wifi/test/wifi-phy-ofdma-test.cc @@ -505,7 +505,7 @@ TestDlOfdmaPhyTransmission::SendMuPpdu (uint16_t rxStaId1, uint16_t rxStaId2) txVector.SetMode (HePhy::GetHeMcs7 (), rxStaId1); txVector.SetNss (1, rxStaId1); - HeRu::RuSpec ru2 (ruType, 2, (m_channelWidth == 160 ? false : true)); + HeRu::RuSpec ru2 (ruType, (m_channelWidth == 160 ? 1 : 2), (m_channelWidth == 160 ? false : true)); txVector.SetRu (ru2, rxStaId2); txVector.SetMode (HePhy::GetHeMcs9 (), rxStaId2); txVector.SetNss (1, rxStaId2); @@ -1440,6 +1440,7 @@ TestMultipleHeTbPreambles::RxHeTbPpdu (uint64_t uid, uint16_t staId, double txPo WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false); HeRu::RuSpec ru (HeRu::RU_106_TONE, staId, false); + ru.SetPhyIndex (DEFAULT_CHANNEL_WIDTH, 0); txVector.SetRu (ru, staId); txVector.SetMode (HePhy::GetHeMcs7 (), staId); txVector.SetNss (1, staId); @@ -1903,16 +1904,15 @@ TestUlOfdmaPhyTransmission::GetTxVectorForHeTbPpdu (uint16_t txStaId, std::size_ NS_ASSERT_MSG (false, "Unsupported channel width"); } - bool primary80MHz; - if (m_channelWidth == 160 && (index == 1)) - { - primary80MHz = true; - } - else + bool primary80MHz = true; + if (m_channelWidth == 160 && index == 2) { primary80MHz = false; + index = 1; } - txVector.SetRu (HeRu::RuSpec (ruType, index, primary80MHz), txStaId); + HeRu::RuSpec ru (ruType, index, primary80MHz); + ru.SetPhyIndex (m_channelWidth, 0); + txVector.SetRu (ru, txStaId); txVector.SetMode (HePhy::GetHeMcs7 (), txStaId); txVector.SetNss (1, txStaId); return txVector;