A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-phy-cca-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "ns3/constant-obss-pd-algorithm.h"
10#include "ns3/eht-configuration.h"
11#include "ns3/eht-phy.h"
12#include "ns3/eht-ppdu.h"
13#include "ns3/he-ppdu.h"
14#include "ns3/ht-ppdu.h"
15#include "ns3/interference-helper.h"
16#include "ns3/log.h"
17#include "ns3/multi-model-spectrum-channel.h"
18#include "ns3/nist-error-rate-model.h"
19#include "ns3/non-communicating-net-device.h"
20#include "ns3/ofdm-ppdu.h"
21#include "ns3/pointer.h"
22#include "ns3/rng-seed-manager.h"
23#include "ns3/spectrum-wifi-helper.h"
24#include "ns3/spectrum-wifi-phy.h"
25#include "ns3/test.h"
26#include "ns3/threshold-preamble-detection-model.h"
27#include "ns3/vht-configuration.h"
28#include "ns3/vht-ppdu.h"
29#include "ns3/waveform-generator.h"
30#include "ns3/wifi-mac-header.h"
31#include "ns3/wifi-net-device.h"
32#include "ns3/wifi-phy-listener.h"
33#include "ns3/wifi-psdu.h"
34#include "ns3/wifi-spectrum-value-helper.h"
35#include "ns3/wifi-standards.h"
36#include "ns3/wifi-utils.h"
37
38#include <memory>
39#include <vector>
40
41using namespace ns3;
42
43NS_LOG_COMPONENT_DEFINE("WifiPhyCcaTest");
44
55// add small delta to be right after aCcaTime, since test checks are scheduled before wifi events
57const std::map<MHz_u, Time> hePpduDurations = {
58 {20, NanoSeconds(1009600)},
59 {40, NanoSeconds(533600)},
60 {80, NanoSeconds(275200)},
61};
62const std::map<MHz_u, Time> ehtPpduDurations = {
63 {20, NanoSeconds(1017600)},
64 {40, NanoSeconds(541600)},
65 {80, NanoSeconds(287200)},
66};
67
68/**
69 * @ingroup wifi-test
70 * @ingroup tests
71 *
72 * @brief PHY CCA thresholds test
73 */
75{
76 public:
78
79 private:
80 void DoSetup() override;
81 void DoTeardown() override;
82 void DoRun() override;
83
84 /**
85 * Run tests for given CCA attributes
86 */
87 void RunOne();
88
89 /**
90 * Create a dummy PSDU whose payload is 1000 bytes
91 * @return a dummy PSDU whose payload is 1000 bytes
92 */
94 /**
95 * Create a non-HT PPDU
96 * @param channel the operating channel of the PHY used for the transmission
97 * @return a non-HT PPDU
98 */
100 /**
101 * Create a HT PPDU
102 * @param bandwidth the bandwidth used for the transmission the PPDU
103 * @param channel the operating channel of the PHY used for the transmission
104 * @return a HT PPDU
105 */
107 /**
108 * Create a VHT PPDU
109 * @param bandwidth the bandwidth used for the transmission the PPDU
110 * @param channel the operating channel of the PHY used for the transmission
111 * @return a VHT PPDU
112 */
114 /**
115 * Create a HE PPDU
116 * @param bandwidth the bandwidth used for the transmission the PPDU
117 * @param channel the operating channel of the PHY used for the transmission
118 * @return a HE PPDU
119 */
121 /**
122 * Create a EHT PPDU
123 * @param bandwidth the bandwidth used for the transmission the PPDU
124 * @param channel the operating channel of the PHY used for the transmission
125 * @return a EHT PPDU
126 */
128
129 /**
130 * Function to verify the CCA threshold that is being reported by a given PHY entity upon
131 * reception of a signal or a PPDU
132 * @param phy the PHY entity to verify
133 * @param ppdu the incoming PPDU or signal (if nullptr)
134 * @param channelType the channel list type that indicates which channel the PPDU or the
135 * signal occupies
136 * @param expectedCcaThreshold the CCA threshold that is expected to be reported
137 */
138 void VerifyCcaThreshold(const Ptr<PhyEntity> phy,
139 const Ptr<const WifiPpdu> ppdu,
140 WifiChannelListType channelType,
141 dBm_u expectedCcaThreshold);
142
143 Ptr<WifiNetDevice> m_device; ///< The WifiNetDevice
144 Ptr<SpectrumWifiPhy> m_phy; ///< The spectrum PHY
145 Ptr<ObssPdAlgorithm> m_obssPdAlgorithm; ///< The OBSS-PD algorithm
146 Ptr<VhtConfiguration> m_vhtConfiguration; ///< The VHT configuration
147 Ptr<EhtConfiguration> m_ehtConfiguration; ///< The EHT configuration
148
149 dBm_u m_CcaEdThreshold; ///< The current CCA-ED threshold for a 20 MHz subchannel
150 dBm_u m_CcaSensitivity; ///< The current CCA sensitivity threshold for signals that occupy the
151 ///< primary 20 MHz channel
152
154 m_secondaryCcaSensitivityThresholds; ///< The current CCA sensitivity thresholds for signals
155 ///< that do not occupy the primary 20 MHz channel
156
157 dBm_u m_obssPdLevel; ///< The current OBSS-PD level
158 dBm_u m_per20CcaSensitivity; ///< The current CCA sensitivity threshold for Per 20MHz check
159};
160
162 : TestCase("Wi-Fi PHY CCA thresholds test"),
163 m_CcaEdThreshold{-62.0},
164 m_CcaSensitivity{-82.0},
165 m_secondaryCcaSensitivityThresholds{dBm_u{-72}, dBm_u{-72}, dBm_u{-69}},
166 m_obssPdLevel{-82.0},
167 m_per20CcaSensitivity{-72.0}
168{
169}
170
173{
174 Ptr<Packet> pkt = Create<Packet>(1000);
175 WifiMacHeader hdr;
177 hdr.SetQosTid(0);
178 return Create<WifiPsdu>(pkt, hdr);
179}
180
183{
185 0,
187 NanoSeconds(800),
188 1,
189 1,
190 0,
191 MHz_u{20},
192 false);
194 return Create<OfdmPpdu>(psdu, txVector, channel, 0);
195}
196
199{
201 0,
203 NanoSeconds(800),
204 1,
205 1,
206 0,
207 bandwidth,
208 false);
210 return Create<HtPpdu>(psdu, txVector, channel, MicroSeconds(100), 0);
211}
212
215 const WifiPhyOperatingChannel& channel)
216{
218 0,
220 NanoSeconds(800),
221 1,
222 1,
223 0,
224 bandwidth,
225 false);
227 return Create<VhtPpdu>(psdu, txVector, channel, MicroSeconds(100), 0);
228}
229
232{
234 0,
236 NanoSeconds(800),
237 1,
238 1,
239 0,
240 bandwidth,
241 false);
243 return Create<HePpdu>(psdu, txVector, channel, MicroSeconds(100), 0);
244}
245
248 const WifiPhyOperatingChannel& channel)
249{
251 0,
253 NanoSeconds(800),
254 1,
255 1,
256 0,
257 bandwidth,
258 false};
259 WifiConstPsduMap psdus;
260 psdus.emplace(1, CreateDummyPsdu());
261 return Create<EhtPpdu>(psdus,
262 txVector,
263 channel,
264 MicroSeconds(100),
265 0,
267}
268
269void
271 const Ptr<const WifiPpdu> ppdu,
272 WifiChannelListType channelType,
273 dBm_u expectedCcaThreshold)
274{
275 NS_LOG_FUNCTION(this << phy << channelType << expectedCcaThreshold);
276 const auto actualThreshold = phy->GetCcaThreshold(ppdu, channelType);
277 NS_LOG_INFO((ppdu == nullptr ? "any signal" : "a PPDU")
278 << " in " << channelType << " channel: " << actualThreshold << "dBm");
279 NS_TEST_EXPECT_MSG_EQ_TOL(actualThreshold,
280 expectedCcaThreshold,
281 dB_u{1e-6},
282 "Actual CCA threshold for "
283 << (ppdu == nullptr ? "any signal" : "a PPDU") << " in "
284 << channelType << " channel " << actualThreshold
285 << "dBm does not match expected threshold "
286 << expectedCcaThreshold << "dBm");
287}
288
289void
291{
292 // WifiHelper::EnableLogComponents ();
293 // LogComponentEnable ("WifiPhyCcaTest", LOG_LEVEL_ALL);
294
296 m_device->SetStandard(WIFI_STANDARD_80211be);
298 m_device->SetVhtConfiguration(m_vhtConfiguration);
300 m_device->SetEhtConfiguration(m_ehtConfiguration);
301
303 m_phy->SetDevice(m_device);
304 m_device->SetPhy(m_phy);
305 m_phy->SetInterferenceHelper(CreateObject<InterferenceHelper>());
307
308 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
309 MHz_u{0},
310 MHz_u{160},
313 ->number;
314 m_phy->SetOperatingChannel(WifiPhy::ChannelTuple{channelNum, 160, WIFI_PHY_BAND_5GHZ, 0});
315 m_phy->ConfigureStandard(WIFI_STANDARD_80211be);
316
318 m_device->AggregateObject(m_obssPdAlgorithm);
319 m_obssPdAlgorithm->ConnectWifiNetDevice(m_device);
320}
321
322void
324{
325 m_device->Dispose();
326 m_device = nullptr;
327}
328
329void
331{
332 m_phy->SetCcaEdThreshold(m_CcaEdThreshold);
333 m_phy->SetCcaSensitivityThreshold(m_CcaSensitivity);
334 m_vhtConfiguration->SetSecondaryCcaSensitivityThresholds(m_secondaryCcaSensitivityThresholds);
335 m_obssPdAlgorithm->SetObssPdLevel(m_obssPdLevel);
336 m_ehtConfiguration->m_per20CcaSensitivityThreshold = m_per20CcaSensitivity;
337
338 // OFDM PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
340 nullptr,
343
344 //-----------------------------------------------------------------------------------------------------------------------------------
345
346 // OFDM PHY: 20 MHz non-HT PPDU in primary channel (20 MHz) if power above CCA sensitivity
347 // threshold
349 CreateDummyNonHtPpdu(m_phy->GetOperatingChannel()),
352
353 //-----------------------------------------------------------------------------------------------------------------------------------
354
355 // HT PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
357 nullptr,
360
361 // HT PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
363 nullptr,
366
367 //-----------------------------------------------------------------------------------------------------------------------------------
368
369 // HT PHY: 20 MHz HT PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
370 // threshold
372 CreateDummyHtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
375
376 // HT PHY: 40 MHz HT PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
377 // threshold
379 CreateDummyHtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
382
383 //-----------------------------------------------------------------------------------------------------------------------------------
384
385 // VHT PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
387 nullptr,
390
391 // VHT PHY: any signal in secondary channel (20 MHz) if power above CCA-ED threshold
393 nullptr,
396
397 // VHT PHY: any signal in secondary40 channel (40 MHz) if power above CCA-ED threshold + 3dB
399 nullptr,
401 m_CcaEdThreshold + dB_u{3.0});
402
403 // VHT PHY: any signal in secondary80 channel (80 MHz) if power above CCA-ED threshold + 6dB
405 nullptr,
407 m_CcaEdThreshold + dB_u{6.0});
408
409 //-----------------------------------------------------------------------------------------------------------------------------------
410
411 // VHT PHY: 20 MHz VHT PPDU in primary channel (20 MHz) if power in primary above CCA
412 // sensitivity threshold
414 CreateDummyVhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
417
418 // VHT PHY: 40 MHz VHT PPDU in primary channel (20 MHz) if power in primary above CCA
419 // sensitivity threshold
421 CreateDummyVhtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
424
425 // VHT PHY: 80 MHz VHT PPDU in primary channel (20 MHz) if power in primary above CCA
426 // sensitivity threshold
428 CreateDummyVhtPpdu(MHz_u{80}, m_phy->GetOperatingChannel()),
431
432 // VHT PHY: 160 MHz VHT PPDU in primary channel (20 MHz) if power in primary above CCA
433 // sensitivity threshold
435 CreateDummyVhtPpdu(MHz_u{160}, m_phy->GetOperatingChannel()),
438
439 //-----------------------------------------------------------------------------------------------------------------------------------
440
441 // VHT PHY: 20 MHz VHT PPDU in secondary channel (20 MHz) if power above the CCA sensitivity
442 // threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
444 CreateDummyVhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
447
448 // VHT PHY: 20 MHz VHT PPDU in secondary40 channel (40 MHz) if power above the CCA sensitivity
449 // threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
451 CreateDummyVhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
454
455 // VHT PHY: 40 MHz VHT PPDU in secondary40 channel (40 MHz) if power above the CCA sensitivity
456 // threshold corresponding to a 40 MHz PPDU that does not occupy the primary 20 MHz
458 CreateDummyVhtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
461
462 // VHT PHY: 20 MHz VHT PPDU in secondary80 channel (80 MHz) if power above the CCA sensitivity
463 // threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
465 CreateDummyVhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
468
469 // VHT PHY: 40 MHz VHT PPDU in secondary80 channel (80 MHz) if power above the CCA sensitivity
470 // threshold corresponding to a 40 MHz PPDU that does not occupy the primary 20 MHz
472 CreateDummyVhtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
475
476 // VHT PHY: 80 MHz VHT PPDU in secondary80 channel (80 MHz) if power above the CCA sensitivity
477 // threshold corresponding to a 80 MHz PPDU that does not occupy the primary 20 MHz
479 CreateDummyVhtPpdu(MHz_u{80}, m_phy->GetOperatingChannel()),
482
483 //-----------------------------------------------------------------------------------------------------------------------------------
484
485 // HE PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
487 nullptr,
490
491 // HE PHY: any signal in secondary channel (20 MHz) if power above CCA-ED threshold
493 nullptr,
496
497 // HE PHY: any signal in secondary40 channel (40 MHz) if power above CCA-ED threshold + 3dB
499 nullptr,
501 m_CcaEdThreshold + dB_u{3.0});
502
503 // HE PHY: any signal in secondary80 channel (80 MHz) if power above CCA-ED threshold + 6dB
505 nullptr,
507 m_CcaEdThreshold + dB_u{6.0});
508
509 //-----------------------------------------------------------------------------------------------------------------------------------
510
511 // HE PHY: 20 MHz HE PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
512 // threshold
514 CreateDummyHePpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
517
518 // HE PHY: 40 MHz HE PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
519 // threshold
521 CreateDummyHePpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
524
525 // HE PHY: 80 MHz HE PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
526 // threshold
528 CreateDummyHePpdu(MHz_u{80}, m_phy->GetOperatingChannel()),
531
532 // HE PHY: 160 MHz HE PPDU in primary channel (20 MHz) if power in primary above CCA sensitivity
533 // threshold
535 CreateDummyHePpdu(MHz_u{160}, m_phy->GetOperatingChannel()),
538
539 //-----------------------------------------------------------------------------------------------------------------------------------
540
541 // HE PHY: 20 MHz HE PPDU in secondary channel (20 MHz) if power above the max between the CCA
542 // sensitivity threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
543 // and the OBSS-PD level
545 CreateDummyHePpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
547 std::max(m_obssPdLevel, std::get<0>(m_secondaryCcaSensitivityThresholds)));
548
549 // HE PHY: 20 MHz HE PPDU in secondary40 channel (40 MHz) if power above the max between the CCA
550 // sensitivity threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
551 // and the OBSS-PD level
553 CreateDummyHePpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
555 std::max(m_obssPdLevel, std::get<0>(m_secondaryCcaSensitivityThresholds)));
556
557 // HE PHY: 40 MHz HE PPDU in secondary40 channel (40 MHz) if power above the max between the CCA
558 // sensitivity threshold corresponding to a 40 MHz PPDU that does not occupy the primary 20 MHz
559 // and the OBSS-PD level plus 3 dB
561 m_phy->GetPhyEntity(WIFI_MOD_CLASS_HE),
562 CreateDummyHePpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
564 std::max(m_obssPdLevel + dB_u{3.0}, std::get<1>(m_secondaryCcaSensitivityThresholds)));
565
566 // HE PHY: 20 MHz HE PPDU in secondary80 channel (80 MHz) if power above the max between the CCA
567 // sensitivity threshold corresponding to a 20 MHz PPDU that does not occupy the primary 20 MHz
568 // and the OBSS-PD level
570 CreateDummyHePpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
572 std::max(m_obssPdLevel, std::get<0>(m_secondaryCcaSensitivityThresholds)));
573
574 // HE PHY: 40 MHz HE PPDU in secondary80 channel (80 MHz) if power above the max between the CCA
575 // sensitivity threshold corresponding to a 40 MHz PPDU that does not occupy the primary 20 MHz
576 // and the OBSS-PD level plus 3 dB
578 m_phy->GetPhyEntity(WIFI_MOD_CLASS_HE),
579 CreateDummyHePpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
581 std::max(m_obssPdLevel + dB_u{3.0}, std::get<1>(m_secondaryCcaSensitivityThresholds)));
582
583 // HE PHY: 80 MHz HE PPDU in secondary80 channel (80 MHz) if power above the max between the CCA
584 // sensitivity threshold corresponding to a 80 MHz PPDU that does not occupy the primary 20 MHz
585 // and the OBSS-PD level plus 6 dB
587 m_phy->GetPhyEntity(WIFI_MOD_CLASS_HE),
588 CreateDummyHePpdu(MHz_u{80}, m_phy->GetOperatingChannel()),
590 std::max(m_obssPdLevel + dB_u{6.0}, std::get<2>(m_secondaryCcaSensitivityThresholds)));
591
592 //-----------------------------------------------------------------------------------------------------------------------------------
593
594 // EHT PHY: any signal in primary channel (20 MHz) if power above CCA-ED threshold
596 nullptr,
599
600 // EHT PHY: any signal in secondary channel (20 MHz) if power above CCA-ED threshold
602 nullptr,
605
606 // EHT PHY: any signal in secondary40 channel (40 MHz) if power in any 20 MHz subchannel above
607 // CCA-ED threshold
609 nullptr,
612
613 // EHT PHY: any signal in secondary80 channel (80 MHz) if power in any 20 MHz subchannel above
614 // CCA-ED threshold
616 nullptr,
619
620 //-----------------------------------------------------------------------------------------------------------------------------------
621 // EHT PHY: 20 MHz EHT PPDU in primary channel (20 MHz) if power in primary above CCA
622 // sensitivity threshold
624 CreateDummyEhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
627 // EHT PHY: 40 MHz EHT PPDU in primary channel (20 MHz) if power in primary above CCA
628 // sensitivity threshold
630 CreateDummyEhtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
633
634 // EHT PHY: 80 MHz EHT PPDU in primary channel (20 MHz) if power in primary above CCA
635 // sensitivity threshold
637 CreateDummyEhtPpdu(MHz_u{80}, m_phy->GetOperatingChannel()),
640
641 // EHT PHY: 160 MHz EHT PPDU in primary channel (20 MHz) if power in primary above CCA
642 // sensitivity threshold
644 CreateDummyEhtPpdu(MHz_u{160}, m_phy->GetOperatingChannel()),
647
648 //-----------------------------------------------------------------------------------------------------------------------------------
649
650 // EHT PHY: 20 MHz EHT PPDU in secondary channel (20 MHz) if power above the max between the CCA
651 // sensitivity threshold for Per 20MHz check and the OBSS-PD level
653 CreateDummyEhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
656
657 // EHT PHY: 20 MHz EHT PPDU in secondary40 channel (40 MHz) if power above the max between the
658 // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level
660 CreateDummyEhtPpdu(MHz_u{20}, m_phy->GetOperatingChannel()),
663
664 // EHT PHY: 40 MHz EHT PPDU in secondary40 channel (40 MHz) if power above the max between the
665 // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level
667 CreateDummyEhtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
670
671 // EHT PHY: 20 MHz EHT PPDU in secondary80 channel (80 MHz) if power above the max between the
672 // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level
674 CreateDummyEhtPpdu(MHz_u{80}, m_phy->GetOperatingChannel()),
677
678 // EHT PHY: 40 MHz EHT PPDU in secondary80 channel (80 MHz) if power above the max between the
679 // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level
681 CreateDummyEhtPpdu(MHz_u{40}, m_phy->GetOperatingChannel()),
684
685 // EHT PHY: 80 MHz EHT PPDU in secondary80 channel (80 MHz) if power above the max between the
686 // CCA sensitivity threshold for Per 20MHz check and the OBSS-PD level
688 CreateDummyEhtPpdu(MHz_u{80}, m_phy->GetOperatingChannel()),
691}
692
693void
695{
696 // default attributes
697 m_CcaEdThreshold = dBm_u{-62};
698 m_CcaSensitivity = dBm_u{-82};
699 m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69});
700 m_obssPdLevel = dBm_u{-82};
702 RunOne();
703
704 // default attributes with OBSS-PD level set to -80 dBm
705 m_CcaEdThreshold = dBm_u{-62};
706 m_CcaSensitivity = dBm_u{-82};
707 m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69});
708 m_obssPdLevel = dBm_u{-80};
710 RunOne();
711
712 // default attributes with OBSS-PD level set to -70 dBm
713 m_CcaEdThreshold = dBm_u{-62};
714 m_CcaSensitivity = dBm_u{-82};
715 m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69});
716 m_obssPdLevel = dBm_u{-70};
718 RunOne();
719
720 // CCA-ED set to -65 dBm
721 m_CcaEdThreshold = dBm_u{-65};
722 m_CcaSensitivity = dBm_u{-82};
723 m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69});
724 m_obssPdLevel = dBm_u{-82};
726 RunOne();
727
728 // CCA sensitivity for signals in primary set to -75 dBm
729 m_CcaEdThreshold = dBm_u{-62};
730 m_CcaSensitivity = dBm_u{-75};
731 m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-72}, dBm_u{-72}, dBm_u{-69});
732 m_obssPdLevel = dBm_u{-82};
734 RunOne();
735
736 // custom CCA sensitivities for signals not in primary
737 m_CcaEdThreshold = dBm_u{-62};
738 m_CcaSensitivity = dBm_u{-72};
739 m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-70}, dBm_u{-70}, dBm_u{-70});
740 m_obssPdLevel = dBm_u{-82};
741 m_per20CcaSensitivity = -75.0;
742 RunOne();
743
744 // custom CCA sensitivities for signals not in primary with OBSS-PD level set to -80 dBm
745 m_CcaEdThreshold = dBm_u{-62};
746 m_CcaSensitivity = dBm_u{-72};
747 m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-70}, dBm_u{-70}, dBm_u{-70});
748 m_obssPdLevel = dBm_u{-80};
749 m_per20CcaSensitivity = -69.0;
750 RunOne();
751
752 // custom CCA sensitivities for signals not in primary with OBSS-PD level set to -70 dBm
753 m_CcaEdThreshold = dBm_u{-62};
754 m_CcaSensitivity = dBm_u{-72};
755 m_secondaryCcaSensitivityThresholds = std::make_tuple(dBm_u{-70}, dBm_u{-70}, dBm_u{-70});
756 m_obssPdLevel = dBm_u{-70};
757 m_per20CcaSensitivity = -66.0;
758 RunOne();
759
761}
762
763/**
764 * @ingroup wifi-test
765 * @ingroup tests
766 *
767 * @brief PHY listener for CCA tests
768 */
770{
771 public:
773
774 void NotifyRxStart(Time duration) override
775 {
776 NS_LOG_FUNCTION(this << duration);
777 }
778
779 void NotifyRxEndOk() override
780 {
781 NS_LOG_FUNCTION(this);
782 }
783
784 void NotifyRxEndError(const WifiTxVector& txVector) override
785 {
786 NS_LOG_FUNCTION(this << txVector);
787 }
788
789 void NotifyTxStart(Time duration, dBm_u txPower) override
790 {
791 NS_LOG_FUNCTION(this << duration << txPower);
792 }
793
795 WifiChannelListType channelType,
796 const std::vector<Time>& per20MhzDurations) override
797 {
798 NS_LOG_FUNCTION(this << duration << channelType << per20MhzDurations.size());
799 m_endCcaBusy = Simulator::Now() + duration;
800 m_lastCcaBusyChannelType = channelType;
801 m_lastPer20MhzCcaBusyDurations = per20MhzDurations;
803 }
804
805 void NotifySwitchingStart(Time duration) override
806 {
807 }
808
809 void NotifySleep() override
810 {
811 }
812
813 void NotifyOff() override
814 {
815 }
816
817 void NotifyWakeup() override
818 {
819 }
820
821 void NotifyOn() override
822 {
823 }
824
825 /**
826 * Reset function
827 */
835
836 std::size_t m_notifications{0}; ///< Number of CCA notifications
837 Time m_endCcaBusy{Seconds(0)}; ///< End of the CCA-BUSY duration
839 WIFI_CHANLIST_PRIMARY}; ///< Channel type indication for the last CCA-BUSY notification
840 std::vector<Time>
841 m_lastPer20MhzCcaBusyDurations{}; ///< End of the CCA-BUSY durations per 20 MHz
842};
843
844/**
845 * @ingroup wifi-test
846 * @ingroup tests
847 *
848 * @brief Wifi Phy Threshold Test base class
849 */
851{
852 public:
853 /**
854 * Constructor
855 *
856 * @param standard the standard to use for the test
857 */
859
860 private:
861 void DoSetup() override;
862 void DoRun() override;
863 void DoTeardown() override;
864
865 /**
866 * Send a HE or EHT SU PPDU
867 * @param txPower the transmit power
868 * @param frequency the center frequency the transmitter is operating on
869 * @param bandwidth the bandwidth to use for the transmission
870 */
871 void SendSuPpdu(dBm_u txPower, MHz_u frequency, MHz_u bandwidth);
872
873 /**
874 * Start to generate a signal
875 * @param signalGenerator the signal generator to use
876 * @param txPower the transmit power
877 * @param frequency the center frequency of the signal to send
878 * @param bandwidth the bandwidth of the signal to send
879 * @param duration the duration of the signal
880 */
881 void StartSignal(Ptr<WaveformGenerator> signalGenerator,
882 dBm_u txPower,
883 MHz_u frequency,
884 MHz_u bandwidth,
885 Time duration);
886 /**
887 * Stop to generate a signal
888 * @param signalGenerator the signal generator to use
889 */
890 void StopSignal(Ptr<WaveformGenerator> signalGenerator);
891
892 /**
893 * Check the PHY state
894 * @param expectedState the expected state of the PHY
895 */
896 void CheckPhyState(WifiPhyState expectedState);
897 /// @copydoc CheckPhyState
898 void DoCheckPhyState(WifiPhyState expectedState);
899
900 /**
901 * Check the last CCA-BUSY notification
902 * @param expectedEndTime the expected CCA-BUSY end time
903 * @param expectedChannelType the expected channel type
904 * @param expectedPer20MhzDurations the expected per-20 MHz CCA-BUSY durations
905 */
906 void CheckLastCcaBusyNotification(Time expectedEndTime,
907 WifiChannelListType expectedChannelType,
908 const std::vector<Time>& expectedPer20MhzDurations);
909
910 /**
911 * Log scenario description
912 *
913 * @param log the scenario description to add to log
914 */
915 void LogScenario(const std::string& log) const;
916
917 /**
918 * structure that holds information to generate signals
919 */
921 {
922 dBm_u power{0.0}; //!< transmit power to use
923 Time startTime{Seconds(0)}; //!< time at which transmission will be started
924 Time duration{Seconds(0)}; //!< the duration of the transmission
925 MHz_u centerFreq{0}; //!< center frequency to use
926 MHz_u bandwidth{0}; //!< bandwidth to use
927 };
928
929 /**
930 * structure that holds information to generate PPDUs
931 */
933 {
934 dBm_u power{0.0}; //!< transmit power to use
935 Time startTime{Seconds(0)}; //!< time at which transmission will be started
936 MHz_u centerFreq{0}; //!< center frequency to use
937 MHz_u bandwidth{0}; //!< bandwidth to use
938 };
939
940 /**
941 * structure that holds information to perform PHY state check
942 */
944 {
945 Time timePoint{Seconds(0)}; //!< time at which the check will performed
946 WifiPhyState expectedPhyState{WifiPhyState::IDLE}; //!< expected PHY state
947 };
948
949 /**
950 * structure that holds information to perform CCA check
951 */
953 {
954 Time timePoint{Seconds(0)}; //!< time at which the check will performed
955 Time expectedCcaEndTime{Seconds(0)}; //!< expected CCA_BUSY end time
958 std::vector<Time> expectedPer20MhzDurations{}; //!< expected per-20 MHz CCA duration
959 };
960
961 /**
962 * Schedule test to perform.
963 * @param delay the reference delay to schedule the events
964 * @param generatedSignals the vector of signals to be generated
965 * @param generatedPpdus the vector of PPDUs to be generated
966 * @param stateCheckpoints the vector of PHY state checks
967 * @param ccaCheckpoints the vector of PHY CCA checks
968 */
969 void ScheduleTest(Time delay,
970 const std::vector<TxSignalInfo>& generatedSignals,
971 const std::vector<TxPpduInfo>& generatedPpdus,
972 const std::vector<StateCheckPoint>& stateCheckpoints,
973 const std::vector<CcaCheckPoint>& ccaCheckpoints);
974
975 /**
976 * Reset function
977 */
978 void Reset();
979
980 /**
981 * Run one function
982 */
983 void RunOne();
984
985 WifiStandard m_standard; ///< The standard to use for the test
986
987 Ptr<SpectrumWifiPhy> m_rxPhy; ///< PHY object of the receiver
988 Ptr<SpectrumWifiPhy> m_txPhy; ///< PHY object of the transmitter
989
990 std::vector<Ptr<WaveformGenerator>> m_signalGenerators; ///< Generators of non-wifi signals
991 std::size_t
992 m_numSignalGenerators; ///< The number of non-wifi signals generators needed for the test
993
994 std::shared_ptr<CcaTestPhyListener>
995 m_rxPhyStateListener; ///< Listener for PHY state transitions
996
997 MHz_u m_frequency; ///< Operating frequency
998 MHz_u m_channelWidth; ///< Operating channel width
999};
1000
1002 : TestCase("Wi-Fi PHY CCA indication test for " + ((standard == WIFI_STANDARD_80211ax)
1003 ? std::string("802.11ax")
1004 : std::string("802.11be"))),
1005 m_standard{standard},
1006 m_numSignalGenerators{2},
1007 m_frequency{P20_CENTER_FREQUENCY},
1008 m_channelWidth{MHz_u{20}}
1009{
1010}
1011
1012void
1014 dBm_u txPower,
1015 MHz_u frequency,
1016 MHz_u bandwidth,
1017 Time duration)
1018{
1019 NS_LOG_FUNCTION(this << signalGenerator << txPower << frequency << bandwidth << duration);
1020
1021 BandInfo bandInfo;
1022 bandInfo.fc = MHzToHz(frequency);
1023 bandInfo.fl = bandInfo.fc - MHzToHz(bandwidth / 2);
1024 bandInfo.fh = bandInfo.fc + MHzToHz(bandwidth / 2);
1025 Bands bands;
1026 bands.push_back(bandInfo);
1027
1028 Ptr<SpectrumModel> spectrumSignal = Create<SpectrumModel>(bands);
1029 Ptr<SpectrumValue> signalPsd = Create<SpectrumValue>(spectrumSignal);
1030 *signalPsd = DbmToW(txPower) / MHzToHz(bandwidth);
1031
1032 signalGenerator->SetTxPowerSpectralDensity(signalPsd);
1033 signalGenerator->SetPeriod(duration);
1034 signalGenerator->Start();
1035 Simulator::Schedule(duration, &WifiPhyCcaIndicationTest::StopSignal, this, signalGenerator);
1036}
1037
1038void
1040{
1041 NS_LOG_FUNCTION(this << signalGenerator);
1042 signalGenerator->Stop();
1043}
1044
1045void
1047{
1048 NS_LOG_FUNCTION(this << txPower);
1049
1050 auto channelNum =
1052 ->number;
1053 m_txPhy->SetOperatingChannel(
1054 WifiPhy::ChannelTuple{channelNum, bandwidth, WIFI_PHY_BAND_5GHZ, 0});
1055
1056 const auto mcs =
1058 const auto preamble =
1060 WifiTxVector txVector{mcs, 0, preamble, NanoSeconds(800), 1, 1, 0, bandwidth, false};
1061 Ptr<Packet> pkt = Create<Packet>(1000);
1062 WifiMacHeader hdr;
1064 hdr.SetQosTid(0);
1065 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
1066
1067 m_txPhy->SetTxPowerStart(txPower);
1068 m_txPhy->SetTxPowerEnd(txPower);
1069
1070 m_txPhy->Send(psdu, txVector);
1071}
1072
1073void
1075{
1076 // This is needed to make sure PHY state will be checked as the last event if a state change
1077 // occurred at the exact same time as the check
1079}
1080
1081void
1083{
1084 WifiPhyState currentState;
1085 PointerValue ptr;
1086 m_rxPhy->GetAttribute("State", ptr);
1088 currentState = state->GetState();
1089 NS_TEST_ASSERT_MSG_EQ(currentState,
1090 expectedState,
1091 "PHY State " << currentState << " does not match expected state "
1092 << expectedState << " at " << Simulator::Now());
1093}
1094
1095void
1097 Time expectedEndTime,
1098 WifiChannelListType expectedChannelType,
1099 const std::vector<Time>& expectedPer20MhzDurations)
1100{
1102 expectedEndTime,
1103 "PHY CCA end time " << m_rxPhyStateListener->m_endCcaBusy
1104 << " does not match expected time " << expectedEndTime
1105 << " at " << Simulator::Now());
1107 expectedChannelType,
1108 "PHY CCA-BUSY for " << m_rxPhyStateListener->m_lastCcaBusyChannelType
1109 << " does not match expected channel type "
1110 << expectedChannelType << " at " << Simulator::Now());
1112 expectedPer20MhzDurations.size(),
1113 "PHY CCA-BUSY per-20 MHz durations does not match expected vector"
1114 << " at " << Simulator::Now());
1115 for (std::size_t i = 0; i < expectedPer20MhzDurations.size(); ++i)
1116 {
1118 expectedPer20MhzDurations.at(i),
1119 "PHY CCA-BUSY per-20 MHz duration at index "
1120 << i << " does not match expected duration at "
1121 << Simulator::Now());
1122 }
1123}
1124
1125void
1126WifiPhyCcaIndicationTest::LogScenario(const std::string& log) const
1127{
1128 NS_LOG_INFO(log);
1129}
1130
1131void
1133 const std::vector<TxSignalInfo>& generatedSignals,
1134 const std::vector<TxPpduInfo>& generatedPpdus,
1135 const std::vector<StateCheckPoint>& stateCheckpoints,
1136 const std::vector<CcaCheckPoint>& ccaCheckpoints)
1137{
1138 for (const auto& generatedPpdu : generatedPpdus)
1139 {
1140 Simulator::Schedule(delay + generatedPpdu.startTime,
1142 this,
1143 generatedPpdu.power,
1144 generatedPpdu.centerFreq,
1145 generatedPpdu.bandwidth);
1146 }
1147
1148 std::size_t index = 0;
1149 for (const auto& generatedSignal : generatedSignals)
1150 {
1151 Simulator::Schedule(delay + generatedSignal.startTime,
1153 this,
1154 m_signalGenerators.at(index++),
1155 generatedSignal.power,
1156 generatedSignal.centerFreq,
1157 generatedSignal.bandwidth,
1158 generatedSignal.duration);
1159 }
1160
1161 for (const auto& checkpoint : ccaCheckpoints)
1162 {
1163 Simulator::Schedule(delay + checkpoint.timePoint,
1165 this,
1166 Simulator::Now() + delay + checkpoint.expectedCcaEndTime,
1167 checkpoint.expectedChannelListType,
1168 checkpoint.expectedPer20MhzDurations);
1169 }
1170
1171 for (const auto& checkpoint : stateCheckpoints)
1172 {
1173 Simulator::Schedule(delay + checkpoint.timePoint,
1175 this,
1176 checkpoint.expectedPhyState);
1177 }
1178
1180}
1181
1182void
1187
1188void
1190{
1191 // WifiHelper::EnableLogComponents ();
1192 // LogComponentEnable ("WifiPhyCcaTest", LOG_LEVEL_ALL);
1193
1195
1196 Ptr<Node> rxNode = CreateObject<Node>();
1198 rxDev->SetStandard(m_standard);
1199 auto vhtConfiguration = CreateObject<VhtConfiguration>();
1200 rxDev->SetVhtConfiguration(vhtConfiguration);
1202 {
1203 auto ehtConfiguration = CreateObject<EhtConfiguration>();
1204 rxDev->SetEhtConfiguration(ehtConfiguration);
1205 }
1207 m_rxPhyStateListener = std::make_unique<CcaTestPhyListener>();
1208 m_rxPhy->RegisterListener(m_rxPhyStateListener);
1210 m_rxPhy->SetInterferenceHelper(rxInterferenceHelper);
1212 m_rxPhy->SetErrorRateModel(rxErrorModel);
1213 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
1215 m_rxPhy->SetPreambleDetectionModel(preambleDetectionModel);
1216 m_rxPhy->AddChannel(spectrumChannel);
1217 m_rxPhy->ConfigureStandard(m_standard);
1218 m_rxPhy->SetDevice(rxDev);
1219 rxDev->SetPhy(m_rxPhy);
1220 rxNode->AddDevice(rxDev);
1221
1222 Ptr<Node> txNode = CreateObject<Node>();
1225 m_txPhy->SetAttribute("ChannelSwitchDelay", TimeValue(Seconds(0)));
1227 m_txPhy->SetInterferenceHelper(txInterferenceHelper);
1229 m_txPhy->SetErrorRateModel(txErrorModel);
1230 m_txPhy->AddChannel(spectrumChannel);
1231 m_txPhy->ConfigureStandard(m_standard);
1232 m_txPhy->SetDevice(txDev);
1233 txDev->SetPhy(m_txPhy);
1234 txNode->AddDevice(txDev);
1235
1236 for (std::size_t i = 0; i < m_numSignalGenerators; ++i)
1237 {
1238 Ptr<Node> signalGeneratorNode = CreateObject<Node>();
1239 Ptr<NonCommunicatingNetDevice> signalGeneratorDev =
1242 signalGenerator->SetDevice(signalGeneratorDev);
1243 signalGenerator->SetChannel(spectrumChannel);
1244 signalGenerator->SetDutyCycle(1);
1245 signalGeneratorNode->AddDevice(signalGeneratorDev);
1246 m_signalGenerators.push_back(signalGenerator);
1247 }
1248}
1249
1250void
1252{
1255 int64_t streamNumber = 0;
1256 m_rxPhy->AssignStreams(streamNumber);
1257 m_txPhy->AssignStreams(streamNumber);
1258
1259 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
1262 m_standard,
1264 ->number;
1265
1266 m_rxPhy->SetOperatingChannel(
1268 m_txPhy->SetOperatingChannel(
1270
1271 const auto& ppduDurations =
1273
1274 std::vector<Time> expectedPer20MhzCcaBusyDurations{};
1275 Time delay;
1277 delay += Seconds(1);
1278
1279 //----------------------------------------------------------------------------------------------------------------------------------
1280 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported when a signal below the
1281 // energy detection threshold occupies P20
1282 Simulator::Schedule(delay,
1284 this,
1285 "Reception of a signal that occupies P20 below ED threshold");
1287 delay,
1288 {{dBm_u{-65}, MicroSeconds(0), MicroSeconds(100), P20_CENTER_FREQUENCY, MHz_u{20}}},
1289 {},
1290 {
1291 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1292 {MicroSeconds(100) - smallDelta,
1293 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1294 {MicroSeconds(100) + smallDelta,
1295 WifiPhyState::IDLE} // IDLE just after the transmission ends
1296 },
1297 {});
1298 delay += Seconds(1);
1299
1300 //----------------------------------------------------------------------------------------------------------------------------------
1301 // Verify PHY state is CCA-BUSY as long as a 20 MHz signal above the energy detection threshold
1302 // occupies P20
1303 Simulator::Schedule(delay,
1305 this,
1306 "Reception of signal that occupies P20 above ED threshold");
1308 delay,
1309 {{dBm_u{-60.0}, MicroSeconds(0), MicroSeconds(100), P20_CENTER_FREQUENCY, MHz_u{20}}},
1310 {},
1311 {
1312 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCcaTimeWithDelta
1313 {MicroSeconds(100) - smallDelta,
1314 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1315 {MicroSeconds(100) + smallDelta,
1316 WifiPhyState::IDLE} // IDLE just after the transmission ends
1317 },
1318 {{MicroSeconds(100) - smallDelta,
1319 MicroSeconds(100),
1321 ((m_channelWidth > MHz_u{20})
1322 ? ((m_channelWidth > MHz_u{40})
1323 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(100),
1324 MicroSeconds(0),
1325 MicroSeconds(0),
1326 MicroSeconds(0),
1327 MicroSeconds(0),
1328 MicroSeconds(0),
1329 MicroSeconds(0),
1330 MicroSeconds(0)}
1331 : std::vector<Time>{MicroSeconds(100),
1332 MicroSeconds(0),
1333 MicroSeconds(0),
1334 MicroSeconds(0)})
1335 : std::vector<Time>{MicroSeconds(100), MicroSeconds(0)})
1336 : std::vector<Time>{})}});
1337 delay += Seconds(1);
1338
1339 //----------------------------------------------------------------------------------------------------------------------------------
1340 // Verify PHY state is CCA-BUSY as long as the sum of 20 MHz signals occupying P20 is above the
1341 // energy detection threshold
1342 Simulator::Schedule(delay,
1344 this,
1345 "Reception of two 20 MHz signals that occupies P20 below ED threshold with "
1346 "sum above ED threshold");
1348 delay,
1349 {{dBm_u{-64.0}, MicroSeconds(0), MicroSeconds(100), P20_CENTER_FREQUENCY, MHz_u{20}},
1350 {dBm_u{-65.0}, MicroSeconds(50), MicroSeconds(200), P20_CENTER_FREQUENCY, MHz_u{20}}},
1351 {},
1352 {
1354 WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCcaTimeWithDelta
1355 {MicroSeconds(100) - smallDelta,
1356 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1357 {MicroSeconds(100) + smallDelta,
1358 WifiPhyState::IDLE} // IDLE just after the transmission ends
1359 },
1360 {{MicroSeconds(100) - smallDelta,
1361 MicroSeconds(100),
1363 ((m_channelWidth > MHz_u{20})
1364 ? ((m_channelWidth > MHz_u{40})
1365 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(50),
1366 MicroSeconds(0),
1367 MicroSeconds(0),
1368 MicroSeconds(0),
1369 MicroSeconds(0),
1370 MicroSeconds(0),
1371 MicroSeconds(0),
1372 MicroSeconds(0)}
1373 : std::vector<Time>{MicroSeconds(50),
1374 MicroSeconds(0),
1375 MicroSeconds(0),
1376 MicroSeconds(0)})
1377 : std::vector<Time>{MicroSeconds(50), MicroSeconds(0)})
1378 : std::vector<Time>{})}});
1379 delay += Seconds(1);
1380
1381 //----------------------------------------------------------------------------------------------------------------------------------
1382 // Verify PHY state stays IDLE when a 20 MHz PPDU with received power below the
1383 // corresponding CCA sensitivity threshold occupies P20
1385 delay,
1387 this,
1388 "Reception of a 20 MHz PPDU that occupies P20 below CCA sensitivity threshold");
1389 ScheduleTest(delay,
1390 {},
1391 {{dBm_u{-85}, MicroSeconds(0), P20_CENTER_FREQUENCY, MHz_u{20}}},
1392 {
1393 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1394 {ppduDurations.at(MHz_u{20}) - smallDelta,
1395 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1396 {ppduDurations.at(MHz_u{20}) + smallDelta,
1397 WifiPhyState::IDLE} // IDLE just after the transmission ends
1398 },
1399 {});
1400 delay += Seconds(1);
1401
1402 //----------------------------------------------------------------------------------------------------------------------------------
1403 // Verify PHY state transitions to CCA-BUSY when an PPDU with received power above the CCA
1404 // sensitivity threshold occupies P20. The per20Bitmap should indicate idle on the primary 20
1405 // MHz subchannel because received power is below -72 dBm (27.3.20.6.5).
1407 delay,
1409 this,
1410 "Reception of a 20 MHz PPDU that occupies P20 above CCA sensitivity threshold");
1412 delay,
1413 {},
1414 {{dBm_u{-80}, MicroSeconds(0), P20_CENTER_FREQUENCY, MHz_u{20}}},
1415 {
1416 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCcaTimeWithDelta
1417 {ppduDurations.at(MHz_u{20}) - smallDelta,
1418 WifiPhyState::RX}, // RX just before the transmission ends
1419 {ppduDurations.at(MHz_u{20}) + smallDelta,
1420 WifiPhyState::IDLE} // IDLE just after the transmission ends
1421 },
1423 MicroSeconds(16),
1425 ((m_channelWidth > MHz_u{20})
1426 ? ((m_channelWidth > MHz_u{40})
1427 ? ((m_channelWidth > MHz_u{80})
1428 ? std::vector<Time>{Seconds(0),
1429 Seconds(0),
1430 Seconds(0),
1431 Seconds(0),
1432 Seconds(0),
1433 Seconds(0),
1434 Seconds(0),
1435 Seconds(0)}
1436 : std::vector<Time>{Seconds(0), Seconds(0), Seconds(0), Seconds(0)})
1437 : std::vector<Time>{Seconds(0), Seconds(0)})
1438 : std::vector<Time>{})}});
1439 delay += Seconds(1);
1440
1441 //----------------------------------------------------------------------------------------------------------------------------------
1442 // Verify PHY state stays IDLE when a 40 MHz PPDU with received power below the CCA
1443 // sensitivity threshold occupies P40
1445 delay,
1447 this,
1448 "Reception of a 40 MHz PPDU that occupies P20 below CCA sensitivity threshold");
1449 ScheduleTest(delay,
1450 {},
1451 {{dBm_u{-80}, MicroSeconds(0), P40_CENTER_FREQUENCY, MHz_u{40}}},
1452 {
1453 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1454 {ppduDurations.at(MHz_u{40}) - smallDelta,
1455 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1456 {ppduDurations.at(MHz_u{40}) + smallDelta,
1457 WifiPhyState::IDLE} // IDLE just after the transmission ends
1458 },
1459 {});
1460 delay += Seconds(1);
1461
1462 //----------------------------------------------------------------------------------------------------------------------------------
1463 // Verify PHY state transitions to CCA-BUSY when an PPDU with received power above the CCA
1464 // sensitivity threshold occupies P40. The per20Bitmap should indicate idle on the primary 20
1465 // MHz subchannel because received power is below -72 dBm (27.3.20.6.5).
1467 delay,
1469 this,
1470 "Reception of a 40 MHz PPDU that occupies P40 above CCA sensitivity threshold");
1472 delay,
1473 {},
1474 {{dBm_u{-75}, MicroSeconds(0), P40_CENTER_FREQUENCY, MHz_u{40}}},
1475 {
1476 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCcaTimeWithDelta
1477 {ppduDurations.at(MHz_u{40}) - smallDelta,
1478 (m_channelWidth > MHz_u{20})
1479 ? WifiPhyState::RX
1480 : WifiPhyState::CCA_BUSY}, // RX or IDLE just before the transmission ends
1481 {ppduDurations.at(MHz_u{40}) + smallDelta,
1482 WifiPhyState::IDLE} // IDLE just after the transmission ends
1483 },
1485 MicroSeconds(16),
1487 ((m_channelWidth > MHz_u{20})
1488 ? ((m_channelWidth > MHz_u{40})
1489 ? ((m_channelWidth > MHz_u{80})
1490 ? std::vector<Time>{Seconds(0),
1491 Seconds(0),
1492 Seconds(0),
1493 Seconds(0),
1494 Seconds(0),
1495 Seconds(0),
1496 Seconds(0),
1497 Seconds(0)}
1498 : std::vector<Time>{Seconds(0), Seconds(0), Seconds(0), Seconds(0)})
1499 : std::vector<Time>{Seconds(0), Seconds(0)})
1500 : std::vector<Time>{})}});
1501 delay += Seconds(1);
1502
1503 if (m_channelWidth > MHz_u{20})
1504 {
1505 //----------------------------------------------------------------------------------------------------------------------------------
1506 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported when a 20 MHz signal
1507 // below the energy detection threshold occupies S20
1508 Simulator::Schedule(delay,
1510 this,
1511 "Reception of a 20 MHz signal that occupies S20 below ED threshold");
1513 delay,
1514 {{dBm_u{-65}, MicroSeconds(0), MicroSeconds(100), S20_CENTER_FREQUENCY, MHz_u{20}}},
1515 {},
1516 {
1517 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1518 {MicroSeconds(100) - smallDelta,
1519 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1520 {MicroSeconds(100) + smallDelta,
1521 WifiPhyState::IDLE} // IDLE just after the transmission ends
1522 },
1523 {});
1524 delay += Seconds(1);
1525
1526 //----------------------------------------------------------------------------------------------------------------------------------
1527 // Verify PHY state stays IDLE but CCA-BUSY indication is reported when a 20 MHz signal
1528 // above the energy detection threshold occupies S20
1529 Simulator::Schedule(delay,
1531 this,
1532 "Reception of a 20 MHz signal that occupies S20 above ED threshold");
1534 delay,
1535 {{dBm_u{-60}, MicroSeconds(0), MicroSeconds(100), S20_CENTER_FREQUENCY, MHz_u{20}}},
1536 {},
1537 {
1538 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1539 {MicroSeconds(100) - smallDelta,
1540 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1541 {MicroSeconds(100) + smallDelta,
1542 WifiPhyState::IDLE} // IDLE just after the transmission ends
1543 },
1544 {{MicroSeconds(100) - smallDelta,
1545 MicroSeconds(100),
1547 ((m_channelWidth > MHz_u{40})
1548 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
1549 MicroSeconds(100),
1550 MicroSeconds(0),
1551 MicroSeconds(0),
1552 MicroSeconds(0),
1553 MicroSeconds(0),
1554 MicroSeconds(0),
1555 MicroSeconds(0)}
1556 : std::vector<Time>{MicroSeconds(0),
1557 MicroSeconds(100),
1558 MicroSeconds(0),
1559 MicroSeconds(0)})
1560 : std::vector<Time>{MicroSeconds(0), MicroSeconds(100)})}});
1561 delay += Seconds(1);
1562
1563 //----------------------------------------------------------------------------------------------------------------------------------
1564 // Verify PHY state is CCA-BUSY as long as a 40 MHz signal above the energy detection
1565 // threshold occupies P40
1566 Simulator::Schedule(delay,
1568 this,
1569 "Reception of a 40 MHz signal that occupies P40 above ED threshold");
1571 delay,
1572 {{dBm_u{-55}, MicroSeconds(0), MicroSeconds(100), P40_CENTER_FREQUENCY, MHz_u{40}}},
1573 {},
1574 {
1575 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCcaTimeWithDelta
1576 {MicroSeconds(100) - smallDelta,
1577 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1578 {MicroSeconds(100) + smallDelta,
1579 WifiPhyState::IDLE} // IDLE just after the transmission ends
1580 },
1581 {{MicroSeconds(100) - smallDelta,
1582 MicroSeconds(100),
1584 ((m_channelWidth > MHz_u{40})
1585 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(100),
1586 MicroSeconds(100),
1587 MicroSeconds(0),
1588 MicroSeconds(0),
1589 MicroSeconds(0),
1590 MicroSeconds(0),
1591 MicroSeconds(0),
1592 MicroSeconds(0)}
1593 : std::vector<Time>{MicroSeconds(100),
1594 MicroSeconds(100),
1595 MicroSeconds(0),
1596 MicroSeconds(0)})
1597 : std::vector<Time>{MicroSeconds(100), MicroSeconds(100)})}});
1598 delay += Seconds(1);
1599
1600 //----------------------------------------------------------------------------------------------------------------------------------
1601 // Verify PHY notifies CCA-BUSY for the primary channel while the secondary channel was
1602 // already in CCA-BUSY state
1603 Simulator::Schedule(delay,
1605 this,
1606 "Reception of a signal that occupies S20 followed by the reception of "
1607 "another signal that occupies P20");
1609 delay,
1611 {dBm_u{-60}, MicroSeconds(50), MicroSeconds(100), P20_CENTER_FREQUENCY, MHz_u{20}}},
1612 {},
1613 {
1615 WifiPhyState::IDLE}, // state of primary stays idle after aCcaTimeWithDelta
1617 WifiPhyState::CCA_BUSY}, // state of primary is CCA-BUSY after aCcaTimeWithDelta
1618 // that followed the second transmission
1619 {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
1620 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
1621 {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
1622 WifiPhyState::IDLE} // IDLE just after the transmission ends
1623 },
1624 {{aCcaTimeWithDelta, // notification upon reception of the first signal
1625 MicroSeconds(100),
1627 ((m_channelWidth > MHz_u{40})
1628 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
1629 MicroSeconds(100),
1630 MicroSeconds(0),
1631 MicroSeconds(0),
1632 MicroSeconds(0),
1633 MicroSeconds(0),
1634 MicroSeconds(0),
1635 MicroSeconds(0)}
1636 : std::vector<Time>{MicroSeconds(0),
1637 MicroSeconds(100),
1638 MicroSeconds(0),
1639 MicroSeconds(0)})
1640 : std::vector<Time>{MicroSeconds(0), MicroSeconds(100)})},
1641 {MicroSeconds(50) +
1642 aCcaTimeWithDelta, // notification upon reception of the second signal
1643 MicroSeconds(50) + MicroSeconds(100),
1645 ((m_channelWidth > MHz_u{40})
1646 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(100),
1647 MicroSeconds(50),
1648 MicroSeconds(0),
1649 MicroSeconds(0),
1650 MicroSeconds(0),
1651 MicroSeconds(0),
1652 MicroSeconds(0),
1653 MicroSeconds(0)}
1654 : std::vector<Time>{MicroSeconds(100),
1655 MicroSeconds(50),
1656 MicroSeconds(0),
1657 MicroSeconds(0)})
1658 : std::vector<Time>{MicroSeconds(100), MicroSeconds(50)})}});
1659 delay += Seconds(1);
1660
1661 //----------------------------------------------------------------------------------------------------------------------------------
1662 // Verify PHY updates per-20 MHz CCA durations if a signal arrives on the secondary channel
1663 // while primary is CCA-BUSY
1664 Simulator::Schedule(delay,
1666 this,
1667 "Reception of a signal that occupies P20 followed by the reception of "
1668 "another signal that occupies S20");
1670 delay,
1672 {dBm_u{-60}, MicroSeconds(50), MicroSeconds(100), S20_CENTER_FREQUENCY, MHz_u{20}}},
1673 {},
1674 {
1675 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCcaTimeWithDelta
1677 WifiPhyState::CCA_BUSY}, // state of primary is still CCA-BUSY after
1678 // aCcaTimeWithDelta that followed the second transmission
1679 {MicroSeconds(100) - smallDelta,
1680 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the first transmission ends
1681 {MicroSeconds(100) + smallDelta,
1682 WifiPhyState::IDLE} // IDLE just after the first transmission ends
1683 },
1684 {{aCcaTimeWithDelta, // notification upon reception of the first signal
1685 MicroSeconds(100),
1687 ((m_channelWidth > MHz_u{40})
1688 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(100),
1689 MicroSeconds(0),
1690 MicroSeconds(0),
1691 MicroSeconds(0),
1692 MicroSeconds(0),
1693 MicroSeconds(0),
1694 MicroSeconds(0),
1695 MicroSeconds(0)}
1696 : std::vector<Time>{MicroSeconds(100),
1697 MicroSeconds(0),
1698 MicroSeconds(0),
1699 MicroSeconds(0)})
1700 : std::vector<Time>{MicroSeconds(100), MicroSeconds(0)})},
1701 {MicroSeconds(50) +
1702 aCcaTimeWithDelta, // notification upon reception of the second signal
1703 MicroSeconds(100),
1705 ((m_channelWidth > MHz_u{40})
1706 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(50),
1707 MicroSeconds(100),
1708 MicroSeconds(0),
1709 MicroSeconds(0),
1710 MicroSeconds(0),
1711 MicroSeconds(0),
1712 MicroSeconds(0),
1713 MicroSeconds(0)}
1714 : std::vector<Time>{MicroSeconds(50),
1715 MicroSeconds(100),
1716 MicroSeconds(0),
1717 MicroSeconds(0)})
1718 : std::vector<Time>{MicroSeconds(50), MicroSeconds(100)})}});
1719 delay += Seconds(1);
1720
1721 //----------------------------------------------------------------------------------------------------------------------------------
1722 // Verify PHY state stays IDLE when a 20 MHz PPDU with received power below the CCA
1723 // sensitivity threshold occupies S40
1725 delay,
1727 this,
1728 "Reception of a 20 MHz PPDU that occupies S20 below CCA sensitivity threshold");
1729 ScheduleTest(delay,
1730 {},
1731 {{dBm_u{-75}, MicroSeconds(0), S20_CENTER_FREQUENCY, MHz_u{20}}},
1732 {
1733 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1734 {ppduDurations.at(MHz_u{20}) - smallDelta,
1735 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1736 {ppduDurations.at(MHz_u{20}) + smallDelta,
1737 WifiPhyState::IDLE} // IDLE just after the transmission ends
1738 },
1739 {});
1740 delay += Seconds(1);
1741
1742 //----------------------------------------------------------------------------------------------------------------------------------
1743 // Verify PHY state stays IDLE but CCA-BUSY indication is reported when a 20 MHz PPDU
1744 // with received power above the CCA sensitivity threshold occupies S20
1746 delay,
1748 this,
1749 "Reception of a 20 MHz PPDU that occupies S20 above CCA sensitivity threshold");
1751 delay,
1752 {},
1753 {{dBm_u{-70}, MicroSeconds(0), S20_CENTER_FREQUENCY, MHz_u{20}}},
1754 {
1755 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1756 {ppduDurations.at(MHz_u{20}) - smallDelta,
1757 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1758 {ppduDurations.at(MHz_u{20}) + smallDelta,
1759 WifiPhyState::IDLE} // IDLE just after the transmission ends
1760 },
1762 ppduDurations.at(MHz_u{20}),
1764 ((m_channelWidth > MHz_u{40})
1765 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{NanoSeconds(0),
1766 ppduDurations.at(MHz_u{20}),
1767 NanoSeconds(0),
1768 NanoSeconds(0),
1769 NanoSeconds(0),
1770 NanoSeconds(0),
1771 NanoSeconds(0),
1772 NanoSeconds(0)}
1773 : std::vector<Time>{NanoSeconds(0),
1774 ppduDurations.at(MHz_u{20}),
1775 NanoSeconds(0),
1776 NanoSeconds(0)})
1777 : std::vector<Time>{NanoSeconds(0), ppduDurations.at(MHz_u{20})})}});
1778 delay += Seconds(1);
1779
1780 //----------------------------------------------------------------------------------------------------------------------------------
1781 // Verify PHY state stays IDLE but CCA-BUSY indication is still reported as long as a signal
1782 // above the energy detection threshold occupies the S20 while a 40 MHz PPDU below the CCA
1783 // sensitivity threshold is received on P40.
1785 delay,
1787 this,
1788 "Reception of a 20 MHz signal that occupies S20 above ED threshold followed by a 40 "
1789 "MHz PPDU that occupies P40 below CCA sensitivity threshold");
1791 delay,
1792 {{dBm_u{-60},
1793 MicroSeconds(0),
1794 MicroSeconds(100),
1796 MHz_u{20}}}, // signal on S20 above threshold
1797 {{dBm_u{-80},
1798 MicroSeconds(50),
1800 MHz_u{40}}}, // PPDU on P40 below threshold
1801 {
1802 {MicroSeconds(50) + aCcaTimeWithDelta, WifiPhyState::IDLE}, // PHY state stays IDLE
1803 },
1804 {{MicroSeconds(50) - smallDelta,
1805 MicroSeconds(100),
1807 ((m_channelWidth > MHz_u{20})
1808 ? ((m_channelWidth > MHz_u{40})
1809 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
1810 MicroSeconds(100),
1811 MicroSeconds(0),
1812 MicroSeconds(0),
1813 MicroSeconds(0),
1814 MicroSeconds(0),
1815 MicroSeconds(0),
1816 MicroSeconds(0)}
1817 : std::vector<Time>{MicroSeconds(0),
1818 MicroSeconds(100),
1819 MicroSeconds(0),
1820 MicroSeconds(0)})
1821 : std::vector<Time>{MicroSeconds(0), MicroSeconds(100)})
1822 : std::vector<Time>{})},
1823 {MicroSeconds(100) - smallDelta,
1824 MicroSeconds(100),
1826 ((m_channelWidth > MHz_u{40})
1827 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
1828 MicroSeconds(46),
1829 MicroSeconds(0),
1830 MicroSeconds(0),
1831 MicroSeconds(0),
1832 MicroSeconds(0),
1833 MicroSeconds(0),
1834 MicroSeconds(0)}
1835 : std::vector<Time>{MicroSeconds(0),
1836 MicroSeconds(46),
1837 MicroSeconds(0),
1838 MicroSeconds(0)})
1839 : std::vector<Time>{MicroSeconds(0), MicroSeconds(46)})}});
1840 delay += Seconds(1);
1841 }
1842
1843 if (m_channelWidth > MHz_u{40})
1844 {
1845 //----------------------------------------------------------------------------------------------------------------------------------
1846 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported when a signal below
1847 // the energy detection threshold occupies S40
1848 Simulator::Schedule(delay,
1850 this,
1851 "Reception of a 20 MHz signal that occupies the first subchannel of "
1852 "S40 below ED threshold");
1853 ScheduleTest(delay,
1854 {{dBm_u{-65},
1855 MicroSeconds(0),
1856 MicroSeconds(100),
1858 MHz_u{20}}},
1859 {},
1860 {
1861 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1862 {MicroSeconds(100) - smallDelta,
1863 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1864 {MicroSeconds(100) + smallDelta,
1865 WifiPhyState::IDLE} // IDLE just after the transmission ends
1866 },
1867 {});
1868 delay += Seconds(1);
1869
1870 //----------------------------------------------------------------------------------------------------------------------------------
1871 // Verify PHY notifies CCA-BUSY for the S40 as long as a signal above the energy detection
1872 // threshold occupies the first 20 MHz subchannel of the S40: 27.3.20.6.4: Any signal within
1873 // the secondary 40 MHz channel at or above a threshold of –59 dBm within a period of
1874 // aCcaTimeWithDelta after the signal arrives at the receiver’s antenna(s).
1875 Simulator::Schedule(delay,
1877 this,
1878 "Reception of a 20 MHz signal that occupies the first subchannel of "
1879 "S40 above ED threshold");
1880 ScheduleTest(delay,
1881 {{dBm_u{-55},
1882 MicroSeconds(0),
1883 MicroSeconds(100),
1885 MHz_u{20}}},
1886 {},
1887 {
1888 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1889 {MicroSeconds(100) - smallDelta,
1890 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1891 {MicroSeconds(100) + smallDelta,
1892 WifiPhyState::IDLE} // IDLE just after the transmission ends
1893 },
1894 {{MicroSeconds(100) - smallDelta,
1895 MicroSeconds(100),
1897 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
1898 MicroSeconds(0),
1899 MicroSeconds(100),
1900 MicroSeconds(0),
1901 MicroSeconds(0),
1902 MicroSeconds(0),
1903 MicroSeconds(0),
1904 MicroSeconds(0)}
1905 : std::vector<Time>{MicroSeconds(0),
1906 MicroSeconds(0),
1907 MicroSeconds(100),
1908 MicroSeconds(0)})}});
1909 delay += Seconds(1);
1910
1911 //----------------------------------------------------------------------------------------------------------------------------------
1912 // Verify PHY state stays IDLE for the S40 if a signal below the energy detection threshold
1913 // occupies the second 20 MHz subchannel of the S40
1914 Simulator::Schedule(delay,
1916 this,
1917 "Reception of a 20 MHz signal that occupies the second subchannel of "
1918 "S40 below ED threshold");
1919 ScheduleTest(delay,
1920 {{dBm_u{-65},
1921 MicroSeconds(0),
1922 MicroSeconds(100),
1924 MHz_u{20}}},
1925 {},
1926 {
1927 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1928 {MicroSeconds(100) - smallDelta,
1929 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1930 {MicroSeconds(100) + smallDelta,
1931 WifiPhyState::IDLE} // IDLE just after the transmission ends
1932 },
1933 {});
1934 delay += Seconds(1);
1935
1936 //----------------------------------------------------------------------------------------------------------------------------------
1937 // Verify PHY notifies CCA-BUSY for the S40 as long as a signal above the energy detection
1938 // threshold occupies the second 20 MHz subchannel of the S40: 27.3.20.6.4: Any signal
1939 // within the secondary 40 MHz channel at or above a threshold of –59 dBm within a period of
1940 // aCcaTimeWithDelta after the signal arrives at the receiver’s antenna(s).
1941 Simulator::Schedule(delay,
1943 this,
1944 "Reception of a 20 MHz signal that occupies the second subchannel of "
1945 "S40 above ED threshold");
1946 ScheduleTest(delay,
1947 {{dBm_u{-55},
1948 MicroSeconds(0),
1949 MicroSeconds(100),
1951 MHz_u{20}}},
1952 {},
1953 {
1954 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1955 {MicroSeconds(100) - smallDelta,
1956 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1957 {MicroSeconds(100) + smallDelta,
1958 WifiPhyState::IDLE} // IDLE just after the transmission ends
1959 },
1960 {{MicroSeconds(100) - smallDelta,
1961 MicroSeconds(100),
1963 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
1964 MicroSeconds(0),
1965 MicroSeconds(0),
1966 MicroSeconds(100),
1967 MicroSeconds(0),
1968 MicroSeconds(0),
1969 MicroSeconds(0),
1970 MicroSeconds(0)}
1971 : std::vector<Time>{MicroSeconds(0),
1972 MicroSeconds(0),
1973 MicroSeconds(0),
1974 MicroSeconds(100)})}});
1975 delay += Seconds(1);
1976
1977 //----------------------------------------------------------------------------------------------------------------------------------
1978 // Verify PHY state stays IDLE for the S40 if a signal below the energy detection threshold
1979 // occupies S40
1980 Simulator::Schedule(delay,
1982 this,
1983 "Reception of a 40 MHz signal that occupies S40 below ED threshold");
1985 delay,
1986 {{dBm_u{-60}, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY, MHz_u{40}}},
1987 {},
1988 {
1989 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
1990 {MicroSeconds(100) - smallDelta,
1991 WifiPhyState::IDLE}, // IDLE just before the transmission ends
1992 {MicroSeconds(100) + smallDelta,
1993 WifiPhyState::IDLE} // IDLE just after the transmission ends
1994 },
1995 {});
1996 delay += Seconds(1);
1997
1998 //----------------------------------------------------------------------------------------------------------------------------------
1999 // Verify PHY notifies CCA-BUSY for the S40 as long as a signal above the energy detection
2000 // threshold occupies S40: 27.3.20.6.4: Any signal within the secondary 40 MHz channel at or
2001 // above a threshold of –59 dBm within a period of aCcaTimeWithDelta after the signal
2002 // arrives at the receiver’s antenna(s).
2003 Simulator::Schedule(delay,
2005 this,
2006 "Reception of a 20 MHz signal that occupies the second subchannel of "
2007 "S40 above ED threshold");
2009 delay,
2010 {{dBm_u{-55}, MicroSeconds(0), MicroSeconds(100), S40_CENTER_FREQUENCY, MHz_u{40}}},
2011 {},
2012 {
2013 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2014 {MicroSeconds(100) - smallDelta,
2015 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2016 {MicroSeconds(100) + smallDelta,
2017 WifiPhyState::IDLE} // IDLE just after the transmission ends
2018 },
2019 {{MicroSeconds(100) - smallDelta,
2020 MicroSeconds(100),
2022 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
2023 MicroSeconds(0),
2024 MicroSeconds(100),
2025 MicroSeconds(100),
2026 MicroSeconds(0),
2027 MicroSeconds(0),
2028 MicroSeconds(0),
2029 MicroSeconds(0)}
2030 : std::vector<Time>{MicroSeconds(0),
2031 MicroSeconds(0),
2032 MicroSeconds(100),
2033 MicroSeconds(100)})}});
2034 delay += Seconds(1);
2035
2036 //----------------------------------------------------------------------------------------------------------------------------------
2037 // Verify PHY state is CCA-BUSY as long as a 80 MHz signal above the energy detection
2038 // threshold occupies P80
2039 Simulator::Schedule(delay,
2041 this,
2042 "Reception of a 80 MHz signal that occupies P80 above ED threshold");
2044 delay,
2045 {{dBm_u{-55}, MicroSeconds(0), MicroSeconds(100), P80_CENTER_FREQUENCY, MHz_u{80}}},
2046 {},
2047 {
2048 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCcaTimeWithDelta
2049 {MicroSeconds(100) - smallDelta,
2050 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
2051 {MicroSeconds(100) + smallDelta,
2052 WifiPhyState::IDLE} // IDLE just after the transmission ends
2053 },
2054 {{MicroSeconds(100) - smallDelta,
2055 MicroSeconds(100),
2057 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(100),
2058 MicroSeconds(100),
2059 MicroSeconds(100),
2060 MicroSeconds(100),
2061 MicroSeconds(0),
2062 MicroSeconds(0),
2063 MicroSeconds(0),
2064 MicroSeconds(0)}
2065 : std::vector<Time>{MicroSeconds(100),
2066 MicroSeconds(100),
2067 MicroSeconds(100),
2068 MicroSeconds(100)})}});
2069 delay += Seconds(1);
2070
2071 //----------------------------------------------------------------------------------------------------------------------------------
2072 // Verify PHY notifies CCA-BUSY for the P20 channel while the S40 channel was already in
2073 // CCA-BUSY state
2074 Simulator::Schedule(delay,
2076 this,
2077 "Reception of a 20 MHz signal that occupies S40 followed by the "
2078 "reception of another 20 MHz signal that occupies P20");
2080 delay,
2081 {{dBm_u{-55},
2082 MicroSeconds(0),
2083 MicroSeconds(100),
2085 MHz_u{20}},
2086 {dBm_u{-55}, MicroSeconds(50), MicroSeconds(100), P20_CENTER_FREQUENCY, MHz_u{20}}},
2087 {},
2088 {
2090 WifiPhyState::IDLE}, // state of primary stays idle after aCcaTimeWithDelta
2092 WifiPhyState::CCA_BUSY}, // state of primary is CCA-BUSY after aCcaTimeWithDelta
2093 // that followed the second transmission
2094 {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
2095 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
2096 {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
2097 WifiPhyState::IDLE} // IDLE just after the transmission ends
2098 },
2099 {{aCcaTimeWithDelta, // notification upon reception of the first signal
2100 MicroSeconds(100),
2102 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
2103 MicroSeconds(0),
2104 MicroSeconds(100),
2105 MicroSeconds(0),
2106 MicroSeconds(0),
2107 MicroSeconds(0),
2108 MicroSeconds(0),
2109 MicroSeconds(0)}
2110 : std::vector<Time>{MicroSeconds(0),
2111 MicroSeconds(0),
2112 MicroSeconds(100),
2113 MicroSeconds(0)})},
2114 {MicroSeconds(50) +
2115 aCcaTimeWithDelta, // notification upon reception of the second signal
2116 MicroSeconds(50) + MicroSeconds(100),
2118 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(100),
2119 MicroSeconds(0),
2120 MicroSeconds(50),
2121 MicroSeconds(0),
2122 MicroSeconds(0),
2123 MicroSeconds(0),
2124 MicroSeconds(0),
2125 MicroSeconds(0)}
2126 : std::vector<Time>{MicroSeconds(100),
2127 MicroSeconds(0),
2128 MicroSeconds(50),
2129 MicroSeconds(0)})}});
2130 delay += Seconds(1);
2131
2132 //----------------------------------------------------------------------------------------------------------------------------------
2133 // Verify PHY state stays IDLE but notifies CCA-BUSY for the S20 channel while the S40
2134 // channel was already in CCA-BUSY state
2135 Simulator::Schedule(delay,
2137 this,
2138 "Reception of a signal that occupies S40 followed by the reception of "
2139 "another signal that occupies S20");
2141 delay,
2142 {{dBm_u{-55},
2143 MicroSeconds(0),
2144 MicroSeconds(100),
2146 MHz_u{20}},
2147 {dBm_u{-55}, MicroSeconds(50), MicroSeconds(100), S20_CENTER_FREQUENCY, MHz_u{20}}},
2148 {},
2149 {
2151 WifiPhyState::IDLE}, // state of primary stays idle after aCcaTimeWithDelta
2153 WifiPhyState::IDLE}, // state of primary stays IDLE
2154 {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
2155 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2156 {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
2157 WifiPhyState::IDLE} // IDLE just after the transmission ends
2158 },
2159 {{aCcaTimeWithDelta, // notification upon reception of the first signal
2160 MicroSeconds(100),
2162 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
2163 MicroSeconds(0),
2164 MicroSeconds(100),
2165 MicroSeconds(0),
2166 MicroSeconds(0),
2167 MicroSeconds(0),
2168 MicroSeconds(0),
2169 MicroSeconds(0)}
2170 : std::vector<Time>{MicroSeconds(0),
2171 MicroSeconds(0),
2172 MicroSeconds(100),
2173 MicroSeconds(0)})},
2174 {MicroSeconds(50) +
2175 aCcaTimeWithDelta, // notification upon reception of the second signal
2176 MicroSeconds(50) + MicroSeconds(100),
2178 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
2179 MicroSeconds(100),
2180 MicroSeconds(50),
2181 MicroSeconds(0),
2182 MicroSeconds(0),
2183 MicroSeconds(0),
2184 MicroSeconds(0),
2185 MicroSeconds(0)}
2186 : std::vector<Time>{MicroSeconds(0),
2187 MicroSeconds(100),
2188 MicroSeconds(50),
2189 MicroSeconds(0)})}});
2190 delay += Seconds(1);
2191
2192 //----------------------------------------------------------------------------------------------------------------------------------
2193 // Verify PHY state stays IDLE when a 40 MHz PPDU with received power below the CCA
2194 // sensitivity threshold occupies S40
2196 delay,
2198 this,
2199 "Reception of a 40 MHz PPDU that occupies S40 below CCA sensitivity threshold");
2200 ScheduleTest(delay,
2201 {},
2202 {{dBm_u{-75}, MicroSeconds(0), S40_CENTER_FREQUENCY, MHz_u{40}}},
2203 {
2204 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2205 {ppduDurations.at(MHz_u{40}) - smallDelta,
2206 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2207 {ppduDurations.at(MHz_u{40}) + smallDelta,
2208 WifiPhyState::IDLE} // IDLE just after the transmission ends
2209 },
2210 {});
2211 delay += Seconds(1);
2212
2213 //----------------------------------------------------------------------------------------------------------------------------------
2214 // Verify PHY state stays IDLE but CCA-BUSY indication is reported when a 40 MHz PPDU
2215 // with received power above the CCA sensitivity threshold occupies S40
2216 const dBm_u rxPower{(m_standard == WIFI_STANDARD_80211ax) ? -70.0 : -67.0};
2218 delay,
2220 this,
2221 "Reception of a 40 MHz PPDU that occupies S40 above CCA sensitivity threshold");
2223 delay,
2224 {},
2225 {{rxPower, MicroSeconds(0), S40_CENTER_FREQUENCY, MHz_u{40}}},
2226 {
2227 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2228 {ppduDurations.at(MHz_u{40}) - smallDelta,
2229 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2230 {ppduDurations.at(MHz_u{40}) + smallDelta,
2231 WifiPhyState::IDLE} // IDLE just after the transmission ends
2232 },
2234 ppduDurations.at(MHz_u{40}),
2236 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{NanoSeconds(0),
2237 NanoSeconds(0),
2238 ppduDurations.at(MHz_u{40}),
2239 ppduDurations.at(MHz_u{40}),
2240 NanoSeconds(0),
2241 NanoSeconds(0),
2242 NanoSeconds(0),
2243 NanoSeconds(0)}
2244 : std::vector<Time>{NanoSeconds(0),
2245 NanoSeconds(0),
2246 ppduDurations.at(MHz_u{40}),
2247 ppduDurations.at(MHz_u{40})})}});
2248 delay += Seconds(1);
2249
2250 //----------------------------------------------------------------------------------------------------------------------------------
2251 // Verify PHY state stays IDLE but CCA-BUSY indication is still reported as long as a signal
2252 // above the energy detection threshold occupies the S40 while a 80 MHz PPDU below the CCA
2253 // sensitivity threshold is received on P80.
2255 delay,
2257 this,
2258 "Reception of a 40 MHz signal that occupies S40 above ED threshold followed by a 80 "
2259 "MHz PPDU that occupies P80 below CCA sensitivity threshold");
2261 delay,
2262 {{dBm_u{-55},
2263 MicroSeconds(0),
2264 MicroSeconds(100),
2266 MHz_u{40}}}, // signal on S40 above threshold
2267 {{dBm_u{-80},
2268 MicroSeconds(50),
2270 MHz_u{80}}}, // PPDU on P80 below threshold
2271 {
2272 {MicroSeconds(50) + aCcaTimeWithDelta, WifiPhyState::IDLE}, // PHY state stays IDLE
2273 },
2274 {{MicroSeconds(50) - smallDelta,
2275 MicroSeconds(100),
2277 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
2278 MicroSeconds(0),
2279 MicroSeconds(100),
2280 MicroSeconds(100),
2281 MicroSeconds(0),
2282 MicroSeconds(0),
2283 MicroSeconds(0),
2284 MicroSeconds(0)}
2285 : std::vector<Time>{MicroSeconds(0),
2286 MicroSeconds(0),
2287 MicroSeconds(100),
2288 MicroSeconds(100)})},
2289 {MicroSeconds(100) - smallDelta,
2290 MicroSeconds(100),
2292 ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{MicroSeconds(0),
2293 MicroSeconds(0),
2294 MicroSeconds(46),
2295 MicroSeconds(46),
2296 MicroSeconds(0),
2297 MicroSeconds(0),
2298 MicroSeconds(0),
2299 MicroSeconds(0)}
2300 : std::vector<Time>{MicroSeconds(0),
2301 MicroSeconds(0),
2302 MicroSeconds(46),
2303 MicroSeconds(46)})}});
2304 delay += Seconds(1);
2305 }
2306 else // 20 or 40 MHz receiver
2307 {
2308 //----------------------------------------------------------------------------------------------------------------------------------
2309 // Verify PHY notifies CCA-BUSY when a 80 MHz PPDU with received power above the CCA
2310 // sensitivity threshold occupies P40 The per20Bitmap should indicate idle for all
2311 // subchannels because received power is below -62 dBm (27.3.20.6.5).
2312 Simulator::Schedule(delay,
2314 this,
2315 "Reception of a 80 MHz PPDU that occupies the 40 MHz band above CCA "
2316 "sensitivity threshold");
2318 delay,
2319 {},
2320 {{dBm_u{-70}, MicroSeconds(0), P80_CENTER_FREQUENCY, MHz_u{80}}},
2321 {
2322 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA_BUSY after aCcaTimeWithDelta
2323 {ppduDurations.at(MHz_u{80}) - smallDelta,
2324 WifiPhyState::CCA_BUSY}, // CCA_BUSY just before the transmission ends
2325 {ppduDurations.at(MHz_u{80}) + smallDelta,
2326 WifiPhyState::IDLE} // IDLE just after the transmission ends
2327 },
2329 MicroSeconds(16),
2331 ((m_channelWidth > MHz_u{20})
2332 ? ((m_channelWidth > MHz_u{40})
2333 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{Seconds(0),
2334 Seconds(0),
2335 Seconds(0),
2336 Seconds(0),
2337 Seconds(0),
2338 Seconds(0),
2339 Seconds(0),
2340 Seconds(0)}
2341 : std::vector<Time>{Seconds(0),
2342 Seconds(0),
2343 Seconds(0),
2344 Seconds(0)})
2345 : std::vector<Time>{Seconds(0), Seconds(0)})
2346 : std::vector<Time>{})},
2347 {ppduDurations.at(MHz_u{80}) - smallDelta,
2348 ppduDurations.at(MHz_u{80}),
2350 ((m_channelWidth > MHz_u{20})
2351 ? ((m_channelWidth > MHz_u{40})
2352 ? ((m_channelWidth > MHz_u{80}) ? std::vector<Time>{Seconds(0),
2353 Seconds(0),
2354 Seconds(0),
2355 Seconds(0),
2356 Seconds(0),
2357 Seconds(0),
2358 Seconds(0),
2359 Seconds(0)}
2360 : std::vector<Time>{Seconds(0),
2361 Seconds(0),
2362 Seconds(0),
2363 Seconds(0)})
2364 : std::vector<Time>{Seconds(0), Seconds(0)})
2365 : std::vector<Time>{})}});
2366 delay += Seconds(1);
2367
2368 //----------------------------------------------------------------------------------------------------------------------------------
2369 // Verify PHY notifies CCA-BUSY when a 80 MHz PPDU with received power above the CCA
2370 // sensitivity threshold occupies P40 The per20Bitmap should indicate CCA_BUSY for all
2371 // subchannels because received power is above -62 dBm (27.3.20.6.5).
2372 Simulator::Schedule(delay,
2374 this,
2375 "Reception of a 80 MHz PPDU that occupies the 40 MHz band above CCA "
2376 "sensitivity threshold");
2378 delay,
2379 {},
2380 {{dBm_u{-55}, MicroSeconds(0), P80_CENTER_FREQUENCY, MHz_u{80}}},
2381 {
2382 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA_BUSY after aCcaTimeWithDelta
2383 {ppduDurations.at(MHz_u{80}) - smallDelta,
2384 WifiPhyState::CCA_BUSY}, // CCA_BUSY just before the transmission ends
2385 {ppduDurations.at(MHz_u{80}) + smallDelta,
2386 WifiPhyState::IDLE} // IDLE just after the transmission ends
2387 },
2389 MicroSeconds(16),
2391 ((m_channelWidth > MHz_u{20})
2392 ? ((m_channelWidth > MHz_u{40})
2393 ? ((m_channelWidth > MHz_u{80})
2394 ? std::vector<Time>{ppduDurations.at(MHz_u{80}) - aCcaTime,
2395 ppduDurations.at(MHz_u{80}) - aCcaTime,
2396 ppduDurations.at(MHz_u{80}) - aCcaTime,
2397 ppduDurations.at(MHz_u{80}) - aCcaTime,
2398 NanoSeconds(0),
2399 NanoSeconds(0),
2400 NanoSeconds(0),
2401 NanoSeconds(0)}
2402 : std::vector<Time>{ppduDurations.at(MHz_u{80}) - aCcaTime,
2403 ppduDurations.at(MHz_u{80}) - aCcaTime,
2404 ppduDurations.at(MHz_u{80}) - aCcaTime,
2405 ppduDurations.at(MHz_u{80}) - aCcaTime})
2406 : std::vector<Time>{ppduDurations.at(MHz_u{80}) - aCcaTime,
2407 ppduDurations.at(MHz_u{80}) - aCcaTime})
2408 : std::vector<Time>{})},
2409 {ppduDurations.at(MHz_u{80}) - smallDelta,
2410 ppduDurations.at(MHz_u{80}),
2412 ((m_channelWidth > MHz_u{20})
2413 ? ((m_channelWidth > MHz_u{40})
2414 ? ((m_channelWidth > MHz_u{80})
2415 ? std::
2416 vector<Time>{ppduDurations.at(MHz_u{80}) - phyHeaderDuration,
2417 ppduDurations.at(MHz_u{80}) - phyHeaderDuration,
2418 ppduDurations.at(MHz_u{80}) - phyHeaderDuration,
2419 ppduDurations.at(MHz_u{80}) - phyHeaderDuration,
2420 NanoSeconds(0),
2421 NanoSeconds(0),
2422 NanoSeconds(0),
2423 NanoSeconds(0)}
2424 : std::vector<
2425 Time>{ppduDurations.at(MHz_u{80}) - phyHeaderDuration,
2426 ppduDurations.at(MHz_u{80}) - phyHeaderDuration,
2427 ppduDurations.at(MHz_u{80}) - phyHeaderDuration,
2428 ppduDurations.at(MHz_u{80}) - phyHeaderDuration})
2429 : std::vector<Time>{ppduDurations.at(MHz_u{80}) - phyHeaderDuration,
2430 ppduDurations.at(MHz_u{80}) - phyHeaderDuration})
2431 : std::vector<Time>{})}});
2432 delay += Seconds(1);
2433
2434 //----------------------------------------------------------------------------------------------------------------------------------
2435 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported when a signal not
2436 // occupying the operational channel is being received
2438 delay,
2440 this,
2441 "Reception of a 40 MHz PPDU that does not occupy the operational channel");
2442 ScheduleTest(delay,
2443 {},
2444 {{dBm_u{-50}, MicroSeconds(0), S40_CENTER_FREQUENCY, MHz_u{40}}},
2445 {
2446 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2447 {ppduDurations.at(MHz_u{20}) - smallDelta,
2448 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2449 {ppduDurations.at(MHz_u{20}) + smallDelta,
2450 WifiPhyState::IDLE} // IDLE just after the transmission ends
2451 },
2452 {});
2453 delay += Seconds(1);
2454 }
2455
2456 if (m_channelWidth > MHz_u{80})
2457 {
2458 //----------------------------------------------------------------------------------------------------------------------------------
2459 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2460 // energy detection threshold occupies the first 20 MHz subchannel of the S80
2461 Simulator::Schedule(delay,
2463 this,
2464 "Reception of a 20 MHz signal that occupies the first subchannel of "
2465 "S80 below ED threshold");
2466 ScheduleTest(delay,
2467 {{dBm_u{-65},
2468 MicroSeconds(0),
2469 MicroSeconds(100),
2471 MHz_u{20}}},
2472 {},
2473 {
2474 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2475 {MicroSeconds(100) - smallDelta,
2476 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2477 {MicroSeconds(100) + smallDelta,
2478 WifiPhyState::IDLE} // IDLE just after the transmission ends
2479 },
2480 {});
2481 delay += Seconds(1);
2482
2483 //----------------------------------------------------------------------------------------------------------------------------------
2484 // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2485 // energy detection threshold occupies the first 20 MHz subchannel of the S80 27.3.20.6.4:
2486 // Any signal within the secondary 80 MHz channel at or above –56 dBm.
2487 Simulator::Schedule(delay,
2489 this,
2490 "Reception of a 20 MHz signal that occupies the first subchannel of "
2491 "S80 above ED threshold");
2492 ScheduleTest(delay,
2493 {{dBm_u{-55},
2494 MicroSeconds(0),
2495 MicroSeconds(100),
2497 MHz_u{20}}},
2498 {},
2499 {
2500 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2501 {MicroSeconds(100) - smallDelta,
2502 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2503 {MicroSeconds(100) + smallDelta,
2504 WifiPhyState::IDLE} // IDLE just after the transmission ends
2505 },
2506 {{MicroSeconds(100) - smallDelta,
2507 MicroSeconds(100),
2509 std::vector<Time>{MicroSeconds(0),
2510 MicroSeconds(0),
2511 MicroSeconds(0),
2512 MicroSeconds(0),
2513 MicroSeconds(100),
2514 MicroSeconds(0),
2515 MicroSeconds(0),
2516 MicroSeconds(0)}}});
2517 delay += Seconds(1);
2518
2519 //----------------------------------------------------------------------------------------------------------------------------------
2520 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2521 // energy detection threshold occupies the second 20 MHz subchannel of the S80
2522 Simulator::Schedule(delay,
2524 this,
2525 "Reception of a 20 MHz signal that occupies the second subchannel of "
2526 "S80 below ED threshold");
2527 ScheduleTest(delay,
2528 {{dBm_u{-65},
2529 MicroSeconds(0),
2530 MicroSeconds(100),
2532 MHz_u{20}}},
2533 {},
2534 {
2535 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2536 {MicroSeconds(100) - smallDelta,
2537 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2538 {MicroSeconds(100) + smallDelta,
2539 WifiPhyState::IDLE} // IDLE just after the transmission ends
2540 },
2541 {});
2542 delay += Seconds(1);
2543
2544 //----------------------------------------------------------------------------------------------------------------------------------
2545 // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2546 // energy detection threshold occupies the second 20 MHz subchannel of the S80 27.3.20.6.4:
2547 // Any signal within the secondary 80 MHz channel at or above –56 dBm.
2548 Simulator::Schedule(delay,
2550 this,
2551 "Reception of a 20 MHz signal that occupies the second subchannel of "
2552 "S80 above ED threshold");
2553 ScheduleTest(delay,
2554 {{dBm_u{-55},
2555 MicroSeconds(0),
2556 MicroSeconds(100),
2558 MHz_u{20}}},
2559 {},
2560 {
2561 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2562 {MicroSeconds(100) - smallDelta,
2563 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2564 {MicroSeconds(100) + smallDelta,
2565 WifiPhyState::IDLE} // IDLE just after the transmission ends
2566 },
2567 {{MicroSeconds(100) - smallDelta,
2568 MicroSeconds(100),
2570 std::vector<Time>{MicroSeconds(0),
2571 MicroSeconds(0),
2572 MicroSeconds(0),
2573 MicroSeconds(0),
2574 MicroSeconds(0),
2575 MicroSeconds(100),
2576 MicroSeconds(0),
2577 MicroSeconds(0)}}});
2578 delay += Seconds(1);
2579
2580 //----------------------------------------------------------------------------------------------------------------------------------
2581 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2582 // energy detection threshold occupies the third 20 MHz subchannel of the S80
2583 Simulator::Schedule(delay,
2585 this,
2586 "Reception of a 20 MHz signal that occupies the third subchannel of "
2587 "S80 below ED threshold");
2588 ScheduleTest(delay,
2589 {{dBm_u{-65},
2590 MicroSeconds(0),
2591 MicroSeconds(100),
2593 MHz_u{20}}},
2594 {},
2595 {
2596 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2597 {MicroSeconds(100) - smallDelta,
2598 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2599 {MicroSeconds(100) + smallDelta,
2600 WifiPhyState::IDLE} // IDLE just after the transmission ends
2601 },
2602 {});
2603 delay += Seconds(1);
2604
2605 //----------------------------------------------------------------------------------------------------------------------------------
2606 // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2607 // energy detection threshold occupies the third 20 MHz subchannel of the S80 27.3.20.6.4:
2608 // Any signal within the secondary 80 MHz channel at or above –56 dBm.
2609 Simulator::Schedule(delay,
2611 this,
2612 "Reception of a 20 MHz signal that occupies the third subchannel of "
2613 "S80 above ED threshold");
2614 ScheduleTest(delay,
2615 {{dBm_u{-55},
2616 MicroSeconds(0),
2617 MicroSeconds(100),
2619 MHz_u{20}}},
2620 {},
2621 {
2622 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2623 {MicroSeconds(100) - smallDelta,
2624 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2625 {MicroSeconds(100) + smallDelta,
2626 WifiPhyState::IDLE} // IDLE just after the transmission ends
2627 },
2628 {{MicroSeconds(100) - smallDelta,
2629 MicroSeconds(100),
2631 std::vector<Time>{MicroSeconds(0),
2632 MicroSeconds(0),
2633 MicroSeconds(0),
2634 MicroSeconds(0),
2635 MicroSeconds(0),
2636 MicroSeconds(0),
2637 MicroSeconds(100),
2638 MicroSeconds(0)}}});
2639 delay += Seconds(1);
2640
2641 //----------------------------------------------------------------------------------------------------------------------------------
2642 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2643 // energy detection threshold occupies the fourth 20 MHz subchannel of the S80
2644 Simulator::Schedule(delay,
2646 this,
2647 "Reception of a 20 MHz signal that occupies the fourth subchannel of "
2648 "S80 below ED threshold");
2649 ScheduleTest(delay,
2650 {{dBm_u{-65},
2651 MicroSeconds(0),
2652 MicroSeconds(100),
2654 MHz_u{20}}},
2655 {},
2656 {
2657 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2658 {MicroSeconds(100) - smallDelta,
2659 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2660 {MicroSeconds(100) + smallDelta,
2661 WifiPhyState::IDLE} // IDLE just after the transmission ends
2662 },
2663 {});
2664 delay += Seconds(1);
2665
2666 //----------------------------------------------------------------------------------------------------------------------------------
2667 // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2668 // energy detection threshold occupies the fourth 20 MHz subchannel of the S80 27.3.20.6.4:
2669 // Any signal within the secondary 80 MHz channel at or above –56 dBm.
2670 Simulator::Schedule(delay,
2672 this,
2673 "Reception of a 20 MHz signal that occupies the fourth subchannel of "
2674 "S80 above ED threshold");
2675 ScheduleTest(delay,
2676 {{dBm_u{-55},
2677 MicroSeconds(0),
2678 MicroSeconds(100),
2680 MHz_u{20}}},
2681 {},
2682 {
2683 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2684 {MicroSeconds(100) - smallDelta,
2685 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2686 {MicroSeconds(100) + smallDelta,
2687 WifiPhyState::IDLE} // IDLE just after the transmission ends
2688 },
2689 {{MicroSeconds(100) - smallDelta,
2690 MicroSeconds(100),
2692 std::vector<Time>{MicroSeconds(0),
2693 MicroSeconds(0),
2694 MicroSeconds(0),
2695 MicroSeconds(0),
2696 MicroSeconds(0),
2697 MicroSeconds(0),
2698 MicroSeconds(0),
2699 MicroSeconds(100)}}});
2700 delay += Seconds(1);
2701
2702 //----------------------------------------------------------------------------------------------------------------------------------
2703 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2704 // energy detection threshold occupies the first and second 20 MHz subchannels of the S80
2705 Simulator::Schedule(delay,
2707 this,
2708 "Reception of a 40 MHz signal that occupies the first and second "
2709 "subchannels of S80 below ED threshold");
2710 ScheduleTest(delay,
2711 {{dBm_u{-65},
2712 MicroSeconds(0),
2713 MicroSeconds(100),
2715 MHz_u{40}}},
2716 {},
2717 {
2718 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2719 {MicroSeconds(100) - smallDelta,
2720 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2721 {MicroSeconds(100) + smallDelta,
2722 WifiPhyState::IDLE} // IDLE just after the transmission ends
2723 },
2724 {});
2725 delay += Seconds(1);
2726
2727 //----------------------------------------------------------------------------------------------------------------------------------
2728 // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2729 // energy detection threshold occupies the first and second 20 MHz subchannels of the S80
2730 // 27.3.20.6.4: Any signal within the secondary 80 MHz channel at or above –56 dBm.
2731 Simulator::Schedule(delay,
2733 this,
2734 "Reception of a 40 MHz signal that occupies the first and second "
2735 "subchannels of S80 above ED threshold");
2736 ScheduleTest(delay,
2737 {{dBm_u{-55},
2738 MicroSeconds(0),
2739 MicroSeconds(100),
2741 MHz_u{40}}},
2742 {},
2743 {
2744 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2745 {MicroSeconds(100) - smallDelta,
2746 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2747 {MicroSeconds(100) + smallDelta,
2748 WifiPhyState::IDLE} // IDLE just after the transmission ends
2749 },
2750 {{MicroSeconds(100) - smallDelta,
2751 MicroSeconds(100),
2753 std::vector<Time>{MicroSeconds(0),
2754 MicroSeconds(0),
2755 MicroSeconds(0),
2756 MicroSeconds(0),
2757 MicroSeconds(100),
2758 MicroSeconds(100),
2759 MicroSeconds(0),
2760 MicroSeconds(0)}}});
2761 delay += Seconds(1);
2762
2763 //----------------------------------------------------------------------------------------------------------------------------------
2764 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2765 // energy detection threshold occupies the third and fourth 20 MHz subchannels of the S80
2766 Simulator::Schedule(delay,
2768 this,
2769 "Reception of a 40 MHz signal that occupies the third and fourth "
2770 "subchannels of S80 below ED threshold");
2771 ScheduleTest(delay,
2772 {{dBm_u{-65},
2773 MicroSeconds(0),
2774 MicroSeconds(100),
2776 MHz_u{40}}},
2777 {},
2778 {
2779 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2780 {MicroSeconds(100) - smallDelta,
2781 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2782 {MicroSeconds(100) + smallDelta,
2783 WifiPhyState::IDLE} // IDLE just after the transmission ends
2784 },
2785 {});
2786 delay += Seconds(1);
2787
2788 //----------------------------------------------------------------------------------------------------------------------------------
2789 // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2790 // energy detection threshold occupies the third and fourth 20 MHz subchannels of the S80
2791 // 27.3.20.6.4: Any signal within the secondary 80 MHz channel at or above –56 dBm.
2792 Simulator::Schedule(delay,
2794 this,
2795 "Reception of a 40 MHz signal that occupies the third and fourth "
2796 "subchannels of S80 above ED threshold");
2797 ScheduleTest(delay,
2798 {{dBm_u{-55},
2799 MicroSeconds(0),
2800 MicroSeconds(100),
2802 MHz_u{40}}},
2803 {},
2804 {
2805 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2806 {MicroSeconds(100) - smallDelta,
2807 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2808 {MicroSeconds(100) + smallDelta,
2809 WifiPhyState::IDLE} // IDLE just after the transmission ends
2810 },
2811 {{MicroSeconds(100) - smallDelta,
2812 MicroSeconds(100),
2814 std::vector<Time>{MicroSeconds(0),
2815 MicroSeconds(0),
2816 MicroSeconds(0),
2817 MicroSeconds(0),
2818 MicroSeconds(0),
2819 MicroSeconds(0),
2820 MicroSeconds(100),
2821 MicroSeconds(100)}}});
2822 delay += Seconds(1);
2823
2824 //----------------------------------------------------------------------------------------------------------------------------------
2825 // Verify PHY state stays IDLE and no CCA-BUSY indication is reported if a signal below the
2826 // energy detection threshold occupies the S80
2827 Simulator::Schedule(delay,
2829 this,
2830 "Reception of a 80 MHz signal that occupies S80 below ED threshold");
2831 ScheduleTest(
2832 delay,
2833 {{dBm_u{-65}, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY, MHz_u{80}}},
2834 {},
2835 {
2836 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2837 {MicroSeconds(100) - smallDelta,
2838 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2839 {MicroSeconds(100) + smallDelta,
2840 WifiPhyState::IDLE} // IDLE just after the transmission ends
2841 },
2842 {});
2843 delay += Seconds(1);
2844
2845 //----------------------------------------------------------------------------------------------------------------------------------
2846 // Verify PHY state stays IDLE and CCA-BUSY indication is reported if a signal above the
2847 // energy detection threshold occupies the S80 27.3.20.6.4: Any signal within the secondary
2848 // 80 MHz channel at or above –56 dBm.
2849 Simulator::Schedule(delay,
2851 this,
2852 "Reception of a 80 MHz signal that occupies S80 above ED threshold");
2853 ScheduleTest(
2854 delay,
2855 {{dBm_u{-55}, MicroSeconds(0), MicroSeconds(100), S80_CENTER_FREQUENCY, MHz_u{80}}},
2856 {},
2857 {
2858 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2859 {MicroSeconds(100) - smallDelta,
2860 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2861 {MicroSeconds(100) + smallDelta,
2862 WifiPhyState::IDLE} // IDLE just after the transmission ends
2863 },
2864 {{MicroSeconds(100) - smallDelta,
2865 MicroSeconds(100),
2867 std::vector<Time>{MicroSeconds(0),
2868 MicroSeconds(0),
2869 MicroSeconds(0),
2870 MicroSeconds(0),
2871 MicroSeconds(100),
2872 MicroSeconds(100),
2873 MicroSeconds(100),
2874 MicroSeconds(100)}}});
2875 delay += Seconds(1);
2876
2877 //----------------------------------------------------------------------------------------------------------------------------------
2878 // Verify PHY state stays IDLE as long as a 160 MHz signal below the energy detection
2879 // threshold occupies the whole band
2881 delay,
2883 this,
2884 "Reception of a 160 MHz signal that occupies the whole band below ED threshold");
2885 ScheduleTest(
2886 delay,
2887 {{dBm_u{-55}, MicroSeconds(0), MicroSeconds(100), P160_CENTER_FREQUENCY, MHz_u{160}}},
2888 {},
2889 {
2890 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
2891 {MicroSeconds(100) - smallDelta,
2892 WifiPhyState::IDLE}, // IDLE just before the transmission ends
2893 {MicroSeconds(100) + smallDelta,
2894 WifiPhyState::IDLE} // IDLE just after the transmission ends
2895 },
2896 {});
2897
2898 delay += Seconds(1);
2899
2900 //----------------------------------------------------------------------------------------------------------------------------------
2901 // Verify PHY state is CCA-BUSY as long as a 160 MHz signal above the energy detection
2902 // threshold occupies the whole band
2904 delay,
2906 this,
2907 "Reception of a 160 MHz signal that occupies the whole band above ED threshold");
2908 ScheduleTest(
2909 delay,
2910 {{dBm_u{-50}, MicroSeconds(0), MicroSeconds(100), P160_CENTER_FREQUENCY, MHz_u{160}}},
2911 {},
2912 {
2913 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCcaTimeWithDelta
2914 {MicroSeconds(100) - smallDelta,
2915 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
2916 {MicroSeconds(100) + smallDelta,
2917 WifiPhyState::IDLE} // IDLE just after the transmission ends
2918 },
2919 {{MicroSeconds(100) - smallDelta,
2920 MicroSeconds(100),
2922 std::vector<Time>{MicroSeconds(100),
2923 MicroSeconds(100),
2924 MicroSeconds(100),
2925 MicroSeconds(100),
2926 MicroSeconds(100),
2927 MicroSeconds(100),
2928 MicroSeconds(100),
2929 MicroSeconds(100)}}});
2930 delay += Seconds(1);
2931
2932 //----------------------------------------------------------------------------------------------------------------------------------
2933 // Verify PHY notifies CCA-BUSY for the P20 channel while the S80 channel was already in
2934 // CCA-BUSY state
2935 Simulator::Schedule(delay,
2937 this,
2938 "Reception of a 20 MHz signal that occupies S80 followed by the "
2939 "reception of another 20 MHz signal that occupies P20");
2940 ScheduleTest(
2941 delay,
2942 {{dBm_u{-55},
2943 MicroSeconds(0),
2944 MicroSeconds(100),
2946 MHz_u{20}},
2947 {dBm_u{-55}, MicroSeconds(50), MicroSeconds(100), P20_CENTER_FREQUENCY, MHz_u{20}}},
2948 {},
2949 {
2951 WifiPhyState::IDLE}, // state of primary stays idle after aCcaTimeWithDelta
2953 WifiPhyState::CCA_BUSY}, // state of primary is CCA-BUSY after aCcaTimeWithDelta
2954 // that followed the second transmission
2955 {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
2956 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
2957 {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
2958 WifiPhyState::IDLE} // IDLE just after the transmission ends
2959 },
2960 {{aCcaTimeWithDelta, // notification upon reception of the first signal
2961 MicroSeconds(100),
2963 std::vector<Time>{MicroSeconds(0),
2964 MicroSeconds(0),
2965 MicroSeconds(0),
2966 MicroSeconds(0),
2967 MicroSeconds(0),
2968 MicroSeconds(0),
2969 MicroSeconds(100),
2970 MicroSeconds(0)}},
2971 {MicroSeconds(50) +
2972 aCcaTimeWithDelta, // notification upon reception of the second signal
2973 MicroSeconds(50) + MicroSeconds(100),
2975 std::vector<Time>{MicroSeconds(100),
2976 MicroSeconds(0),
2977 MicroSeconds(00),
2978 MicroSeconds(0),
2979 MicroSeconds(0),
2980 MicroSeconds(0),
2981 MicroSeconds(50),
2982 MicroSeconds(0)}}});
2983 delay += Seconds(1);
2984
2985 //----------------------------------------------------------------------------------------------------------------------------------
2986 // Verify PHY state stays IDLE but notifies CCA-BUSY for the S40 channel while the S80
2987 // channel was already in CCA-BUSY state
2988 Simulator::Schedule(delay,
2990 this,
2991 "Reception of a signal that occupies S80 followed by the reception of "
2992 "another signal that occupies S40");
2993 ScheduleTest(
2994 delay,
2995 {{dBm_u{-55},
2996 MicroSeconds(0),
2997 MicroSeconds(100),
2999 MHz_u{20}},
3000 {dBm_u{-55},
3001 MicroSeconds(50),
3002 MicroSeconds(100),
3004 MHz_u{20}}},
3005 {},
3006 {
3008 WifiPhyState::IDLE}, // state of primary stays idle after aCcaTimeWithDelta
3010 WifiPhyState::IDLE}, // state of primary stays IDLE
3011 {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
3012 WifiPhyState::IDLE}, // IDLE just before the transmission ends
3013 {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
3014 WifiPhyState::IDLE} // IDLE just after the transmission ends
3015 },
3016 {{aCcaTimeWithDelta, // notification upon reception of the first signal
3017 MicroSeconds(100),
3019 std::vector<Time>{MicroSeconds(0),
3020 MicroSeconds(0),
3021 MicroSeconds(0),
3022 MicroSeconds(0),
3023 MicroSeconds(0),
3024 MicroSeconds(0),
3025 MicroSeconds(0),
3026 MicroSeconds(100)}},
3027 {MicroSeconds(50) +
3028 aCcaTimeWithDelta, // notification upon reception of the second signal
3029 MicroSeconds(50) + MicroSeconds(100),
3031 std::vector<Time>{MicroSeconds(0),
3032 MicroSeconds(0),
3033 MicroSeconds(100),
3034 MicroSeconds(0),
3035 MicroSeconds(0),
3036 MicroSeconds(0),
3037 MicroSeconds(0),
3038 MicroSeconds(50)}}});
3039 delay += Seconds(1);
3040
3041 //----------------------------------------------------------------------------------------------------------------------------------
3042 // Verify PHY state stays IDLE but notifies CCA-BUSY for the S20 channel while the S80
3043 // channel was already in CCA-BUSY state
3044 Simulator::Schedule(delay,
3046 this,
3047 "Reception of a signal that occupies S80 followed by the reception of "
3048 "another signal that occupies S20");
3049 ScheduleTest(
3050 delay,
3051 {{dBm_u{-55},
3052 MicroSeconds(0),
3053 MicroSeconds(100),
3055 MHz_u{20}},
3056 {dBm_u{-55}, MicroSeconds(50), MicroSeconds(100), S20_CENTER_FREQUENCY, MHz_u{20}}},
3057 {},
3058 {
3060 WifiPhyState::IDLE}, // state of primary stays idle after aCcaTimeWithDelta
3062 WifiPhyState::IDLE}, // state of primary stays IDLE
3063 {MicroSeconds(50) + MicroSeconds(100) - smallDelta,
3064 WifiPhyState::IDLE}, // IDLE just before the transmission ends
3065 {MicroSeconds(50) + MicroSeconds(100) + smallDelta,
3066 WifiPhyState::IDLE} // IDLE just after the transmission ends
3067 },
3068 {{aCcaTimeWithDelta, // notification upon reception of the first signal
3069 MicroSeconds(100),
3071 std::vector<Time>{MicroSeconds(0),
3072 MicroSeconds(0),
3073 MicroSeconds(0),
3074 MicroSeconds(0),
3075 MicroSeconds(100),
3076 MicroSeconds(0),
3077 MicroSeconds(0),
3078 MicroSeconds(0)}},
3079 {MicroSeconds(50) +
3080 aCcaTimeWithDelta, // notification upon reception of the second signal
3081 MicroSeconds(50) + MicroSeconds(100),
3083 std::vector<Time>{MicroSeconds(0),
3084 MicroSeconds(100),
3085 MicroSeconds(0),
3086 MicroSeconds(0),
3087 MicroSeconds(50),
3088 MicroSeconds(0),
3089 MicroSeconds(0),
3090 MicroSeconds(0)}}});
3091 delay += Seconds(1);
3092
3093 //----------------------------------------------------------------------------------------------------------------------------------
3094 // Verify PHY state stays IDLE when a 80 MHz PPDU with received power below the CCA
3095 // sensitivity threshold occupies S80
3097 delay,
3099 this,
3100 "Reception of a 80 MHz PPDU that occupies S80 below CCA sensitivity threshold");
3101 ScheduleTest(delay,
3102 {},
3103 {{dBm_u{-70}, MicroSeconds(0), S80_CENTER_FREQUENCY, MHz_u{80}}},
3104 {
3105 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
3106 {ppduDurations.at(MHz_u{80}) - smallDelta,
3107 WifiPhyState::IDLE}, // IDLE just before the transmission ends
3108 {ppduDurations.at(MHz_u{80}) + smallDelta,
3109 WifiPhyState::IDLE} // IDLE just after the transmission ends
3110 },
3111 {});
3112 delay += Seconds(1);
3113
3114 //----------------------------------------------------------------------------------------------------------------------------------
3115 // Verify PHY state stays IDLE but CCA-BUSY indication is reported when a 80 MHz PPDU
3116 // with received power above the CCA sensitivity threshold occupies S80
3118 delay,
3120 this,
3121 "Reception of a 80 MHz PPDU that occupies S80 above CCA sensitivity threshold");
3122 ScheduleTest(delay,
3123 {},
3124 {{dBm_u{-65}, MicroSeconds(0), S80_CENTER_FREQUENCY, MHz_u{80}}},
3125 {
3126 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
3127 {ppduDurations.at(MHz_u{80}) - smallDelta,
3128 WifiPhyState::IDLE}, // IDLE just before the transmission ends
3129 {ppduDurations.at(MHz_u{80}) + smallDelta,
3130 WifiPhyState::IDLE} // IDLE just after the transmission ends
3131 },
3133 ppduDurations.at(MHz_u{80}),
3135 std::vector<Time>{NanoSeconds(0),
3136 NanoSeconds(0),
3137 NanoSeconds(0),
3138 NanoSeconds(0),
3139 ppduDurations.at(MHz_u{80}),
3140 ppduDurations.at(MHz_u{80}),
3141 ppduDurations.at(MHz_u{80}),
3142 ppduDurations.at(MHz_u{80})}}});
3143 delay += Seconds(1);
3144
3145 if (m_standard == WIFI_STANDARD_80211ax)
3146 {
3147 //----------------------------------------------------------------------------------------------------------------------------------
3148 // Verify PHY state stays IDLE and CCA-BUSY indication is reported if only the
3149 // per20bitmap parameter changes
3151 delay,
3153 this,
3154 "Reception of a 20 MHz signal that generates a per20bitmap parameter "
3155 "change when previous CCA indication reports IDLE");
3156 ScheduleTest(
3157 delay,
3158 {{dBm_u{-60.0},
3159 MicroSeconds(0),
3160 MicroSeconds(100),
3162 MHz_u{20}}},
3163 {},
3164 {
3165 {aCcaTimeWithDelta, WifiPhyState::IDLE}, // IDLE after aCcaTimeWithDelta
3166 {MicroSeconds(100) - smallDelta,
3167 WifiPhyState::IDLE}, // IDLE just before the transmission ends
3168 {MicroSeconds(100) + smallDelta,
3169 WifiPhyState::IDLE} // IDLE just after the transmission ends
3170 },
3172 Seconds(0),
3174 std::vector<Time>{MicroSeconds(0),
3175 MicroSeconds(0),
3176 MicroSeconds(0),
3177 MicroSeconds(0),
3178 MicroSeconds(0),
3179 MicroSeconds(0),
3180 MicroSeconds(0),
3181 MicroSeconds(100)}}});
3182 delay += Seconds(1);
3183
3184 //----------------------------------------------------------------------------------------------------------------------------------
3185 // Verify PHY state stays CCA_BUSY and CCA-BUSY indication is reported if only the
3186 // per20bitmap parameter changes
3188 delay,
3190 this,
3191 "Reception of a 20 MHz signal that generates a per20bitmap parameter change when "
3192 "previous CCA indication reports BUSY for the primary channel");
3193 ScheduleTest(
3194 delay,
3195 {{dBm_u{-50.0},
3196 MicroSeconds(0),
3197 MicroSeconds(100),
3199 MHz_u{80}},
3200 {dBm_u{-60.0},
3201 MicroSeconds(50),
3202 MicroSeconds(200),
3204 MHz_u{20}}},
3205 {},
3206 {
3207 {aCcaTimeWithDelta, WifiPhyState::CCA_BUSY}, // CCA-BUSY after aCcaTimeWithDelta
3208 {MicroSeconds(100) - smallDelta,
3209 WifiPhyState::CCA_BUSY}, // CCA-BUSY just before the transmission ends
3210 {MicroSeconds(100) + smallDelta,
3211 WifiPhyState::IDLE} // IDLE just after the transmission ends
3212 },
3214 MicroSeconds(100),
3216 std::vector<Time>{MicroSeconds(100),
3217 MicroSeconds(100),
3218 MicroSeconds(100),
3219 MicroSeconds(100),
3220 MicroSeconds(0),
3221 MicroSeconds(0),
3222 MicroSeconds(0),
3223 MicroSeconds(0)}},
3224 {MicroSeconds(50) +
3225 aCcaTimeWithDelta, // notification upon reception of the second signal
3226 MicroSeconds(100),
3228 std::vector<Time>{MicroSeconds(50),
3229 MicroSeconds(50),
3230 MicroSeconds(50),
3231 MicroSeconds(50),
3232 MicroSeconds(0),
3233 MicroSeconds(0),
3234 MicroSeconds(0),
3235 MicroSeconds(200)}}});
3236 delay += Seconds(1);
3237 }
3238 }
3239
3241}
3242
3243void
3245{
3246 m_frequency = MHz_u{5180};
3247 m_channelWidth = MHz_u{20};
3248 RunOne();
3249
3250 m_frequency = MHz_u{5190};
3251 m_channelWidth = MHz_u{40};
3252 RunOne();
3253
3254 m_frequency = MHz_u{5210};
3255 m_channelWidth = MHz_u{80};
3256 RunOne();
3257
3258 m_frequency = MHz_u{5250};
3259 m_channelWidth = MHz_u{160};
3260 RunOne();
3261
3263}
3264
3265void
3267{
3268 m_rxPhy->Dispose();
3269 m_rxPhy = nullptr;
3270 m_txPhy->Dispose();
3271 m_txPhy = nullptr;
3272 for (auto& signalGenerator : m_signalGenerators)
3273 {
3274 signalGenerator->Dispose();
3275 signalGenerator = nullptr;
3276 }
3277}
3278
3279/**
3280 * @ingroup wifi-test
3281 * @ingroup tests
3282 *
3283 * @brief Wi-Fi PHY CCA Test Suite
3284 */
3286{
3287 public:
3289};
3290
3292 : TestSuite("wifi-phy-cca", Type::UNIT)
3293{
3294 AddTestCase(new WifiPhyCcaThresholdsTest, TestCase::Duration::QUICK);
3295 AddTestCase(new WifiPhyCcaIndicationTest(WIFI_STANDARD_80211ax), TestCase::Duration::QUICK);
3296 AddTestCase(new WifiPhyCcaIndicationTest(WIFI_STANDARD_80211be), TestCase::Duration::QUICK);
3297}
3298
3299static WifiPhyCcaTestSuite WifiPhyCcaTestSuite; ///< the test suite
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 NotifyTxStart(Time duration, dBm_u txPower) override
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,...
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
void NotifyRxEndError(const WifiTxVector &txVector) override
Wifi Phy Threshold Test base class.
MHz_u m_channelWidth
Operating channel width.
std::size_t m_numSignalGenerators
The number of non-wifi signals generators needed for the test.
WifiStandard m_standard
The standard to use for the test.
void SendSuPpdu(dBm_u txPower, MHz_u frequency, MHz_u bandwidth)
Send a HE or EHT SU PPDU.
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.
MHz_u m_frequency
Operating frequency.
void StartSignal(Ptr< WaveformGenerator > signalGenerator, dBm_u txPower, MHz_u frequency, MHz_u bandwidth, Time duration)
Start to generate a signal.
void RunOne()
Run one function.
void DoCheckPhyState(WifiPhyState expectedState)
Check the PHY state.
std::shared_ptr< CcaTestPhyListener > m_rxPhyStateListener
Listener for PHY state transitions.
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.
WifiPhyCcaIndicationTest(WifiStandard standard)
Constructor.
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.
Wi-Fi PHY CCA Test Suite.
PHY CCA thresholds test.
void VerifyCcaThreshold(const Ptr< PhyEntity > phy, const Ptr< const WifiPpdu > ppdu, WifiChannelListType channelType, dBm_u expectedCcaThreshold)
Function to verify the CCA threshold that is being reported by a given PHY entity upon reception of a...
Ptr< WifiNetDevice > m_device
The WifiNetDevice.
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.
Ptr< SpectrumWifiPhy > m_phy
The spectrum PHY.
Ptr< ObssPdAlgorithm > m_obssPdAlgorithm
The OBSS-PD algorithm.
dBm_u m_obssPdLevel
The current OBSS-PD level.
Ptr< EhtConfiguration > m_ehtConfiguration
The EHT configuration.
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.
void RunOne()
Run tests for given CCA attributes.
Ptr< VhtConfiguration > m_vhtConfiguration
The VHT configuration.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< EhtPpdu > CreateDummyEhtPpdu(MHz_u bandwidth, const WifiPhyOperatingChannel &channel)
Create a EHT PPDU.
dBm_u m_per20CcaSensitivity
The current CCA sensitivity threshold for Per 20MHz check.
Ptr< VhtPpdu > CreateDummyVhtPpdu(MHz_u bandwidth, const WifiPhyOperatingChannel &channel)
Create a VHT PPDU.
Ptr< HtPpdu > CreateDummyHtPpdu(MHz_u bandwidth, const WifiPhyOperatingChannel &channel)
Create a HT PPDU.
Ptr< OfdmPpdu > CreateDummyNonHtPpdu(const WifiPhyOperatingChannel &channel)
Create a non-HT PPDU.
dBm_u m_CcaEdThreshold
The current CCA-ED threshold for a 20 MHz subchannel.
dBm_u m_CcaSensitivity
The current CCA sensitivity threshold for signals that occupy the primary 20 MHz channel.
Ptr< HePpdu > CreateDummyHePpdu(MHz_u bandwidth, const WifiPhyOperatingChannel &channel)
Create a HE PPDU.
static WifiMode GetEhtMcs0()
Return MCS 0 from EHT MCS values.
static WifiMode GetHeMcs0()
Return MCS 0 from HE MCS values.
@ PSD_NON_HE_PORTION
Non-HE portion of an HE PPDU.
Definition he-ppdu.h:105
static WifiMode GetHtMcs0()
Return MCS 0 from HT MCS values.
static WifiMode GetOfdmRate6Mbps()
Return a WifiMode for OFDM at 6 Mbps.
AttributeValue implementation for Pointer.
Ptr< T > Get() const
Definition pointer.h:223
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:595
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
AttributeValue implementation for Time.
Definition nstime.h:1432
std::tuple< dBm_u, dBm_u, dBm_u > SecondaryCcaSensitivityThresholds
Tuple identifying CCA sensitivity thresholds for secondary channels.
static WifiMode GetVhtMcs0()
Return MCS 0 from VHT MCS values.
Implements the IEEE 802.11 MAC header.
virtual 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.
std::tuple< uint8_t, MHz_u, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying a segment of an operating channel.
Definition wifi-phy.h:937
receive notifications about PHY events.
Class that keeps track of all information about the current PHY operating channel.
static ConstIterator FindFirst(uint8_t number, MHz_u frequency, MHz_u width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first frequency segment matching the specified parameters.
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:191
#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:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#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:134
#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:500
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_EHT_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PREAMBLE_VHT_SU
@ WIFI_PREAMBLE_HT_MF
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_MOD_CLASS_OFDM
OFDM (Clause 17)
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ 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.
WifiPhyState
The state of the PHY layer.
std::vector< BandInfo > Bands
Container of BandInfo.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
@ WIFI_MAC_QOSDATA
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
Definition wifi-utils.cc:34
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
Definition wifi-utils.h:111
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
STL namespace.
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
Time startTime
time at which transmission will be started
MHz_u centerFreq
center frequency to use
structure that holds information to generate signals
MHz_u centerFreq
center frequency to use
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
const Time aCcaTime
const Time aCcaTimeWithDelta
constexpr MHz_u S80_CENTER_FREQUENCY
static WifiPhyCcaTestSuite WifiPhyCcaTestSuite
the test suite
constexpr MHz_u S20_CENTER_FREQUENCY
constexpr MHz_u P20_CENTER_FREQUENCY
const Time phyHeaderDuration
constexpr MHz_u S40_CENTER_FREQUENCY
const std::map< MHz_u, Time > ehtPpduDurations
const Time smallDelta
constexpr MHz_u P160_CENTER_FREQUENCY
constexpr MHz_u P80_CENTER_FREQUENCY
constexpr MHz_u P40_CENTER_FREQUENCY
const std::map< MHz_u, Time > hePpduDurations