diff --git a/src/wifi/test/wifi-phy-cca-test.cc b/src/wifi/test/wifi-phy-cca-test.cc index 5ee9c7129..a5023525f 100644 --- a/src/wifi/test/wifi-phy-cca-test.cc +++ b/src/wifi/test/wifi-phy-cca-test.cc @@ -7,7 +7,9 @@ */ #include "ns3/constant-obss-pd-algorithm.h" -#include "ns3/he-phy.h" +#include "ns3/eht-configuration.h" +#include "ns3/eht-phy.h" +#include "ns3/eht-ppdu.h" #include "ns3/he-ppdu.h" #include "ns3/ht-ppdu.h" #include "ns3/interference-helper.h" @@ -30,6 +32,7 @@ #include "ns3/wifi-phy-listener.h" #include "ns3/wifi-psdu.h" #include "ns3/wifi-spectrum-value-helper.h" +#include "ns3/wifi-standards.h" #include "ns3/wifi-utils.h" #include @@ -47,13 +50,20 @@ constexpr MHz_u P80_CENTER_FREQUENCY = P40_CENTER_FREQUENCY + MHz_u{20}; constexpr MHz_u S80_CENTER_FREQUENCY = P80_CENTER_FREQUENCY + MHz_u{80}; constexpr MHz_u P160_CENTER_FREQUENCY = P80_CENTER_FREQUENCY + MHz_u{40}; const Time smallDelta = NanoSeconds(1); -// add small delta to be right after aCCATime, since test checks are scheduled before wifi events -const Time aCcaTime = MicroSeconds(4) + smallDelta; -const std::map PpduDurations = { +const Time aCcaTime = MicroSeconds(4); +const Time phyHeaderDuration = MicroSeconds(32); +// add small delta to be right after aCcaTime, since test checks are scheduled before wifi events +const Time aCcaTimeWithDelta = aCcaTime + smallDelta; +const std::map hePpduDurations = { {20, NanoSeconds(1009600)}, {40, NanoSeconds(533600)}, {80, NanoSeconds(275200)}, }; +const std::map ehtPpduDurations = { + {20, NanoSeconds(1017600)}, + {40, NanoSeconds(541600)}, + {80, NanoSeconds(287200)}, +}; /** * @ingroup wifi-test @@ -108,6 +118,13 @@ class WifiPhyCcaThresholdsTest : public TestCase * @return a HE PPDU */ Ptr CreateDummyHePpdu(MHz_u bandwidth, const WifiPhyOperatingChannel& channel); + /** + * Create a EHT PPDU + * @param bandwidth the bandwidth used for the transmission the PPDU + * @param channel the operating channel of the PHY used for the transmission + * @return a EHT PPDU + */ + Ptr CreateDummyEhtPpdu(MHz_u bandwidth, const WifiPhyOperatingChannel& channel); /** * Function to verify the CCA threshold that is being reported by a given PHY entity upon @@ -127,6 +144,7 @@ class WifiPhyCcaThresholdsTest : public TestCase Ptr m_phy; ///< The spectrum PHY Ptr m_obssPdAlgorithm; ///< The OBSS-PD algorithm Ptr m_vhtConfiguration; ///< The VHT configuration + Ptr m_ehtConfiguration; ///< The EHT configuration dBm_u m_CcaEdThreshold; ///< The current CCA-ED threshold for a 20 MHz subchannel dBm_u m_CcaSensitivity; ///< The current CCA sensitivity threshold for signals that occupy the @@ -136,7 +154,8 @@ class WifiPhyCcaThresholdsTest : public TestCase m_secondaryCcaSensitivityThresholds; ///< The current CCA sensitivity thresholds for signals ///< that do not occupy the primary 20 MHz channel - dBm_u m_obssPdLevel; ///< The current OBSS-PD level + dBm_u m_obssPdLevel; ///< The current OBSS-PD level + dBm_u m_per20CcaSensitivity; ///< The current CCA sensitivity threshold for Per 20MHz check }; WifiPhyCcaThresholdsTest::WifiPhyCcaThresholdsTest() @@ -144,7 +163,8 @@ WifiPhyCcaThresholdsTest::WifiPhyCcaThresholdsTest() m_CcaEdThreshold{-62.0}, m_CcaSensitivity{-82.0}, m_secondaryCcaSensitivityThresholds{dBm_u{-72}, dBm_u{-72}, dBm_u{-69}}, - m_obssPdLevel{-82.0} + m_obssPdLevel{-82.0}, + m_per20CcaSensitivity{-72.0} { } @@ -223,6 +243,29 @@ WifiPhyCcaThresholdsTest::CreateDummyHePpdu(MHz_u bandwidth, const WifiPhyOperat return Create(psdu, txVector, channel, MicroSeconds(100), 0); } +Ptr +WifiPhyCcaThresholdsTest::CreateDummyEhtPpdu(MHz_u bandwidth, + const WifiPhyOperatingChannel& channel) +{ + WifiTxVector txVector{EhtPhy::GetEhtMcs0(), + 0, + WIFI_PREAMBLE_EHT_MU, + NanoSeconds(800), + 1, + 1, + 0, + bandwidth, + false}; + WifiConstPsduMap psdus; + psdus.emplace(1, CreateDummyPsdu()); + return Create(psdus, + txVector, + channel, + MicroSeconds(100), + 0, + HePpdu::PSD_NON_HE_PORTION); +} + void WifiPhyCcaThresholdsTest::VerifyCcaThreshold(const Ptr phy, const Ptr ppdu, @@ -250,9 +293,11 @@ WifiPhyCcaThresholdsTest::DoSetup() // LogComponentEnable ("WifiPhyCcaTest", LOG_LEVEL_ALL); m_device = CreateObject(); - m_device->SetStandard(WIFI_STANDARD_80211ax); + m_device->SetStandard(WIFI_STANDARD_80211be); m_vhtConfiguration = CreateObject(); m_device->SetVhtConfiguration(m_vhtConfiguration); + m_ehtConfiguration = CreateObject(); + m_device->SetEhtConfiguration(m_ehtConfiguration); m_phy = CreateObject(); m_phy->SetDevice(m_device); @@ -263,11 +308,11 @@ WifiPhyCcaThresholdsTest::DoSetup() auto channelNum = WifiPhyOperatingChannel::FindFirst(0, MHz_u{0}, MHz_u{160}, - WIFI_STANDARD_80211ax, + WIFI_STANDARD_80211be, WIFI_PHY_BAND_5GHZ) ->number; m_phy->SetOperatingChannel(WifiPhy::ChannelTuple{channelNum, 160, WIFI_PHY_BAND_5GHZ, 0}); - m_phy->ConfigureStandard(WIFI_STANDARD_80211ax); + m_phy->ConfigureStandard(WIFI_STANDARD_80211be); m_obssPdAlgorithm = CreateObject(); m_device->AggregateObject(m_obssPdAlgorithm); @@ -288,6 +333,7 @@ WifiPhyCcaThresholdsTest::RunOne() m_phy->SetCcaSensitivityThreshold(m_CcaSensitivity); m_vhtConfiguration->SetSecondaryCcaSensitivityThresholds(m_secondaryCcaSensitivityThresholds); m_obssPdAlgorithm->SetObssPdLevel(m_obssPdLevel); + m_ehtConfiguration->m_per20CcaSensitivityThreshold = m_per20CcaSensitivity; // OFDM PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_OFDM), @@ -542,6 +588,106 @@ WifiPhyCcaThresholdsTest::RunOne() CreateDummyHePpdu(MHz_u{80}, m_phy->GetOperatingChannel()), WIFI_CHANLIST_SECONDARY80, std::max(m_obssPdLevel + dB_u{6.0}, std::get<2>(m_secondaryCcaSensitivityThresholds))); + + //----------------------------------------------------------------------------------------------------------------------------------- + + // EHT PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + nullptr, + WIFI_CHANLIST_PRIMARY, + m_CcaEdThreshold); + + // EHT PHY: any signal in secondary channel (20 MHz) if power above CCA-ED threshold + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + nullptr, + WIFI_CHANLIST_SECONDARY, + m_CcaEdThreshold); + + // EHT PHY: any signal in secondary40 channel (40 MHz) if power in any 20 MHz subchannel above + // CCA-ED threshold + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + nullptr, + WIFI_CHANLIST_SECONDARY40, + m_CcaEdThreshold); + + // EHT PHY: any signal in secondary80 channel (80 MHz) if power in any 20 MHz subchannel above + // CCA-ED threshold + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + nullptr, + WIFI_CHANLIST_SECONDARY80, + m_CcaEdThreshold); + + //----------------------------------------------------------------------------------------------------------------------------------- + // EHT PHY: 20 MHz EHT PPDU in primary channel (20 MHz) if power in primary above CCA + // sensitivity threshold + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_PRIMARY, + m_CcaSensitivity); + // EHT PHY: 40 MHz EHT PPDU in primary channel (20 MHz) if power in primary above CCA + // sensitivity threshold + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_PRIMARY, + m_CcaSensitivity); + + // EHT PHY: 80 MHz EHT PPDU in primary channel (20 MHz) if power in primary above CCA + // sensitivity threshold + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{80}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_PRIMARY, + m_CcaSensitivity); + + // EHT PHY: 160 MHz EHT PPDU in primary channel (20 MHz) if power in primary above CCA + // sensitivity threshold + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{160}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_PRIMARY, + m_CcaSensitivity); + + //----------------------------------------------------------------------------------------------------------------------------------- + + // EHT PHY: 20 MHz EHT PPDU in secondary channel (20 MHz) if power above the max between the CCA + // sensitivity threshold for Per 20MHz check and the OBSS-PD level + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_SECONDARY, + std::max(m_obssPdLevel, m_per20CcaSensitivity)); + + // EHT PHY: 20 MHz EHT PPDU in secondary40 channel (40 MHz) if power above the max between the + // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_SECONDARY40, + std::max(m_obssPdLevel, m_per20CcaSensitivity)); + + // EHT PHY: 40 MHz EHT PPDU in secondary40 channel (40 MHz) if power above the max between the + // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_SECONDARY40, + std::max(m_obssPdLevel, m_per20CcaSensitivity)); + + // EHT PHY: 20 MHz EHT PPDU in secondary80 channel (80 MHz) if power above the max between the + // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{80}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_SECONDARY80, + std::max(m_obssPdLevel, m_per20CcaSensitivity)); + + // EHT PHY: 40 MHz EHT PPDU in secondary80 channel (80 MHz) if power above the max between the + // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_SECONDARY80, + std::max(m_obssPdLevel, m_per20CcaSensitivity)); + + // EHT PHY: 80 MHz EHT PPDU in secondary80 channel (80 MHz) if power above the max between the + // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level + VerifyCcaThreshold(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT), + CreateDummyEhtPpdu(MHz_u{80}, m_phy->GetOperatingChannel()), + WIFI_CHANLIST_SECONDARY80, + std::max(m_obssPdLevel, m_per20CcaSensitivity)); } void @@ -552,6 +698,7 @@ WifiPhyCcaThresholdsTest::DoRun() m_CcaSensitivity = dBm_u{-82}; m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69}); m_obssPdLevel = dBm_u{-82}; + m_per20CcaSensitivity = dBm_u{-72.0}; RunOne(); // default attributes with OBSS-PD level set to -80 dBm @@ -559,6 +706,7 @@ WifiPhyCcaThresholdsTest::DoRun() m_CcaSensitivity = dBm_u{-82}; m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69}); m_obssPdLevel = dBm_u{-80}; + m_per20CcaSensitivity = dBm_u{-72.0}; RunOne(); // default attributes with OBSS-PD level set to -70 dBm @@ -566,6 +714,7 @@ WifiPhyCcaThresholdsTest::DoRun() m_CcaSensitivity = dBm_u{-82}; m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69}); m_obssPdLevel = dBm_u{-70}; + m_per20CcaSensitivity = dBm_u{-72.0}; RunOne(); // CCA-ED set to -65 dBm @@ -573,6 +722,7 @@ WifiPhyCcaThresholdsTest::DoRun() m_CcaSensitivity = dBm_u{-82}; m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69}); m_obssPdLevel = dBm_u{-82}; + m_per20CcaSensitivity = dBm_u{-72.0}; RunOne(); // CCA sensitivity for signals in primary set to -75 dBm @@ -580,6 +730,7 @@ WifiPhyCcaThresholdsTest::DoRun() m_CcaSensitivity = dBm_u{-75}; m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69}); m_obssPdLevel = dBm_u{-82}; + m_per20CcaSensitivity = dBm_u{-72.0}; RunOne(); // custom CCA sensitivities for signals not in primary @@ -587,6 +738,7 @@ WifiPhyCcaThresholdsTest::DoRun() m_CcaSensitivity = dBm_u{-72}; m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-70}, dBm_u{-70}, dBm_u{-70}); m_obssPdLevel = dBm_u{-82}; + m_per20CcaSensitivity = -75.0; RunOne(); // custom CCA sensitivities for signals not in primary with OBSS-PD level set to -80 dBm @@ -594,6 +746,7 @@ WifiPhyCcaThresholdsTest::DoRun() m_CcaSensitivity = dBm_u{-72}; m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-70}, dBm_u{-70}, dBm_u{-70}); m_obssPdLevel = dBm_u{-80}; + m_per20CcaSensitivity = -69.0; RunOne(); // custom CCA sensitivities for signals not in primary with OBSS-PD level set to -70 dBm @@ -601,6 +754,7 @@ WifiPhyCcaThresholdsTest::DoRun() m_CcaSensitivity = dBm_u{-72}; m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-70}, dBm_u{-70}, dBm_u{-70}); m_obssPdLevel = dBm_u{-70}; + m_per20CcaSensitivity = -66.0; RunOne(); Simulator::Destroy(); @@ -696,7 +850,12 @@ class CcaTestPhyListener : public ns3::WifiPhyListener class WifiPhyCcaIndicationTest : public TestCase { public: - WifiPhyCcaIndicationTest(); + /** + * Constructor + * + * @param standard the standard to use for the test + */ + WifiPhyCcaIndicationTest(WifiStandard standard); private: void DoSetup() override; @@ -704,12 +863,12 @@ class WifiPhyCcaIndicationTest : public TestCase void DoTeardown() override; /** - * Send an HE SU PPDU + * Send a HE or EHT SU PPDU * @param txPower the transmit power * @param frequency the center frequency the transmitter is operating on * @param bandwidth the bandwidth to use for the transmission */ - void SendHeSuPpdu(dBm_u txPower, MHz_u frequency, MHz_u bandwidth); + void SendSuPpdu(dBm_u txPower, MHz_u frequency, MHz_u bandwidth); /** * Start to generate a signal @@ -823,6 +982,8 @@ class WifiPhyCcaIndicationTest : public TestCase */ void RunOne(); + WifiStandard m_standard; ///< The standard to use for the test + Ptr m_rxPhy; ///< PHY object of the receiver Ptr m_txPhy; ///< PHY object of the transmitter @@ -837,11 +998,14 @@ class WifiPhyCcaIndicationTest : public TestCase MHz_u m_channelWidth; ///< Operating channel width }; -WifiPhyCcaIndicationTest::WifiPhyCcaIndicationTest() - : TestCase("Wi-Fi PHY CCA indication test"), - m_numSignalGenerators(2), - m_frequency(P20_CENTER_FREQUENCY), - m_channelWidth(MHz_u{20}) +WifiPhyCcaIndicationTest::WifiPhyCcaIndicationTest(WifiStandard standard) + : TestCase("Wi-Fi PHY CCA indication test for " + ((standard == WIFI_STANDARD_80211ax) + ? std::string("802.11ax") + : std::string("802.11be"))), + m_standard{standard}, + m_numSignalGenerators{2}, + m_frequency{P20_CENTER_FREQUENCY}, + m_channelWidth{MHz_u{20}} { } @@ -879,29 +1043,21 @@ WifiPhyCcaIndicationTest::StopSignal(Ptr signalGenerator) } void -WifiPhyCcaIndicationTest::SendHeSuPpdu(dBm_u txPower, MHz_u frequency, MHz_u bandwidth) +WifiPhyCcaIndicationTest::SendSuPpdu(dBm_u txPower, MHz_u frequency, MHz_u bandwidth) { NS_LOG_FUNCTION(this << txPower); - auto channelNum = WifiPhyOperatingChannel::FindFirst(0, - frequency, - bandwidth, - WIFI_STANDARD_80211ax, - WIFI_PHY_BAND_5GHZ) - ->number; + auto channelNum = + WifiPhyOperatingChannel::FindFirst(0, frequency, bandwidth, m_standard, WIFI_PHY_BAND_5GHZ) + ->number; m_txPhy->SetOperatingChannel( WifiPhy::ChannelTuple{channelNum, bandwidth, WIFI_PHY_BAND_5GHZ, 0}); - WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs0(), - 0, - WIFI_PREAMBLE_HE_SU, - NanoSeconds(800), - 1, - 1, - 0, - bandwidth, - false); - + const auto mcs = + (m_standard == WIFI_STANDARD_80211ax) ? HePhy::GetHeMcs0() : EhtPhy::GetEhtMcs0(); + const auto preamble = + (m_standard == WIFI_STANDARD_80211ax) ? WIFI_PREAMBLE_HE_SU : WIFI_PREAMBLE_EHT_MU; + WifiTxVector txVector{mcs, 0, preamble, NanoSeconds(800), 1, 1, 0, bandwidth, false}; Ptr pkt = Create(1000); WifiMacHeader hdr; hdr.SetType(WIFI_MAC_QOSDATA); @@ -982,7 +1138,7 @@ WifiPhyCcaIndicationTest::ScheduleTest(Time delay, for (const auto& generatedPpdu : generatedPpdus) { Simulator::Schedule(delay + generatedPpdu.startTime, - &WifiPhyCcaIndicationTest::SendHeSuPpdu, + &WifiPhyCcaIndicationTest::SendSuPpdu, this, generatedPpdu.power, generatedPpdu.centerFreq, @@ -1039,9 +1195,14 @@ WifiPhyCcaIndicationTest::DoSetup() Ptr rxNode = CreateObject(); Ptr rxDev = CreateObject(); - rxDev->SetStandard(WIFI_STANDARD_80211ax); - Ptr vhtConfiguration = CreateObject(); + rxDev->SetStandard(m_standard); + auto vhtConfiguration = CreateObject(); rxDev->SetVhtConfiguration(vhtConfiguration); + if (m_standard > WIFI_STANDARD_80211ax) + { + auto ehtConfiguration = CreateObject(); + rxDev->SetEhtConfiguration(ehtConfiguration); + } m_rxPhy = CreateObject(); m_rxPhyStateListener = std::make_unique(); m_rxPhy->RegisterListener(m_rxPhyStateListener); @@ -1053,7 +1214,7 @@ WifiPhyCcaIndicationTest::DoSetup() CreateObject(); m_rxPhy->SetPreambleDetectionModel(preambleDetectionModel); m_rxPhy->AddChannel(spectrumChannel); - m_rxPhy->ConfigureStandard(WIFI_STANDARD_80211ax); + m_rxPhy->ConfigureStandard(m_standard); m_rxPhy->SetDevice(rxDev); rxDev->SetPhy(m_rxPhy); rxNode->AddDevice(rxDev); @@ -1067,7 +1228,7 @@ WifiPhyCcaIndicationTest::DoSetup() Ptr txErrorModel = CreateObject(); m_txPhy->SetErrorRateModel(txErrorModel); m_txPhy->AddChannel(spectrumChannel); - m_txPhy->ConfigureStandard(WIFI_STANDARD_80211ax); + m_txPhy->ConfigureStandard(m_standard); m_txPhy->SetDevice(txDev); txDev->SetPhy(m_txPhy); txNode->AddDevice(txDev); @@ -1098,7 +1259,7 @@ WifiPhyCcaIndicationTest::RunOne() auto channelNum = WifiPhyOperatingChannel::FindFirst(0, m_frequency, m_channelWidth, - WIFI_STANDARD_80211ax, + m_standard, WIFI_PHY_BAND_5GHZ) ->number; @@ -1107,6 +1268,9 @@ WifiPhyCcaIndicationTest::RunOne() m_txPhy->SetOperatingChannel( WifiPhy::ChannelTuple{channelNum, m_channelWidth, WIFI_PHY_BAND_5GHZ, 0}); + const auto& ppduDurations = + (m_standard == WIFI_STANDARD_80211ax) ? hePpduDurations : ehtPpduDurations; + std::vector