A Discrete-Event Network Simulator
API
wifi-phy-cca-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
18  */
19 
20 #include "ns3/constant-obss-pd-algorithm.h"
21 #include "ns3/he-phy.h"
22 #include "ns3/he-ppdu.h"
23 #include "ns3/ht-ppdu.h"
24 #include "ns3/interference-helper.h"
25 #include "ns3/log.h"
26 #include "ns3/multi-model-spectrum-channel.h"
27 #include "ns3/nist-error-rate-model.h"
28 #include "ns3/non-communicating-net-device.h"
29 #include "ns3/ofdm-ppdu.h"
30 #include "ns3/pointer.h"
31 #include "ns3/rng-seed-manager.h"
32 #include "ns3/spectrum-wifi-helper.h"
33 #include "ns3/spectrum-wifi-phy.h"
34 #include "ns3/test.h"
35 #include "ns3/threshold-preamble-detection-model.h"
36 #include "ns3/vht-configuration.h"
37 #include "ns3/vht-ppdu.h"
38 #include "ns3/waveform-generator.h"
39 #include "ns3/wifi-mac-header.h"
40 #include "ns3/wifi-net-device.h"
41 #include "ns3/wifi-phy-listener.h"
42 #include "ns3/wifi-psdu.h"
43 #include "ns3/wifi-spectrum-value-helper.h"
44 #include "ns3/wifi-utils.h"
45 
46 #include <memory>
47 #include <vector>
48 
49 using namespace ns3;
50 
51 NS_LOG_COMPONENT_DEFINE("WifiPhyCcaTest");
52 
53 constexpr uint32_t P20_CENTER_FREQUENCY = 5180; // MHz
54 constexpr uint32_t S20_CENTER_FREQUENCY = P20_CENTER_FREQUENCY + 20;
55 constexpr uint32_t P40_CENTER_FREQUENCY = P20_CENTER_FREQUENCY + 10;
56 constexpr uint32_t S40_CENTER_FREQUENCY = P40_CENTER_FREQUENCY + 40;
57 constexpr uint32_t P80_CENTER_FREQUENCY = P40_CENTER_FREQUENCY + 20;
58 constexpr uint32_t S80_CENTER_FREQUENCY = P80_CENTER_FREQUENCY + 80;
59 constexpr uint32_t P160_CENTER_FREQUENCY = P80_CENTER_FREQUENCY + 40;
61 // add small delta to be right after aCCATime, since test checks are scheduled before wifi events
63 const std::map<uint16_t, Time> PpduDurations = {
64  {20, NanoSeconds(1009600)},
65  {40, NanoSeconds(533600)},
66  {80, NanoSeconds(275200)},
67 };
68 
76 {
77  public:
79 
80  private:
81  void DoSetup() override;
82  void DoTeardown() override;
83  void DoRun() override;
84 
88  void RunOne();
89 
94  Ptr<WifiPsdu> CreateDummyPsdu();
99  Ptr<OfdmPpdu> CreateDummyNonHtPpdu();
105  Ptr<HtPpdu> CreateDummyHtPpdu(uint16_t bandwidth);
111  Ptr<VhtPpdu> CreateDummyVhtPpdu(uint16_t bandwidth);
117  Ptr<HePpdu> CreateDummyHePpdu(uint16_t bandwidth);
118 
128  void VerifyCcaThreshold(const Ptr<PhyEntity> phy,
129  const Ptr<const WifiPpdu> ppdu,
130  WifiChannelListType channelType,
131  double expectedCcaThresholdDbm);
132 
137 
141 
146 
147  double m_obssPdLevel;
148 };
149 
151  : TestCase("Wi-Fi PHY CCA thresholds test"),
152  m_CcaEdThresholdDbm{-62.0},
153  m_CcaSensitivityDbm{-82.0},
154  m_secondaryCcaSensitivityThresholds{-72.0, -72.0, -69.0},
155  m_obssPdLevel{-82.0}
156 {
157 }
158 
161 {
162  Ptr<Packet> pkt = Create<Packet>(1000);
163  WifiMacHeader hdr;
165  hdr.SetQosTid(0);
166  return Create<WifiPsdu>(pkt, hdr);
167 }
168 
171 {
172  WifiTxVector txVector =
173  WifiTxVector(OfdmPhy::GetOfdmRate6Mbps(), 0, WIFI_PREAMBLE_LONG, 800, 1, 1, 0, 20, false);
175  return Create<OfdmPpdu>(psdu, txVector, P20_CENTER_FREQUENCY, WIFI_PHY_BAND_5GHZ, 0);
176 }
177 
180 {
181  WifiTxVector txVector =
182  WifiTxVector(HtPhy::GetHtMcs0(), 0, WIFI_PREAMBLE_HT_MF, 800, 1, 1, 0, bandwidth, false);
184  return Create<HtPpdu>(psdu,
185  txVector,
187  MicroSeconds(100),
189  0);
190 }
191 
194 {
195  WifiTxVector txVector =
196  WifiTxVector(VhtPhy::GetVhtMcs0(), 0, WIFI_PREAMBLE_VHT_SU, 800, 1, 1, 0, bandwidth, false);
198  return Create<VhtPpdu>(psdu,
199  txVector,
201  MicroSeconds(100),
203  0);
204 }
205 
208 {
209  WifiTxVector txVector =
210  WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, bandwidth, false);
212  return Create<HePpdu>(psdu,
213  txVector,
215  MicroSeconds(100),
217  0);
218 }
219 
220 void
222  const Ptr<const WifiPpdu> ppdu,
223  WifiChannelListType channelType,
224  double expectedCcaThresholdDbm)
225 {
226  NS_LOG_FUNCTION(this << phy << channelType << expectedCcaThresholdDbm);
227  double actualThresholdDbm = phy->GetCcaThreshold(ppdu, channelType);
228  NS_LOG_INFO((ppdu == nullptr ? "any signal" : "a PPDU")
229  << " in " << channelType << " channel: " << actualThresholdDbm << "dBm");
230  NS_TEST_EXPECT_MSG_EQ_TOL(actualThresholdDbm,
231  expectedCcaThresholdDbm,
232  1e-6,
233  "Actual CCA threshold for "
234  << (ppdu == nullptr ? "any signal" : "a PPDU") << " in "
235  << channelType << " channel " << actualThresholdDbm
236  << "dBm does not match expected threshold "
237  << expectedCcaThresholdDbm << "dBm");
238 }
239 
240 void
242 {
243  // WifiHelper::EnableLogComponents ();
244  // LogComponentEnable ("WifiPhyCcaTest", LOG_LEVEL_ALL);
245 
246  m_device = CreateObject<WifiNetDevice>();
248  m_vhtConfiguration = CreateObject<VhtConfiguration>();
250 
251  m_phy = Create<SpectrumWifiPhy>();
254 
255  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
257  20,
263 
264  m_obssPdAlgorithm = CreateObject<ConstantObssPdAlgorithm>();
267 }
268 
269 void
271 {
272  m_device->Dispose();
273  m_device = nullptr;
274 }
275 
276 void
278 {
283 
284  // OFDM PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
286  nullptr,
289 
290  //-----------------------------------------------------------------------------------------------------------------------------------
291 
292  // OFDM PHY: 20 MHz non-HT PPDU in primary channel (20 MHz) if power above CCA sensitivity
293  // threshold
298 
299  //-----------------------------------------------------------------------------------------------------------------------------------
300 
301  // HT PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
303  nullptr,
306 
307  // HT PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
309  nullptr,
312 
313  //-----------------------------------------------------------------------------------------------------------------------------------
314 
315  // HT PHY: 20 MHz HT PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
316  // threshold
318  CreateDummyHtPpdu(20),
321 
322  // HT PHY: 40 MHz HT PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
323  // threshold
325  CreateDummyHtPpdu(40),
328 
329  //-----------------------------------------------------------------------------------------------------------------------------------
330 
331  // VHT PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
333  nullptr,
336 
337  // VHT PHY: any signal in secondary channel (20 MHz) if power above CCA-ED threshold
339  nullptr,
342 
343  // VHT PHY: any signal in secondary40 channel (40 MHz) if power above CCA-ED threshold + 3dB
345  nullptr,
347  m_CcaEdThresholdDbm + 3);
348 
349  // VHT PHY: any signal in secondary80 channel (80 MHz) if power above CCA-ED threshold + 6dB
351  nullptr,
353  m_CcaEdThresholdDbm + 6);
354 
355  //-----------------------------------------------------------------------------------------------------------------------------------
356 
357  // VHT PHY: 20 MHz VHT PPDU in primary channel (20 MHz) if power in primary above CCA
358  // sensitivity threshold
360  CreateDummyVhtPpdu(20),
363 
364  // VHT PHY: 40 MHz VHT PPDU in primary channel (20 MHz) if power in primary above CCA
365  // sensitivity threshold
367  CreateDummyVhtPpdu(40),
370 
371  // VHT PHY: 80 MHz VHT PPDU in primary channel (20 MHz) if power in primary above CCA
372  // sensitivity threshold
374  CreateDummyVhtPpdu(80),
377 
378  // VHT PHY: 160 MHz VHT PPDU in primary channel (20 MHz) if power in primary above CCA
379  // sensitivity threshold
381  CreateDummyVhtPpdu(160),
384 
385  //-----------------------------------------------------------------------------------------------------------------------------------
386 
387  // VHT PHY: 20 MHz VHT PPDU in secondary channel (20 MHz) if power above the CCA sensitivity
388  // threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
390  CreateDummyVhtPpdu(20),
393 
394  // VHT PHY: 20 MHz VHT PPDU in secondary40 channel (40 MHz) if power above the CCA sensitivity
395  // threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
397  CreateDummyVhtPpdu(20),
400 
401  // VHT PHY: 40 MHz VHT PPDU in secondary40 channel (40 MHz) if power above the CCA sensitivity
402  // threshold corresponding to a 40 MHz PPDU that does not occupy the primary 20 MHz
404  CreateDummyVhtPpdu(40),
407 
408  // VHT PHY: 20 MHz VHT PPDU in secondary80 channel (80 MHz) if power above the CCA sensitivity
409  // threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
411  CreateDummyVhtPpdu(20),
414 
415  // VHT PHY: 40 MHz VHT PPDU in secondary80 channel (80 MHz) if power above the CCA sensitivity
416  // threshold corresponding to a 40 MHz PPDU that does not occupy the primary 20 MHz
418  CreateDummyVhtPpdu(40),
421 
422  // VHT PHY: 80 MHz VHT PPDU in secondary80 channel (80 MHz) if power above the CCA sensitivity
423  // threshold corresponding to a 80 MHz PPDU that does not occupy the primary 20 MHz
425  CreateDummyVhtPpdu(80),
428 
429  //-----------------------------------------------------------------------------------------------------------------------------------
430 
431  // HE PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
433  nullptr,
436 
437  // HE PHY: any signal in secondary channel (20 MHz) if power above CCA-ED threshold
439  nullptr,
442 
443  // HE PHY: any signal in secondary40 channel (40 MHz) if power above CCA-ED threshold + 3dB
445  nullptr,
447  m_CcaEdThresholdDbm + 3);
448 
449  // HE PHY: any signal in secondary80 channel (80 MHz) if power above CCA-ED threshold + 6dB
451  nullptr,
453  m_CcaEdThresholdDbm + 6);
454 
455  //-----------------------------------------------------------------------------------------------------------------------------------
456 
457  // HE PHY: 20 MHz HE PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
458  // threshold
460  CreateDummyHePpdu(20),
463 
464  // HE PHY: 40 MHz HE PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
465  // threshold
467  CreateDummyHePpdu(40),
470 
471  // HE PHY: 80 MHz HE PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
472  // threshold
474  CreateDummyHePpdu(80),
477 
478  // HE PHY: 160 MHz HE PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
479  // threshold
481  CreateDummyHePpdu(160),
484 
485  //-----------------------------------------------------------------------------------------------------------------------------------
486 
487  // HE PHY: 20 MHz HE PPDU in secondary channel (20 MHz) if power above the max between the CCA
488  // sensitivity threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
489  // and the OBSS-PD level
491  CreateDummyHePpdu(20),
494 
495  // HE PHY: 20 MHz HE PPDU in secondary40 channel (40 MHz) if power above the max between the CCA
496  // sensitivity threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
497  // and the OBSS-PD level
499  CreateDummyHePpdu(20),
502 
503  // HE PHY: 40 MHz HE PPDU in secondary40 channel (40 MHz) if power above the max between the CCA
504  // sensitivity threshold corresponding to a 40 MHz PPDU that does not occupy the primary 20 MHz
505  // and the OBSS-PD level plus 3 dB
508  CreateDummyHePpdu(40),
511 
512  // HE PHY: 20 MHz HE PPDU in secondary80 channel (80 MHz) if power above the max between the CCA
513  // sensitivity threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
514  // and the OBSS-PD level
516  CreateDummyHePpdu(20),
519 
520  // HE PHY: 40 MHz HE PPDU in secondary80 channel (80 MHz) if power above the max between the CCA
521  // sensitivity threshold corresponding to a 40 MHz PPDU that does not occupy the primary 20 MHz
522  // and the OBSS-PD level plus 3 dB
525  CreateDummyHePpdu(40),
528 
529  // HE PHY: 80 MHz HE PPDU in secondary80 channel (80 MHz) if power above the max between the CCA
530  // sensitivity threshold corresponding to a 80 MHz PPDU that does not occupy the primary 20 MHz
531  // and the OBSS-PD level plus 6 dB
534  CreateDummyHePpdu(80),
537 }
538 
539 void
541 {
542  // default attributes
543  m_CcaEdThresholdDbm = -62.0;
544  m_CcaSensitivityDbm = -82.0;
545  m_secondaryCcaSensitivityThresholds = std::make_tuple(-72.0, -72.0, -69.0);
546  m_obssPdLevel = -82.0;
547  RunOne();
548 
549  // default attributes with OBSS-PD level set to -80 dBm
550  m_CcaEdThresholdDbm = -62.0;
551  m_CcaSensitivityDbm = -82.0;
552  m_secondaryCcaSensitivityThresholds = std::make_tuple(-72.0, -72.0, -69.0);
553  m_obssPdLevel = -80.0;
554  RunOne();
555 
556  // default attributes with OBSS-PD level set to -70 dBm
557  m_CcaEdThresholdDbm = -62.0;
558  m_CcaSensitivityDbm = -82.0;
559  m_secondaryCcaSensitivityThresholds = std::make_tuple(-72.0, -72.0, -69.0);
560  m_obssPdLevel = -70.0;
561  RunOne();
562 
563  // CCA-ED set to -65 dBm
564  m_CcaEdThresholdDbm = -65.0;
565  m_CcaSensitivityDbm = -82.0;
566  m_secondaryCcaSensitivityThresholds = std::make_tuple(-72.0, -72.0, -69.0);
567  m_obssPdLevel = -82.0;
568  RunOne();
569 
570  // CCA sensitivity for signals in primary set to -75 dBm
571  m_CcaEdThresholdDbm = -62.0;
572  m_CcaSensitivityDbm = -75.0;
573  m_secondaryCcaSensitivityThresholds = std::make_tuple(-72.0, -72.0, -69.0);
574  m_obssPdLevel = -82.0;
575  RunOne();
576 
577  // custom CCA sensitivities for signals not in primary
578  m_CcaEdThresholdDbm = -62.0;
579  m_CcaSensitivityDbm = -72.0;
580  m_secondaryCcaSensitivityThresholds = std::make_tuple(-70.0, -70.0, -70.0);
581  m_obssPdLevel = -82.0;
582  RunOne();
583 
584  // custom CCA sensitivities for signals not in primary with OBSS-PD level set to -80 dBm
585  m_CcaEdThresholdDbm = -62.0;
586  m_CcaSensitivityDbm = -72.0;
587  m_secondaryCcaSensitivityThresholds = std::make_tuple(-70.0, -70.0, -70.0);
588  m_obssPdLevel = -80.0;
589  RunOne();
590 
591  // custom CCA sensitivities for signals not in primary with OBSS-PD level set to -70 dBm
592  m_CcaEdThresholdDbm = -62.0;
593  m_CcaSensitivityDbm = -72.0;
594  m_secondaryCcaSensitivityThresholds = std::make_tuple(-70.0, -70.0, -70.0);
595  m_obssPdLevel = -70.0;
596  RunOne();
597 
598  Simulator::Destroy();
599 }
600 
608 {
609  public:
610  CcaTestPhyListener() = default;
611 
612  void NotifyRxStart(Time duration) override
613  {
614  NS_LOG_FUNCTION(this << duration);
615  }
616 
617  void NotifyRxEndOk() override
618  {
619  NS_LOG_FUNCTION(this);
620  }
621 
622  void NotifyRxEndError() override
623  {
624  NS_LOG_FUNCTION(this);
625  }
626 
627  void NotifyTxStart(Time duration, double txPowerDbm) override
628  {
629  NS_LOG_FUNCTION(this << duration << txPowerDbm);
630  }
631 
632  void NotifyCcaBusyStart(Time duration,
633  WifiChannelListType channelType,
634  const std::vector<Time>& per20MhzDurations) override
635  {
636  NS_LOG_FUNCTION(this << duration << channelType << per20MhzDurations.size());
637  m_endCcaBusy = Simulator::Now() + duration;
638  m_lastCcaBusyChannelType = channelType;
639  m_lastPer20MhzCcaBusyDurations = per20MhzDurations;
640  m_notifications++;
641  }
642 
643  void NotifySwitchingStart(Time duration) override
644  {
645  }
646 
647  void NotifySleep() override
648  {
649  }
650 
651  void NotifyOff() override
652  {
653  }
654 
655  void NotifyWakeup() override
656  {
657  }
658 
659  void NotifyOn() override
660  {
661  }
662 
666  void Reset()
667  {
668  m_notifications = 0;
669  m_endCcaBusy = Seconds(0);
672  }
673 
674  std::size_t m_notifications{0};
678  std::vector<Time>
680 };
681 
689 {
690  public:
692 
693  private:
694  void DoSetup() override;
695  void DoRun() override;
696  void DoTeardown() override;
697 
704  void SendHeSuPpdu(double txPowerDbm, uint16_t frequency, uint16_t bandwidth);
705 
714  void StartSignal(Ptr<WaveformGenerator> signalGenerator,
715  double txPowerDbm,
716  uint16_t frequency,
717  uint16_t bandwidth,
718  Time duration);
723  void StopSignal(Ptr<WaveformGenerator> signalGenerator);
724 
729  void CheckPhyState(WifiPhyState expectedState);
731  void DoCheckPhyState(WifiPhyState expectedState);
732 
739  void CheckLastCcaBusyNotification(Time expectedEndTime,
740  WifiChannelListType expectedChannelType,
741  const std::vector<Time>& expectedPer20MhzDurations);
742 
748  void LogScenario(const std::string& log) const;
749 
754  {
755  double power{0.0};
758  uint16_t centerFreq{0};
759  uint16_t bandwidth{0};
760  };
761 
765  struct TxPpduInfo
766  {
767  double power{0.0};
769  uint16_t centerFreq{0};
770  uint16_t bandwidth{0};
771  };
772 
777  {
780  };
781 
786  {
791  std::vector<Time> expectedPer20MhzDurations{};
792  };
793 
802  void ScheduleTest(Time delay,
803  const std::vector<TxSignalInfo>& generatedSignals,
804  const std::vector<TxPpduInfo>& generatedPpdus,
805  const std::vector<StateCheckPoint>& stateCheckpoints,
806  const std::vector<CcaCheckPoint>& ccaCheckpoints);
807 
811  void Reset();
812 
816  void RunOne();
817 
820 
821  std::vector<Ptr<WaveformGenerator>> m_signalGenerators;
822  std::size_t
824 
825  std::unique_ptr<CcaTestPhyListener>
827 
828  uint16_t m_frequency;
829  uint16_t m_channelWidth;
830 };
831 
833  : TestCase("Wi-Fi PHY CCA indication test"),
834  m_numSignalGenerators(2),
835  m_frequency(P20_CENTER_FREQUENCY),
836  m_channelWidth(20)
837 {
838 }
839 
840 void
842  double txPowerDbm,
843  uint16_t frequency,
844  uint16_t bandwidth,
845  Time duration)
846 {
847  NS_LOG_FUNCTION(this << signalGenerator << txPowerDbm << frequency << bandwidth << duration);
848 
849  BandInfo bandInfo;
850  bandInfo.fc = frequency * 1e6;
851  bandInfo.fl = bandInfo.fc - ((bandwidth / 2) * 1e6);
852  bandInfo.fh = bandInfo.fc + ((bandwidth / 2) * 1e6);
853  Bands bands;
854  bands.push_back(bandInfo);
855 
856  Ptr<SpectrumModel> spectrumSignal = Create<SpectrumModel>(bands);
857  Ptr<SpectrumValue> signalPsd = Create<SpectrumValue>(spectrumSignal);
858  *signalPsd = DbmToW(txPowerDbm) / (bandwidth * 1e6);
859 
860  signalGenerator->SetTxPowerSpectralDensity(signalPsd);
861  signalGenerator->SetPeriod(duration);
862  signalGenerator->Start();
863  Simulator::Schedule(duration, &WifiPhyCcaIndicationTest::StopSignal, this, signalGenerator);
864 }
865 
866 void
868 {
869  NS_LOG_FUNCTION(this << signalGenerator);
870  signalGenerator->Stop();
871 }
872 
873 void
874 WifiPhyCcaIndicationTest::SendHeSuPpdu(double txPowerDbm, uint16_t frequency, uint16_t bandwidth)
875 {
876  NS_LOG_FUNCTION(this << txPowerDbm);
877 
878  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
879  frequency,
880  bandwidth,
884  WifiPhy::ChannelTuple{channelNum, bandwidth, WIFI_PHY_BAND_5GHZ, 0});
885 
886  WifiTxVector txVector =
887  WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, bandwidth, false);
888 
889  Ptr<Packet> pkt = Create<Packet>(1000);
890  WifiMacHeader hdr;
892  hdr.SetQosTid(0);
893  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
894 
895  m_txPhy->SetTxPowerStart(txPowerDbm);
896  m_txPhy->SetTxPowerEnd(txPowerDbm);
897 
898  m_txPhy->Send(psdu, txVector);
899 }
900 
901 void
903 {
904  // This is needed to make sure PHY state will be checked as the last event if a state change
905  // occurred at the exact same time as the check
906  Simulator::ScheduleNow(&WifiPhyCcaIndicationTest::DoCheckPhyState, this, expectedState);
907 }
908 
909 void
911 {
912  WifiPhyState currentState;
913  PointerValue ptr;
914  m_rxPhy->GetAttribute("State", ptr);
915  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
916  currentState = state->GetState();
917  NS_TEST_ASSERT_MSG_EQ(currentState,
918  expectedState,
919  "PHY State " << currentState << " does not match expected state "
920  << expectedState << " at " << Simulator::Now());
921 }
922 
923 void
925  Time expectedEndTime,
926  WifiChannelListType expectedChannelType,
927  const std::vector<Time>& expectedPer20MhzDurations)
928 {
930  expectedEndTime,
931  "PHY CCA end time " << m_rxPhyStateListener->m_endCcaBusy
932  << " does not match expected time " << expectedEndTime
933  << " at " << Simulator::Now());
934  NS_TEST_ASSERT_MSG_EQ(m_rxPhyStateListener->m_lastCcaBusyChannelType,
935  expectedChannelType,
936  "PHY CCA-BUSY for " << m_rxPhyStateListener->m_lastCcaBusyChannelType
937  << " does not match expected channel type "
938  << expectedChannelType << " at " << Simulator::Now());
939  NS_TEST_ASSERT_MSG_EQ(m_rxPhyStateListener->m_lastPer20MhzCcaBusyDurations.size(),
940  expectedPer20MhzDurations.size(),
941  "PHY CCA-BUSY per-20 MHz durations does not match expected vector"
942  << " at " << Simulator::Now());
943  for (std::size_t i = 0; i < expectedPer20MhzDurations.size(); ++i)
944  {
945  NS_TEST_ASSERT_MSG_EQ(m_rxPhyStateListener->m_lastPer20MhzCcaBusyDurations.at(i),
946  expectedPer20MhzDurations.at(i),
947  "PHY CCA-BUSY per-20 MHz duration at index "
948  << i << " does not match expected duration at "
949  << Simulator::Now());
950  }
951 }
952 
953 void
954 WifiPhyCcaIndicationTest::LogScenario(const std::string& log) const
955 {
956  NS_LOG_INFO(log);
957 }
958 
959 void
961  const std::vector<TxSignalInfo>& generatedSignals,
962  const std::vector<TxPpduInfo>& generatedPpdus,
963  const std::vector<StateCheckPoint>& stateCheckpoints,
964  const std::vector<CcaCheckPoint>& ccaCheckpoints)
965 {
966  for (const auto& generatedPpdu : generatedPpdus)
967  {
968  Simulator::Schedule(delay + generatedPpdu.startTime,
970  this,
971  generatedPpdu.power,
972  generatedPpdu.centerFreq,
973  generatedPpdu.bandwidth);
974  }
975 
976  std::size_t index = 0;
977  for (const auto& generatedSignal : generatedSignals)
978  {
979  Simulator::Schedule(delay + generatedSignal.startTime,
981  this,
982  m_signalGenerators.at(index++),
983  generatedSignal.power,
984  generatedSignal.centerFreq,
985  generatedSignal.bandwidth,
986  generatedSignal.duration);
987  }
988 
989  for (const auto& checkpoint : ccaCheckpoints)
990  {
991  Simulator::Schedule(delay + checkpoint.timePoint,
993  this,
994  Simulator::Now() + delay + checkpoint.expectedCcaEndTime,
995  checkpoint.expectedChannelListType,
996  checkpoint.expectedPer20MhzDurations);
997  }
998 
999  for (const auto& checkpoint : stateCheckpoints)
1000  {
1001  Simulator::Schedule(delay + checkpoint.timePoint,
1003  this,
1004  checkpoint.expectedPhyState);
1005  }
1006 
1007  Simulator::Schedule(delay + Seconds(0.5), &WifiPhyCcaIndicationTest::Reset, this);
1008 }
1009 
1010 void
1012 {
1013  m_rxPhyStateListener->Reset();
1014 }
1015 
1016 void
1018 {
1019  // WifiHelper::EnableLogComponents ();
1020  // LogComponentEnable ("WifiPhyCcaTest", LOG_LEVEL_ALL);
1021 
1022  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1023 
1024  Ptr<Node> rxNode = CreateObject<Node>();
1025  Ptr<WifiNetDevice> rxDev = CreateObject<WifiNetDevice>();
1027  Ptr<VhtConfiguration> vhtConfiguration = CreateObject<VhtConfiguration>();
1028  rxDev->SetVhtConfiguration(vhtConfiguration);
1029  m_rxPhy = CreateObject<SpectrumWifiPhy>();
1031  m_rxPhyStateListener = std::make_unique<CcaTestPhyListener>();
1034  Ptr<InterferenceHelper> rxInterferenceHelper = CreateObject<InterferenceHelper>();
1035  m_rxPhy->SetInterferenceHelper(rxInterferenceHelper);
1036  Ptr<ErrorRateModel> rxErrorModel = CreateObject<NistErrorRateModel>();
1037  m_rxPhy->SetErrorRateModel(rxErrorModel);
1038  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
1039  CreateObject<ThresholdPreambleDetectionModel>();
1040  m_rxPhy->SetPreambleDetectionModel(preambleDetectionModel);
1041  m_rxPhy->SetChannel(spectrumChannel);
1042  m_rxPhy->SetDevice(rxDev);
1043  rxDev->SetPhy(m_rxPhy);
1044  rxNode->AddDevice(rxDev);
1045 
1046  Ptr<Node> txNode = CreateObject<Node>();
1047  Ptr<WifiNetDevice> txDev = CreateObject<WifiNetDevice>();
1048  m_txPhy = CreateObject<SpectrumWifiPhy>();
1051  m_txPhy->SetAttribute("ChannelSwitchDelay", TimeValue(Seconds(0)));
1052  Ptr<InterferenceHelper> txInterferenceHelper = CreateObject<InterferenceHelper>();
1053  m_txPhy->SetInterferenceHelper(txInterferenceHelper);
1054  Ptr<ErrorRateModel> txErrorModel = CreateObject<NistErrorRateModel>();
1055  m_txPhy->SetErrorRateModel(txErrorModel);
1056  m_txPhy->SetChannel(spectrumChannel);
1057  m_txPhy->SetDevice(txDev);
1058  txDev->SetPhy(m_txPhy);
1059  txNode->AddDevice(txDev);
1060 
1061  for (std::size_t i = 0; i < m_numSignalGenerators; ++i)
1062  {
1063  Ptr<Node> signalGeneratorNode = CreateObject<Node>();
1064  Ptr<NonCommunicatingNetDevice> signalGeneratorDev =
1065  CreateObject<NonCommunicatingNetDevice>();
1066  Ptr<WaveformGenerator> signalGenerator = CreateObject<WaveformGenerator>();
1067  signalGenerator->SetDevice(signalGeneratorDev);
1068  signalGenerator->SetChannel(spectrumChannel);
1069  signalGenerator->SetDutyCycle(1);
1070  signalGeneratorNode->AddDevice(signalGeneratorDev);
1071  m_signalGenerators.push_back(signalGenerator);
1072  }
1073 }
1074 
1075 void
1077 {
1078  RngSeedManager::SetSeed(1);
1079  RngSeedManager::SetRun(1);
1080  int64_t streamNumber = 0;
1081  m_rxPhy->AssignStreams(streamNumber);
1082  m_txPhy->AssignStreams(streamNumber);
1083 
1084  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1085  m_frequency,
1089 
1094 
1095  std::vector<Time> expectedPer20MhzCcaBusyDurations{};
1096  Time delay = Seconds(0.0);
1097  Simulator::Schedule(delay, &WifiPhyCcaIndicationTest::Reset, this);
1098  delay += Seconds(1.0);
1099 
1100  //----------------------------------------------------------------------------------------------------------------------------------
1101  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported when a signal below the
1102  // energy detection threshold occupies P20
1103  Simulator::Schedule(delay,
1105  this,
1106  "Reception of a signal that occupies P20 below ED threshold");
1107  ScheduleTest(delay,
1108  {{-65.0, MicroSeconds(0), MicroSeconds(100), P20_CENTER_FREQUENCY, 20}},
1109  {},
1110  {
1111  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1112  {MicroSeconds(100) - smallDelta,
1113  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1114  {MicroSeconds(100) + smallDelta,
1115  WifiPhyState::IDLE} // IDLE just after the transmission ends
1116  },
1117  {});
1118  delay += Seconds(1.0);
1119 
1120  //----------------------------------------------------------------------------------------------------------------------------------
1121  // Verify PHY state is CCA-BUSY as long as a 20 MHz signal above the energy detection threshold
1122  // occupies P20
1123  Simulator::Schedule(delay,
1125  this,
1126  "Reception of signal that occupies P20 above ED threshold");
1127  ScheduleTest(delay,
1128  {{-60.0, MicroSeconds(0), MicroSeconds(100), P20_CENTER_FREQUENCY, 20}},
1129  {},
1130  {
1131  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCCATime
1132  {MicroSeconds(100) - smallDelta,
1133  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1134  {MicroSeconds(100) + smallDelta,
1135  WifiPhyState::IDLE} // IDLE just after the transmission ends
1136  },
1137  {{MicroSeconds(100) - smallDelta,
1138  MicroSeconds(100),
1140  ((m_channelWidth > 20)
1141  ? ((m_channelWidth > 40)
1142  ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(100),
1143  MicroSeconds(0),
1144  MicroSeconds(0),
1145  MicroSeconds(0),
1146  MicroSeconds(0),
1147  MicroSeconds(0),
1148  MicroSeconds(0),
1149  MicroSeconds(0)}
1150  : std::vector<Time>{MicroSeconds(100),
1151  MicroSeconds(0),
1152  MicroSeconds(0),
1153  MicroSeconds(0)})
1154  : std::vector<Time>{MicroSeconds(100), MicroSeconds(0)})
1155  : std::vector<Time>{})}});
1156  delay += Seconds(1.0);
1157 
1158  //----------------------------------------------------------------------------------------------------------------------------------
1159  // Verify PHY state is CCA-BUSY as long as the sum of 20 MHz signals occupying P20 is above the
1160  // energy detection threshold
1161  Simulator::Schedule(delay,
1163  this,
1164  "Reception of two 20 MHz signals that occupies P20 below ED threshold with "
1165  "sum above ED threshold");
1166  ScheduleTest(
1167  delay,
1168  {{-64.0, MicroSeconds(0), MicroSeconds(100), P20_CENTER_FREQUENCY, 20},
1169  {-65.0, MicroSeconds(50), MicroSeconds(200), P20_CENTER_FREQUENCY, 20}},
1170  {},
1171  {
1172  {MicroSeconds(50) + aCcaTime, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCCATime
1173  {MicroSeconds(100) - smallDelta,
1174  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1175  {MicroSeconds(100) + smallDelta,
1176  WifiPhyState::IDLE} // IDLE just after the transmission ends
1177  },
1178  {{MicroSeconds(100) - smallDelta,
1179  MicroSeconds(100),
1181  ((m_channelWidth > 20)
1182  ? ((m_channelWidth > 40)
1183  ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(50),
1184  MicroSeconds(0),
1185  MicroSeconds(0),
1186  MicroSeconds(0),
1187  MicroSeconds(0),
1188  MicroSeconds(0),
1189  MicroSeconds(0),
1190  MicroSeconds(0)}
1191  : std::vector<Time>{MicroSeconds(50),
1192  MicroSeconds(0),
1193  MicroSeconds(0),
1194  MicroSeconds(0)})
1195  : std::vector<Time>{MicroSeconds(50), MicroSeconds(0)})
1196  : std::vector<Time>{})}});
1197  delay += Seconds(1.0);
1198 
1199  //----------------------------------------------------------------------------------------------------------------------------------
1200  // Verify PHY state stays IDLE when a 20 MHz HE SU PPDU with received power below the
1201  // corresponding CCA sensitivity threshold occupies P20
1202  Simulator::Schedule(
1203  delay,
1205  this,
1206  "Reception of a 20 MHz HE PPDU that occupies P20 below CCA sensitivity threshold");
1207  ScheduleTest(delay,
1208  {},
1209  {{-85.0, MicroSeconds(0), P20_CENTER_FREQUENCY, 20}},
1210  {
1211  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1212  {PpduDurations.at(20) - smallDelta,
1213  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1214  {PpduDurations.at(20) + smallDelta,
1215  WifiPhyState::IDLE} // IDLE just after the transmission ends
1216  },
1217  {});
1218  delay += Seconds(1.0);
1219 
1220  //----------------------------------------------------------------------------------------------------------------------------------
1221  // Verify PHY state transitions to CCA-BUSY when an HE SU PPDU with received power above the CCA
1222  // sensitivity threshold occupies P20. The per20Bitmap should indicate idle on the primary 20
1223  // MHz subchannel because received power is below -72 dBm (27.3.20.6.5).
1224  Simulator::Schedule(
1225  delay,
1227  this,
1228  "Reception of a 20 MHz HE PPDU that occupies P20 above CCA sensitivity threshold");
1229  ScheduleTest(
1230  delay,
1231  {},
1232  {{-80.0, MicroSeconds(0), P20_CENTER_FREQUENCY, 20}},
1233  {
1234  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCCATime
1235  {PpduDurations.at(20) - smallDelta,
1236  WifiPhyState::RX}, // RX just before the transmission ends
1237  {PpduDurations.at(20) + smallDelta,
1238  WifiPhyState::IDLE} // IDLE just after the transmission ends
1239  },
1240  {{aCcaTime,
1241  MicroSeconds(16),
1243  ((m_channelWidth > 20)
1244  ? ((m_channelWidth > 40)
1245  ? ((m_channelWidth > 80)
1246  ? std::vector<Time>{Seconds(0),
1247  Seconds(0),
1248  Seconds(0),
1249  Seconds(0),
1250  Seconds(0),
1251  Seconds(0),
1252  Seconds(0),
1253  Seconds(0)}
1254  : std::vector<Time>{Seconds(0), Seconds(0), Seconds(0), Seconds(0)})
1255  : std::vector<Time>{Seconds(0), Seconds(0)})
1256  : std::vector<Time>{})}});
1257  delay += Seconds(1.0);
1258 
1259  //----------------------------------------------------------------------------------------------------------------------------------
1260  // Verify PHY state stays IDLE when a 40 MHz HE SU PPDU with received power below the CCA
1261  // sensitivity threshold occupies P40
1262  Simulator::Schedule(
1263  delay,
1265  this,
1266  "Reception of a 40 MHz HE PPDU that occupies P20 below CCA sensitivity threshold");
1267  ScheduleTest(delay,
1268  {},
1269  {{-80.0, MicroSeconds(0), P40_CENTER_FREQUENCY, 40}},
1270  {
1271  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1272  {PpduDurations.at(40) - smallDelta,
1273  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1274  {PpduDurations.at(40) + smallDelta,
1275  WifiPhyState::IDLE} // IDLE just after the transmission ends
1276  },
1277  {});
1278  delay += Seconds(1.0);
1279 
1280  //----------------------------------------------------------------------------------------------------------------------------------
1281  // Verify PHY state transitions to CCA-BUSY when an HE SU PPDU with received power above the CCA
1282  // sensitivity threshold occupies P40. The per20Bitmap should indicate idle on the primary 20
1283  // MHz subchannel because received power is below -72 dBm (27.3.20.6.5).
1284  Simulator::Schedule(
1285  delay,
1287  this,
1288  "Reception of a 40 MHz HE PPDU that occupies P40 above CCA sensitivity threshold");
1289  ScheduleTest(
1290  delay,
1291  {},
1292  {{-75.0, MicroSeconds(0), P40_CENTER_FREQUENCY, 40}},
1293  {
1294  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCCATime
1295  {PpduDurations.at(40) - smallDelta,
1296  (m_channelWidth > 20)
1298  : WifiPhyState::CCA_BUSY}, // RX or IDLE just before the transmission ends
1299  {PpduDurations.at(40) + smallDelta,
1300  WifiPhyState::IDLE} // IDLE just after the transmission ends
1301  },
1302  {{aCcaTime,
1303  MicroSeconds(16),
1305  ((m_channelWidth > 20)
1306  ? ((m_channelWidth > 40)
1307  ? ((m_channelWidth > 80)
1308  ? std::vector<Time>{Seconds(0),
1309  Seconds(0),
1310  Seconds(0),
1311  Seconds(0),
1312  Seconds(0),
1313  Seconds(0),
1314  Seconds(0),
1315  Seconds(0)}
1316  : std::vector<Time>{Seconds(0), Seconds(0), Seconds(0), Seconds(0)})
1317  : std::vector<Time>{Seconds(0), Seconds(0)})
1318  : std::vector<Time>{})}});
1319  delay += Seconds(1.0);
1320 
1321  if (m_channelWidth > 20)
1322  {
1323  //----------------------------------------------------------------------------------------------------------------------------------
1324  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported when a 20 MHz signal
1325  // below the energy detection threshold occupies S20
1326  Simulator::Schedule(delay,
1328  this,
1329  "Reception of a 20 MHz signal that occupies S20 below ED threshold");
1330  ScheduleTest(delay,
1331  {{-65.0, MicroSeconds(0), MicroSeconds(100), S20_CENTER_FREQUENCY, 20}},
1332  {},
1333  {
1334  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1335  {MicroSeconds(100) - smallDelta,
1336  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1337  {MicroSeconds(100) + smallDelta,
1338  WifiPhyState::IDLE} // IDLE just after the transmission ends
1339  },
1340  {});
1341  delay += Seconds(1.0);
1342 
1343  //----------------------------------------------------------------------------------------------------------------------------------
1344  // Verify PHY state stays IDLE but CCA-BUSY indication is reported when a 20 MHz signal
1345  // above the energy detection threshold occupies S20
1346  Simulator::Schedule(delay,
1348  this,
1349  "Reception of a 20 MHz signal that occupies S20 above ED threshold");
1350  ScheduleTest(
1351  delay,
1352  {{-60.0, MicroSeconds(0), MicroSeconds(100), S20_CENTER_FREQUENCY, 20}},
1353  {},
1354  {
1355  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1356  {MicroSeconds(100) - smallDelta,
1357  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1358  {MicroSeconds(100) + smallDelta,
1359  WifiPhyState::IDLE} // IDLE just after the transmission ends
1360  },
1361  {{MicroSeconds(100) - smallDelta,
1362  MicroSeconds(100),
1364  ((m_channelWidth > 40) ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1365  MicroSeconds(100),
1366  MicroSeconds(0),
1367  MicroSeconds(0),
1368  MicroSeconds(0),
1369  MicroSeconds(0),
1370  MicroSeconds(0),
1371  MicroSeconds(0)}
1372  : std::vector<Time>{MicroSeconds(0),
1373  MicroSeconds(100),
1374  MicroSeconds(0),
1375  MicroSeconds(0)})
1376  : std::vector<Time>{MicroSeconds(0), MicroSeconds(100)})}});
1377  delay += Seconds(1.0);
1378 
1379  //----------------------------------------------------------------------------------------------------------------------------------
1380  // Verify PHY state is CCA-BUSY as long as a 40 MHz signal above the energy detection
1381  // threshold occupies P40
1382  Simulator::Schedule(delay,
1384  this,
1385  "Reception of a 40 MHz signal that occupies P40 above ED threshold");
1386  ScheduleTest(
1387  delay,
1388  {{-55.0, MicroSeconds(0), MicroSeconds(100), P40_CENTER_FREQUENCY, 40}},
1389  {},
1390  {
1391  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCCATime
1392  {MicroSeconds(100) - smallDelta,
1393  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1394  {MicroSeconds(100) + smallDelta,
1395  WifiPhyState::IDLE} // IDLE just after the transmission ends
1396  },
1397  {{MicroSeconds(100) - smallDelta,
1398  MicroSeconds(100),
1400  ((m_channelWidth > 40) ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(100),
1401  MicroSeconds(100),
1402  MicroSeconds(0),
1403  MicroSeconds(0),
1404  MicroSeconds(0),
1405  MicroSeconds(0),
1406  MicroSeconds(0),
1407  MicroSeconds(0)}
1408  : std::vector<Time>{MicroSeconds(100),
1409  MicroSeconds(100),
1410  MicroSeconds(0),
1411  MicroSeconds(0)})
1412  : std::vector<Time>{MicroSeconds(100), MicroSeconds(100)})}});
1413  delay += Seconds(1.0);
1414 
1415  //----------------------------------------------------------------------------------------------------------------------------------
1416  // Verify PHY notifies CCA-BUSY for the primary channel while the secondary channel was
1417  // already in CCA-BUSY state
1418  Simulator::Schedule(delay,
1420  this,
1421  "Reception of a signal that occupies S20 followed by the reception of "
1422  "another signal that occupies P20");
1423  ScheduleTest(
1424  delay,
1425  {{-60.0, MicroSeconds(0), MicroSeconds(100), S20_CENTER_FREQUENCY, 20},
1426  {-60.0, MicroSeconds(50), MicroSeconds(100), P20_CENTER_FREQUENCY, 20}},
1427  {},
1428  {
1429  {aCcaTime, WifiPhyState::IDLE}, // state of primary stays idle after aCCATime
1430  {MicroSeconds(50) + aCcaTime,
1431  WifiPhyState::CCA_BUSY}, // state of primary is CCA-BUSY after aCCATime that
1432  // followed the second transmission
1433  {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
1434  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1435  {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
1436  WifiPhyState::IDLE} // IDLE just after the transmission ends
1437  },
1438  {{aCcaTime, // notification upon reception of the first signal
1439  MicroSeconds(100),
1441  ((m_channelWidth > 40) ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1442  MicroSeconds(100),
1443  MicroSeconds(0),
1444  MicroSeconds(0),
1445  MicroSeconds(0),
1446  MicroSeconds(0),
1447  MicroSeconds(0),
1448  MicroSeconds(0)}
1449  : std::vector<Time>{MicroSeconds(0),
1450  MicroSeconds(100),
1451  MicroSeconds(0),
1452  MicroSeconds(0)})
1453  : std::vector<Time>{MicroSeconds(0), MicroSeconds(100)})},
1454  {MicroSeconds(50) + aCcaTime, // notification upon reception of the second signal
1455  MicroSeconds(50) + MicroSeconds(100),
1457  ((m_channelWidth > 40) ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(100),
1458  MicroSeconds(50),
1459  MicroSeconds(0),
1460  MicroSeconds(0),
1461  MicroSeconds(0),
1462  MicroSeconds(0),
1463  MicroSeconds(0),
1464  MicroSeconds(0)}
1465  : std::vector<Time>{MicroSeconds(100),
1466  MicroSeconds(50),
1467  MicroSeconds(0),
1468  MicroSeconds(0)})
1469  : std::vector<Time>{MicroSeconds(100), MicroSeconds(50)})}});
1470  delay += Seconds(1.0);
1471 
1472  //----------------------------------------------------------------------------------------------------------------------------------
1473  // Verify PHY updates per-20 MHz CCA durations if a signal arrives on the secondary channel
1474  // while primary is CCA-BUSY
1475  Simulator::Schedule(delay,
1477  this,
1478  "Reception of a signal that occupies P20 followed by the reception of "
1479  "another signal that occupies S20");
1480  ScheduleTest(
1481  delay,
1482  {{-60.0, MicroSeconds(0), MicroSeconds(100), P20_CENTER_FREQUENCY, 20},
1483  {-60.0, MicroSeconds(50), MicroSeconds(100), S20_CENTER_FREQUENCY, 20}},
1484  {},
1485  {
1486  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCCATime
1487  {MicroSeconds(50) + aCcaTime,
1488  WifiPhyState::CCA_BUSY}, // state of primary is still CCA-BUSY after aCCATime that
1489  // followed the second transmission
1490  {MicroSeconds(100) - smallDelta,
1491  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the first transmission ends
1492  {MicroSeconds(100) + smallDelta,
1493  WifiPhyState::IDLE} // IDLE just after the first transmission ends
1494  },
1495  {{aCcaTime, // notification upon reception of the first signal
1496  MicroSeconds(100),
1498  ((m_channelWidth > 40) ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(100),
1499  MicroSeconds(0),
1500  MicroSeconds(0),
1501  MicroSeconds(0),
1502  MicroSeconds(0),
1503  MicroSeconds(0),
1504  MicroSeconds(0),
1505  MicroSeconds(0)}
1506  : std::vector<Time>{MicroSeconds(100),
1507  MicroSeconds(0),
1508  MicroSeconds(0),
1509  MicroSeconds(0)})
1510  : std::vector<Time>{MicroSeconds(100), MicroSeconds(0)})},
1511  {MicroSeconds(50) + aCcaTime, // notification upon reception of the second signal
1512  MicroSeconds(100),
1514  ((m_channelWidth > 40) ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(50),
1515  MicroSeconds(100),
1516  MicroSeconds(0),
1517  MicroSeconds(0),
1518  MicroSeconds(0),
1519  MicroSeconds(0),
1520  MicroSeconds(0),
1521  MicroSeconds(0)}
1522  : std::vector<Time>{MicroSeconds(50),
1523  MicroSeconds(100),
1524  MicroSeconds(0),
1525  MicroSeconds(0)})
1526  : std::vector<Time>{MicroSeconds(50), MicroSeconds(100)})}});
1527  delay += Seconds(1.0);
1528 
1529  //----------------------------------------------------------------------------------------------------------------------------------
1530  // Verify PHY state stays IDLE when a 20 MHz HE SU PPDU with received power below the CCA
1531  // sensitivity threshold occupies S40
1532  Simulator::Schedule(
1533  delay,
1535  this,
1536  "Reception of a 20 MHz HE PPDU that occupies S20 below CCA sensitivity threshold");
1537  ScheduleTest(delay,
1538  {},
1539  {{-75.0, MicroSeconds(0), S20_CENTER_FREQUENCY, 20}},
1540  {
1541  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1542  {PpduDurations.at(20) - smallDelta,
1543  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1544  {PpduDurations.at(20) + smallDelta,
1545  WifiPhyState::IDLE} // IDLE just after the transmission ends
1546  },
1547  {});
1548  delay += Seconds(1.0);
1549 
1550  //----------------------------------------------------------------------------------------------------------------------------------
1551  // Verify PHY state stays IDLE but CCA-BUSY indication is reported when a 20 MHz HE SU PPDU
1552  // with received power above the CCA sensitivity threshold occupies S20
1553  Simulator::Schedule(
1554  delay,
1556  this,
1557  "Reception of a 20 MHz HE PPDU that occupies S20 above CCA sensitivity threshold");
1558  ScheduleTest(delay,
1559  {},
1560  {{-70.0, MicroSeconds(0), S20_CENTER_FREQUENCY, 20}},
1561  {
1562  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1563  {PpduDurations.at(20) - smallDelta,
1564  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1565  {PpduDurations.at(20) + smallDelta,
1566  WifiPhyState::IDLE} // IDLE just after the transmission ends
1567  },
1568  {{aCcaTime,
1569  PpduDurations.at(20),
1571  ((m_channelWidth > 40)
1572  ? ((m_channelWidth > 80) ? std::vector<Time>{NanoSeconds(0),
1573  PpduDurations.at(20),
1574  NanoSeconds(0),
1575  NanoSeconds(0),
1576  NanoSeconds(0),
1577  NanoSeconds(0),
1578  NanoSeconds(0),
1579  NanoSeconds(0)}
1580  : std::vector<Time>{NanoSeconds(0),
1581  PpduDurations.at(20),
1582  NanoSeconds(0),
1583  NanoSeconds(0)})
1584  : std::vector<Time>{NanoSeconds(0), PpduDurations.at(20)})}});
1585  delay += Seconds(1.0);
1586 
1587  //----------------------------------------------------------------------------------------------------------------------------------
1588  // Verify PHY state stays IDLE but CCA-BUSY indication is still reported as long as a signal
1589  // above the energy detection threshold occupies the S20 while a 40 MHz PPDU below the CCA
1590  // sensitivity threshold is received on P40.
1591  Simulator::Schedule(
1592  delay,
1594  this,
1595  "Reception of a 20 MHz signal that occupies S20 above ED threshold followed by a 40 "
1596  "MHz HE PPDU that occupies P40 below CCA sensitivity threshold");
1597  ScheduleTest(
1598  delay,
1599  {{-60.0,
1600  MicroSeconds(0),
1601  MicroSeconds(100),
1603  20}}, // signal on S20 above threshold
1604  {{-80.0, MicroSeconds(50), P40_CENTER_FREQUENCY, 40}}, // PPDU on P40 below threshold
1605  {
1606  {MicroSeconds(50) + aCcaTime, WifiPhyState::IDLE}, // PHY state stays IDLE
1607  },
1608  {{MicroSeconds(50) - smallDelta,
1609  MicroSeconds(100),
1611  ((m_channelWidth > 20)
1612  ? ((m_channelWidth > 40)
1613  ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1614  MicroSeconds(100),
1615  MicroSeconds(0),
1616  MicroSeconds(0),
1617  MicroSeconds(0),
1618  MicroSeconds(0),
1619  MicroSeconds(0),
1620  MicroSeconds(0)}
1621  : std::vector<Time>{MicroSeconds(0),
1622  MicroSeconds(100),
1623  MicroSeconds(0),
1624  MicroSeconds(0)})
1625  : std::vector<Time>{MicroSeconds(0), MicroSeconds(100)})
1626  : std::vector<Time>{})},
1627  {MicroSeconds(100) - smallDelta,
1628  MicroSeconds(100),
1630  ((m_channelWidth > 40) ? ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1631  MicroSeconds(46),
1632  MicroSeconds(0),
1633  MicroSeconds(0),
1634  MicroSeconds(0),
1635  MicroSeconds(0),
1636  MicroSeconds(0),
1637  MicroSeconds(0)}
1638  : std::vector<Time>{MicroSeconds(0),
1639  MicroSeconds(46),
1640  MicroSeconds(0),
1641  MicroSeconds(0)})
1642  : std::vector<Time>{MicroSeconds(0), MicroSeconds(46)})}});
1643  delay += Seconds(1.0);
1644  }
1645 
1646  if (m_channelWidth > 40)
1647  {
1648  //----------------------------------------------------------------------------------------------------------------------------------
1649  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported when a signal below
1650  // the energy detection threshold occupies S40
1651  Simulator::Schedule(delay,
1653  this,
1654  "Reception of a 20 MHz signal that occupies the first subchannel of "
1655  "S40 below ED threshold");
1656  ScheduleTest(delay,
1657  {{-65.0, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY - 10, 20}},
1658  {},
1659  {
1660  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1661  {MicroSeconds(100) - smallDelta,
1662  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1663  {MicroSeconds(100) + smallDelta,
1664  WifiPhyState::IDLE} // IDLE just after the transmission ends
1665  },
1666  {});
1667  delay += Seconds(1.0);
1668 
1669  //----------------------------------------------------------------------------------------------------------------------------------
1670  // Verify PHY notifies CCA-BUSY for the S40 as long as a signal above the energy detection
1671  // threshold occupies the first 20 MHz subchannel of the S40: 27.3.20.6.4: Any signal within
1672  // the secondary 40 MHz channel at or above a threshold of –59 dBm within a period of
1673  // aCCATime after the signal arrives at the receiver’s antenna(s).
1674  Simulator::Schedule(delay,
1676  this,
1677  "Reception of a 20 MHz signal that occupies the first subchannel of "
1678  "S40 above ED threshold");
1679  ScheduleTest(delay,
1680  {{-55.0, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY - 10, 20}},
1681  {},
1682  {
1683  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1684  {MicroSeconds(100) - smallDelta,
1685  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1686  {MicroSeconds(100) + smallDelta,
1687  WifiPhyState::IDLE} // IDLE just after the transmission ends
1688  },
1689  {{MicroSeconds(100) - smallDelta,
1690  MicroSeconds(100),
1692  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1693  MicroSeconds(0),
1694  MicroSeconds(100),
1695  MicroSeconds(0),
1696  MicroSeconds(0),
1697  MicroSeconds(0),
1698  MicroSeconds(0),
1699  MicroSeconds(0)}
1700  : std::vector<Time>{MicroSeconds(0),
1701  MicroSeconds(0),
1702  MicroSeconds(100),
1703  MicroSeconds(0)})}});
1704  delay += Seconds(1.0);
1705 
1706  //----------------------------------------------------------------------------------------------------------------------------------
1707  // Verify PHY state stays IDLE for the S40 if a signal below the energy detection threshold
1708  // occupies the second 20 MHz subchannel of the S40
1709  Simulator::Schedule(delay,
1711  this,
1712  "Reception of a 20 MHz signal that occupies the second subchannel of "
1713  "S40 below ED threshold");
1714  ScheduleTest(delay,
1715  {{-65.0, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY + 10, 20}},
1716  {},
1717  {
1718  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1719  {MicroSeconds(100) - smallDelta,
1720  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1721  {MicroSeconds(100) + smallDelta,
1722  WifiPhyState::IDLE} // IDLE just after the transmission ends
1723  },
1724  {});
1725  delay += Seconds(1.0);
1726 
1727  //----------------------------------------------------------------------------------------------------------------------------------
1728  // Verify PHY notifies CCA-BUSY for the S40 as long as a signal above the energy detection
1729  // threshold occupies the second 20 MHz subchannel of the S40: 27.3.20.6.4: Any signal
1730  // within the secondary 40 MHz channel at or above a threshold of –59 dBm within a period of
1731  // aCCATime after the signal arrives at the receiver’s antenna(s).
1732  Simulator::Schedule(delay,
1734  this,
1735  "Reception of a 20 MHz signal that occupies the second subchannel of "
1736  "S40 above ED threshold");
1737  ScheduleTest(delay,
1738  {{-55.0, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY + 10, 20}},
1739  {},
1740  {
1741  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1742  {MicroSeconds(100) - smallDelta,
1743  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1744  {MicroSeconds(100) + smallDelta,
1745  WifiPhyState::IDLE} // IDLE just after the transmission ends
1746  },
1747  {{MicroSeconds(100) - smallDelta,
1748  MicroSeconds(100),
1750  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1751  MicroSeconds(0),
1752  MicroSeconds(0),
1753  MicroSeconds(100),
1754  MicroSeconds(0),
1755  MicroSeconds(0),
1756  MicroSeconds(0),
1757  MicroSeconds(0)}
1758  : std::vector<Time>{MicroSeconds(0),
1759  MicroSeconds(0),
1760  MicroSeconds(0),
1761  MicroSeconds(100)})}});
1762  delay += Seconds(1.0);
1763 
1764  //----------------------------------------------------------------------------------------------------------------------------------
1765  // Verify PHY state stays IDLE for the S40 if a signal below the energy detection threshold
1766  // occupies S40
1767  Simulator::Schedule(delay,
1769  this,
1770  "Reception of a 40 MHz signal that occupies S40 below ED threshold");
1771  ScheduleTest(delay,
1772  {{-60.0, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY, 40}},
1773  {},
1774  {
1775  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1776  {MicroSeconds(100) - smallDelta,
1777  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1778  {MicroSeconds(100) + smallDelta,
1779  WifiPhyState::IDLE} // IDLE just after the transmission ends
1780  },
1781  {});
1782  delay += Seconds(1.0);
1783 
1784  //----------------------------------------------------------------------------------------------------------------------------------
1785  // Verify PHY notifies CCA-BUSY for the S40 as long as a signal above the energy detection
1786  // threshold occupies S40: 27.3.20.6.4: Any signal within the secondary 40 MHz channel at or
1787  // above a threshold of –59 dBm within a period of aCCATime after the signal arrives at the
1788  // receiver’s antenna(s).
1789  Simulator::Schedule(delay,
1791  this,
1792  "Reception of a 20 MHz signal that occupies the second subchannel of "
1793  "S40 above ED threshold");
1794  ScheduleTest(delay,
1795  {{-55.0, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY, 40}},
1796  {},
1797  {
1798  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1799  {MicroSeconds(100) - smallDelta,
1800  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1801  {MicroSeconds(100) + smallDelta,
1802  WifiPhyState::IDLE} // IDLE just after the transmission ends
1803  },
1804  {{MicroSeconds(100) - smallDelta,
1805  MicroSeconds(100),
1807  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1808  MicroSeconds(0),
1809  MicroSeconds(100),
1810  MicroSeconds(100),
1811  MicroSeconds(0),
1812  MicroSeconds(0),
1813  MicroSeconds(0),
1814  MicroSeconds(0)}
1815  : std::vector<Time>{MicroSeconds(0),
1816  MicroSeconds(0),
1817  MicroSeconds(100),
1818  MicroSeconds(100)})}});
1819  delay += Seconds(1.0);
1820 
1821  //----------------------------------------------------------------------------------------------------------------------------------
1822  // Verify PHY state is CCA-BUSY as long as a 80 MHz signal above the energy detection
1823  // threshold occupies P80
1824  Simulator::Schedule(delay,
1826  this,
1827  "Reception of a 80 MHz signal that occupies P80 above ED threshold");
1828  ScheduleTest(delay,
1829  {{-55.0, MicroSeconds(0), MicroSeconds(100), P80_CENTER_FREQUENCY, 80}},
1830  {},
1831  {
1832  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCCATime
1833  {MicroSeconds(100) - smallDelta,
1834  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1835  {MicroSeconds(100) + smallDelta,
1836  WifiPhyState::IDLE} // IDLE just after the transmission ends
1837  },
1838  {{MicroSeconds(100) - smallDelta,
1839  MicroSeconds(100),
1841  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(100),
1842  MicroSeconds(100),
1843  MicroSeconds(100),
1844  MicroSeconds(100),
1845  MicroSeconds(0),
1846  MicroSeconds(0),
1847  MicroSeconds(0),
1848  MicroSeconds(0)}
1849  : std::vector<Time>{MicroSeconds(100),
1850  MicroSeconds(100),
1851  MicroSeconds(100),
1852  MicroSeconds(100)})}});
1853  delay += Seconds(1.0);
1854 
1855  //----------------------------------------------------------------------------------------------------------------------------------
1856  // Verify PHY notifies CCA-BUSY for the P20 channel while the S40 channel was already in
1857  // CCA-BUSY state
1858  Simulator::Schedule(delay,
1860  this,
1861  "Reception of a 20 MHz signal that occupies S40 followed by the "
1862  "reception of another 20 MHz signal that occupies P20");
1863  ScheduleTest(
1864  delay,
1865  {{-55.0, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY - 10, 20},
1866  {-55.0, MicroSeconds(50), MicroSeconds(100), P20_CENTER_FREQUENCY, 20}},
1867  {},
1868  {
1869  {aCcaTime, WifiPhyState::IDLE}, // state of primary stays idle after aCCATime
1870  {MicroSeconds(50) + aCcaTime,
1871  WifiPhyState::CCA_BUSY}, // state of primary is CCA-BUSY after aCCATime that
1872  // followed the second transmission
1873  {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
1874  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1875  {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
1876  WifiPhyState::IDLE} // IDLE just after the transmission ends
1877  },
1878  {{aCcaTime, // notification upon reception of the first signal
1879  MicroSeconds(100),
1881  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1882  MicroSeconds(0),
1883  MicroSeconds(100),
1884  MicroSeconds(0),
1885  MicroSeconds(0),
1886  MicroSeconds(0),
1887  MicroSeconds(0),
1888  MicroSeconds(0)}
1889  : std::vector<Time>{MicroSeconds(0),
1890  MicroSeconds(0),
1891  MicroSeconds(100),
1892  MicroSeconds(0)})},
1893  {MicroSeconds(50) + aCcaTime, // notification upon reception of the second signal
1894  MicroSeconds(50) + MicroSeconds(100),
1896  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(100),
1897  MicroSeconds(0),
1898  MicroSeconds(50),
1899  MicroSeconds(0),
1900  MicroSeconds(0),
1901  MicroSeconds(0),
1902  MicroSeconds(0),
1903  MicroSeconds(0)}
1904  : std::vector<Time>{MicroSeconds(100),
1905  MicroSeconds(0),
1906  MicroSeconds(50),
1907  MicroSeconds(0)})}});
1908  delay += Seconds(1.0);
1909 
1910  //----------------------------------------------------------------------------------------------------------------------------------
1911  // Verify PHY state stays IDLE but notifies CCA-BUSY for the S20 channel while the S40
1912  // channel was already in CCA-BUSY state
1913  Simulator::Schedule(delay,
1915  this,
1916  "Reception of a signal that occupies S40 followed by the reception of "
1917  "another signal that occupies S20");
1918  ScheduleTest(
1919  delay,
1920  {{-55.0, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY - 10, 20},
1921  {-55.0, MicroSeconds(50), MicroSeconds(100), S20_CENTER_FREQUENCY, 20}},
1922  {},
1923  {
1924  {aCcaTime, WifiPhyState::IDLE}, // state of primary stays idle after aCCATime
1925  {MicroSeconds(50) + aCcaTime, WifiPhyState::IDLE}, // state of primary stays IDLE
1926  {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
1927  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1928  {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
1929  WifiPhyState::IDLE} // IDLE just after the transmission ends
1930  },
1931  {{aCcaTime, // notification upon reception of the first signal
1932  MicroSeconds(100),
1934  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1935  MicroSeconds(0),
1936  MicroSeconds(100),
1937  MicroSeconds(0),
1938  MicroSeconds(0),
1939  MicroSeconds(0),
1940  MicroSeconds(0),
1941  MicroSeconds(0)}
1942  : std::vector<Time>{MicroSeconds(0),
1943  MicroSeconds(0),
1944  MicroSeconds(100),
1945  MicroSeconds(0)})},
1946  {MicroSeconds(50) + aCcaTime, // notification upon reception of the second signal
1947  MicroSeconds(50) + MicroSeconds(100),
1949  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
1950  MicroSeconds(100),
1951  MicroSeconds(50),
1952  MicroSeconds(0),
1953  MicroSeconds(0),
1954  MicroSeconds(0),
1955  MicroSeconds(0),
1956  MicroSeconds(0)}
1957  : std::vector<Time>{MicroSeconds(0),
1958  MicroSeconds(100),
1959  MicroSeconds(50),
1960  MicroSeconds(0)})}});
1961  delay += Seconds(1.0);
1962 
1963  //----------------------------------------------------------------------------------------------------------------------------------
1964  // Verify PHY state stays IDLE when a 40 MHz HE SU PPDU with received power below the CCA
1965  // sensitivity threshold occupies S40
1966  Simulator::Schedule(
1967  delay,
1969  this,
1970  "Reception of a 40 MHz HE PPDU that occupies S40 below CCA sensitivity threshold");
1971  ScheduleTest(delay,
1972  {},
1973  {{-75.0, MicroSeconds(0), S40_CENTER_FREQUENCY, 40}},
1974  {
1975  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1976  {PpduDurations.at(20) - smallDelta,
1977  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1978  {PpduDurations.at(20) + smallDelta,
1979  WifiPhyState::IDLE} // IDLE just after the transmission ends
1980  },
1981  {});
1982  delay += Seconds(1.0);
1983 
1984  //----------------------------------------------------------------------------------------------------------------------------------
1985  // Verify PHY state stays IDLE but CCA-BUSY indication is reported when a 40 MHz HE SU PPDU
1986  // with received power above the CCA sensitivity threshold occupies S40
1987  Simulator::Schedule(
1988  delay,
1990  this,
1991  "Reception of a 40 MHz HE PPDU that occupies S40 above CCA sensitivity threshold");
1992  ScheduleTest(delay,
1993  {},
1994  {{-70.0, MicroSeconds(0), S40_CENTER_FREQUENCY, 40}},
1995  {
1996  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
1997  {PpduDurations.at(40) - smallDelta,
1998  WifiPhyState::IDLE}, // IDLE just before the transmission ends
1999  {PpduDurations.at(40) + smallDelta,
2000  WifiPhyState::IDLE} // IDLE just after the transmission ends
2001  },
2002  {{aCcaTime,
2003  PpduDurations.at(40),
2005  ((m_channelWidth > 80) ? std::vector<Time>{NanoSeconds(0),
2006  NanoSeconds(0),
2007  PpduDurations.at(40),
2008  PpduDurations.at(40),
2009  NanoSeconds(0),
2010  NanoSeconds(0),
2011  NanoSeconds(0),
2012  NanoSeconds(0)}
2013  : std::vector<Time>{NanoSeconds(0),
2014  NanoSeconds(0),
2015  PpduDurations.at(40),
2016  PpduDurations.at(40)})}});
2017  delay += Seconds(1.0);
2018 
2019  //----------------------------------------------------------------------------------------------------------------------------------
2020  // Verify PHY state stays IDLE but CCA-BUSY indication is still reported as long as a signal
2021  // above the energy detection threshold occupies the S40 while a 80 MHz PPDU below the CCA
2022  // sensitivity threshold is received on P80.
2023  Simulator::Schedule(
2024  delay,
2026  this,
2027  "Reception of a 40 MHz signal that occupies S40 above ED threshold followed by a 80 "
2028  "MHz HE PPDU that occupies P80 below CCA sensitivity threshold");
2029  ScheduleTest(
2030  delay,
2031  {{-55.0,
2032  MicroSeconds(0),
2033  MicroSeconds(100),
2035  40}}, // signal on S40 above threshold
2036  {{-80.0, MicroSeconds(50), P80_CENTER_FREQUENCY, 80}}, // PPDU on P80 below threshold
2037  {
2038  {MicroSeconds(50) + aCcaTime, WifiPhyState::IDLE}, // PHY state stays IDLE
2039  },
2040  {{MicroSeconds(50) - smallDelta,
2041  MicroSeconds(100),
2043  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
2044  MicroSeconds(0),
2045  MicroSeconds(100),
2046  MicroSeconds(100),
2047  MicroSeconds(0),
2048  MicroSeconds(0),
2049  MicroSeconds(0),
2050  MicroSeconds(0)}
2051  : std::vector<Time>{MicroSeconds(0),
2052  MicroSeconds(0),
2053  MicroSeconds(100),
2054  MicroSeconds(100)})},
2055  {MicroSeconds(100) - smallDelta,
2056  MicroSeconds(100),
2058  ((m_channelWidth > 80) ? std::vector<Time>{MicroSeconds(0),
2059  MicroSeconds(0),
2060  MicroSeconds(46),
2061  MicroSeconds(46),
2062  MicroSeconds(0),
2063  MicroSeconds(0),
2064  MicroSeconds(0),
2065  MicroSeconds(0)}
2066  : std::vector<Time>{MicroSeconds(0),
2067  MicroSeconds(0),
2068  MicroSeconds(46),
2069  MicroSeconds(46)})}});
2070  delay += Seconds(1.0);
2071  }
2072  else // 20 or 40 MHz receiver
2073  {
2074  //----------------------------------------------------------------------------------------------------------------------------------
2075  // Verify PHY notifies CCA-BUSY when a 80 MHz HE SU PPDU with received power above the CCA
2076  // sensitivity threshold occupies P40 The per20Bitmap should indicate idle for all
2077  // subchannels because received power is below -62 dBm (27.3.20.6.5).
2078  Simulator::Schedule(delay,
2080  this,
2081  "Reception of a 80 MHz HE PPDU that occupies the 40 MHz band above CCA "
2082  "sensitivity threshold");
2083  ScheduleTest(delay,
2084  {},
2085  {{-70.0, MicroSeconds(0), P80_CENTER_FREQUENCY, 80}},
2086  {
2087  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA_BUSY after aCCATime
2088  {PpduDurations.at(80) - smallDelta,
2089  WifiPhyState::CCA_BUSY}, // CCA_BUSY just before the transmission ends
2090  {PpduDurations.at(80) + smallDelta,
2091  WifiPhyState::IDLE} // IDLE just after the transmission ends
2092  },
2093  {{aCcaTime,
2094  MicroSeconds(16),
2096  ((m_channelWidth > 20)
2097  ? ((m_channelWidth > 40)
2098  ? ((m_channelWidth > 80) ? std::vector<Time>{Seconds(0),
2099  Seconds(0),
2100  Seconds(0),
2101  Seconds(0),
2102  Seconds(0),
2103  Seconds(0),
2104  Seconds(0),
2105  Seconds(0)}
2106  : std::vector<Time>{Seconds(0),
2107  Seconds(0),
2108  Seconds(0),
2109  Seconds(0)})
2110  : std::vector<Time>{Seconds(0), Seconds(0)})
2111  : std::vector<Time>{})},
2112  {PpduDurations.at(80) - smallDelta,
2113  PpduDurations.at(80),
2115  ((m_channelWidth > 20)
2116  ? ((m_channelWidth > 40)
2117  ? ((m_channelWidth > 80) ? std::vector<Time>{Seconds(0),
2118  Seconds(0),
2119  Seconds(0),
2120  Seconds(0),
2121  Seconds(0),
2122  Seconds(0),
2123  Seconds(0),
2124  Seconds(0)}
2125  : std::vector<Time>{Seconds(0),
2126  Seconds(0),
2127  Seconds(0),
2128  Seconds(0)})
2129  : std::vector<Time>{Seconds(0), Seconds(0)})
2130  : std::vector<Time>{})}});
2131  delay += Seconds(1.0);
2132 
2133  //----------------------------------------------------------------------------------------------------------------------------------
2134  // Verify PHY notifies CCA-BUSY when a 80 MHz HE SU PPDU with received power above the CCA
2135  // sensitivity threshold occupies P40 The per20Bitmap should indicate CCA_BUSY for all
2136  // subchannels because received power is above -62 dBm (27.3.20.6.5).
2137  Simulator::Schedule(delay,
2139  this,
2140  "Reception of a 80 MHz HE PPDU that occupies the 40 MHz band above CCA "
2141  "sensitivity threshold");
2142  ScheduleTest(
2143  delay,
2144  {},
2145  {{-55.0, MicroSeconds(0), P80_CENTER_FREQUENCY, 80}},
2146  {
2147  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA_BUSY after aCCATime
2148  {PpduDurations.at(80) - smallDelta,
2149  WifiPhyState::CCA_BUSY}, // CCA_BUSY just before the transmission ends
2150  {PpduDurations.at(80) + smallDelta,
2151  WifiPhyState::IDLE} // IDLE just after the transmission ends
2152  },
2153  {{aCcaTime,
2154  MicroSeconds(16),
2156  ((m_channelWidth > 20)
2157  ? ((m_channelWidth > 40)
2158  ? ((m_channelWidth > 80) ? std::vector<Time>{NanoSeconds(271200),
2159  NanoSeconds(271200),
2160  NanoSeconds(271200),
2161  NanoSeconds(271200),
2162  NanoSeconds(0),
2163  NanoSeconds(0),
2164  NanoSeconds(0),
2165  NanoSeconds(0)}
2166  : std::vector<Time>{NanoSeconds(271200),
2167  NanoSeconds(271200),
2168  NanoSeconds(271200),
2169  NanoSeconds(271200)})
2170  : std::vector<Time>{NanoSeconds(271200), NanoSeconds(271200)})
2171  : std::vector<Time>{})},
2172  {PpduDurations.at(80) - smallDelta,
2173  PpduDurations.at(80),
2175  ((m_channelWidth > 20)
2176  ? ((m_channelWidth > 40)
2177  ? ((m_channelWidth > 80) ? std::vector<Time>{NanoSeconds(243200),
2178  NanoSeconds(243200),
2179  NanoSeconds(243200),
2180  NanoSeconds(243200),
2181  NanoSeconds(0),
2182  NanoSeconds(0),
2183  NanoSeconds(0),
2184  NanoSeconds(0)}
2185  : std::vector<Time>{NanoSeconds(243200),
2186  NanoSeconds(243200),
2187  NanoSeconds(243200),
2188  NanoSeconds(243200)})
2189  : std::vector<Time>{NanoSeconds(243200), NanoSeconds(243200)})
2190  : std::vector<Time>{})}});
2191  delay += Seconds(1.0);
2192 
2193  //----------------------------------------------------------------------------------------------------------------------------------
2194  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported when a signal not
2195  // occupying the operational channel is being received
2196  Simulator::Schedule(
2197  delay,
2199  this,
2200  "Reception of a 40 MHz HE PPDU that does not occupy the operational channel");
2201  ScheduleTest(delay,
2202  {},
2203  {{-50.0, MicroSeconds(0), S40_CENTER_FREQUENCY, 40}},
2204  {
2205  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2206  {PpduDurations.at(20) - smallDelta,
2207  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2208  {PpduDurations.at(20) + smallDelta,
2209  WifiPhyState::IDLE} // IDLE just after the transmission ends
2210  },
2211  {});
2212  delay += Seconds(1.0);
2213  }
2214 
2215  if (m_channelWidth > 80)
2216  {
2217  //----------------------------------------------------------------------------------------------------------------------------------
2218  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2219  // energy detection threshold occupies the first 20 MHz subchannel of the S80
2220  Simulator::Schedule(delay,
2222  this,
2223  "Reception of a 20 MHz signal that occupies the first subchannel of "
2224  "S80 below ED threshold");
2225  ScheduleTest(delay,
2226  {{-65.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY - 30, 20}},
2227  {},
2228  {
2229  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2230  {MicroSeconds(100) - smallDelta,
2231  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2232  {MicroSeconds(100) + smallDelta,
2233  WifiPhyState::IDLE} // IDLE just after the transmission ends
2234  },
2235  {});
2236  delay += Seconds(1.0);
2237 
2238  //----------------------------------------------------------------------------------------------------------------------------------
2239  // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2240  // energy detection threshold occupies the first 20 MHz subchannel of the S80 27.3.20.6.4:
2241  // Any signal within the secondary 80 MHz channel at or above –56 dBm.
2242  Simulator::Schedule(delay,
2244  this,
2245  "Reception of a 20 MHz signal that occupies the first subchannel of "
2246  "S80 above ED threshold");
2247  ScheduleTest(delay,
2248  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY - 30, 20}},
2249  {},
2250  {
2251  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2252  {MicroSeconds(100) - smallDelta,
2253  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2254  {MicroSeconds(100) + smallDelta,
2255  WifiPhyState::IDLE} // IDLE just after the transmission ends
2256  },
2257  {{MicroSeconds(100) - smallDelta,
2258  MicroSeconds(100),
2260  std::vector<Time>{MicroSeconds(0),
2261  MicroSeconds(0),
2262  MicroSeconds(0),
2263  MicroSeconds(0),
2264  MicroSeconds(100),
2265  MicroSeconds(0),
2266  MicroSeconds(0),
2267  MicroSeconds(0)}}});
2268  delay += Seconds(1.0);
2269 
2270  //----------------------------------------------------------------------------------------------------------------------------------
2271  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2272  // energy detection threshold occupies the second 20 MHz subchannel of the S80
2273  Simulator::Schedule(delay,
2275  this,
2276  "Reception of a 20 MHz signal that occupies the second subchannel of "
2277  "S80 below ED threshold");
2278  ScheduleTest(delay,
2279  {{-65.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY - 10, 20}},
2280  {},
2281  {
2282  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2283  {MicroSeconds(100) - smallDelta,
2284  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2285  {MicroSeconds(100) + smallDelta,
2286  WifiPhyState::IDLE} // IDLE just after the transmission ends
2287  },
2288  {});
2289  delay += Seconds(1.0);
2290 
2291  //----------------------------------------------------------------------------------------------------------------------------------
2292  // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2293  // energy detection threshold occupies the second 20 MHz subchannel of the S80 27.3.20.6.4:
2294  // Any signal within the secondary 80 MHz channel at or above –56 dBm.
2295  Simulator::Schedule(delay,
2297  this,
2298  "Reception of a 20 MHz signal that occupies the second subchannel of "
2299  "S80 above ED threshold");
2300  ScheduleTest(delay,
2301  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY - 10, 20}},
2302  {},
2303  {
2304  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2305  {MicroSeconds(100) - smallDelta,
2306  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2307  {MicroSeconds(100) + smallDelta,
2308  WifiPhyState::IDLE} // IDLE just after the transmission ends
2309  },
2310  {{MicroSeconds(100) - smallDelta,
2311  MicroSeconds(100),
2313  std::vector<Time>{MicroSeconds(0),
2314  MicroSeconds(0),
2315  MicroSeconds(0),
2316  MicroSeconds(0),
2317  MicroSeconds(0),
2318  MicroSeconds(100),
2319  MicroSeconds(0),
2320  MicroSeconds(0)}}});
2321  delay += Seconds(1.0);
2322 
2323  //----------------------------------------------------------------------------------------------------------------------------------
2324  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2325  // energy detection threshold occupies the third 20 MHz subchannel of the S80
2326  Simulator::Schedule(delay,
2328  this,
2329  "Reception of a 20 MHz signal that occupies the third subchannel of "
2330  "S80 below ED threshold");
2331  ScheduleTest(delay,
2332  {{-65.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY + 10, 20}},
2333  {},
2334  {
2335  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2336  {MicroSeconds(100) - smallDelta,
2337  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2338  {MicroSeconds(100) + smallDelta,
2339  WifiPhyState::IDLE} // IDLE just after the transmission ends
2340  },
2341  {});
2342  delay += Seconds(1.0);
2343 
2344  //----------------------------------------------------------------------------------------------------------------------------------
2345  // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2346  // energy detection threshold occupies the third 20 MHz subchannel of the S80 27.3.20.6.4:
2347  // Any signal within the secondary 80 MHz channel at or above –56 dBm.
2348  Simulator::Schedule(delay,
2350  this,
2351  "Reception of a 20 MHz signal that occupies the third subchannel of "
2352  "S80 above ED threshold");
2353  ScheduleTest(delay,
2354  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY + 10, 20}},
2355  {},
2356  {
2357  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2358  {MicroSeconds(100) - smallDelta,
2359  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2360  {MicroSeconds(100) + smallDelta,
2361  WifiPhyState::IDLE} // IDLE just after the transmission ends
2362  },
2363  {{MicroSeconds(100) - smallDelta,
2364  MicroSeconds(100),
2366  std::vector<Time>{MicroSeconds(0),
2367  MicroSeconds(0),
2368  MicroSeconds(0),
2369  MicroSeconds(0),
2370  MicroSeconds(0),
2371  MicroSeconds(0),
2372  MicroSeconds(100),
2373  MicroSeconds(0)}}});
2374  delay += Seconds(1.0);
2375 
2376  //----------------------------------------------------------------------------------------------------------------------------------
2377  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2378  // energy detection threshold occupies the fourth 20 MHz subchannel of the S80
2379  Simulator::Schedule(delay,
2381  this,
2382  "Reception of a 20 MHz signal that occupies the fourth subchannel of "
2383  "S80 below ED threshold");
2384  ScheduleTest(delay,
2385  {{-65.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY + 30, 20}},
2386  {},
2387  {
2388  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2389  {MicroSeconds(100) - smallDelta,
2390  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2391  {MicroSeconds(100) + smallDelta,
2392  WifiPhyState::IDLE} // IDLE just after the transmission ends
2393  },
2394  {});
2395  delay += Seconds(1.0);
2396 
2397  //----------------------------------------------------------------------------------------------------------------------------------
2398  // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2399  // energy detection threshold occupies the fourth 20 MHz subchannel of the S80 27.3.20.6.4:
2400  // Any signal within the secondary 80 MHz channel at or above –56 dBm.
2401  Simulator::Schedule(delay,
2403  this,
2404  "Reception of a 20 MHz signal that occupies the fourth subchannel of "
2405  "S80 above ED threshold");
2406  ScheduleTest(delay,
2407  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY + 30, 20}},
2408  {},
2409  {
2410  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2411  {MicroSeconds(100) - smallDelta,
2412  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2413  {MicroSeconds(100) + smallDelta,
2414  WifiPhyState::IDLE} // IDLE just after the transmission ends
2415  },
2416  {{MicroSeconds(100) - smallDelta,
2417  MicroSeconds(100),
2419  std::vector<Time>{MicroSeconds(0),
2420  MicroSeconds(0),
2421  MicroSeconds(0),
2422  MicroSeconds(0),
2423  MicroSeconds(0),
2424  MicroSeconds(0),
2425  MicroSeconds(0),
2426  MicroSeconds(100)}}});
2427  delay += Seconds(1.0);
2428 
2429  //----------------------------------------------------------------------------------------------------------------------------------
2430  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2431  // energy detection threshold occupies the first and second 20 MHz subchannels of the S80
2432  Simulator::Schedule(delay,
2434  this,
2435  "Reception of a 40 MHz signal that occupies the first and second "
2436  "subchannels of S80 below ED threshold");
2437  ScheduleTest(delay,
2438  {{-65.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY - 20, 40}},
2439  {},
2440  {
2441  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2442  {MicroSeconds(100) - smallDelta,
2443  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2444  {MicroSeconds(100) + smallDelta,
2445  WifiPhyState::IDLE} // IDLE just after the transmission ends
2446  },
2447  {});
2448  delay += Seconds(1.0);
2449 
2450  //----------------------------------------------------------------------------------------------------------------------------------
2451  // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2452  // energy detection threshold occupies the first and second 20 MHz subchannels of the S80
2453  // 27.3.20.6.4: Any signal within the secondary 80 MHz channel at or above –56 dBm.
2454  Simulator::Schedule(delay,
2456  this,
2457  "Reception of a 40 MHz signal that occupies the first and second "
2458  "subchannels of S80 above ED threshold");
2459  ScheduleTest(delay,
2460  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY - 20, 40}},
2461  {},
2462  {
2463  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2464  {MicroSeconds(100) - smallDelta,
2465  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2466  {MicroSeconds(100) + smallDelta,
2467  WifiPhyState::IDLE} // IDLE just after the transmission ends
2468  },
2469  {{MicroSeconds(100) - smallDelta,
2470  MicroSeconds(100),
2472  std::vector<Time>{MicroSeconds(0),
2473  MicroSeconds(0),
2474  MicroSeconds(0),
2475  MicroSeconds(0),
2476  MicroSeconds(100),
2477  MicroSeconds(100),
2478  MicroSeconds(0),
2479  MicroSeconds(0)}}});
2480  delay += Seconds(1.0);
2481 
2482  //----------------------------------------------------------------------------------------------------------------------------------
2483  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2484  // energy detection threshold occupies the third and fourth 20 MHz subchannels of the S80
2485  Simulator::Schedule(delay,
2487  this,
2488  "Reception of a 40 MHz signal that occupies the third and fourth "
2489  "subchannels of S80 below ED threshold");
2490  ScheduleTest(delay,
2491  {{-65.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY + 20, 40}},
2492  {},
2493  {
2494  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2495  {MicroSeconds(100) - smallDelta,
2496  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2497  {MicroSeconds(100) + smallDelta,
2498  WifiPhyState::IDLE} // IDLE just after the transmission ends
2499  },
2500  {});
2501  delay += Seconds(1.0);
2502 
2503  //----------------------------------------------------------------------------------------------------------------------------------
2504  // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2505  // energy detection threshold occupies the third and fourth 20 MHz subchannels of the S80
2506  // 27.3.20.6.4: Any signal within the secondary 80 MHz channel at or above –56 dBm.
2507  Simulator::Schedule(delay,
2509  this,
2510  "Reception of a 40 MHz signal that occupies the third and fourth "
2511  "subchannels of S80 above ED threshold");
2512  ScheduleTest(delay,
2513  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY + 20, 40}},
2514  {},
2515  {
2516  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2517  {MicroSeconds(100) - smallDelta,
2518  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2519  {MicroSeconds(100) + smallDelta,
2520  WifiPhyState::IDLE} // IDLE just after the transmission ends
2521  },
2522  {{MicroSeconds(100) - smallDelta,
2523  MicroSeconds(100),
2525  std::vector<Time>{MicroSeconds(0),
2526  MicroSeconds(0),
2527  MicroSeconds(0),
2528  MicroSeconds(0),
2529  MicroSeconds(0),
2530  MicroSeconds(0),
2531  MicroSeconds(100),
2532  MicroSeconds(100)}}});
2533  delay += Seconds(1.0);
2534 
2535  //----------------------------------------------------------------------------------------------------------------------------------
2536  // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2537  // energy detection threshold occupies the S80
2538  Simulator::Schedule(delay,
2540  this,
2541  "Reception of a 80 MHz signal that occupies S80 below ED threshold");
2542  ScheduleTest(delay,
2543  {{-65.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY, 80}},
2544  {},
2545  {
2546  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2547  {MicroSeconds(100) - smallDelta,
2548  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2549  {MicroSeconds(100) + smallDelta,
2550  WifiPhyState::IDLE} // IDLE just after the transmission ends
2551  },
2552  {});
2553  delay += Seconds(1.0);
2554 
2555  //----------------------------------------------------------------------------------------------------------------------------------
2556  // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2557  // energy detection threshold occupies the S80 27.3.20.6.4: Any signal within the secondary
2558  // 80 MHz channel at or above –56 dBm.
2559  Simulator::Schedule(delay,
2561  this,
2562  "Reception of a 80 MHz signal that occupies S80 above ED threshold");
2563  ScheduleTest(delay,
2564  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY, 80}},
2565  {},
2566  {
2567  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2568  {MicroSeconds(100) - smallDelta,
2569  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2570  {MicroSeconds(100) + smallDelta,
2571  WifiPhyState::IDLE} // IDLE just after the transmission ends
2572  },
2573  {{MicroSeconds(100) - smallDelta,
2574  MicroSeconds(100),
2576  std::vector<Time>{MicroSeconds(0),
2577  MicroSeconds(0),
2578  MicroSeconds(0),
2579  MicroSeconds(0),
2580  MicroSeconds(100),
2581  MicroSeconds(100),
2582  MicroSeconds(100),
2583  MicroSeconds(100)}}});
2584  delay += Seconds(1.0);
2585 
2586  //----------------------------------------------------------------------------------------------------------------------------------
2587  // Verify PHY state stays IDLE as long as a 160 MHz signal below the energy detection
2588  // threshold occupies the whole band
2589  Simulator::Schedule(
2590  delay,
2592  this,
2593  "Reception of a 160 MHz signal that occupies the whole band below ED threshold");
2594  ScheduleTest(delay,
2595  {{-55.0, MicroSeconds(0), MicroSeconds(100), P160_CENTER_FREQUENCY, 160}},
2596  {},
2597  {
2598  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2599  {MicroSeconds(100) - smallDelta,
2600  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2601  {MicroSeconds(100) + smallDelta,
2602  WifiPhyState::IDLE} // IDLE just after the transmission ends
2603  },
2604  {});
2605 
2606  delay += Seconds(1.0);
2607 
2608  //----------------------------------------------------------------------------------------------------------------------------------
2609  // Verify PHY state is CCA-BUSY as long as a 160 MHz signal above the energy detection
2610  // threshold occupies the whole band
2611  Simulator::Schedule(
2612  delay,
2614  this,
2615  "Reception of a 160 MHz signal that occupies the whole band above ED threshold");
2616  ScheduleTest(delay,
2617  {{-50.0, MicroSeconds(0), MicroSeconds(100), P160_CENTER_FREQUENCY, 160}},
2618  {},
2619  {
2620  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCCATime
2621  {MicroSeconds(100) - smallDelta,
2622  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
2623  {MicroSeconds(100) + smallDelta,
2624  WifiPhyState::IDLE} // IDLE just after the transmission ends
2625  },
2626  {{MicroSeconds(100) - smallDelta,
2627  MicroSeconds(100),
2629  std::vector<Time>{MicroSeconds(100),
2630  MicroSeconds(100),
2631  MicroSeconds(100),
2632  MicroSeconds(100),
2633  MicroSeconds(100),
2634  MicroSeconds(100),
2635  MicroSeconds(100),
2636  MicroSeconds(100)}}});
2637  delay += Seconds(1.0);
2638 
2639  //----------------------------------------------------------------------------------------------------------------------------------
2640  // Verify PHY notifies CCA-BUSY for the P20 channel while the S80 channel was already in
2641  // CCA-BUSY state
2642  Simulator::Schedule(delay,
2644  this,
2645  "Reception of a 20 MHz signal that occupies S80 followed by the "
2646  "reception of another 20 MHz signal that occupies P20");
2647  ScheduleTest(
2648  delay,
2649  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY + 10, 20},
2650  {-55.0, MicroSeconds(50), MicroSeconds(100), P20_CENTER_FREQUENCY, 20}},
2651  {},
2652  {
2653  {aCcaTime, WifiPhyState::IDLE}, // state of primary stays idle after aCCATime
2654  {MicroSeconds(50) + aCcaTime,
2655  WifiPhyState::CCA_BUSY}, // state of primary is CCA-BUSY after aCCATime that
2656  // followed the second transmission
2657  {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
2658  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
2659  {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
2660  WifiPhyState::IDLE} // IDLE just after the transmission ends
2661  },
2662  {{aCcaTime, // notification upon reception of the first signal
2663  MicroSeconds(100),
2665  std::vector<Time>{MicroSeconds(0),
2666  MicroSeconds(0),
2667  MicroSeconds(0),
2668  MicroSeconds(0),
2669  MicroSeconds(0),
2670  MicroSeconds(0),
2671  MicroSeconds(100),
2672  MicroSeconds(0)}},
2673  {MicroSeconds(50) + aCcaTime, // notification upon reception of the second signal
2674  MicroSeconds(50) + MicroSeconds(100),
2676  std::vector<Time>{MicroSeconds(100),
2677  MicroSeconds(0),
2678  MicroSeconds(00),
2679  MicroSeconds(0),
2680  MicroSeconds(0),
2681  MicroSeconds(0),
2682  MicroSeconds(50),
2683  MicroSeconds(0)}}});
2684  delay += Seconds(1.0);
2685 
2686  //----------------------------------------------------------------------------------------------------------------------------------
2687  // Verify PHY state stays IDLE but notifies CCA-BUSY for the S40 channel while the S80
2688  // channel was already in CCA-BUSY state
2689  Simulator::Schedule(delay,
2691  this,
2692  "Reception of a signal that occupies S80 followed by the reception of "
2693  "another signal that occupies S40");
2694  ScheduleTest(
2695  delay,
2696  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY + 30, 20},
2697  {-55.0, MicroSeconds(50), MicroSeconds(100), S40_CENTER_FREQUENCY - 10, 20}},
2698  {},
2699  {
2700  {aCcaTime, WifiPhyState::IDLE}, // state of primary stays idle after aCCATime
2701  {MicroSeconds(50) + aCcaTime, WifiPhyState::IDLE}, // state of primary stays IDLE
2702  {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
2703  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2704  {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
2705  WifiPhyState::IDLE} // IDLE just after the transmission ends
2706  },
2707  {{aCcaTime, // notification upon reception of the first signal
2708  MicroSeconds(100),
2710  std::vector<Time>{MicroSeconds(0),
2711  MicroSeconds(0),
2712  MicroSeconds(0),
2713  MicroSeconds(0),
2714  MicroSeconds(0),
2715  MicroSeconds(0),
2716  MicroSeconds(0),
2717  MicroSeconds(100)}},
2718  {MicroSeconds(50) + aCcaTime, // notification upon reception of the second signal
2719  MicroSeconds(50) + MicroSeconds(100),
2721  std::vector<Time>{MicroSeconds(0),
2722  MicroSeconds(0),
2723  MicroSeconds(100),
2724  MicroSeconds(0),
2725  MicroSeconds(0),
2726  MicroSeconds(0),
2727  MicroSeconds(0),
2728  MicroSeconds(50)}}});
2729  delay += Seconds(1.0);
2730 
2731  //----------------------------------------------------------------------------------------------------------------------------------
2732  // Verify PHY state stays IDLE but notifies CCA-BUSY for the S20 channel while the S80
2733  // channel was already in CCA-BUSY state
2734  Simulator::Schedule(delay,
2736  this,
2737  "Reception of a signal that occupies S80 followed by the reception of "
2738  "another signal that occupies S20");
2739  ScheduleTest(
2740  delay,
2741  {{-55.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY - 30, 20},
2742  {-55.0, MicroSeconds(50), MicroSeconds(100), S20_CENTER_FREQUENCY, 20}},
2743  {},
2744  {
2745  {aCcaTime, WifiPhyState::IDLE}, // state of primary stays idle after aCCATime
2746  {MicroSeconds(50) + aCcaTime, WifiPhyState::IDLE}, // state of primary stays IDLE
2747  {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
2748  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2749  {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
2750  WifiPhyState::IDLE} // IDLE just after the transmission ends
2751  },
2752  {{aCcaTime, // notification upon reception of the first signal
2753  MicroSeconds(100),
2755  std::vector<Time>{MicroSeconds(0),
2756  MicroSeconds(0),
2757  MicroSeconds(0),
2758  MicroSeconds(0),
2759  MicroSeconds(100),
2760  MicroSeconds(0),
2761  MicroSeconds(0),
2762  MicroSeconds(0)}},
2763  {MicroSeconds(50) + aCcaTime, // notification upon reception of the second signal
2764  MicroSeconds(50) + MicroSeconds(100),
2766  std::vector<Time>{MicroSeconds(0),
2767  MicroSeconds(100),
2768  MicroSeconds(0),
2769  MicroSeconds(0),
2770  MicroSeconds(50),
2771  MicroSeconds(0),
2772  MicroSeconds(0),
2773  MicroSeconds(0)}}});
2774  delay += Seconds(1.0);
2775 
2776  //----------------------------------------------------------------------------------------------------------------------------------
2777  // Verify PHY state stays IDLE when a 80 MHz HE SU PPDU with received power below the CCA
2778  // sensitivity threshold occupies S80
2779  Simulator::Schedule(
2780  delay,
2782  this,
2783  "Reception of a 40 MHz HE PPDU that occupies S40 below CCA sensitivity threshold");
2784  ScheduleTest(delay,
2785  {},
2786  {{-70.0, MicroSeconds(0), S80_CENTER_FREQUENCY, 80}},
2787  {
2788  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2789  {PpduDurations.at(20) - smallDelta,
2790  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2791  {PpduDurations.at(20) + smallDelta,
2792  WifiPhyState::IDLE} // IDLE just after the transmission ends
2793  },
2794  {});
2795  delay += Seconds(1.0);
2796 
2797  //----------------------------------------------------------------------------------------------------------------------------------
2798  // Verify PHY state stays IDLE but CCA-BUSY indication is reported when a 80 MHz HE SU PPDU
2799  // with received power above the CCA sensitivity threshold occupies S80
2800  Simulator::Schedule(
2801  delay,
2803  this,
2804  "Reception of a 80 MHz HE PPDU that occupies S80 above CCA sensitivity threshold");
2805  ScheduleTest(delay,
2806  {},
2807  {{-65.0, MicroSeconds(0), S80_CENTER_FREQUENCY, 80}},
2808  {
2809  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2810  {PpduDurations.at(80) - smallDelta,
2811  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2812  {PpduDurations.at(80) + smallDelta,
2813  WifiPhyState::IDLE} // IDLE just after the transmission ends
2814  },
2815  {{aCcaTime,
2816  PpduDurations.at(80),
2818  std::vector<Time>{NanoSeconds(0),
2819  NanoSeconds(0),
2820  NanoSeconds(0),
2821  NanoSeconds(0),
2822  PpduDurations.at(80),
2823  PpduDurations.at(80),
2824  PpduDurations.at(80),
2825  PpduDurations.at(80)}}});
2826  delay += Seconds(1.0);
2827 
2828  //----------------------------------------------------------------------------------------------------------------------------------
2829  // Verify PHY state stays IDLE and CCA-BUSY indication is reported if only the per20bitmap
2830  // parameter changes
2831  Simulator::Schedule(delay,
2833  this,
2834  "Reception of a 20 MHz signal that generates a per20bitmap parameter "
2835  "change when previous CCA indication reports IDLE");
2836  ScheduleTest(delay,
2837  {{-60.0, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY + 30, 20}},
2838  {},
2839  {
2840  {aCcaTime, WifiPhyState::IDLE}, // IDLE after aCCATime
2841  {MicroSeconds(100) - smallDelta,
2842  WifiPhyState::IDLE}, // IDLE just before the transmission ends
2843  {MicroSeconds(100) + smallDelta,
2844  WifiPhyState::IDLE} // IDLE just after the transmission ends
2845  },
2846  {{aCcaTime,
2847  Seconds(0),
2849  std::vector<Time>{MicroSeconds(0),
2850  MicroSeconds(0),
2851  MicroSeconds(0),
2852  MicroSeconds(0),
2853  MicroSeconds(0),
2854  MicroSeconds(0),
2855  MicroSeconds(0),
2856  MicroSeconds(100)}}});
2857  delay += Seconds(1.0);
2858 
2859  //----------------------------------------------------------------------------------------------------------------------------------
2860  // Verify PHY state stays CCA_BUSY and CCA-BUSY indication is reported if only the
2861  // per20bitmap parameter changes
2862  Simulator::Schedule(
2863  delay,
2865  this,
2866  "Reception of a 20 MHz signal that generates a per20bitmap parameter change when "
2867  "previous CCA indication reports BUSY for the primary channel");
2868  ScheduleTest(
2869  delay,
2870  {{-50.0, MicroSeconds(0), MicroSeconds(100), P80_CENTER_FREQUENCY, 80},
2871  {-60.0, MicroSeconds(50), MicroSeconds(200), S80_CENTER_FREQUENCY + 30, 20}},
2872  {},
2873  {
2874  {aCcaTime, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCCATime
2875  {MicroSeconds(100) - smallDelta,
2876  WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
2877  {MicroSeconds(100) + smallDelta,
2878  WifiPhyState::IDLE} // IDLE just after the transmission ends
2879  },
2880  {{aCcaTime,
2881  MicroSeconds(100),
2883  std::vector<Time>{MicroSeconds(100),
2884  MicroSeconds(100),
2885  MicroSeconds(100),
2886  MicroSeconds(100),
2887  MicroSeconds(0),
2888  MicroSeconds(0),
2889  MicroSeconds(0),
2890  MicroSeconds(0)}},
2891  {MicroSeconds(50) + aCcaTime, // notification upon reception of the second signal
2892  MicroSeconds(100),
2894  std::vector<Time>{MicroSeconds(50),
2895  MicroSeconds(50),
2896  MicroSeconds(50),
2897  MicroSeconds(50),
2898  MicroSeconds(0),
2899  MicroSeconds(0),
2900  MicroSeconds(0),
2901  MicroSeconds(200)}}});
2902  delay += Seconds(1.0);
2903  }
2904 
2905  Simulator::Run();
2906 }
2907 
2908 void
2910 {
2911  m_frequency = 5180;
2912  m_channelWidth = 20;
2913  RunOne();
2914 
2915  m_frequency = 5190;
2916  m_channelWidth = 40;
2917  RunOne();
2918 
2919  m_frequency = 5210;
2920  m_channelWidth = 80;
2921  RunOne();
2922 
2923  m_frequency = 5250;
2924  m_channelWidth = 160;
2925  RunOne();
2926 
2927  Simulator::Destroy();
2928 }
2929 
2930 void
2932 {
2933  m_rxPhy->Dispose();
2934  m_rxPhy = nullptr;
2935  m_txPhy->Dispose();
2936  m_txPhy = nullptr;
2937  for (auto& signalGenerator : m_signalGenerators)
2938  {
2939  signalGenerator->Dispose();
2940  signalGenerator = nullptr;
2941  }
2942 }
2943 
2951 {
2952  public:
2954 };
2955 
2957  : TestSuite("wifi-phy-cca", UNIT)
2958 {
2959  AddTestCase(new WifiPhyCcaThresholdsTest, TestCase::QUICK);
2960  AddTestCase(new WifiPhyCcaIndicationTest, TestCase::QUICK);
2961 }
2962 
#define max(a, b)
Definition: 80211b.c:43
PHY listener for CCA tests.
void NotifyOn() override
Notify listeners that we went to switch on.
WifiChannelListType m_lastCcaBusyChannelType
Channel type indication for the last CCA-BUSY notification.
void NotifyRxEndError() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &per20MhzDurations) override
void NotifySleep() override
Notify listeners that we went to sleep.
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyTxStart(Time duration, double txPowerDbm) override
CcaTestPhyListener()=default
void NotifyOff() override
Notify listeners that we went to switch off.
std::size_t m_notifications
Number of CCA notifications.
void NotifyRxStart(Time duration) override
Time m_endCcaBusy
End of the CCA-BUSY duration.
void Reset()
Reset function.
void NotifyWakeup() override
Notify listeners that we woke up.
std::vector< Time > m_lastPer20MhzCcaBusyDurations
End of the CCA-BUSY durations per 20 MHz.
void NotifySwitchingStart(Time duration) override
Wifi Phy Threshold Test base class.
std::size_t m_numSignalGenerators
The number of non-wifi signals generators needed for the test.
void CheckPhyState(WifiPhyState expectedState)
Check the PHY state.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void CheckLastCcaBusyNotification(Time expectedEndTime, WifiChannelListType expectedChannelType, const std::vector< Time > &expectedPer20MhzDurations)
Check the last CCA-BUSY notification.
std::unique_ptr< CcaTestPhyListener > m_rxPhyStateListener
Listener for PHY state transitions.
void SendHeSuPpdu(double txPowerDbm, uint16_t frequency, uint16_t bandwidth)
Send an HE SU PPDU.
void StartSignal(Ptr< WaveformGenerator > signalGenerator, double txPowerDbm, uint16_t frequency, uint16_t bandwidth, Time duration)
Start to generate a signal.
void RunOne()
Run one function.
void DoCheckPhyState(WifiPhyState expectedState)
Check the PHY state.
std::vector< Ptr< WaveformGenerator > > m_signalGenerators
Generators of non-wifi signals.
void ScheduleTest(Time delay, const std::vector< TxSignalInfo > &generatedSignals, const std::vector< TxPpduInfo > &generatedPpdus, const std::vector< StateCheckPoint > &stateCheckpoints, const std::vector< CcaCheckPoint > &ccaCheckpoints)
Schedule test to perform.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint16_t m_frequency
Operating frequency in MHz.
void DoRun() override
Implementation to actually run this TestCase.
void LogScenario(const std::string &log) const
Log scenario description.
void Reset()
Reset function.
Ptr< SpectrumWifiPhy > m_rxPhy
PHY object of the receiver.
Ptr< SpectrumWifiPhy > m_txPhy
PHY object of the transmitter.
void StopSignal(Ptr< WaveformGenerator > signalGenerator)
Stop to generate a signal.
uint16_t m_channelWidth
Operating channel width in MHz.
Wi-Fi PHY CCA Test Suite.
PHY CCA thresholds test.
Ptr< OfdmPpdu > CreateDummyNonHtPpdu()
Create a non-HT PPDU.
Ptr< WifiNetDevice > m_device
The WifiNetDevice.
Ptr< HePpdu > CreateDummyHePpdu(uint16_t bandwidth)
Create a HE PPDU.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
double m_CcaSensitivityDbm
The current CCA sensitivity threshold for signals that occupy the primary 20 MHz channel (in dBm)
Ptr< HtPpdu > CreateDummyHtPpdu(uint16_t bandwidth)
Create a HT PPDU.
Ptr< SpectrumWifiPhy > m_phy
The spectrum PHY.
Ptr< ObssPdAlgorithm > m_obssPdAlgorithm
The OBSS-PD algorithm.
void VerifyCcaThreshold(const Ptr< PhyEntity > phy, const Ptr< const WifiPpdu > ppdu, WifiChannelListType channelType, double expectedCcaThresholdDbm)
Function to verify the CCA threshold that is being reported by a given PHY entity upon reception of a...
Ptr< WifiPsdu > CreateDummyPsdu()
Create a dummy PSDU whose payload is 1000 bytes.
VhtConfiguration::SecondaryCcaSensitivityThresholds m_secondaryCcaSensitivityThresholds
The current CCA sensitivity thresholds for signals that do not occupy the primary 20 MHz channel (in ...
Ptr< VhtPpdu > CreateDummyVhtPpdu(uint16_t bandwidth)
Create a VHT PPDU.
void RunOne()
Run tests for given CCA attributes.
Ptr< VhtConfiguration > m_vhtConfiguration
The VHT configuration.
double m_CcaEdThresholdDbm
The current CCA-ED threshold for a 20 MHz subchannel (in dBm)
void DoRun() override
Implementation to actually run this TestCase.
double m_obssPdLevel
The current OBSS-PD level (in dBm)
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:138
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:200
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:240
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:259
void Dispose()
Dispose of this Object.
Definition: object.cc:219
void SetObssPdLevel(double level)
virtual void ConnectWifiNetDevice(const Ptr< WifiNetDevice > device)
Connect the WifiNetDevice and setup eventual callbacks.
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:206
void SetChannel(const Ptr< SpectrumChannel > channel)
Set the SpectrumChannel this SpectrumWifiPhy is to be connected to.
void CreateWifiSpectrumPhyInterface(Ptr< NetDevice > device)
Method to encapsulate the creation of the WifiSpectrumPhyInterface object (used to bind the WifiSpect...
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1423
std::tuple< double, double, double > SecondaryCcaSensitivityThresholds
Tuple identifying CCA sensitivity thresholds for secondary channels.
void SetSecondaryCcaSensitivityThresholds(const SecondaryCcaSensitivityThresholds &thresholds)
Sets the CCA sensitivity thresholds for PPDUs that do not occupy the primary channel.
void SetDevice(Ptr< NetDevice > d) override
Set the associated NetDevice instance.
void SetChannel(Ptr< SpectrumChannel > c) override
Set the channel attached to this device.
virtual void Start()
Start the waveform generator.
void SetTxPowerSpectralDensity(Ptr< SpectrumValue > txs)
Set the Power Spectral Density used for outgoing waveforms.
void SetDutyCycle(double value)
void SetPeriod(Time period)
Set the period according to which the WaveformGenerator switches on and off.
virtual void Stop()
Stop the waveform generator.
Implements the IEEE 802.11 MAC header.
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetVhtConfiguration(Ptr< VhtConfiguration > vhtConfiguration)
void SetStandard(WifiStandard standard)
Set the Wifi standard.
void SetPhy(const Ptr< WifiPhy > phy)
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:624
void Send(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
This function is a wrapper for the Send variant that accepts a WifiConstPsduMap as first argument.
Definition: wifi-phy.cc:1693
void SetCcaEdThreshold(double threshold)
Sets the CCA energy detection threshold (dBm).
Definition: wifi-phy.cc:485
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:632
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:941
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:1062
void SetCcaSensitivityThreshold(double threshold)
Sets the CCA sensitivity threshold (dBm).
Definition: wifi-phy.cc:498
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:704
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:600
void SetTxPowerEnd(double end)
Sets the maximum available transmission power level (dBm).
Definition: wifi-phy.cc:535
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:652
void RegisterListener(WifiPhyListener *listener)
Definition: wifi-phy.cc:454
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:870
void SetTxPowerStart(double start)
Sets the minimum available transmission power level (dBm).
Definition: wifi-phy.cc:522
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: wifi-phy.cc:2184
receive notifications about PHY events.
This objects implements the PHY state machine of the Wifi device.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:144
#define NS_TEST_EXPECT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report if ...
Definition: test.h:510
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PREAMBLE_VHT_SU
@ WIFI_PREAMBLE_HT_MF
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ WIFI_MOD_CLASS_OFDM
OFDM (Clause 17)
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ WIFI_CHANLIST_PRIMARY
@ WIFI_CHANLIST_SECONDARY40
@ WIFI_CHANLIST_SECONDARY
@ WIFI_CHANLIST_SECONDARY80
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::vector< BandInfo > Bands
Container of BandInfo.
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
@ WIFI_MAC_QOSDATA
phy
Definition: third.py:82
structure that holds information to perform CCA check
Time expectedCcaEndTime
expected CCA_BUSY end time
Time timePoint
time at which the check will performed
std::vector< Time > expectedPer20MhzDurations
expected per-20 MHz CCA duration
WifiChannelListType expectedChannelListType
expected channel list type
structure that holds information to perform PHY state check
WifiPhyState expectedPhyState
expected PHY state
Time timePoint
time at which the check will performed
structure that holds information to generate PPDUs
uint16_t centerFreq
center frequency to use in MHz
Time startTime
time at which transmission will be started
uint16_t bandwidth
bandwidth to use in MHz
double power
transmit power to use in dBm
structure that holds information to generate signals
uint16_t centerFreq
center frequency to use in MHz
double power
transmit power to use in dBm
uint16_t bandwidth
bandwidth to use in MHz
Time startTime
time at which transmission will be started
Time duration
the duration of the transmission
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
constexpr uint32_t P40_CENTER_FREQUENCY
constexpr uint32_t P20_CENTER_FREQUENCY
const Time aCcaTime
const std::map< uint16_t, Time > PpduDurations
static WifiPhyCcaTestSuite WifiPhyCcaTestSuite
the test suite
constexpr uint32_t P160_CENTER_FREQUENCY
constexpr uint32_t P80_CENTER_FREQUENCY
constexpr uint32_t S40_CENTER_FREQUENCY
const Time smallDelta
constexpr uint32_t S80_CENTER_FREQUENCY
constexpr uint32_t S20_CENTER_FREQUENCY
WifiPhyState
The state of the PHY layer.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ RX
The PHY layer is receiving a packet.
@ IDLE
The PHY layer is IDLE.