A Discrete-Event Network Simulator
API
wifi-phy-reception-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 University of Washington
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
18  */
19 
20 #include "ns3/ampdu-tag.h"
21 #include "ns3/ap-wifi-mac.h"
22 #include "ns3/boolean.h"
23 #include "ns3/config.h"
24 #include "ns3/double.h"
25 #include "ns3/he-phy.h"
26 #include "ns3/he-ppdu.h"
27 #include "ns3/interference-helper.h"
28 #include "ns3/log.h"
29 #include "ns3/mobility-helper.h"
30 #include "ns3/mpdu-aggregator.h"
31 #include "ns3/multi-model-spectrum-channel.h"
32 #include "ns3/nist-error-rate-model.h"
33 #include "ns3/packet-socket-address.h"
34 #include "ns3/packet-socket-client.h"
35 #include "ns3/packet-socket-helper.h"
36 #include "ns3/packet-socket-server.h"
37 #include "ns3/pointer.h"
38 #include "ns3/rng-seed-manager.h"
39 #include "ns3/simple-frame-capture-model.h"
40 #include "ns3/single-model-spectrum-channel.h"
41 #include "ns3/spectrum-wifi-helper.h"
42 #include "ns3/spectrum-wifi-phy.h"
43 #include "ns3/test.h"
44 #include "ns3/threshold-preamble-detection-model.h"
45 #include "ns3/wifi-bandwidth-filter.h"
46 #include "ns3/wifi-mac-header.h"
47 #include "ns3/wifi-mpdu.h"
48 #include "ns3/wifi-net-device.h"
49 #include "ns3/wifi-psdu.h"
50 #include "ns3/wifi-spectrum-phy-interface.h"
51 #include "ns3/wifi-spectrum-signal-parameters.h"
52 #include "ns3/wifi-spectrum-value-helper.h"
53 #include "ns3/wifi-utils.h"
54 
55 #include <optional>
56 
57 using namespace ns3;
58 
59 NS_LOG_COMPONENT_DEFINE("WifiPhyReceptionTest");
60 
61 static const uint8_t CHANNEL_NUMBER = 36;
62 static const uint32_t FREQUENCY = 5180; // MHz
63 static const uint16_t CHANNEL_WIDTH = 20; // MHz
64 static const uint16_t GUARD_WIDTH =
65  CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
66 
74 {
75  public:
81  WifiPhyReceptionTest(std::string test_name);
85  ~WifiPhyReceptionTest() override = default;
86 
87  protected:
88  void DoSetup() override;
89  void DoTeardown() override;
90 
97  void SendPacket(double rxPowerDbm, uint32_t packetSize, uint8_t mcs);
98 
103  void CheckPhyState(WifiPhyState expectedState);
108  void DoCheckPhyState(WifiPhyState expectedState);
109 
111  uint64_t m_uid{0};
112 };
113 
115  : TestCase{test_name}
116 {
117 }
118 
119 void
120 WifiPhyReceptionTest::SendPacket(double rxPowerDbm, uint32_t packetSize, uint8_t mcs)
121 {
122  WifiTxVector txVector =
123  WifiTxVector(HePhy::GetHeMcs(mcs), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
124 
125  Ptr<Packet> pkt = Create<Packet>(packetSize);
126  WifiMacHeader hdr;
127 
129  hdr.SetQosTid(0);
130 
131  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
132  Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
133 
134  Ptr<WifiPpdu> ppdu =
135  Create<HePpdu>(psdu, txVector, m_phy->GetOperatingChannel(), txDuration, m_uid++);
136 
137  Ptr<SpectrumValue> txPowerSpectrum =
138  WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
140  DbmToW(rxPowerDbm),
141  GUARD_WIDTH);
142 
143  Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
144  txParams->psd = txPowerSpectrum;
145  txParams->txPhy = nullptr;
146  txParams->duration = txDuration;
147  txParams->ppdu = ppdu;
148 
149  m_phy->StartRx(txParams, nullptr);
150 }
151 
152 void
154 {
155  // This is needed to make sure PHY state will be checked as the last event if a state change
156  // occurred at the exact same time as the check
157  Simulator::ScheduleNow(&WifiPhyReceptionTest::DoCheckPhyState, this, expectedState);
158 }
159 
160 void
162 {
163  WifiPhyState currentState;
164  PointerValue ptr;
165  m_phy->GetAttribute("State", ptr);
166  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
167  currentState = state->GetState();
168  NS_LOG_FUNCTION(this << currentState);
169  NS_TEST_ASSERT_MSG_EQ(currentState,
170  expectedState,
171  "PHY State " << currentState << " does not match expected state "
172  << expectedState << " at " << Simulator::Now());
173 }
174 
175 void
177 {
178  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
179  Ptr<Node> node = CreateObject<Node>();
180  Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
181  m_phy = CreateObject<SpectrumWifiPhy>();
182  Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
183  m_phy->SetInterferenceHelper(interferenceHelper);
184  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
185  m_phy->SetErrorRateModel(error);
186  m_phy->SetDevice(dev);
187  m_phy->AddChannel(spectrumChannel);
190  dev->SetPhy(m_phy);
191  node->AddDevice(dev);
192 }
193 
194 void
196 {
197  m_phy->Dispose();
198  m_phy = nullptr;
199 }
200 
208 {
209  public:
211 
212  protected:
213  void DoSetup() override;
214 
222  void RxSuccess(Ptr<const WifiPsdu> psdu,
223  RxSignalInfo rxSignalInfo,
224  WifiTxVector txVector,
225  std::vector<bool> statusPerMpdu);
230  void RxFailure(Ptr<const WifiPsdu> psdu);
231  uint32_t m_countRxSuccess{0};
232  uint32_t m_countRxFailure{0};
233 
234  private:
235  void DoRun() override;
236 
242  void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
243 };
244 
248  "Threshold preamble detection model test when no frame capture model is applied")
249 {
250 }
251 
252 void
254  uint32_t expectedFailureCount)
255 {
257  expectedSuccessCount,
258  "Didn't receive right number of successful packets");
260  expectedFailureCount,
261  "Didn't receive right number of unsuccessful packets");
262 }
263 
264 void
266  RxSignalInfo rxSignalInfo,
267  WifiTxVector txVector,
268  std::vector<bool> statusPerMpdu)
269 {
270  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
272 }
273 
274 void
276 {
277  NS_LOG_FUNCTION(this << *psdu);
279 }
280 
281 void
283 {
285 
290 
291  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
292  CreateObject<ThresholdPreambleDetectionModel>();
293  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
294  preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
295  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
296 }
297 
298 void
300 {
301  RngSeedManager::SetSeed(1);
302  RngSeedManager::SetRun(1);
303  int64_t streamNumber = 0;
304  m_phy->AssignStreams(streamNumber);
305 
306  // RX power > CCA-ED > CCA-PD
307  double rxPowerDbm = -50;
308 
309  // CASE 1: send one packet and check PHY state:
310  // All reception stages should succeed and PHY state should be RX for the duration of the packet
311  // minus the time to detect the preamble, otherwise it should be IDLE.
312 
313  Simulator::Schedule(Seconds(1.0),
315  this,
316  rxPowerDbm,
317  1000,
318  7);
319  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
320  // CCA_BUSY
321  Simulator::Schedule(Seconds(1.0) + NanoSeconds(3999),
323  this,
325  Simulator::Schedule(Seconds(1.0) + NanoSeconds(4000),
327  this,
329  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
330  // CCA_BUSY to RX
331  Simulator::Schedule(Seconds(1.0) + NanoSeconds(43999),
333  this,
335  Simulator::Schedule(Seconds(1.0) + NanoSeconds(44000),
337  this,
339  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
340  Simulator::Schedule(Seconds(1.0) + NanoSeconds(152799),
342  this,
344  Simulator::Schedule(Seconds(1.0) + NanoSeconds(152800),
346  this,
348  // Packet should have been successfully received
349  Simulator::Schedule(Seconds(1.1),
351  this,
352  1,
353  0);
354 
355  // CASE 2: send two packets with same power within the 4us window and check PHY state:
356  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
357  // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
358  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
359  // time to detect the preamble.
360 
361  Simulator::Schedule(Seconds(2.0),
363  this,
364  rxPowerDbm,
365  1000,
366  7);
367  Simulator::Schedule(Seconds(2.0) + MicroSeconds(2.0),
369  this,
370  rxPowerDbm,
371  1000,
372  7);
373  // At 4us, no preamble is successfully detected and STA PHY STATE should move from IDLE to
374  // CCA_BUSY
375  Simulator::Schedule(Seconds(2.0) + NanoSeconds(3999),
377  this,
379  Simulator::Schedule(Seconds(2.0) + NanoSeconds(4000),
381  this,
383  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
384  // = 154.8us
385  Simulator::Schedule(Seconds(2.0) + NanoSeconds(154799),
387  this,
389  Simulator::Schedule(Seconds(2.0) + NanoSeconds(154800),
391  this,
393  // No more packet should have been successfully received, and since preamble detection did not
394  // pass, the packet should not have been counted as a failure
395  Simulator::Schedule(Seconds(2.1),
397  this,
398  1,
399  0);
400 
401  // CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY
402  // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
403  // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
404  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
405  // time to detect the preamble.
406 
407  Simulator::Schedule(Seconds(3.0),
409  this,
410  rxPowerDbm,
411  1000,
412  7);
413  Simulator::Schedule(Seconds(3.0) + MicroSeconds(2.0),
415  this,
416  rxPowerDbm - 3,
417  1000,
418  7);
419  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
420  // CCA_BUSY
421  Simulator::Schedule(Seconds(3.0) + NanoSeconds(3999),
423  this,
425  Simulator::Schedule(Seconds(3.0) + NanoSeconds(4000),
427  this,
429  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
430  // = 154.8us
431  Simulator::Schedule(Seconds(3.0) + NanoSeconds(154799),
433  this,
435  Simulator::Schedule(Seconds(3.0) + NanoSeconds(154800),
437  this,
439  // No more packet should have been successfully received, and since preamble detection did not
440  // pass the packet should not have been counted as a failure
441  Simulator::Schedule(Seconds(3.1),
443  this,
444  1,
445  0);
446 
447  // CASE 4: send two packets with second one 6 dB weaker within the 4us window and check PHY
448  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
449  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
450  // decode the modulation).
451 
452  Simulator::Schedule(Seconds(4.0),
454  this,
455  rxPowerDbm,
456  1000,
457  7);
458  Simulator::Schedule(Seconds(4.0) + MicroSeconds(2.0),
460  this,
461  rxPowerDbm - 6,
462  1000,
463  7);
464  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
465  // CCA_BUSY
466  Simulator::Schedule(Seconds(4.0) + NanoSeconds(3999),
468  this,
470  Simulator::Schedule(Seconds(4.0) + NanoSeconds(4000),
472  this,
474  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
475  // CCA_BUSY to RX
476  Simulator::Schedule(Seconds(4.0) + NanoSeconds(43999),
478  this,
480  Simulator::Schedule(Seconds(4.0) + NanoSeconds(44000),
482  this,
484  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
485  // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
486  // should first be seen as CCA_BUSY for 2us.
487  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152799),
489  this,
491  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152800),
493  this,
495  Simulator::Schedule(Seconds(4.0) + NanoSeconds(154799),
497  this,
499  Simulator::Schedule(Seconds(4.0) + NanoSeconds(154800),
501  this,
503  // In this case, the first packet should be marked as a failure
504  Simulator::Schedule(Seconds(4.1),
506  this,
507  1,
508  1);
509 
510  // CASE 5: send two packets with second one 3 dB higher within the 4us window and check PHY
511  // state: PHY preamble detection should fail because SNR is too low (around -3 dB, which is
512  // lower than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is
513  // above CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus
514  // the time to detect the preamble.
515 
516  Simulator::Schedule(Seconds(5.0),
518  this,
519  rxPowerDbm,
520  1000,
521  7);
522  Simulator::Schedule(Seconds(5.0) + MicroSeconds(2.0),
524  this,
525  rxPowerDbm + 3,
526  1000,
527  7);
528  // At 6us (hence 4us after the last signal is received), no preamble is successfully detected,
529  // hence STA PHY STATE should move from IDLE to CCA_BUSY
530  Simulator::Schedule(Seconds(5.0) + NanoSeconds(5999),
532  this,
534  Simulator::Schedule(Seconds(5.0) + NanoSeconds(6000),
536  this,
538  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
539  // = 154.8us
540  Simulator::Schedule(Seconds(5.0) + NanoSeconds(154799),
542  this,
544  Simulator::Schedule(Seconds(5.0) + NanoSeconds(154800),
546  this,
548  // No more packet should have been successfully received, and since preamble detection did not
549  // pass the packet should not have been counted as a failure
550  Simulator::Schedule(Seconds(5.1),
552  this,
553  1,
554  1);
555 
556  // CCA-PD < RX power < CCA-ED
557  rxPowerDbm = -70;
558 
559  // CASE 6: send one packet and check PHY state:
560  // All reception stages should succeed and PHY state should be RX for the duration of the packet
561  // minus the time to detect the preamble, otherwise it should be IDLE.
562 
563  Simulator::Schedule(Seconds(6.0),
565  this,
566  rxPowerDbm,
567  1000,
568  7);
569  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
570  // CCA_BUSY
571  Simulator::Schedule(Seconds(6.0) + NanoSeconds(3999),
573  this,
575  Simulator::Schedule(Seconds(6.0) + NanoSeconds(4000),
577  this,
579  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
580  // CCA_BUSY to RX
581  Simulator::Schedule(Seconds(6.0) + NanoSeconds(43999),
583  this,
585  Simulator::Schedule(Seconds(6.0) + NanoSeconds(44000),
587  this,
589  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
590  Simulator::Schedule(Seconds(6.0) + NanoSeconds(152799),
592  this,
594  Simulator::Schedule(Seconds(6.0) + NanoSeconds(152800),
596  this,
598  // Packet should have been successfully received
599  Simulator::Schedule(Seconds(6.1),
601  this,
602  2,
603  1);
604 
605  // CASE 7: send two packets with same power within the 4us window and check PHY state:
606  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
607  // the threshold of 4 dB), and PHY state should be CCA_BUSY since it should detect the start of
608  // a valid OFDM transmission at a receive level greater than or equal to the minimum modulation
609  // and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
610 
611  Simulator::Schedule(Seconds(7.0),
613  this,
614  rxPowerDbm,
615  1000,
616  7);
617  Simulator::Schedule(Seconds(7.0) + MicroSeconds(2.0),
619  this,
620  rxPowerDbm,
621  1000,
622  7);
623  // At 4us, STA PHY STATE should stay IDLE
624  Simulator::Schedule(Seconds(7.0) + MicroSeconds(4.0),
626  this,
628  // No more packet should have been successfully received, and since preamble detection did not
629  // pass the packet should not have been counted as a failure
630  Simulator::Schedule(Seconds(7.1),
632  this,
633  2,
634  1);
635 
636  // CASE 8: send two packets with second one 3 dB weaker within the 4us window and check PHY
637  // state: PHY preamble detection should fail PHY preamble detection should fail because SNR is
638  // too low (around 3 dB, which is lower than the threshold of 4 dB), and PHY state should be
639  // CCA_BUSY since it should detect the start of a valid OFDM transmission at a receive level
640  // greater than or equal to the minimum modulation and coding rate sensitivity (–82 dBm for 20
641  // MHz channel spacing).
642 
643  Simulator::Schedule(Seconds(8.0),
645  this,
646  rxPowerDbm,
647  1000,
648  7);
649  Simulator::Schedule(Seconds(8.0) + MicroSeconds(2.0),
651  this,
652  rxPowerDbm - 3,
653  1000,
654  7);
655  // At 4us, STA PHY STATE should stay IDLE
656  Simulator::Schedule(Seconds(8.0) + MicroSeconds(4.0),
658  this,
660  // No more packet should have been successfully received, and since preamble detection did not
661  // pass the packet should not have been counted as a failure
662  Simulator::Schedule(Seconds(8.1),
664  this,
665  2,
666  1);
667 
668  // CASE 9: send two packets with second one 6 dB weaker within the 4us window and check PHY
669  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
670  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
671  // decode the modulation).
672 
673  Simulator::Schedule(Seconds(9.0),
675  this,
676  rxPowerDbm,
677  1000,
678  7);
679  Simulator::Schedule(Seconds(9.0) + MicroSeconds(2.0),
681  this,
682  rxPowerDbm - 6,
683  1000,
684  7);
685  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
686  // CCA_BUSY
687  Simulator::Schedule(Seconds(9.0) + NanoSeconds(3999),
689  this,
691  Simulator::Schedule(Seconds(9.0) + NanoSeconds(4000),
693  this,
695  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
696  // CCA_BUSY to RX
697  Simulator::Schedule(Seconds(9.0) + NanoSeconds(43999),
699  this,
701  Simulator::Schedule(Seconds(9.0) + NanoSeconds(44000),
703  this,
705  // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
706  // 152.8us.
707  Simulator::Schedule(Seconds(9.0) + NanoSeconds(152799),
709  this,
711  Simulator::Schedule(Seconds(9.0) + NanoSeconds(152800),
713  this,
715  // In this case, the first packet should be marked as a failure
716  Simulator::Schedule(Seconds(9.1),
718  this,
719  2,
720  2);
721 
722  // CASE 10: send two packets with second one 3 dB higher within the 4us window and check PHY
723  // state: PHY preamble detection should fail because SNR is too low (around -3 dB, which is
724  // lower than the threshold of 4 dB), and PHY state should stay IDLE since the total energy is
725  // below CCA-ED (-62 dBm).
726 
727  Simulator::Schedule(Seconds(10.0),
729  this,
730  rxPowerDbm,
731  1000,
732  7);
733  Simulator::Schedule(Seconds(10.0) + MicroSeconds(2.0),
735  this,
736  rxPowerDbm + 3,
737  1000,
738  7);
739  // At 4us, STA PHY STATE should stay IDLE
740  Simulator::Schedule(Seconds(10.0) + MicroSeconds(4.0),
742  this,
744  // No more packet should have been successfully received, and since preamble detection did not
745  // pass the packet should not have been counted as a failure
746  Simulator::Schedule(Seconds(10.1),
748  this,
749  2,
750  2);
751 
752  // CASE 11: send one packet with a power slightly above the minimum RSSI needed for the preamble
753  // detection (-82 dBm) and check PHY state: preamble detection should succeed and PHY state
754  // should move to RX.
755 
756  rxPowerDbm = -81;
757 
758  Simulator::Schedule(Seconds(11.0),
760  this,
761  rxPowerDbm,
762  1000,
763  7);
764  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
765  // CCA_BUSY
766  Simulator::Schedule(Seconds(11.0) + NanoSeconds(3999),
768  this,
770  Simulator::Schedule(Seconds(11.0) + NanoSeconds(4000),
772  this,
774  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
775  // CCA_BUSY to RX
776  Simulator::Schedule(Seconds(11.0) + NanoSeconds(43999),
778  this,
780  Simulator::Schedule(Seconds(11.0) + NanoSeconds(44000),
782  this,
784  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
785  Simulator::Schedule(Seconds(11.0) + NanoSeconds(152799),
787  this,
789  Simulator::Schedule(Seconds(11.0) + NanoSeconds(152800),
791  this,
793 
794  // RX power < CCA-PD < CCA-ED
795  rxPowerDbm = -83;
796 
797  // CASE 12: send one packet with a power slightly below the minimum RSSI needed for the preamble
798  // detection (-82 dBm) and check PHY state: preamble detection should fail and PHY should be
799  // kept in IDLE state.
800 
801  Simulator::Schedule(Seconds(12.0),
803  this,
804  rxPowerDbm,
805  1000,
806  7);
807  // At 4us, STA PHY state should be IDLE
808  Simulator::Schedule(Seconds(12.0) + MicroSeconds(4.0),
810  this,
812 
813  Simulator::Run();
814  Simulator::Destroy();
815 }
816 
824 {
825  public:
827 
828  protected:
829  void DoSetup() override;
830 
838  void RxSuccess(Ptr<const WifiPsdu> psdu,
839  RxSignalInfo rxSignalInfo,
840  WifiTxVector txVector,
841  std::vector<bool> statusPerMpdu);
846  void RxFailure(Ptr<const WifiPsdu> psdu);
847  uint32_t m_countRxSuccess{0};
848  uint32_t m_countRxFailure{0};
849 
850  private:
851  void DoRun() override;
852 
858  void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
859 };
860 
863  "Threshold preamble detection model test when simple frame capture model is applied")
864 {
865 }
866 
867 void
869  uint32_t expectedFailureCount)
870 {
872  expectedSuccessCount,
873  "Didn't receive right number of successful packets");
875  expectedFailureCount,
876  "Didn't receive right number of unsuccessful packets");
877 }
878 
879 void
881  RxSignalInfo rxSignalInfo,
882  WifiTxVector txVector,
883  std::vector<bool> statusPerMpdu)
884 {
885  NS_LOG_FUNCTION(this << *psdu << txVector);
887 }
888 
889 void
891 {
892  NS_LOG_FUNCTION(this << *psdu);
894 }
895 
896 void
898 {
900 
905 
906  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
907  CreateObject<ThresholdPreambleDetectionModel>();
908  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
909  preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
910  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
911 
912  Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
913  frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
914  frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
915  m_phy->SetFrameCaptureModel(frameCaptureModel);
916 }
917 
918 void
920 {
921  RngSeedManager::SetSeed(1);
922  RngSeedManager::SetRun(1);
923  int64_t streamNumber = 1;
924  m_phy->AssignStreams(streamNumber);
925 
926  // RX power > CCA-ED > CCA-PD
927  double rxPowerDbm = -50;
928 
929  // CASE 1: send one packet and check PHY state:
930  // All reception stages should succeed and PHY state should be RX for the duration of the packet
931  // minus the time to detect the preamble, otherwise it should be IDLE.
932 
933  Simulator::Schedule(Seconds(1.0),
935  this,
936  rxPowerDbm,
937  1000,
938  7);
939  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
940  // CCA_BUSY
941  Simulator::Schedule(Seconds(1.0) + NanoSeconds(3999),
943  this,
945  Simulator::Schedule(Seconds(1.0) + NanoSeconds(4000),
947  this,
949  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
950  // CCA_BUSY to RX
951  Simulator::Schedule(Seconds(1.0) + NanoSeconds(43999),
953  this,
955  Simulator::Schedule(Seconds(1.0) + NanoSeconds(44000),
957  this,
959  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
960  Simulator::Schedule(Seconds(1.0) + NanoSeconds(152799),
962  this,
964  Simulator::Schedule(Seconds(1.0) + NanoSeconds(152800),
966  this,
968  // Packet should have been successfully received
969  Simulator::Schedule(Seconds(1.1),
971  this,
972  1,
973  0);
974 
975  // CASE 2: send two packets with same power within the 4us window and check PHY state:
976  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
977  // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
978  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
979  // time to detect the preamble.
980 
981  Simulator::Schedule(Seconds(2.0),
983  this,
984  rxPowerDbm,
985  1000,
986  7);
987  Simulator::Schedule(Seconds(2.0) + MicroSeconds(2.0),
989  this,
990  rxPowerDbm,
991  1000,
992  7);
993  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
994  // CCA_BUSY
995  Simulator::Schedule(Seconds(2.0) + NanoSeconds(3999),
997  this,
999  Simulator::Schedule(Seconds(2.0) + NanoSeconds(4000),
1001  this,
1003  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1004  // = 154.8us
1005  Simulator::Schedule(Seconds(2.0) + NanoSeconds(154799),
1007  this,
1009  Simulator::Schedule(Seconds(2.0) + NanoSeconds(154800),
1011  this,
1013  // No more packet should have been successfully received, and since preamble detection did not
1014  // pass the packet should not have been counted as a failure
1015  Simulator::Schedule(Seconds(2.1),
1017  this,
1018  1,
1019  0);
1020 
1021  // CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY
1022  // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
1023  // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1024  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1025  // time to detect the preamble.
1026 
1027  Simulator::Schedule(Seconds(3.0),
1029  this,
1030  rxPowerDbm,
1031  1000,
1032  7);
1033  Simulator::Schedule(Seconds(3.0) + MicroSeconds(2.0),
1035  this,
1036  rxPowerDbm - 3,
1037  1000,
1038  7);
1039  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1040  // CCA_BUSY
1041  Simulator::Schedule(Seconds(3.0) + NanoSeconds(3999),
1043  this,
1045  Simulator::Schedule(Seconds(3.0) + NanoSeconds(4000),
1047  this,
1049  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1050  // = 154.8us
1051  Simulator::Schedule(Seconds(3.0) + NanoSeconds(154799),
1053  this,
1055  Simulator::Schedule(Seconds(3.0) + NanoSeconds(154800),
1057  this,
1059  // No more packet should have been successfully received, and since preamble detection did not
1060  // pass the packet should not have been counted as a failure
1061  Simulator::Schedule(Seconds(3.1),
1063  this,
1064  1,
1065  0);
1066 
1067  // CASE 4: send two packets with second one 6 dB weaker within the 4us window and check PHY
1068  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1069  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1070  // decode the modulation).
1071 
1072  Simulator::Schedule(Seconds(4.0),
1074  this,
1075  rxPowerDbm,
1076  1000,
1077  7);
1078  Simulator::Schedule(Seconds(4.0) + MicroSeconds(2.0),
1080  this,
1081  rxPowerDbm - 6,
1082  1000,
1083  7);
1084  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1085  // CCA_BUSY
1086  Simulator::Schedule(Seconds(4.0) + NanoSeconds(3999),
1088  this,
1090  Simulator::Schedule(Seconds(4.0) + NanoSeconds(4000),
1092  this,
1094  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1095  // CCA_BUSY to RX
1096  Simulator::Schedule(Seconds(4.0) + NanoSeconds(43999),
1098  this,
1100  Simulator::Schedule(Seconds(4.0) + NanoSeconds(44000),
1102  this,
1104  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
1105  // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
1106  // should first be seen as CCA_BUSY for 2us.
1107  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152799),
1109  this,
1111  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152800),
1113  this,
1115  Simulator::Schedule(Seconds(4.0) + NanoSeconds(154799),
1117  this,
1119  Simulator::Schedule(Seconds(4.0) + NanoSeconds(154800),
1121  this,
1123  // In this case, the first packet should be marked as a failure
1124  Simulator::Schedule(Seconds(4.1),
1126  this,
1127  1,
1128  1);
1129 
1130  // CASE 5: send two packets with second one 3 dB higher within the 4us window and check PHY
1131  // state: PHY preamble detection should switch because a higher packet is received within the
1132  // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1133  // lower than the threshold of 4 dB), PHY state should be CCA_BUSY since the total energy is
1134  // above CCA-ED (-62 dBm).
1135 
1136  Simulator::Schedule(Seconds(5.0),
1138  this,
1139  rxPowerDbm,
1140  1000,
1141  7);
1142  Simulator::Schedule(Seconds(5.0) + MicroSeconds(2.0),
1144  this,
1145  rxPowerDbm + 3,
1146  1000,
1147  7);
1148  // At 4us, STA PHY STATE should stay IDLE
1149  Simulator::Schedule(Seconds(5.0) + MicroSeconds(4.0),
1151  this,
1153  // At 6us, STA PHY STATE should move from IDLE to CCA_BUSY
1154  Simulator::Schedule(Seconds(5.0) + NanoSeconds(5999),
1156  this,
1158  Simulator::Schedule(Seconds(5.0) + NanoSeconds(6000),
1160  this,
1162  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1163  // = 154.8us
1164  Simulator::Schedule(Seconds(5.0) + NanoSeconds(154799),
1166  this,
1168  Simulator::Schedule(Seconds(5.0) + NanoSeconds(154800),
1170  this,
1172  // No more packet should have been successfully received, and since preamble detection did not
1173  // pass the packet should not have been counted as a failure
1174  Simulator::Schedule(Seconds(5.1),
1176  this,
1177  1,
1178  1);
1179 
1180  // CASE 6: send two packets with second one 6 dB higher within the 4us window and check PHY
1181  // state: PHY preamble detection should switch because a higher packet is received within the
1182  // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1183  // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1184  // decode the modulation).
1185 
1186  Simulator::Schedule(Seconds(6.0),
1188  this,
1189  rxPowerDbm,
1190  1000,
1191  7);
1192  Simulator::Schedule(Seconds(6.0) + MicroSeconds(2.0),
1194  this,
1195  rxPowerDbm + 6,
1196  1000,
1197  7);
1198  // At 4us, STA PHY STATE should stay IDLE
1199  Simulator::Schedule(Seconds(6.0) + MicroSeconds(4.0),
1201  this,
1203  // At 6us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1204  // CCA_BUSY
1205  Simulator::Schedule(Seconds(6.0) + NanoSeconds(5999),
1207  this,
1209  Simulator::Schedule(Seconds(6.0) + NanoSeconds(6000),
1211  this,
1213  // At 46us, PHY header should be successfully received and STA PHY STATE should move from
1214  // CCA_BUSY to RX
1215  Simulator::Schedule(Seconds(6.0) + NanoSeconds(45999),
1217  this,
1219  Simulator::Schedule(Seconds(6.0) + NanoSeconds(46000),
1221  this,
1223  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1224  // = 154.8us
1225  Simulator::Schedule(Seconds(6.0) + NanoSeconds(154799),
1227  this,
1229  Simulator::Schedule(Seconds(6.0) + NanoSeconds(154800),
1231  this,
1233  // In this case, the second packet should be marked as a failure
1234  Simulator::Schedule(Seconds(6.1),
1236  this,
1237  1,
1238  2);
1239 
1240  // CASE 7: send two packets with same power at the exact same time and check PHY state:
1241  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
1242  // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1243  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1244  // time to detect the preamble.
1245 
1246  Simulator::Schedule(Seconds(7.0),
1248  this,
1249  rxPowerDbm,
1250  1000,
1251  7);
1252  Simulator::Schedule(Seconds(7.0),
1254  this,
1255  rxPowerDbm,
1256  1000,
1257  7);
1258  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1259  // CCA_BUSY
1260  Simulator::Schedule(Seconds(7.0) + NanoSeconds(3999),
1262  this,
1264  Simulator::Schedule(Seconds(7.0) + NanoSeconds(4000),
1266  this,
1268  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1269  // = 154.8us
1270  Simulator::Schedule(Seconds(7.0) + NanoSeconds(152799),
1272  this,
1274  Simulator::Schedule(Seconds(7.0) + NanoSeconds(152800),
1276  this,
1278  // No more packet should have been successfully received, and since preamble detection did not
1279  // pass the packet should not have been counted as a failure
1280  Simulator::Schedule(Seconds(7.1),
1282  this,
1283  1,
1284  2);
1285 
1286  // CASE 8: send two packets with second one 3 dB weaker at the exact same time and check PHY
1287  // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
1288  // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1289  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1290  // time to detect the preamble.
1291 
1292  Simulator::Schedule(Seconds(8.0),
1294  this,
1295  rxPowerDbm,
1296  1000,
1297  7);
1298  Simulator::Schedule(Seconds(8.0),
1300  this,
1301  rxPowerDbm - 3,
1302  1000,
1303  7);
1304  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1305  // CCA_BUSY
1306  Simulator::Schedule(Seconds(8.0) + NanoSeconds(3999),
1308  this,
1310  Simulator::Schedule(Seconds(8.0) + NanoSeconds(4000),
1312  this,
1314  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1315  Simulator::Schedule(Seconds(8.0) + NanoSeconds(152799),
1317  this,
1319  Simulator::Schedule(Seconds(8.0) + NanoSeconds(152800),
1321  this,
1323  // No more packet should have been successfully received, and since preamble detection did not
1324  // pass the packet should not have been counted as a failure
1325  Simulator::Schedule(Seconds(8.1),
1327  this,
1328  1,
1329  2);
1330 
1331  // CASE 9: send two packets with second one 6 dB weaker at the exact same time and check PHY
1332  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1333  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1334  // decode the modulation).
1335 
1336  Simulator::Schedule(Seconds(9.0),
1338  this,
1339  rxPowerDbm,
1340  1000,
1341  7);
1342  Simulator::Schedule(Seconds(9.0),
1344  this,
1345  rxPowerDbm - 6,
1346  1000,
1347  7);
1348  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1349  // CCA_BUSY
1350  Simulator::Schedule(Seconds(9.0) + NanoSeconds(3999),
1352  this,
1354  Simulator::Schedule(Seconds(9.0) + NanoSeconds(4000),
1356  this,
1358  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1359  // CCA_BUSY to RX
1360  Simulator::Schedule(Seconds(9.0) + NanoSeconds(43999),
1362  this,
1364  Simulator::Schedule(Seconds(9.0) + NanoSeconds(44000),
1366  this,
1368  // Since it takes 152.8us to transmit the packets, PHY should be back to IDLE at time 152.8us.
1369  Simulator::Schedule(Seconds(9.0) + NanoSeconds(152799),
1371  this,
1373  Simulator::Schedule(Seconds(9.0) + NanoSeconds(152800),
1375  this,
1377  // In this case, the first packet should be marked as a failure
1378  Simulator::Schedule(Seconds(9.1),
1380  this,
1381  1,
1382  3);
1383 
1384  // CASE 10: send two packets with second one 3 dB higher at the exact same time and check PHY
1385  // state: PHY preamble detection should switch because a higher packet is received within the
1386  // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1387  // lower than the threshold of 4 dB), PHY state should be CCA_BUSY since the total energy is
1388  // above CCA-ED (-62 dBm).
1389 
1390  Simulator::Schedule(Seconds(10.0),
1392  this,
1393  rxPowerDbm,
1394  1000,
1395  7);
1396  Simulator::Schedule(Seconds(10.0),
1398  this,
1399  rxPowerDbm + 3,
1400  1000,
1401  7);
1402  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1403  // CCA_BUSY
1404  Simulator::Schedule(Seconds(10.0) + NanoSeconds(3999),
1406  this,
1408  Simulator::Schedule(Seconds(10.0) + NanoSeconds(4000),
1410  this,
1412  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1413  Simulator::Schedule(Seconds(10.0) + NanoSeconds(152799),
1415  this,
1417  Simulator::Schedule(Seconds(10.0) + NanoSeconds(152800),
1419  this,
1421  // No more packet should have been successfully received, and since preamble detection did not
1422  // pass the packet should not have been counted as a failure
1423  Simulator::Schedule(Seconds(10.1),
1425  this,
1426  1,
1427  3);
1428 
1429  // CASE 11: send two packets with second one 6 dB higher at the exact same time and check PHY
1430  // state: PHY preamble detection should switch because a higher packet is received within the
1431  // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1432  // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1433  // decode the modulation).
1434 
1435  Simulator::Schedule(Seconds(11.0),
1437  this,
1438  rxPowerDbm,
1439  1000,
1440  7);
1441  Simulator::Schedule(Seconds(11.0),
1443  this,
1444  rxPowerDbm + 6,
1445  1000,
1446  7);
1447  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1448  // CCA_BUSY
1449  Simulator::Schedule(Seconds(11.0) + NanoSeconds(3999),
1451  this,
1453  Simulator::Schedule(Seconds(11.0) + NanoSeconds(4000),
1455  this,
1457  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1458  // CCA_BUSY to RX
1459  Simulator::Schedule(Seconds(11.0) + NanoSeconds(43999),
1461  this,
1463  Simulator::Schedule(Seconds(11.0) + NanoSeconds(44000),
1465  this,
1467  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1468  Simulator::Schedule(Seconds(11.0) + NanoSeconds(152799),
1470  this,
1472  Simulator::Schedule(Seconds(11.0) + NanoSeconds(152800),
1474  this,
1476  // In this case, the second packet should be marked as a failure
1477  Simulator::Schedule(Seconds(11.1),
1479  this,
1480  1,
1481  4);
1482 
1483  // CCA-PD < RX power < CCA-ED
1484  rxPowerDbm = -70;
1485 
1486  // CASE 12: send one packet and check PHY state:
1487  // All reception stages should succeed and PHY state should be RX for the duration of the packet
1488  // minus the time to detect the preamble, otherwise it should be IDLE.
1489 
1490  Simulator::Schedule(Seconds(12.0),
1492  this,
1493  rxPowerDbm,
1494  1000,
1495  7);
1496  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1497  // CCA_BUSY
1498  Simulator::Schedule(Seconds(12.0) + NanoSeconds(3999),
1500  this,
1502  Simulator::Schedule(Seconds(12.0) + NanoSeconds(4000),
1504  this,
1506  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1507  // CCA_BUSY to RX
1508  Simulator::Schedule(Seconds(12.0) + NanoSeconds(43999),
1510  this,
1512  Simulator::Schedule(Seconds(12.0) + NanoSeconds(44000),
1514  this,
1516  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
1517  Simulator::Schedule(Seconds(12.0) + NanoSeconds(152799),
1519  this,
1521  Simulator::Schedule(Seconds(12.0) + NanoSeconds(152800),
1523  this,
1525  // Packet should have been successfully received
1526  Simulator::Schedule(Seconds(12.1),
1528  this,
1529  2,
1530  4);
1531 
1532  // CASE 13: send two packets with same power within the 4us window and check PHY state:
1533  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
1534  // the threshold of 4 dB), and PHY state should be CCA_BUSY since it should detect the start of
1535  // a valid OFDM transmission at a receive level greater than or equal to the minimum modulation
1536  // and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
1537 
1538  Simulator::Schedule(Seconds(13.0),
1540  this,
1541  rxPowerDbm,
1542  1000,
1543  7);
1544  Simulator::Schedule(Seconds(13.0) + MicroSeconds(2.0),
1546  this,
1547  rxPowerDbm,
1548  1000,
1549  7);
1550  // At 4us, STA PHY STATE should stay IDLE
1551  Simulator::Schedule(Seconds(13.0) + MicroSeconds(4.0),
1553  this,
1555  // No more packet should have been successfully received, and since preamble detection did not
1556  // pass the packet should not have been counted as a failure
1557  Simulator::Schedule(Seconds(13.1),
1559  this,
1560  2,
1561  4);
1562 
1563  // CASE 14: send two packets with second one 3 dB weaker within the 4us window and check PHY
1564  // state: PHY preamble detection should fail PHY preamble detection should fail because SNR is
1565  // too low (around 3 dB, which is lower than the threshold of 4 dB), and PHY state should be
1566  // CCA_BUSY since it should detect the start of a valid OFDM transmission at a receive level
1567  // greater than or equal to the minimum modulation and coding rate sensitivity (–82 dBm for 20
1568  // MHz channel spacing).
1569 
1570  Simulator::Schedule(Seconds(14.0),
1572  this,
1573  rxPowerDbm,
1574  1000,
1575  7);
1576  Simulator::Schedule(Seconds(14.0) + MicroSeconds(2.0),
1578  this,
1579  rxPowerDbm - 3,
1580  1000,
1581  7);
1582  // At 4us, STA PHY STATE should stay IDLE
1583  Simulator::Schedule(Seconds(14.0) + MicroSeconds(4.0),
1585  this,
1587  // No more packet should have been successfully received, and since preamble detection did not
1588  // pass the packet should not have been counted as a failure
1589  Simulator::Schedule(Seconds(14.1),
1591  this,
1592  2,
1593  4);
1594 
1595  // CASE 15: send two packets with second one 6 dB weaker within the 4us window and check PHY
1596  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1597  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1598  // decode the modulation).
1599 
1600  Simulator::Schedule(Seconds(15.0),
1602  this,
1603  rxPowerDbm,
1604  1000,
1605  7);
1606  Simulator::Schedule(Seconds(15.0) + MicroSeconds(2.0),
1608  this,
1609  rxPowerDbm - 6,
1610  1000,
1611  7);
1612  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1613  // CCA_BUSY
1614  Simulator::Schedule(Seconds(15.0) + NanoSeconds(3999),
1616  this,
1618  Simulator::Schedule(Seconds(15.0) + NanoSeconds(4000),
1620  this,
1622  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1623  // CCA_BUSY to RX
1624  Simulator::Schedule(Seconds(15.0) + NanoSeconds(43999),
1626  this,
1628  Simulator::Schedule(Seconds(15.0) + NanoSeconds(44000),
1630  this,
1632  // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
1633  // 152.8us.
1634  Simulator::Schedule(Seconds(15.0) + NanoSeconds(152799),
1636  this,
1638  Simulator::Schedule(Seconds(15.0) + NanoSeconds(152800),
1640  this,
1642  // In this case, the first packet should be marked as a failure
1643  Simulator::Schedule(Seconds(15.1),
1645  this,
1646  2,
1647  5);
1648 
1649  // CASE 16: send two packets with second one 3 dB higher within the 4us window and check PHY
1650  // state: PHY preamble detection should switch because a higher packet is received within the
1651  // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1652  // lower than the threshold of 4 dB). and PHY state should be CCA_BUSY since it should detect
1653  // the start of a valid OFDM transmission at a receive level greater than or equal to the
1654  // minimum modulation and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
1655 
1656  Simulator::Schedule(Seconds(16.0),
1658  this,
1659  rxPowerDbm,
1660  1000,
1661  7);
1662  Simulator::Schedule(Seconds(16.0) + MicroSeconds(2.0),
1664  this,
1665  rxPowerDbm + 3,
1666  1000,
1667  7);
1668  // At 4us, STA PHY STATE should stay IDLE
1669  Simulator::Schedule(Seconds(16.0) + MicroSeconds(4.0),
1671  this,
1673  // At 6us, STA PHY STATE should be CCA_BUSY
1674  Simulator::Schedule(Seconds(16.0) + MicroSeconds(6.0),
1676  this,
1678  // No more packet should have been successfully received, and since preamble detection did not
1679  // pass the packet should not have been counted as a failure
1680  Simulator::Schedule(Seconds(16.1),
1682  this,
1683  2,
1684  5);
1685 
1686  // CASE 17: send two packets with second one 6 dB higher within the 4us window and check PHY
1687  // state: PHY preamble detection should switch because a higher packet is received within the
1688  // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1689  // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1690  // decode the modulation).
1691 
1692  Simulator::Schedule(Seconds(17.0),
1694  this,
1695  rxPowerDbm,
1696  1000,
1697  7);
1698  Simulator::Schedule(Seconds(17.0) + MicroSeconds(2.0),
1700  this,
1701  rxPowerDbm + 6,
1702  1000,
1703  7);
1704  // At 4us, STA PHY STATE should stay IDLE
1705  Simulator::Schedule(Seconds(17.0) + MicroSeconds(4.0),
1707  this,
1709  // At 6us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1710  // CCA_BUSY
1711  Simulator::Schedule(Seconds(17.0) + NanoSeconds(5999),
1713  this,
1715  Simulator::Schedule(Seconds(17.0) + NanoSeconds(6000),
1717  this,
1719  // At 46us, PHY header should be successfully received and STA PHY STATE should move from
1720  // CCA_BUSY to RX
1721  Simulator::Schedule(Seconds(17.0) + NanoSeconds(45999),
1723  this,
1725  Simulator::Schedule(Seconds(17.0) + NanoSeconds(46000),
1727  this,
1729  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1730  // = 154.8us
1731  Simulator::Schedule(Seconds(17.0) + NanoSeconds(154799),
1733  this,
1735  Simulator::Schedule(Seconds(17.0) + NanoSeconds(154800),
1737  this,
1739  // In this case, the second packet should be marked as a failure
1740  Simulator::Schedule(Seconds(17.1),
1742  this,
1743  2,
1744  6);
1745 
1746  rxPowerDbm = -50;
1747  // CASE 18: send two packets with second one 50 dB higher within the 4us window
1748 
1749  Simulator::Schedule(Seconds(18.0),
1751  this,
1752  rxPowerDbm,
1753  1000,
1754  7);
1755  Simulator::Schedule(Seconds(18.0) + MicroSeconds(2.0),
1757  this,
1758  rxPowerDbm + 50,
1759  1000,
1760  7);
1761  // The second packet should be received successfully
1762  Simulator::Schedule(Seconds(18.1),
1764  this,
1765  3,
1766  6);
1767 
1768  // CASE 19: send two packets with second one 10 dB higher within the 4us window
1769 
1770  Simulator::Schedule(Seconds(19.0),
1772  this,
1773  rxPowerDbm,
1774  1000,
1775  7);
1776  Simulator::Schedule(Seconds(19.0) + MicroSeconds(2.0),
1778  this,
1779  rxPowerDbm + 10,
1780  1000,
1781  7);
1782  // The second packet should be captured, but not decoded since SNR to low for used MCS
1783  Simulator::Schedule(Seconds(19.1),
1785  this,
1786  3,
1787  7);
1788 
1789  // CASE 20: send two packets with second one 50 dB higher in the same time
1790 
1791  Simulator::Schedule(Seconds(20.0),
1793  this,
1794  rxPowerDbm,
1795  1000,
1796  7);
1797  Simulator::Schedule(Seconds(20.0),
1799  this,
1800  rxPowerDbm + 50,
1801  1000,
1802  7);
1803  // The second packet should be received successfully, same as in CASE 13
1804  Simulator::Schedule(Seconds(20.1),
1806  this,
1807  4,
1808  7);
1809 
1810  // CASE 21: send two packets with second one 10 dB higher in the same time
1811 
1812  Simulator::Schedule(Seconds(21.0),
1814  this,
1815  rxPowerDbm,
1816  1000,
1817  7);
1818  Simulator::Schedule(Seconds(21.0),
1820  this,
1821  rxPowerDbm + 10,
1822  1000,
1823  7);
1824  // The second packet should be captured, but not decoded since SNR to low for used MCS, same as
1825  // in CASE 19
1826  Simulator::Schedule(Seconds(21.1),
1828  this,
1829  4,
1830  8);
1831 
1832  Simulator::Run();
1833  Simulator::Destroy();
1834 }
1835 
1843 {
1844  public:
1846 
1847  private:
1848  void DoSetup() override;
1849  void DoRun() override;
1850 
1854  void Reset();
1862  void RxSuccess(Ptr<const WifiPsdu> psdu,
1863  RxSignalInfo rxSignalInfo,
1864  WifiTxVector txVector,
1865  std::vector<bool> statusPerMpdu);
1872 
1884  void Expect1000BPacketDropped();
1888  void Expect1500BPacketDropped();
1889 
1890  bool m_rxSuccess1000B{false};
1891  bool m_rxSuccess1500B{false};
1892  bool m_rxDropped1000B{false};
1893  bool m_rxDropped1500B{false};
1894 };
1895 
1897  : WifiPhyReceptionTest("Simple frame capture model test")
1898 {
1899 }
1900 
1901 void
1903  RxSignalInfo rxSignalInfo,
1904  WifiTxVector txVector,
1905  std::vector<bool> statusPerMpdu)
1906 {
1907  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1908  NS_ASSERT(!psdu->IsAggregate() || psdu->IsSingle());
1909  if (psdu->GetSize() == 1030)
1910  {
1911  m_rxSuccess1000B = true;
1912  }
1913  else if (psdu->GetSize() == 1530)
1914  {
1915  m_rxSuccess1500B = true;
1916  }
1917 }
1918 
1919 void
1921 {
1922  NS_LOG_FUNCTION(this << p << reason);
1923  if (p->GetSize() == 1030)
1924  {
1925  m_rxDropped1000B = true;
1926  }
1927  else if (p->GetSize() == 1530)
1928  {
1929  m_rxDropped1500B = true;
1930  }
1931 }
1932 
1933 void
1935 {
1936  m_rxSuccess1000B = false;
1937  m_rxSuccess1500B = false;
1938  m_rxDropped1000B = false;
1939  m_rxDropped1500B = false;
1940 }
1941 
1942 void
1944 {
1945  NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1000B, true, "Didn't receive 1000B packet");
1946 }
1947 
1948 void
1950 {
1951  NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1500B, true, "Didn't receive 1500B packet");
1952 }
1953 
1954 void
1956 {
1957  NS_TEST_ASSERT_MSG_EQ(m_rxDropped1000B, true, "Didn't drop 1000B packet");
1958 }
1959 
1960 void
1962 {
1963  NS_TEST_ASSERT_MSG_EQ(m_rxDropped1500B, true, "Didn't drop 1500B packet");
1964 }
1965 
1966 void
1968 {
1970 
1972  m_phy->TraceConnectWithoutContext("PhyRxDrop",
1974 
1975  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
1976  CreateObject<ThresholdPreambleDetectionModel>();
1977  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(2));
1978  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
1979 
1980  Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
1981  frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
1982  frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
1983  m_phy->SetFrameCaptureModel(frameCaptureModel);
1984 }
1985 
1986 void
1988 {
1989  RngSeedManager::SetSeed(1);
1990  RngSeedManager::SetRun(1);
1991  int64_t streamNumber = 2;
1992  double rxPowerDbm = -30;
1993  m_phy->AssignStreams(streamNumber);
1994 
1995  // CASE 1: send two packets with same power within the capture window:
1996  // PHY should not switch reception because they have same power.
1997 
1998  Simulator::Schedule(Seconds(1.0),
2000  this,
2001  rxPowerDbm,
2002  1000,
2003  0);
2004  Simulator::Schedule(Seconds(1.0) + MicroSeconds(10.0),
2006  this,
2007  rxPowerDbm,
2008  1500,
2009  0);
2010  Simulator::Schedule(Seconds(1.1), &TestSimpleFrameCaptureModel::Expect1500BPacketDropped, this);
2011  Simulator::Schedule(Seconds(1.2), &TestSimpleFrameCaptureModel::Reset, this);
2012 
2013  // CASE 2: send two packets with second one 6 dB weaker within the capture window:
2014  // PHY should not switch reception because first one has higher power.
2015 
2016  Simulator::Schedule(Seconds(2.0),
2018  this,
2019  rxPowerDbm,
2020  1000,
2021  0);
2022  Simulator::Schedule(Seconds(2.0) + MicroSeconds(10.0),
2024  this,
2025  rxPowerDbm - 6,
2026  1500,
2027  0);
2028  Simulator::Schedule(Seconds(2.1),
2030  this);
2031  Simulator::Schedule(Seconds(2.1), &TestSimpleFrameCaptureModel::Expect1500BPacketDropped, this);
2032  Simulator::Schedule(Seconds(2.2), &TestSimpleFrameCaptureModel::Reset, this);
2033 
2034  // CASE 3: send two packets with second one 6 dB higher within the capture window:
2035  // PHY should switch reception because the second one has a higher power.
2036 
2037  Simulator::Schedule(Seconds(3.0),
2039  this,
2040  rxPowerDbm,
2041  1000,
2042  0);
2043  Simulator::Schedule(Seconds(3.0) + MicroSeconds(10.0),
2045  this,
2046  rxPowerDbm + 6,
2047  1500,
2048  0);
2049  Simulator::Schedule(Seconds(3.1), &TestSimpleFrameCaptureModel::Expect1000BPacketDropped, this);
2050  Simulator::Schedule(Seconds(3.1),
2052  this);
2053  Simulator::Schedule(Seconds(3.2), &TestSimpleFrameCaptureModel::Reset, this);
2054 
2055  // CASE 4: send two packets with second one 6 dB higher after the capture window:
2056  // PHY should not switch reception because capture window duration has elapsed when the second
2057  // packet arrives.
2058 
2059  Simulator::Schedule(Seconds(4.0),
2061  this,
2062  rxPowerDbm,
2063  1000,
2064  0);
2065  Simulator::Schedule(Seconds(4.0) + MicroSeconds(25.0),
2067  this,
2068  rxPowerDbm + 6,
2069  1500,
2070  0);
2071  Simulator::Schedule(Seconds(4.1), &TestSimpleFrameCaptureModel::Expect1500BPacketDropped, this);
2072  Simulator::Schedule(Seconds(4.2), &TestSimpleFrameCaptureModel::Reset, this);
2073 
2074  Simulator::Run();
2075  Simulator::Destroy();
2076 }
2077 
2085 {
2086  public:
2088 
2089  private:
2090  void DoRun() override;
2091 };
2092 
2094  : WifiPhyReceptionTest("PHY headers reception test")
2095 {
2096 }
2097 
2098 void
2100 {
2101  RngSeedManager::SetSeed(1);
2102  RngSeedManager::SetRun(1);
2103  int64_t streamNumber = 0;
2104  m_phy->AssignStreams(streamNumber);
2105 
2106  // RX power > CCA-ED
2107  double rxPowerDbm = -50;
2108 
2109  // CASE 1: send one packet followed by a second one with same power between the end of the 4us
2110  // preamble detection window and the start of L-SIG of the first packet: reception should be
2111  // aborted since L-SIG cannot be decoded (SNR too low).
2112 
2113  Simulator::Schedule(Seconds(1.0),
2115  this,
2116  rxPowerDbm,
2117  1000,
2118  7);
2119  Simulator::Schedule(Seconds(1.0) + MicroSeconds(10),
2121  this,
2122  rxPowerDbm,
2123  1000,
2124  7);
2125  // At 10 us, STA PHY STATE should be CCA_BUSY.
2126  Simulator::Schedule(Seconds(1.0) + MicroSeconds(10.0),
2128  this,
2130  // At 44us (end of PHY header), STA PHY STATE should not have moved to RX and be kept to
2131  // CCA_BUSY.
2132  Simulator::Schedule(Seconds(1.0) + NanoSeconds(44000),
2134  this,
2136  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8 + 10
2137  // = 162.8us.
2138  Simulator::Schedule(Seconds(1.0) + NanoSeconds(162799),
2140  this,
2142  Simulator::Schedule(Seconds(1.0) + NanoSeconds(162800),
2144  this,
2146 
2147  // CASE 2: send one packet followed by a second one 3 dB weaker between the end of the 4us
2148  // preamble detection window and the start of L-SIG of the first packet: reception should not be
2149  // aborted since L-SIG can be decoded (SNR high enough).
2150 
2151  Simulator::Schedule(Seconds(2.0),
2153  this,
2154  rxPowerDbm,
2155  1000,
2156  7);
2157  Simulator::Schedule(Seconds(2.0) + MicroSeconds(10),
2159  this,
2160  rxPowerDbm - 3,
2161  1000,
2162  7);
2163  // At 10 us, STA PHY STATE should be CCA_BUSY.
2164  Simulator::Schedule(Seconds(2.0) + MicroSeconds(10.0),
2166  this,
2168  // At 44us (end of PHY header), STA PHY STATE should have moved to RX since PHY header reception
2169  // should have succeeded.
2170  Simulator::Schedule(Seconds(2.0) + NanoSeconds(43999),
2172  this,
2174  Simulator::Schedule(Seconds(2.0) + NanoSeconds(44000),
2176  this,
2178  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
2179  // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
2180  // should first be seen as CCA_BUSY for 10us.
2181  Simulator::Schedule(Seconds(2.0) + NanoSeconds(152799),
2183  this,
2185  Simulator::Schedule(Seconds(2.0) + NanoSeconds(152800),
2187  this,
2189  Simulator::Schedule(Seconds(2.0) + NanoSeconds(162799),
2191  this,
2193  Simulator::Schedule(Seconds(2.0) + NanoSeconds(162800),
2195  this,
2197 
2198  // CASE 3: send one packet followed by a second one with same power between the end of L-SIG and
2199  // the start of HE-SIG of the first packet: PHY header reception should not succeed but PHY
2200  // should stay in RX state for the duration estimated from L-SIG.
2201 
2202  Simulator::Schedule(Seconds(3.0),
2204  this,
2205  rxPowerDbm,
2206  1000,
2207  7);
2208  Simulator::Schedule(Seconds(3.0) + MicroSeconds(25),
2210  this,
2211  rxPowerDbm,
2212  1000,
2213  7);
2214  // At 44us (end of PHY header), STA PHY STATE should not have moved to RX (HE-SIG failed) and be
2215  // kept to CCA_BUSY.
2216  Simulator::Schedule(Seconds(3.0) + MicroSeconds(44.0),
2218  this,
2220  // STA PHY STATE should move back to IDLE once the duration estimated from L-SIG has elapsed,
2221  // i.e. at 152.8us. However, since there is a second packet transmitted with a power above
2222  // CCA-ED (-62 dBm), PHY should first be seen as CCA_BUSY for 25us.
2223  Simulator::Schedule(Seconds(3.0) + NanoSeconds(152799),
2225  this,
2227  Simulator::Schedule(Seconds(3.0) + NanoSeconds(152800),
2229  this,
2231  Simulator::Schedule(Seconds(3.0) + NanoSeconds(177799),
2233  this,
2235  Simulator::Schedule(Seconds(3.0) + NanoSeconds(177800),
2237  this,
2239 
2240  // CASE 4: send one packet followed by a second one 3 dB weaker between the end of L-SIG and the
2241  // start of HE-SIG of the first packet: PHY header reception should succeed.
2242 
2243  Simulator::Schedule(Seconds(4.0),
2245  this,
2246  rxPowerDbm,
2247  1000,
2248  7);
2249  Simulator::Schedule(Seconds(4.0) + MicroSeconds(25),
2251  this,
2252  rxPowerDbm - 3,
2253  1000,
2254  7);
2255  // At 10 us, STA PHY STATE should be CCA_BUSY.
2256  Simulator::Schedule(Seconds(4.0) + MicroSeconds(10.0),
2258  this,
2260  // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2261  // should have succeeded.
2262  Simulator::Schedule(Seconds(4.0) + NanoSeconds(43999),
2264  this,
2266  Simulator::Schedule(Seconds(4.0) + NanoSeconds(44000),
2268  this,
2270  // STA PHY STATE should move back to IDLE once the duration estimated from L-SIG has elapsed,
2271  // i.e. at 152.8us. However, since there is a second packet transmitted with a power above
2272  // CCA-ED (-62 dBm), PHY should first be seen as CCA_BUSY for 25us.
2273  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152799),
2275  this,
2277  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152800),
2279  this,
2281  Simulator::Schedule(Seconds(4.0) + NanoSeconds(177799),
2283  this,
2285  Simulator::Schedule(Seconds(4.0) + NanoSeconds(177800),
2287  this,
2289 
2290  // RX power < CCA-ED
2291  rxPowerDbm = -70;
2292 
2293  // CASE 5: send one packet followed by a second one with same power between the end of the 4us
2294  // preamble detection window and the start of L-SIG of the first packet: reception should be
2295  // aborted since L-SIG cannot be decoded (SNR too low).
2296 
2297  Simulator::Schedule(Seconds(5.0),
2299  this,
2300  rxPowerDbm,
2301  1000,
2302  7);
2303  Simulator::Schedule(Seconds(5.0) + MicroSeconds(10),
2305  this,
2306  rxPowerDbm,
2307  1000,
2308  7);
2309  // At 10 us, STA PHY STATE should be CCA_BUSY.
2310  Simulator::Schedule(Seconds(5.0) + MicroSeconds(10.0),
2312  this,
2314  // At 24us (end of L-SIG), STA PHY STATE stay CCA_BUSY because L-SIG reception failed and the
2315  // start of a valid OFDM transmission has been detected
2316  Simulator::Schedule(Seconds(5.0) + NanoSeconds(24000),
2318  this,
2320 
2321  // CASE 6: send one packet followed by a second one 3 dB weaker between the end of the 4us
2322  // preamble detection window and the start of L-SIG of the first packet: reception should not be
2323  // aborted since L-SIG can be decoded (SNR high enough).
2324 
2325  Simulator::Schedule(Seconds(6.0),
2327  this,
2328  rxPowerDbm,
2329  1000,
2330  7);
2331  Simulator::Schedule(Seconds(6.0) + MicroSeconds(10),
2333  this,
2334  rxPowerDbm - 3,
2335  1000,
2336  7);
2337  // At 10 us, STA PHY STATE should be CCA_BUSY.
2338  Simulator::Schedule(Seconds(6.0) + MicroSeconds(10.0),
2340  this,
2342  // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2343  // succeeded.
2344  Simulator::Schedule(Seconds(6.0) + MicroSeconds(24.0),
2346  this,
2348  // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2349  // should have succeeded.
2350  Simulator::Schedule(Seconds(6.0) + NanoSeconds(43999),
2352  this,
2354  Simulator::Schedule(Seconds(6.0) + NanoSeconds(44000),
2356  this,
2358  // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
2359  // 152.8us.
2360  Simulator::Schedule(Seconds(6.0) + NanoSeconds(152799),
2362  this,
2364  Simulator::Schedule(Seconds(6.0) + NanoSeconds(152800),
2366  this,
2368 
2369  // CASE 7: send one packet followed by a second one with same power between the end of L-SIG and
2370  // the start of HE-SIG of the first packet: PHY header reception should not succeed but PHY
2371  // should stay in RX state for the duration estimated from L-SIG.
2372 
2373  Simulator::Schedule(Seconds(7.0),
2375  this,
2376  rxPowerDbm,
2377  1000,
2378  7);
2379  Simulator::Schedule(Seconds(7.0) + MicroSeconds(25),
2381  this,
2382  rxPowerDbm,
2383  1000,
2384  7);
2385  // At 10 us, STA PHY STATE should be CCA_BUSY.
2386  Simulator::Schedule(Seconds(7.0) + MicroSeconds(10.0),
2388  this,
2390  // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2391  // succeeded.
2392  Simulator::Schedule(Seconds(7.0) + MicroSeconds(24.0),
2394  this,
2396  // At 44 us (end of HE-SIG), STA PHY STATE should be not have moved to RX since reception of
2397  // HE-SIG should have failed.
2398  Simulator::Schedule(Seconds(7.0) + MicroSeconds(44.0),
2400  this,
2402  // STA PHY STATE should keep CCA_BUSY once the duration estimated from L-SIG has elapsed, i.e.
2403  // at 152.8us.
2404  Simulator::Schedule(Seconds(7.0) + NanoSeconds(152800),
2406  this,
2408 
2409  // CASE 8: send one packet followed by a second one 3 dB weaker between the end of L-SIG and the
2410  // start of HE-SIG of the first packet: PHY header reception should succeed.
2411 
2412  Simulator::Schedule(Seconds(8.0),
2414  this,
2415  rxPowerDbm,
2416  1000,
2417  7);
2418  Simulator::Schedule(Seconds(8.0) + MicroSeconds(25),
2420  this,
2421  rxPowerDbm - 3,
2422  1000,
2423  7);
2424  // At 10 us, STA PHY STATE should be CCA_BUSY.
2425  Simulator::Schedule(Seconds(8.0) + MicroSeconds(10.0),
2427  this,
2429  // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2430  // succeeded.
2431  Simulator::Schedule(Seconds(8.0) + MicroSeconds(24.0),
2433  this,
2435  // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2436  // should have succeeded.
2437  Simulator::Schedule(Seconds(8.0) + NanoSeconds(43999),
2439  this,
2441  Simulator::Schedule(Seconds(8.0) + NanoSeconds(44000),
2443  this,
2445  // STA PHY STATE should move back to CCA_BUSY once the duration estimated from L-SIG has
2446  // elapsed, i.e. at 152.8us.
2447  Simulator::Schedule(Seconds(8.0) + NanoSeconds(152799),
2449  this,
2451  Simulator::Schedule(Seconds(8.0) + NanoSeconds(152800),
2453  this,
2455 
2456  Simulator::Run();
2457  Simulator::Destroy();
2458 }
2459 
2467 {
2468  public:
2470 
2471  private:
2472  void DoSetup() override;
2473  void DoRun() override;
2474 
2482  void RxSuccess(Ptr<const WifiPsdu> psdu,
2483  RxSignalInfo rxSignalInfo,
2484  WifiTxVector txVector,
2485  std::vector<bool> statusPerMpdu);
2490  void RxFailure(Ptr<const WifiPsdu> psdu);
2501  void IncrementSuccessBitmap(uint32_t size);
2506  void IncrementFailureBitmap(uint32_t size);
2507 
2511  void ResetBitmaps();
2512 
2520  void SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize);
2521 
2526  void CheckRxSuccessBitmapAmpdu1(uint8_t expected);
2531  void CheckRxSuccessBitmapAmpdu2(uint8_t expected);
2536  void CheckRxFailureBitmapAmpdu1(uint8_t expected);
2541  void CheckRxFailureBitmapAmpdu2(uint8_t expected);
2546  void CheckRxDroppedBitmapAmpdu1(uint8_t expected);
2551  void CheckRxDroppedBitmapAmpdu2(uint8_t expected);
2552 
2557  void CheckPhyState(WifiPhyState expectedState);
2558 
2561 
2564 
2567 };
2568 
2570  : WifiPhyReceptionTest("A-MPDU reception test")
2571 {
2572 }
2573 
2574 void
2576 {
2583 }
2584 
2585 void
2587  RxSignalInfo rxSignalInfo,
2588  WifiTxVector txVector,
2589  std::vector<bool> statusPerMpdu)
2590 {
2591  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
2592  if (statusPerMpdu.empty()) // wait for the whole A-MPDU
2593  {
2594  return;
2595  }
2596  NS_ABORT_MSG_IF(psdu->GetNMpdus() != statusPerMpdu.size(),
2597  "Should have one receive status per MPDU");
2598  auto rxOkForMpdu = statusPerMpdu.begin();
2599  for (auto mpdu = psdu->begin(); mpdu != psdu->end(); ++mpdu)
2600  {
2601  if (*rxOkForMpdu)
2602  {
2603  IncrementSuccessBitmap((*mpdu)->GetSize());
2604  }
2605  else
2606  {
2607  IncrementFailureBitmap((*mpdu)->GetSize());
2608  }
2609  ++rxOkForMpdu;
2610  }
2611 }
2612 
2613 void
2615 {
2616  if (size == 1030) // A-MPDU 1 - MPDU #1
2617  {
2619  }
2620  else if (size == 1130) // A-MPDU 1 - MPDU #2
2621  {
2622  m_rxSuccessBitmapAmpdu1 |= (1 << 1);
2623  }
2624  else if (size == 1230) // A-MPDU 1 - MPDU #3
2625  {
2626  m_rxSuccessBitmapAmpdu1 |= (1 << 2);
2627  }
2628  else if (size == 1330) // A-MPDU 2 - MPDU #1
2629  {
2631  }
2632  else if (size == 1430) // A-MPDU 2 - MPDU #2
2633  {
2634  m_rxSuccessBitmapAmpdu2 |= (1 << 1);
2635  }
2636  else if (size == 1530) // A-MPDU 2 - MPDU #3
2637  {
2638  m_rxSuccessBitmapAmpdu2 |= (1 << 2);
2639  }
2640 }
2641 
2642 void
2644 {
2645  NS_LOG_FUNCTION(this << *psdu);
2646  for (auto mpdu = psdu->begin(); mpdu != psdu->end(); ++mpdu)
2647  {
2648  IncrementFailureBitmap((*mpdu)->GetSize());
2649  }
2650 }
2651 
2652 void
2654 {
2655  if (size == 1030) // A-MPDU 1 - MPDU #1
2656  {
2658  }
2659  else if (size == 1130) // A-MPDU 1 - MPDU #2
2660  {
2661  m_rxFailureBitmapAmpdu1 |= (1 << 1);
2662  }
2663  else if (size == 1230) // A-MPDU 1 - MPDU #3
2664  {
2665  m_rxFailureBitmapAmpdu1 |= (1 << 2);
2666  }
2667  else if (size == 1330) // A-MPDU 2 - MPDU #1
2668  {
2670  }
2671  else if (size == 1430) // A-MPDU 2 - MPDU #2
2672  {
2673  m_rxFailureBitmapAmpdu2 |= (1 << 1);
2674  }
2675  else if (size == 1530) // A-MPDU 2 - MPDU #3
2676  {
2677  m_rxFailureBitmapAmpdu2 |= (1 << 2);
2678  }
2679 }
2680 
2681 void
2683 {
2684  NS_LOG_FUNCTION(this << p << reason);
2685  if (p->GetSize() == 1030) // A-MPDU 1 - MPDU #1
2686  {
2688  }
2689  else if (p->GetSize() == 1130) // A-MPDU 1 - MPDU #2
2690  {
2691  m_rxDroppedBitmapAmpdu1 |= (1 << 1);
2692  }
2693  else if (p->GetSize() == 1230) // A-MPDU 1 - MPDU #3
2694  {
2695  m_rxDroppedBitmapAmpdu1 |= (1 << 2);
2696  }
2697  else if (p->GetSize() == 1330) // A-MPDU 2 - MPDU #1
2698  {
2700  }
2701  else if (p->GetSize() == 1430) // A-MPDU 2 - MPDU #2
2702  {
2703  m_rxDroppedBitmapAmpdu2 |= (1 << 1);
2704  }
2705  else if (p->GetSize() == 1530) // A-MPDU 2 - MPDU #3
2706  {
2707  m_rxDroppedBitmapAmpdu2 |= (1 << 2);
2708  }
2709 }
2710 
2711 void
2713 {
2715  expected,
2716  "RX success bitmap for A-MPDU 1 is not as expected");
2717 }
2718 
2719 void
2721 {
2723  expected,
2724  "RX success bitmap for A-MPDU 2 is not as expected");
2725 }
2726 
2727 void
2729 {
2731  expected,
2732  "RX failure bitmap for A-MPDU 1 is not as expected");
2733 }
2734 
2735 void
2737 {
2739  expected,
2740  "RX failure bitmap for A-MPDU 2 is not as expected");
2741 }
2742 
2743 void
2745 {
2747  expected,
2748  "RX dropped bitmap for A-MPDU 1 is not as expected");
2749 }
2750 
2751 void
2753 {
2755  expected,
2756  "RX dropped bitmap for A-MPDU 2 is not as expected");
2757 }
2758 
2759 void
2761 {
2762  WifiPhyState currentState;
2763  PointerValue ptr;
2764  m_phy->GetAttribute("State", ptr);
2765  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
2766  currentState = state->GetState();
2767  NS_TEST_ASSERT_MSG_EQ(currentState,
2768  expectedState,
2769  "PHY State " << currentState << " does not match expected state "
2770  << expectedState << " at " << Simulator::Now());
2771 }
2772 
2773 void
2774 TestAmpduReception::SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize)
2775 {
2776  WifiTxVector txVector =
2777  WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, true);
2778 
2779  WifiMacHeader hdr;
2781  hdr.SetQosTid(0);
2782 
2783  std::vector<Ptr<WifiMpdu>> mpduList;
2784  for (size_t i = 0; i < 3; ++i)
2785  {
2786  Ptr<Packet> p = Create<Packet>(referencePacketSize + i * 100);
2787  mpduList.push_back(Create<WifiMpdu>(p, hdr));
2788  }
2789  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(mpduList);
2790 
2791  Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
2792 
2793  Ptr<WifiPpdu> ppdu =
2794  Create<HePpdu>(psdu, txVector, m_phy->GetOperatingChannel(), txDuration, m_uid++);
2795 
2796  Ptr<SpectrumValue> txPowerSpectrum =
2797  WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
2798  CHANNEL_WIDTH,
2799  DbmToW(rxPowerDbm),
2800  GUARD_WIDTH);
2801 
2802  Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
2803  txParams->psd = txPowerSpectrum;
2804  txParams->txPhy = nullptr;
2805  txParams->duration = txDuration;
2806  txParams->ppdu = ppdu;
2807 
2808  m_phy->StartRx(txParams, nullptr);
2809 }
2810 
2811 void
2813 {
2815 
2818  m_phy->TraceConnectWithoutContext("PhyRxDrop",
2820 
2821  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2822  CreateObject<ThresholdPreambleDetectionModel>();
2823  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(2));
2824  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2825 
2826  Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
2827  frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
2828  frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
2829  m_phy->SetFrameCaptureModel(frameCaptureModel);
2830 }
2831 
2832 void
2834 {
2835  RngSeedManager::SetSeed(1);
2836  RngSeedManager::SetRun(2);
2837  int64_t streamNumber = 1;
2838  double rxPowerDbm = -30;
2839  m_phy->AssignStreams(streamNumber);
2840 
2842  // CASE 1: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
2843  // power under RX sensitivity. The second A-MPDU is received 2 microseconds after the first
2844  // A-MPDU (i.e. during preamble detection).
2846 
2847  // A-MPDU 1
2848  Simulator::Schedule(Seconds(1.0),
2850  this,
2851  rxPowerDbm - 100,
2852  1000);
2853 
2854  // A-MPDU 2
2855  Simulator::Schedule(Seconds(1.0) + MicroSeconds(2),
2857  this,
2858  rxPowerDbm,
2859  1300);
2860 
2861  // All MPDUs of A-MPDU 1 should have been ignored.
2862  Simulator::Schedule(Seconds(1.1),
2864  this,
2865  0b00000000);
2866  Simulator::Schedule(Seconds(1.1),
2868  this,
2869  0b00000000);
2870  Simulator::Schedule(Seconds(1.1),
2872  this,
2873  0b00000000);
2874 
2875  // All MPDUs of A-MPDU 2 should have been successfully received.
2876  Simulator::Schedule(Seconds(1.1),
2878  this,
2879  0b00000111);
2880  Simulator::Schedule(Seconds(1.1),
2882  this,
2883  0b00000000);
2884  Simulator::Schedule(Seconds(1.1),
2886  this,
2887  0b00000000);
2888 
2889  Simulator::Schedule(Seconds(1.2), &TestAmpduReception::ResetBitmaps, this);
2890 
2892  // CASE 2: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
2893  // with power under RX sensitivity. The second A-MPDU is received 2 microseconds after the first
2894  // A-MPDU (i.e. during preamble detection).
2896 
2897  // A-MPDU 1
2898  Simulator::Schedule(Seconds(2.0),
2900  this,
2901  rxPowerDbm,
2902  1000);
2903 
2904  // A-MPDU 2
2905  Simulator::Schedule(Seconds(2.0) + MicroSeconds(2),
2907  this,
2908  rxPowerDbm - 100,
2909  1300);
2910 
2911  // All MPDUs of A-MPDU 1 should have been received.
2912  Simulator::Schedule(Seconds(2.1),
2914  this,
2915  0b00000111);
2916  Simulator::Schedule(Seconds(2.1),
2918  this,
2919  0b00000000);
2920  Simulator::Schedule(Seconds(2.1),
2922  this,
2923  0b00000000);
2924 
2925  // All MPDUs of A-MPDU 2 should have been ignored.
2926  Simulator::Schedule(Seconds(2.1),
2928  this,
2929  0b00000000);
2930  Simulator::Schedule(Seconds(2.1),
2932  this,
2933  0b00000000);
2934  Simulator::Schedule(Seconds(2.1),
2936  this,
2937  0b00000000);
2938 
2939  Simulator::Schedule(Seconds(2.2), &TestAmpduReception::ResetBitmaps, this);
2940 
2942  // CASE 3: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
2943  // power under RX sensitivity. The second A-MPDU is received 10 microseconds after the first
2944  // A-MPDU (i.e. during the frame capture window).
2946 
2947  // A-MPDU 1
2948  Simulator::Schedule(Seconds(3.0),
2950  this,
2951  rxPowerDbm - 100,
2952  1000);
2953 
2954  // A-MPDU 2
2955  Simulator::Schedule(Seconds(3.0) + MicroSeconds(10),
2957  this,
2958  rxPowerDbm,
2959  1300);
2960 
2961  // All MPDUs of A-MPDU 1 should have been ignored.
2962  Simulator::Schedule(Seconds(3.1),
2964  this,
2965  0b00000000);
2966  Simulator::Schedule(Seconds(3.1),
2968  this,
2969  0b00000000);
2970  Simulator::Schedule(Seconds(3.1),
2972  this,
2973  0b00000000);
2974 
2975  // All MPDUs of A-MPDU 2 should have been successfully received.
2976  Simulator::Schedule(Seconds(3.1),
2978  this,
2979  0b00000111);
2980  Simulator::Schedule(Seconds(3.1),
2982  this,
2983  0b00000000);
2984  Simulator::Schedule(Seconds(3.1),
2986  this,
2987  0b00000000);
2988 
2989  Simulator::Schedule(Seconds(3.2), &TestAmpduReception::ResetBitmaps, this);
2990 
2992  // CASE 4: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
2993  // with power under RX sensitivity. The second A-MPDU is received 10 microseconds after the
2994  // first A-MPDU (i.e. during the frame capture window).
2996 
2997  // A-MPDU 1
2998  Simulator::Schedule(Seconds(4.0),
3000  this,
3001  rxPowerDbm,
3002  1000);
3003 
3004  // A-MPDU 2
3005  Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
3007  this,
3008  rxPowerDbm - 100,
3009  1300);
3010 
3011  // All MPDUs of A-MPDU 1 should have been received.
3012  Simulator::Schedule(Seconds(4.1),
3014  this,
3015  0b00000111);
3016  Simulator::Schedule(Seconds(4.1),
3018  this,
3019  0b00000000);
3020  Simulator::Schedule(Seconds(4.1),
3022  this,
3023  0b00000000);
3024 
3025  // All MPDUs of A-MPDU 2 should have been ignored.
3026  Simulator::Schedule(Seconds(4.1),
3028  this,
3029  0b00000000);
3030  Simulator::Schedule(Seconds(4.1),
3032  this,
3033  0b00000000);
3034  Simulator::Schedule(Seconds(4.1),
3036  this,
3037  0b00000000);
3038 
3039  Simulator::Schedule(Seconds(4.2), &TestAmpduReception::ResetBitmaps, this);
3040 
3042  // CASE 5: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3043  // power under RX sensitivity. The second A-MPDU is received 100 microseconds after the first
3044  // A-MPDU (i.e. after the frame capture window, during the payload of MPDU #1).
3046 
3047  // A-MPDU 1
3048  Simulator::Schedule(Seconds(5.0),
3050  this,
3051  rxPowerDbm - 100,
3052  1000);
3053 
3054  // A-MPDU 2
3055  Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
3057  this,
3058  rxPowerDbm,
3059  1300);
3060 
3061  // All MPDUs of A-MPDU 1 should have been ignored.
3062  Simulator::Schedule(Seconds(5.1),
3064  this,
3065  0b00000000);
3066  Simulator::Schedule(Seconds(5.1),
3068  this,
3069  0b00000000);
3070  Simulator::Schedule(Seconds(5.1),
3072  this,
3073  0b00000000);
3074 
3075  // All MPDUs of A-MPDU 2 should have been successfully received.
3076  Simulator::Schedule(Seconds(5.1),
3078  this,
3079  0b00000111);
3080  Simulator::Schedule(Seconds(5.1),
3082  this,
3083  0b00000000);
3084  Simulator::Schedule(Seconds(5.1),
3086  this,
3087  0b00000000);
3088 
3089  Simulator::Schedule(Seconds(5.2), &TestAmpduReception::ResetBitmaps, this);
3090 
3092  // CASE 6: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3093  // with power under RX sensitivity. The second A-MPDU is received 100 microseconds after the
3094  // first A-MPDU (i.e. after the frame capture window, during the payload of MPDU #1).
3096 
3097  // A-MPDU 1
3098  Simulator::Schedule(Seconds(6.0),
3100  this,
3101  rxPowerDbm,
3102  1000);
3103 
3104  // A-MPDU 2
3105  Simulator::Schedule(Seconds(6.0) + MicroSeconds(100),
3107  this,
3108  rxPowerDbm - 100,
3109  1300);
3110 
3111  // All MPDUs of A-MPDU 1 should have been received.
3112  Simulator::Schedule(Seconds(6.1),
3114  this,
3115  0b00000111);
3116  Simulator::Schedule(Seconds(6.1),
3118  this,
3119  0b00000000);
3120  Simulator::Schedule(Seconds(6.1),
3122  this,
3123  0b00000000);
3124 
3125  // All MPDUs of A-MPDU 2 should have been ignored.
3126  Simulator::Schedule(Seconds(6.1),
3128  this,
3129  0b00000000);
3130  Simulator::Schedule(Seconds(6.1),
3132  this,
3133  0b00000000);
3134  Simulator::Schedule(Seconds(6.1),
3136  this,
3137  0b00000000);
3138 
3139  Simulator::Schedule(Seconds(6.2), &TestAmpduReception::ResetBitmaps, this);
3140 
3142  // CASE 7: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3143  // power under RX sensitivity. The second A-MPDU is received during the payload of MPDU #2.
3145 
3146  // A-MPDU 1
3147  Simulator::Schedule(Seconds(7.0),
3149  this,
3150  rxPowerDbm - 100,
3151  1000);
3152 
3153  // A-MPDU 2
3154  Simulator::Schedule(Seconds(7.0) + NanoSeconds(1100000),
3156  this,
3157  rxPowerDbm,
3158  1300);
3159 
3160  // All MPDUs of A-MPDU 1 should have been ignored.
3161  Simulator::Schedule(Seconds(7.1),
3163  this,
3164  0b00000000);
3165  Simulator::Schedule(Seconds(7.1),
3167  this,
3168  0b00000000);
3169  Simulator::Schedule(Seconds(7.1),
3171  this,
3172  0b00000000);
3173 
3174  // All MPDUs of A-MPDU 2 should have been successfully received.
3175  Simulator::Schedule(Seconds(7.1),
3177  this,
3178  0b00000111);
3179  Simulator::Schedule(Seconds(7.1),
3181  this,
3182  0b00000000);
3183  Simulator::Schedule(Seconds(7.1),
3185  this,
3186  0b00000000);
3187 
3188  Simulator::Schedule(Seconds(7.2), &TestAmpduReception::ResetBitmaps, this);
3189 
3191  // CASE 8: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3192  // with power under RX sensitivity. The second A-MPDU is received during the payload of MPDU #2.
3194 
3195  // A-MPDU 1
3196  Simulator::Schedule(Seconds(8.0),
3198  this,
3199  rxPowerDbm,
3200  1000);
3201 
3202  // A-MPDU 2
3203  Simulator::Schedule(Seconds(8.0) + NanoSeconds(1100000),
3205  this,
3206  rxPowerDbm - 100,
3207  1300);
3208 
3209  // All MPDUs of A-MPDU 1 should have been received.
3210  Simulator::Schedule(Seconds(8.1),
3212  this,
3213  0b00000111);
3214  Simulator::Schedule(Seconds(8.1),
3216  this,
3217  0b00000000);
3218  Simulator::Schedule(Seconds(8.1),
3220  this,
3221  0b00000000);
3222 
3223  // All MPDUs of A-MPDU 2 should have been ignored.
3224  Simulator::Schedule(Seconds(8.1),
3226  this,
3227  0b00000000);
3228  Simulator::Schedule(Seconds(8.1),
3230  this,
3231  0b00000000);
3232  Simulator::Schedule(Seconds(8.1),
3234  this,
3235  0b00000000);
3236 
3237  Simulator::Schedule(Seconds(8.2), &TestAmpduReception::ResetBitmaps, this);
3238 
3240  // CASE 9: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power 3
3241  // dB higher. The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during
3242  // preamble detection).
3244 
3245  // A-MPDU 1
3246  Simulator::Schedule(Seconds(9.0),
3248  this,
3249  rxPowerDbm,
3250  1000);
3251 
3252  // A-MPDU 2
3253  Simulator::Schedule(Seconds(9.0) + MicroSeconds(2),
3255  this,
3256  rxPowerDbm + 3,
3257  1300);
3258 
3259  // All MPDUs of A-MPDU 1 should have been dropped.
3260  Simulator::Schedule(Seconds(9.1),
3262  this,
3263  0b00000000);
3264  Simulator::Schedule(Seconds(9.1),
3266  this,
3267  0b00000000);
3268  Simulator::Schedule(Seconds(9.1),
3270  this,
3271  0b00000111);
3272 
3273  // All MPDUs of A-MPDU 2 should have been received with errors.
3274  Simulator::Schedule(Seconds(9.1),
3276  this,
3277  0b00000000);
3278  Simulator::Schedule(Seconds(9.1),
3280  this,
3281  0b00000111);
3282  Simulator::Schedule(Seconds(9.1),
3284  this,
3285  0b00000000);
3286 
3287  Simulator::Schedule(Seconds(9.2), &TestAmpduReception::ResetBitmaps, this);
3288 
3290  // CASE 10: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3291  // The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during preamble
3292  // detection).
3294 
3295  // A-MPDU 1
3296  Simulator::Schedule(Seconds(10.0),
3298  this,
3299  rxPowerDbm,
3300  1000);
3301 
3302  // A-MPDU 2
3303  Simulator::Schedule(Seconds(10.0) + MicroSeconds(2),
3305  this,
3306  rxPowerDbm,
3307  1300);
3308 
3309  // All MPDUs of A-MPDU 1 should have been dropped (preamble detection failed).
3310  Simulator::Schedule(Seconds(10.1),
3312  this,
3313  0b00000000);
3314  Simulator::Schedule(Seconds(10.1),
3316  this,
3317  0b00000000);
3318  Simulator::Schedule(Seconds(10.1),
3320  this,
3321  0b00000111);
3322 
3323  // All MPDUs of A-MPDU 2 should have been dropped as well.
3324  Simulator::Schedule(Seconds(10.1),
3326  this,
3327  0b00000000);
3328  Simulator::Schedule(Seconds(10.1),
3330  this,
3331  0b00000000);
3332  Simulator::Schedule(Seconds(10.1),
3334  this,
3335  0b00000111);
3336 
3337  Simulator::Schedule(Seconds(10.2), &TestAmpduReception::ResetBitmaps, this);
3338 
3340  // CASE 11: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 3
3341  // dB higher. The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during
3342  // preamble detection).
3344 
3345  // A-MPDU 1
3346  Simulator::Schedule(Seconds(11.0),
3348  this,
3349  rxPowerDbm + 3,
3350  1000);
3351 
3352  // A-MPDU 2
3353  Simulator::Schedule(Seconds(11.0) + MicroSeconds(2),
3355  this,
3356  rxPowerDbm,
3357  1300);
3358 
3359  // All MPDUs of A-MPDU 1 should have been received with errors.
3360  Simulator::Schedule(Seconds(11.1),
3362  this,
3363  0b00000000);
3364  Simulator::Schedule(Seconds(11.1),
3366  this,
3367  0b00000111);
3368  Simulator::Schedule(Seconds(11.1),
3370  this,
3371  0b00000000);
3372 
3373  // All MPDUs of A-MPDU 2 should have been dropped.
3374  Simulator::Schedule(Seconds(11.1),
3376  this,
3377  0b00000000);
3378  Simulator::Schedule(Seconds(11.1),
3380  this,
3381  0b00000000);
3382  Simulator::Schedule(Seconds(11.1),
3384  this,
3385  0b00000111);
3386 
3387  Simulator::Schedule(Seconds(11.2), &TestAmpduReception::ResetBitmaps, this);
3388 
3390  // CASE 12: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3391  // 3 dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e.
3392  // during the frame capture window).
3394 
3395  // A-MPDU 1
3396  Simulator::Schedule(Seconds(12.0),
3398  this,
3399  rxPowerDbm,
3400  1000);
3401 
3402  // A-MPDU 2
3403  Simulator::Schedule(Seconds(12.0) + MicroSeconds(10),
3405  this,
3406  rxPowerDbm + 3,
3407  1300);
3408 
3409  // All MPDUs of A-MPDU 1 should have been received with errors (PHY header reception failed and
3410  // thus incorrect decoding of payload).
3411  Simulator::Schedule(Seconds(12.1),
3413  this,
3414  0b00000000);
3415  Simulator::Schedule(Seconds(12.1),
3417  this,
3418  0b00000000);
3419  Simulator::Schedule(Seconds(12.1),
3421  this,
3422  0b00000111);
3423 
3424  // All MPDUs of A-MPDU 2 should have been dropped (even though TX power is higher, it is not
3425  // high enough to get the PHY reception switched)
3426  Simulator::Schedule(Seconds(12.1),
3428  this,
3429  0b00000000);
3430  Simulator::Schedule(Seconds(12.1),
3432  this,
3433  0b00000000);
3434  Simulator::Schedule(Seconds(12.1),
3436  this,
3437  0b00000111);
3438 
3439  Simulator::Schedule(Seconds(12.2), &TestAmpduReception::ResetBitmaps, this);
3440 
3442  // CASE 13: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3443  // The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during the frame
3444  // capture window).
3446 
3447  // A-MPDU 1
3448  Simulator::Schedule(Seconds(13.0),
3450  this,
3451  rxPowerDbm,
3452  1000);
3453 
3454  // A-MPDU 2
3455  Simulator::Schedule(Seconds(13.0) + MicroSeconds(10),
3457  this,
3458  rxPowerDbm,
3459  1300);
3460 
3461  // All MPDUs of A-MPDU 1 should have been received with errors (PHY header reception failed and
3462  // thus incorrect decoding of payload).
3463  Simulator::Schedule(Seconds(13.1),
3465  this,
3466  0b00000000);
3467  Simulator::Schedule(Seconds(13.1),
3469  this,
3470  0b00000000);
3471  Simulator::Schedule(Seconds(13.1),
3473  this,
3474  0b00000111);
3475 
3476  // All MPDUs of A-MPDU 2 should have been dropped as well.
3477  Simulator::Schedule(Seconds(13.1),
3479  this,
3480  0b00000000);
3481  Simulator::Schedule(Seconds(13.1),
3483  this,
3484  0b00000000);
3485  Simulator::Schedule(Seconds(13.1),
3487  this,
3488  0b00000111);
3489 
3490  Simulator::Schedule(Seconds(13.2), &TestAmpduReception::ResetBitmaps, this);
3491 
3493  // CASE 14: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 3
3494  // dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during
3495  // the frame capture window).
3497 
3498  // A-MPDU 1
3499  Simulator::Schedule(Seconds(14.0),
3501  this,
3502  rxPowerDbm + 3,
3503  1000);
3504 
3505  // A-MPDU 2
3506  Simulator::Schedule(Seconds(14.0) + MicroSeconds(10),
3508  this,
3509  rxPowerDbm,
3510  1300);
3511 
3512  // All MPDUs of A-MPDU 1 should have been received with errors.
3513  Simulator::Schedule(Seconds(14.1),
3515  this,
3516  0b00000000);
3517  Simulator::Schedule(Seconds(14.1),
3519  this,
3520  0b00000111);
3521  Simulator::Schedule(Seconds(14.1),
3523  this,
3524  0b00000000);
3525 
3526  // All MPDUs of A-MPDU 2 should have been dropped.
3527  Simulator::Schedule(Seconds(14.1),
3529  this,
3530  0b00000000);
3531  Simulator::Schedule(Seconds(14.1),
3533  this,
3534  0b00000000);
3535  Simulator::Schedule(Seconds(14.1),
3537  this,
3538  0b00000111);
3539 
3540  Simulator::Schedule(Seconds(14.2), &TestAmpduReception::ResetBitmaps, this);
3541 
3543  // CASE 15: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3544  // 6 dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e.
3545  // during the frame capture window).
3547 
3548  // A-MPDU 1
3549  Simulator::Schedule(Seconds(15.0),
3551  this,
3552  rxPowerDbm,
3553  1000);
3554 
3555  // A-MPDU 2
3556  Simulator::Schedule(Seconds(15.0) + MicroSeconds(10),
3558  this,
3559  rxPowerDbm + 6,
3560  1300);
3561 
3562  // All MPDUs of A-MPDU 1 should have been dropped because PHY reception switched to A-MPDU 2.
3563  Simulator::Schedule(Seconds(15.1),
3565  this,
3566  0b00000000);
3567  Simulator::Schedule(Seconds(15.1),
3569  this,
3570  0b00000000);
3571  Simulator::Schedule(Seconds(15.1),
3573  this,
3574  0b00000111);
3575 
3576  // All MPDUs of A-MPDU 2 should have been successfully received
3577  Simulator::Schedule(Seconds(15.1),
3579  this,
3580  0b00000111);
3581  Simulator::Schedule(Seconds(15.1),
3583  this,
3584  0b00000000);
3585  Simulator::Schedule(Seconds(15.1),
3587  this,
3588  0b00000000);
3589 
3590  Simulator::Schedule(Seconds(15.2), &TestAmpduReception::ResetBitmaps, this);
3591 
3593  // CASE 16: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3594  // dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during
3595  // the frame capture window).
3597 
3598  // A-MPDU 1
3599  Simulator::Schedule(Seconds(16.0),
3601  this,
3602  rxPowerDbm + 6,
3603  1000);
3604 
3605  // A-MPDU 2
3606  Simulator::Schedule(Seconds(16.0) + MicroSeconds(10),
3608  this,
3609  rxPowerDbm,
3610  1300);
3611 
3612  // All MPDUs of A-MPDU 1 should have been successfully received.
3613  Simulator::Schedule(Seconds(16.1),
3615  this,
3616  0b00000111);
3617  Simulator::Schedule(Seconds(16.1),
3619  this,
3620  0b00000000);
3621  Simulator::Schedule(Seconds(16.1),
3623  this,
3624  0b00000000);
3625 
3626  // All MPDUs of A-MPDU 2 should have been dropped.
3627  Simulator::Schedule(Seconds(16.1),
3629  this,
3630  0b00000000);
3631  Simulator::Schedule(Seconds(16.1),
3633  this,
3634  0b00000000);
3635  Simulator::Schedule(Seconds(16.1),
3637  this,
3638  0b00000111);
3639 
3640  Simulator::Schedule(Seconds(16.2), &TestAmpduReception::ResetBitmaps, this);
3641 
3643  // CASE 17: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3644  // 6 dB higher. The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after
3645  // the frame capture window, but still during PHY header).
3647 
3648  // A-MPDU 1
3649  Simulator::Schedule(Seconds(17.0),
3651  this,
3652  rxPowerDbm,
3653  1000);
3654 
3655  // A-MPDU 2
3656  Simulator::Schedule(Seconds(17.0) + MicroSeconds(25),
3658  this,
3659  rxPowerDbm + 6,
3660  1300);
3661 
3662  // All MPDUs of A-MPDU 1 should have been received with errors.
3663  Simulator::Schedule(Seconds(17.1),
3665  this,
3666  0b00000000);
3667  Simulator::Schedule(Seconds(17.1),
3669  this,
3670  0b00000000);
3671  Simulator::Schedule(Seconds(17.1),
3673  this,
3674  0b00000111);
3675 
3676  // All MPDUs of A-MPDU 2 should have been dropped (no reception switch, MPDUs dropped because
3677  // PHY is already in RX state).
3678  Simulator::Schedule(Seconds(17.1),
3680  this,
3681  0b00000000);
3682  Simulator::Schedule(Seconds(17.1),
3684  this,
3685  0b00000000);
3686  Simulator::Schedule(Seconds(17.1),
3688  this,
3689  0b00000111);
3690 
3691  Simulator::Schedule(Seconds(17.2), &TestAmpduReception::ResetBitmaps, this);
3692 
3694  // CASE 18: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3695  // dB higher. The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after
3696  // the frame capture window, but still during PHY header).
3698 
3699  // A-MPDU 1
3700  Simulator::Schedule(Seconds(18.0),
3702  this,
3703  rxPowerDbm + 6,
3704  1000);
3705 
3706  // A-MPDU 2
3707  Simulator::Schedule(Seconds(18.0) + MicroSeconds(25),
3709  this,
3710  rxPowerDbm,
3711  1300);
3712 
3713  // All MPDUs of A-MPDU 1 should have been successfully received.
3714  Simulator::Schedule(Seconds(18.1),
3716  this,
3717  0b00000111);
3718  Simulator::Schedule(Seconds(18.1),
3720  this,
3721  0b00000000);
3722  Simulator::Schedule(Seconds(18.1),
3724  this,
3725  0b00000000);
3726 
3727  // All MPDUs of A-MPDU 2 should have been dropped.
3728  Simulator::Schedule(Seconds(18.1),
3730  this,
3731  0b00000000);
3732  Simulator::Schedule(Seconds(18.1),
3734  this,
3735  0b00000000);
3736  Simulator::Schedule(Seconds(18.1),
3738  this,
3739  0b00000111);
3740 
3741  Simulator::Schedule(Seconds(18.2), &TestAmpduReception::ResetBitmaps, this);
3742 
3744  // CASE 19: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3745  // The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after the frame
3746  // capture window, but still during PHY header).
3748 
3749  // A-MPDU 1
3750  Simulator::Schedule(Seconds(19.0),
3752  this,
3753  rxPowerDbm,
3754  1000);
3755 
3756  // A-MPDU 2
3757  Simulator::Schedule(Seconds(19.0) + MicroSeconds(25),
3759  this,
3760  rxPowerDbm,
3761  1300);
3762 
3763  // All MPDUs of A-MPDU 1 should have been received with errors.
3764  Simulator::Schedule(Seconds(19.1),
3766  this,
3767  0b00000000);
3768  Simulator::Schedule(Seconds(19.1),
3770  this,
3771  0b00000000);
3772  Simulator::Schedule(Seconds(19.1),
3774  this,
3775  0b00000111);
3776 
3777  // All MPDUs of A-MPDU 2 should have been dropped.
3778  Simulator::Schedule(Seconds(19.1),
3780  this,
3781  0b00000000);
3782  Simulator::Schedule(Seconds(19.1),
3784  this,
3785  0b00000000);
3786  Simulator::Schedule(Seconds(19.1),
3788  this,
3789  0b00000111);
3790 
3791  Simulator::Schedule(Seconds(19.2), &TestAmpduReception::ResetBitmaps, this);
3792 
3794  // CASE 20: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3795  // 6 dB higher. The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e.
3796  // during the payload of MPDU #1).
3798 
3799  // A-MPDU 1
3800  Simulator::Schedule(Seconds(20.0),
3802  this,
3803  rxPowerDbm,
3804  1000);
3805 
3806  // A-MPDU 2
3807  Simulator::Schedule(Seconds(20.0) + MicroSeconds(100),
3809  this,
3810  rxPowerDbm + 6,
3811  1300);
3812 
3813  // All MPDUs of A-MPDU 1 should have been received with errors.
3814  Simulator::Schedule(Seconds(20.1),
3816  this,
3817  0b00000000);
3818  Simulator::Schedule(Seconds(20.1),
3820  this,
3821  0b00000111);
3822  Simulator::Schedule(Seconds(20.1),
3824  this,
3825  0b00000000);
3826 
3827  // All MPDUs of A-MPDU 2 should have been dropped (no reception switch, MPDUs dropped because
3828  // PHY is already in RX state).
3829  Simulator::Schedule(Seconds(20.1),
3831  this,
3832  0b00000000);
3833  Simulator::Schedule(Seconds(20.1),
3835  this,
3836  0b00000000);
3837  Simulator::Schedule(Seconds(20.1),
3839  this,
3840  0b00000111);
3841 
3842  Simulator::Schedule(Seconds(20.2), &TestAmpduReception::ResetBitmaps, this);
3843 
3845  // CASE 21: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3846  // dB higher. The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e. during
3847  // the payload of MPDU #1).
3849 
3850  // A-MPDU 1
3851  Simulator::Schedule(Seconds(21.0),
3853  this,
3854  rxPowerDbm + 6,
3855  1000);
3856 
3857  // A-MPDU 2
3858  Simulator::Schedule(Seconds(21.0) + MicroSeconds(100),
3860  this,
3861  rxPowerDbm,
3862  1300);
3863 
3864  // All MPDUs of A-MPDU 1 should have been successfully received.
3865  Simulator::Schedule(Seconds(21.1),
3867  this,
3868  0b00000111);
3869  Simulator::Schedule(Seconds(21.1),
3871  this,
3872  0b00000000);
3873  Simulator::Schedule(Seconds(21.1),
3875  this,
3876  0b00000000);
3877 
3878  // All MPDUs of A-MPDU 2 should have been dropped.
3879  Simulator::Schedule(Seconds(21.1),
3881  this,
3882  0b00000000);
3883  Simulator::Schedule(Seconds(21.1),
3885  this,
3886  0b00000000);
3887  Simulator::Schedule(Seconds(21.1),
3889  this,
3890  0b00000111);
3891 
3892  Simulator::Schedule(Seconds(21.2), &TestAmpduReception::ResetBitmaps, this);
3893 
3895  // CASE 22: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3896  // The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e. during the
3897  // payload of MPDU #1).
3899 
3900  // A-MPDU 1
3901  Simulator::Schedule(Seconds(22.0),
3903  this,
3904  rxPowerDbm,
3905  1000);
3906 
3907  // A-MPDU 2
3908  Simulator::Schedule(Seconds(22.0) + MicroSeconds(100),
3910  this,
3911  rxPowerDbm,
3912  1300);
3913 
3914  // All MPDUs of A-MPDU 1 should have been received with errors.
3915  Simulator::Schedule(Seconds(22.1),
3917  this,
3918  0b00000000);
3919  Simulator::Schedule(Seconds(22.1),
3921  this,
3922  0b00000111);
3923  Simulator::Schedule(Seconds(22.1),
3925  this,
3926  0b00000000);
3927 
3928  // All MPDUs of A-MPDU 2 should have been dropped.
3929  Simulator::Schedule(Seconds(22.1),
3931  this,
3932  0b00000000);
3933  Simulator::Schedule(Seconds(22.1),
3935  this,
3936  0b00000000);
3937  Simulator::Schedule(Seconds(22.1),
3939  this,
3940  0b00000111);
3941 
3942  Simulator::Schedule(Seconds(22.2), &TestAmpduReception::ResetBitmaps, this);
3943 
3945  // CASE 23: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3946  // The second A-MPDU is received during the payload of MPDU #2.
3948 
3949  // A-MPDU 1
3950  Simulator::Schedule(Seconds(23.0),
3952  this,
3953  rxPowerDbm,
3954  1000);
3955 
3956  // A-MPDU 2
3957  Simulator::Schedule(Seconds(23.0) + NanoSeconds(1100000),
3959  this,
3960  rxPowerDbm,
3961  1300);
3962 
3963  // The first MPDU of A-MPDU 1 should have been successfully received (no interference).
3964  // The two other MPDUs failed due to interference and are marked as failure (and dropped).
3965  Simulator::Schedule(Seconds(23.1),
3967  this,
3968  0b00000001);
3969  Simulator::Schedule(Seconds(23.1),
3971  this,
3972  0b00000110);
3973  Simulator::Schedule(Seconds(23.1),
3975  this,
3976  0b00000000);
3977 
3978  // The two first MPDUs of A-MPDU 2 are dropped because PHY is already in RX state (receiving
3979  // A-MPDU 1). The last MPDU of A-MPDU 2 is interference free (A-MPDU 1 transmission is finished)
3980  // but is dropped because its PHY preamble and header were not received.
3981  Simulator::Schedule(Seconds(23.1),
3983  this,
3984  0b00000000);
3985  Simulator::Schedule(Seconds(23.1),
3987  this,
3988  0b00000000);
3989  Simulator::Schedule(Seconds(23.1),
3991  this,
3992  0b00000111);
3993 
3994  Simulator::Schedule(Seconds(23.2), &TestAmpduReception::ResetBitmaps, this);
3995 
3996  Simulator::Run();
3997  Simulator::Destroy();
3998 }
3999 
4021 {
4022  public:
4025 
4026  private:
4027  void DoRun() override;
4028 
4035  void Dropped(std::string context, Ptr<const Packet> packet, WifiPhyRxfailureReason reason);
4039  void CheckResults();
4040 
4041  uint16_t m_dropped{0};
4042 };
4043 
4045  : TestCase("Check correct behavior when a STA is receiving a transmission using an unsupported "
4046  "modulation")
4047 {
4048 }
4049 
4050 void
4052  Ptr<const Packet> packet,
4053  WifiPhyRxfailureReason reason)
4054 {
4055  // Print if the test is executed through test-runner
4056  if (reason == RXING)
4057  {
4058  std::cout << "Dropped a packet because already receiving" << std::endl;
4059  m_dropped++;
4060  }
4061 }
4062 
4063 void
4065 {
4066  uint16_t m_nStations = 2;
4067  NetDeviceContainer m_staDevices;
4068  NetDeviceContainer m_apDevices;
4069 
4070  int64_t streamNumber = 100;
4071 
4073  wifiApNode.Create(1);
4074 
4076  wifiStaNodes.Create(m_nStations);
4077 
4078  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
4079  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
4080  spectrumChannel->AddPropagationLossModel(lossModel);
4082  CreateObject<ConstantSpeedPropagationDelayModel>();
4083  spectrumChannel->SetPropagationDelayModel(delayModel);
4084 
4086  phy.SetChannel(spectrumChannel);
4087 
4088  Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue(65535));
4089 
4090  WifiHelper wifi;
4091  wifi.SetRemoteStationManager("ns3::IdealWifiManager");
4092 
4094  mac.SetType("ns3::StaWifiMac",
4095  "QosSupported",
4096  BooleanValue(true),
4097  "Ssid",
4098  SsidValue(Ssid("non-existent-ssid")));
4099 
4100  wifi.SetStandard(WIFI_STANDARD_80211ax);
4101  m_staDevices.Add(wifi.Install(phy, mac, wifiStaNodes.Get(0)));
4102  wifi.SetStandard(WIFI_STANDARD_80211ac);
4103  m_staDevices.Add(wifi.Install(phy, mac, wifiStaNodes.Get(1)));
4104 
4105  wifi.SetStandard(WIFI_STANDARD_80211ax);
4106  mac.SetType("ns3::ApWifiMac",
4107  "QosSupported",
4108  BooleanValue(true),
4109  "Ssid",
4110  SsidValue(Ssid("wifi-backoff-ssid")),
4111  "BeaconInterval",
4112  TimeValue(MicroSeconds(102400)),
4113  "EnableBeaconJitter",
4114  BooleanValue(false));
4115 
4116  m_apDevices = wifi.Install(phy, mac, wifiApNode);
4117 
4118  // schedule association requests at different times
4119  Time init = MilliSeconds(100);
4120  Ptr<WifiNetDevice> dev;
4121 
4122  for (uint16_t i = 0; i < m_nStations; i++)
4123  {
4124  dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
4125  Simulator::Schedule(init + i * MicroSeconds(102400),
4126  &WifiMac::SetSsid,
4127  dev->GetMac(),
4128  Ssid("wifi-backoff-ssid"));
4129  }
4130 
4131  // Assign fixed streams to random variables in use
4132  wifi.AssignStreams(m_apDevices, streamNumber);
4133 
4135  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
4136 
4137  positionAlloc->Add(Vector(0.0, 0.0, 0.0));
4138  positionAlloc->Add(Vector(1.0, 0.0, 0.0));
4139  positionAlloc->Add(Vector(0.0, 1.0, 0.0));
4140  positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
4141  mobility.SetPositionAllocator(positionAlloc);
4142 
4143  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
4144  mobility.Install(wifiApNode);
4145  mobility.Install(wifiStaNodes);
4146 
4147  // set the TXOP limit on BE AC
4148  dev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
4149  PointerValue ptr;
4150  dev->GetMac()->GetAttribute("BE_Txop", ptr);
4151 
4152  PacketSocketHelper packetSocket;
4153  packetSocket.Install(wifiApNode);
4154  packetSocket.Install(wifiStaNodes);
4155 
4156  // UL Traffic
4157  for (uint16_t i = 0; i < m_nStations; i++)
4158  {
4159  PacketSocketAddress socket;
4160  socket.SetSingleDevice(m_staDevices.Get(0)->GetIfIndex());
4161  socket.SetPhysicalAddress(m_apDevices.Get(0)->GetAddress());
4162  socket.SetProtocol(1);
4163  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
4164  client->SetAttribute("PacketSize", UintegerValue(1500));
4165  client->SetAttribute("MaxPackets", UintegerValue(200));
4166  client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
4167  client->SetRemote(socket);
4168  wifiStaNodes.Get(i)->AddApplication(client);
4169  client->SetStartTime(MicroSeconds(400000));
4170  client->SetStopTime(Seconds(1.0));
4171  Ptr<PacketSocketClient> legacyStaClient = CreateObject<PacketSocketClient>();
4172  legacyStaClient->SetAttribute("PacketSize", UintegerValue(1500));
4173  legacyStaClient->SetAttribute("MaxPackets", UintegerValue(200));
4174  legacyStaClient->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
4175  legacyStaClient->SetRemote(socket);
4176  wifiStaNodes.Get(i)->AddApplication(legacyStaClient);
4177  legacyStaClient->SetStartTime(MicroSeconds(400000));
4178  legacyStaClient->SetStopTime(Seconds(1.0));
4179  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
4180  server->SetLocal(socket);
4181  wifiApNode.Get(0)->AddApplication(server);
4182  server->SetStartTime(Seconds(0.0));
4183  server->SetStopTime(Seconds(1.0));
4184  }
4185 
4186  // Trace dropped packets
4187  Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxDrop",
4189 
4190  Simulator::Stop(Seconds(1));
4191  Simulator::Run();
4192 
4193  CheckResults();
4194 
4195  Simulator::Destroy();
4196 }
4197 
4198 void
4200 {
4201  NS_TEST_EXPECT_MSG_EQ(m_dropped, 0, "Dropped some packets unexpectedly");
4202 }
4203 
4216 {
4217  public:
4219 
4220  private:
4221  void DoSetup() override;
4222  void DoTeardown() override;
4223  void DoRun() override;
4224 
4231  void SendPpdu(uint16_t centerFreqMhz, uint16_t bandwidthMhz);
4232 
4240  void RxSuccess(Ptr<const WifiPsdu> psdu,
4241  RxSignalInfo rxSignalInfo,
4242  WifiTxVector txVector,
4243  std::vector<bool> statusPerMpdu);
4244 
4249  void RxFailure(Ptr<const WifiPsdu> psdu);
4250 
4256  void RxDropped(Ptr<const Packet> packet, WifiPhyRxfailureReason reason);
4257 
4269  void CheckRx(uint32_t expectedCountRxSuccess,
4270  uint32_t expectedCountRxFailure,
4271  uint32_t expectedCountRxDropped,
4272  std::optional<Time> expectedLastRxSucceeded,
4273  std::optional<Time> expectedLastRxFailed,
4274  std::optional<Time> expectedLastRxDropped);
4275 
4276  uint32_t m_countRxSuccess;
4277  uint32_t m_countRxFailure;
4278  uint32_t m_countRxDropped;
4279 
4280  std::optional<Time> m_lastRxSucceeded;
4281  std::optional<Time> m_lastRxFailed;
4282  std::optional<Time> m_lastRxDropped;
4283 
4286 };
4287 
4289  : TestCase("Check correct behavior when a STA is receiving a transmission using an unsupported "
4290  "bandwidth"),
4291  m_countRxSuccess(0),
4292  m_countRxFailure(0),
4293  m_countRxDropped(0),
4294  m_lastRxSucceeded(std::nullopt),
4295  m_lastRxFailed(std::nullopt),
4296  m_lastRxDropped(std::nullopt)
4297 {
4298 }
4299 
4300 void
4301 TestUnsupportedBandwidthReception::SendPpdu(uint16_t centerFreqMhz, uint16_t bandwidthMhz)
4302 {
4303  auto txVector =
4304  WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, bandwidthMhz, false);
4305 
4306  auto pkt = Create<Packet>(1000);
4307  WifiMacHeader hdr;
4308 
4310  hdr.SetQosTid(0);
4311 
4312  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4313  Time txDuration =
4314  m_rxPhy->CalculateTxDuration(psdu->GetSize(), txVector, m_rxPhy->GetPhyBand());
4315 
4316  auto ppdu = Create<HePpdu>(psdu, txVector, m_txPhy->GetOperatingChannel(), txDuration, 0);
4317 
4318  auto txPowerSpectrum =
4319  WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(centerFreqMhz,
4320  bandwidthMhz,
4321  DbmToW(-50),
4322  bandwidthMhz);
4323 
4324  auto txParams = Create<WifiSpectrumSignalParameters>();
4325  txParams->psd = txPowerSpectrum;
4326  txParams->txPhy = nullptr;
4327  txParams->duration = txDuration;
4328  txParams->ppdu = ppdu;
4329 
4330  m_rxPhy->StartRx(txParams, nullptr);
4331 }
4332 
4333 void
4335  RxSignalInfo rxSignalInfo,
4336  WifiTxVector txVector,
4337  std::vector<bool> statusPerMpdu)
4338 {
4339  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
4340  m_countRxSuccess++;
4342 }
4343 
4344 void
4346 {
4347  NS_LOG_FUNCTION(this << *psdu);
4348  m_countRxFailure++;
4350 }
4351 
4352 void
4354 {
4355  NS_LOG_FUNCTION(this << p << reason);
4356  NS_ASSERT(reason == UNSUPPORTED_SETTINGS);
4357  m_countRxDropped++;
4359 }
4360 
4361 void
4362 TestUnsupportedBandwidthReception::CheckRx(uint32_t expectedCountRxSuccess,
4363  uint32_t expectedCountRxFailure,
4364  uint32_t expectedCountRxDropped,
4365  std::optional<Time> expectedLastRxSucceeded,
4366  std::optional<Time> expectedLastRxFailed,
4367  std::optional<Time> expectedLastRxDropped)
4368 {
4370  expectedCountRxSuccess,
4371  "Didn't receive right number of successful packets");
4372 
4374  expectedCountRxFailure,
4375  "Didn't receive right number of unsuccessful packets");
4376 
4378  expectedCountRxDropped,
4379  "Didn't receive right number of dropped packets");
4380 
4381  if (expectedCountRxSuccess > 0)
4382  {
4383  NS_ASSERT(m_lastRxSucceeded.has_value());
4384  NS_ASSERT(expectedLastRxSucceeded.has_value());
4386  expectedLastRxSucceeded.value(),
4387  "Didn't receive the last successful packet at the expected time");
4388  }
4389 
4390  if (expectedCountRxFailure > 0)
4391  {
4392  NS_ASSERT(m_lastRxFailed.has_value());
4393  NS_ASSERT(expectedLastRxFailed.has_value());
4395  expectedLastRxFailed.value(),
4396  "Didn't receive the last unsuccessful packet at the expected time");
4397  }
4398 
4399  if (expectedCountRxDropped > 0)
4400  {
4401  NS_ASSERT(m_lastRxDropped.has_value());
4402  NS_ASSERT(expectedLastRxDropped.has_value());
4404  expectedLastRxDropped.value(),
4405  "Didn't drop the last filtered packet at the expected time");
4406  }
4407 }
4408 
4409 void
4411 {
4412  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
4413  Ptr<Node> node = CreateObject<Node>();
4414  Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
4415  m_rxPhy = CreateObject<SpectrumWifiPhy>();
4416  auto rxInterferenceHelper = CreateObject<InterferenceHelper>();
4417  m_rxPhy->SetInterferenceHelper(rxInterferenceHelper);
4418  auto rxErrorRateModel = CreateObject<NistErrorRateModel>();
4419  m_rxPhy->SetErrorRateModel(rxErrorRateModel);
4420  m_rxPhy->SetDevice(dev);
4421  m_rxPhy->AddChannel(spectrumChannel);
4423  dev->SetPhy(m_rxPhy);
4424  node->AddDevice(dev);
4425 
4431  "PhyRxDrop",
4433 
4434  m_txPhy = CreateObject<SpectrumWifiPhy>();
4435  auto txInterferenceHelper = CreateObject<InterferenceHelper>();
4436  m_txPhy->SetInterferenceHelper(txInterferenceHelper);
4437  auto txErrorRateModel = CreateObject<NistErrorRateModel>();
4438  m_txPhy->SetErrorRateModel(txErrorRateModel);
4439  m_txPhy->AddChannel(spectrumChannel);
4441 }
4442 
4443 void
4445 {
4446  m_rxPhy->Dispose();
4447  m_rxPhy = nullptr;
4448 
4449  m_txPhy->Dispose();
4450  m_txPhy = nullptr;
4451 }
4452 
4453 void
4455 {
4456  RngSeedManager::SetSeed(1);
4457  RngSeedManager::SetRun(1);
4458 
4459  int64_t streamNumber = 0;
4460  m_rxPhy->AssignStreams(streamNumber);
4461 
4462  // Case 1: the PHY is operating on channel 36 (20 MHz) and receives a 40 MHz PPDU (channel 38).
4463  // The PPDU should be dropped once HE-SIG-A is successfully received, since it contains
4464  // indication about the BW used for the transmission and the PHY shall detect it is larger than
4465  // its operating BW.
4468 
4469  Simulator::Schedule(Seconds(1.0), &TestUnsupportedBandwidthReception::SendPpdu, this, 5190, 40);
4470 
4471  auto heSigAExpectedRxTime = Seconds(1.0) + MicroSeconds(32);
4472  Simulator::Schedule(Seconds(1.5),
4474  this,
4475  0,
4476  0,
4477  1,
4478  std::nullopt,
4479  std::nullopt,
4480  heSigAExpectedRxTime);
4481 
4482  // TODO: this test can be extended with other scenarios
4483 
4484  Simulator::Run();
4485  Simulator::Destroy();
4486 }
4487 
4497 {
4498  public:
4500 
4501  private:
4502  void DoSetup() override;
4503  void DoRun() override;
4504  void DoTeardown() override;
4505 
4512  Ptr<HePpdu> CreatePpdu(uint16_t ppduCenterFreqMhz);
4513 
4526  void RunOne(WifiPhyBand band,
4527  uint16_t phyCenterFreqMhz,
4528  uint8_t p20Index,
4529  uint16_t ppduCenterFreqMhz,
4530  bool expectedP20Overlap,
4531  bool expectedP20Covered);
4532 
4535 };
4536 
4538  : TestCase("Check correct detection of whether P20 is fully covered (hence it can be received) "
4539  "or overlaps with the bandwidth of an incoming PPDU")
4540 {
4541 }
4542 
4544 TestPrimary20CoveredByPpdu::CreatePpdu(uint16_t ppduCenterFreqMhz)
4545 {
4546  [[maybe_unused]] auto [channelNumber, centerFreq, channelWidth, type, phyBand] =
4547  (*WifiPhyOperatingChannel::FindFirst(0,
4548  ppduCenterFreqMhz,
4549  0,
4551  m_rxPhy->GetPhyBand()));
4552  m_txPhy->SetOperatingChannel(WifiPhy::ChannelTuple{channelNumber, channelWidth, phyBand, 0});
4553  auto txVector =
4554  WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, channelWidth, false);
4555 
4556  auto pkt = Create<Packet>(1000);
4558 
4559  auto psdu = Create<WifiPsdu>(pkt, hdr);
4560  auto txDuration = m_txPhy->CalculateTxDuration(psdu->GetSize(), txVector, phyBand);
4561 
4562  return Create<HePpdu>(psdu, txVector, m_txPhy->GetOperatingChannel(), txDuration, 0);
4563 }
4564 
4565 void
4567 {
4568  m_rxPhy = CreateObject<SpectrumWifiPhy>();
4569  auto rxInterferenceHelper = CreateObject<InterferenceHelper>();
4570  m_rxPhy->SetInterferenceHelper(rxInterferenceHelper);
4571  auto rxErrorRateModel = CreateObject<NistErrorRateModel>();
4572  m_rxPhy->SetErrorRateModel(rxErrorRateModel);
4573  m_rxPhy->AddChannel(CreateObject<MultiModelSpectrumChannel>());
4575 
4576  m_txPhy = CreateObject<SpectrumWifiPhy>();
4577  auto txInterferenceHelper = CreateObject<InterferenceHelper>();
4578  m_txPhy->SetInterferenceHelper(txInterferenceHelper);
4579  auto txErrorRateModel = CreateObject<NistErrorRateModel>();
4580  m_txPhy->SetErrorRateModel(txErrorRateModel);
4581  m_txPhy->AddChannel(CreateObject<MultiModelSpectrumChannel>());
4583 }
4584 
4585 void
4587 {
4588  m_rxPhy->Dispose();
4589  m_rxPhy = nullptr;
4590  m_txPhy->Dispose();
4591  m_txPhy = nullptr;
4592 }
4593 
4594 void
4596  uint16_t phyCenterFreqMhz,
4597  uint8_t p20Index,
4598  uint16_t ppduCenterFreqMhz,
4599  bool expectedP20Overlap,
4600  bool expectedP20Covered)
4601 {
4602  [[maybe_unused]] const auto [channelNumber, centerFreq, channelWidth, type, phyBand] =
4603  (*WifiPhyOperatingChannel::FindFirst(0, phyCenterFreqMhz, 0, WIFI_STANDARD_80211ax, band));
4604 
4606  WifiPhy::ChannelTuple{channelNumber, channelWidth, band, p20Index});
4607  auto p20CenterFreq = m_rxPhy->GetOperatingChannel().GetPrimaryChannelCenterFrequency(20);
4608  auto p20MinFreq = p20CenterFreq - 10;
4609  auto p20MaxFreq = p20CenterFreq + 10;
4610 
4611  auto ppdu = CreatePpdu(ppduCenterFreqMhz);
4612 
4613  auto p20Overlap = ppdu->DoesOverlapChannel(p20MinFreq, p20MaxFreq);
4614  NS_TEST_ASSERT_MSG_EQ(p20Overlap,
4615  expectedP20Overlap,
4616  "PPDU is " << (expectedP20Overlap ? "expected" : "not expected")
4617  << " to overlap with the P20");
4618 
4619  auto p20Covered = m_rxPhy->GetPhyEntity(WIFI_STANDARD_80211ax)
4620  ->CanStartRx(ppdu); // CanStartRx returns true is the P20 is fully covered
4621  NS_TEST_ASSERT_MSG_EQ(p20Covered,
4622  expectedP20Covered,
4623  "PPDU is " << (expectedP20Covered ? "expected" : "not expected")
4624  << " to cover the whole P20");
4625 }
4626 
4627 void
4629 {
4630  /*
4631  * Receiver PHY Operating Channel: 2.4 GHz Channel 4 (2417 MHz – 2437 MHz)
4632  * Transmitted 20 MHz PPDU: 2.4 GHz Channel 4 (2417 MHz – 2437 MHz)
4633  * Overlap with primary 20 MHz: yes
4634  * Primary 20 MHz fully covered: yes
4635  */
4636  RunOne(WIFI_PHY_BAND_2_4GHZ, 2427, 0, 2427, true, true);
4637 
4638  /*
4639  * Receiver PHY Operating Channel: 2.4 GHz Channel 4 (2417 MHz – 2437 MHz)
4640  * Transmitted 20 MHz PPDU: 2.4 GHz Channel 6 (2427 MHz – 2447 MHz)
4641  * Overlap with primary 20 MHz: yes
4642  * Primary 20 MHz fully covered: no
4643  */
4644  RunOne(WIFI_PHY_BAND_2_4GHZ, 2427, 0, 2437, true, false);
4645 
4646  /*
4647  * Receiver PHY Operating Channel: 5 GHz Channel 36 (5170 MHz – 5190 MHz)
4648  * Transmitted 40 MHz PPDU: 5 GHz Channel 38 (5170 MHz – 5210 MHz)
4649  * Overlap with primary 20 MHz: yes
4650  * Primary 20 MHz fully covered: yes
4651  */
4652  RunOne(WIFI_PHY_BAND_5GHZ, 5180, 0, 5190, true, true);
4653 
4654  /*
4655  * Receiver PHY Operating Channel: 5 GHz Channel 36 (5170 MHz–5190 MHz)
4656  * Transmitted 20 MHz PPDU: 5 GHz Channel 40 (5190 MHz – 5210 MHz)
4657  * Overlap with primary 20 MHz: no
4658  * Primary 20 MHz fully covered: no
4659  */
4660  RunOne(WIFI_PHY_BAND_5GHZ, 5180, 0, 5200, false, false);
4661 
4662  /*
4663  * Receiver PHY Operating Channel: 5 GHz Channel 38 (5170 MHz – 5210 MHz) with P20 index 0
4664  * Transmitted 20 MHz PPDU: 5 GHz Channel 36 (5170 MHz – 5190 MHz)
4665  * Overlap with primary 20 MHz: yes
4666  * Primary 20 MHz fully covered: yes
4667  */
4668  RunOne(WIFI_PHY_BAND_5GHZ, 5190, 0, 5180, true, true);
4669 
4670  /*
4671  * Receiver PHY Operating Channel: 5 GHz Channel 38 (5170 MHz – 5210 MHz) with P20 index 1
4672  * Transmitted 20 MHz PPDU: 5 GHz Channel 36 (5170 MHz – 5190 MHz)
4673  * Overlap with primary 20 MHz: no
4674  * Primary 20 MHz fully covered: no
4675  */
4676  RunOne(WIFI_PHY_BAND_5GHZ, 5190, 1, 5180, false, false);
4677 
4678  Simulator::Destroy();
4679 }
4680 
4691 {
4692  public:
4699  TestSpectrumChannelWithBandwidthFilter(uint16_t channel, uint16_t expectedValue);
4700 
4701  protected:
4702  void DoSetup() override;
4703  void DoTeardown() override;
4704 
4705  private:
4714  void RxBegin(bool signalType, uint32_t senderNodeId, double rxPower, Time duration);
4715 
4719  void Send() const;
4720 
4726  void CheckRxPacketCount(uint16_t expectedValue);
4727 
4728  void DoRun() override;
4729 
4732  uint32_t m_countRxBegin{0};
4733  uint16_t m_channel{36};
4734  uint16_t m_expectedValue{0};
4735 };
4736 
4738  uint16_t channel,
4739  uint16_t expectedValue)
4740  : TestCase("Test for early discard of signal in single-model-spectrum-channel::StartTx()"),
4741  m_channel(channel),
4742  m_expectedValue(expectedValue)
4743 {
4744 }
4745 
4746 void
4748 {
4749  WifiTxVector txVector =
4750  WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
4751 
4752  Ptr<Packet> pkt = Create<Packet>(1000);
4753  WifiMacHeader hdr;
4754 
4756  hdr.SetQosTid(0);
4757 
4758  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4759  m_tx->Send(psdu, txVector);
4760 }
4761 
4762 void
4764 {
4766  expectedValue,
4767  "Received a different amount of packets than expected.");
4768 }
4769 
4770 void
4771 TestSpectrumChannelWithBandwidthFilter::RxBegin(bool signalType [[maybe_unused]],
4772  uint32_t senderNodeId [[maybe_unused]],
4773  double rxPower [[maybe_unused]],
4774  Time duration [[maybe_unused]])
4775 {
4776  NS_LOG_FUNCTION(this << signalType << senderNodeId << rxPower << duration);
4777  m_countRxBegin++;
4778 }
4779 
4780 void
4782 {
4783  NS_LOG_FUNCTION(this);
4784  Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel>();
4785 
4786  Ptr<WifiBandwidthFilter> wifiFilter = CreateObject<WifiBandwidthFilter>();
4787  channel->AddSpectrumTransmitFilter(wifiFilter);
4788 
4789  Ptr<Node> node = CreateObject<Node>();
4790  Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
4791  m_tx = CreateObject<SpectrumWifiPhy>();
4792  m_tx->SetDevice(dev);
4793  m_tx->SetTxPowerStart(20);
4794  m_tx->SetTxPowerEnd(20);
4795 
4796  Ptr<Node> nodeRx = CreateObject<Node>();
4797  Ptr<WifiNetDevice> devRx = CreateObject<WifiNetDevice>();
4798  m_rx = CreateObject<SpectrumWifiPhy>();
4799  m_rx->SetDevice(devRx);
4800 
4801  Ptr<InterferenceHelper> interferenceTx = CreateObject<InterferenceHelper>();
4802  m_tx->SetInterferenceHelper(interferenceTx);
4803  Ptr<ErrorRateModel> errorTx = CreateObject<NistErrorRateModel>();
4804  m_tx->SetErrorRateModel(errorTx);
4805 
4806  Ptr<InterferenceHelper> interferenceRx = CreateObject<InterferenceHelper>();
4807  m_rx->SetInterferenceHelper(interferenceRx);
4808  Ptr<ErrorRateModel> errorRx = CreateObject<NistErrorRateModel>();
4809  m_rx->SetErrorRateModel(errorRx);
4810 
4813 
4816 
4817  dev->SetPhy(m_tx);
4818  node->AddDevice(dev);
4819  devRx->SetPhy(m_rx);
4820  nodeRx->AddDevice(devRx);
4821 
4823  "SignalArrival",
4825 }
4826 
4827 void
4829 {
4830  m_tx->Dispose();
4831  m_rx->Dispose();
4832 }
4833 
4834 void
4836 {
4837  NS_LOG_FUNCTION(this);
4840 
4841  Simulator::Schedule(MilliSeconds(100), &TestSpectrumChannelWithBandwidthFilter::Send, this);
4842  Simulator::Schedule(MilliSeconds(101),
4844  this,
4845  m_expectedValue);
4846 
4847  Simulator::Run();
4848  Simulator::Destroy();
4849 }
4850 
4858 {
4859  public:
4861 };
4862 
4864  : TestSuite("wifi-phy-reception", UNIT)
4865 {
4868  AddTestCase(new TestSimpleFrameCaptureModel, TestCase::QUICK);
4869  AddTestCase(new TestPhyHeadersReception, TestCase::QUICK);
4870  AddTestCase(new TestAmpduReception, TestCase::QUICK);
4871  AddTestCase(new TestUnsupportedModulationReception(), TestCase::QUICK);
4872  AddTestCase(new TestUnsupportedBandwidthReception(), TestCase::QUICK);
4873  AddTestCase(new TestPrimary20CoveredByPpdu(), TestCase::QUICK);
4874  // The below three test cases are related. The test involves a receiver tuned to
4875  // channel 36 and a transmitter sending on channels 36, 40, and 44, respectively.
4876  // The second argument corresponds to the number of signals expected to be received.
4877  // Signals on channel 36 and 40 will fall within the receiver bandwidth, while
4878  // a signal on channel 44 will fall completely outside and will be filtered.
4879  AddTestCase(new TestSpectrumChannelWithBandwidthFilter(36, 1), TestCase::QUICK);
4880  AddTestCase(new TestSpectrumChannelWithBandwidthFilter(40, 1), TestCase::QUICK);
4881  AddTestCase(new TestSpectrumChannelWithBandwidthFilter(44, 0), TestCase::QUICK);
4882 }
4883 
A-MPDU reception test.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
RX success function.
void IncrementSuccessBitmap(uint32_t size)
Increment reception success bitmap.
uint8_t m_rxDroppedBitmapAmpdu2
bitmap of dropped MPDUs in A-MPDU #2
void CheckRxSuccessBitmapAmpdu2(uint8_t expected)
Check the RX success bitmap for A-MPDU 2.
void DoRun() override
Implementation to actually run this TestCase.
void CheckRxDroppedBitmapAmpdu1(uint8_t expected)
Check the RX dropped bitmap for A-MPDU 1.
uint8_t m_rxSuccessBitmapAmpdu1
bitmap of successfully received MPDUs in A-MPDU #1
uint8_t m_rxFailureBitmapAmpdu1
bitmap of unsuccessfully received MPDUs in A-MPDU #1
uint8_t m_rxFailureBitmapAmpdu2
bitmap of unsuccessfully received MPDUs in A-MPDU #2
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize)
Send A-MPDU with 3 MPDUs of different size (i-th MSDU will have 100 bytes more than (i-1)-th).
void RxFailure(Ptr< const WifiPsdu > psdu)
RX failure function.
void CheckRxFailureBitmapAmpdu2(uint8_t expected)
Check the RX failure bitmap for A-MPDU 2.
uint8_t m_rxDroppedBitmapAmpdu1
bitmap of dropped MPDUs in A-MPDU #1
void IncrementFailureBitmap(uint32_t size)
Increment reception failure bitmap.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void ResetBitmaps()
Reset bitmaps function.
void CheckPhyState(WifiPhyState expectedState)
Check the PHY state.
void CheckRxSuccessBitmapAmpdu1(uint8_t expected)
Check the RX success bitmap for A-MPDU 1.
void CheckRxFailureBitmapAmpdu1(uint8_t expected)
Check the RX failure bitmap for A-MPDU 1.
uint8_t m_rxSuccessBitmapAmpdu2
bitmap of successfully received MPDUs in A-MPDU #2
void CheckRxDroppedBitmapAmpdu2(uint8_t expected)
Check the RX dropped bitmap for A-MPDU 2.
Test PHY state upon success or failure of L-SIG and SIG-A.
void DoRun() override
Implementation to actually run this TestCase.
Primary 20 MHz Covered By Ppdu Test This test checks whether the functions WifiPpdu::DoesOverlapChann...
Ptr< SpectrumWifiPhy > m_rxPhy
RX PHY.
void RunOne(WifiPhyBand band, uint16_t phyCenterFreqMhz, uint8_t p20Index, uint16_t ppduCenterFreqMhz, bool expectedP20Overlap, bool expectedP20Covered)
Run one function.
Ptr< HePpdu > CreatePpdu(uint16_t ppduCenterFreqMhz)
Function to create a PPDU.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_txPhy
TX PHY.
Simple frame capture model test.
void Expect1000BPacketReceived()
Verify whether 1000 bytes packet has been received.
bool m_rxDropped1500B
count dropped packets with 1500B payload
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void Expect1500BPacketDropped()
Verify whether 1500 bytes packet has been dropped.
void Expect1000BPacketDropped()
Verify whether 1000 bytes packet has been dropped.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Spectrum wifi receive success function.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRun() override
Implementation to actually run this TestCase.
bool m_rxSuccess1000B
count received packets with 1000B payload
bool m_rxSuccess1500B
count received packets with 1500B payload
void Expect1500BPacketReceived()
Verify whether 1500 bytes packet has been received.
bool m_rxDropped1000B
count dropped packets with 1000B payload
This test verifies the correct function of the WifiBandwidthFilter.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint16_t m_expectedValue
expected count of receive events
void Send() const
Send function (sends a single packet)
TestSpectrumChannelWithBandwidthFilter(uint16_t channel, uint16_t expectedValue)
Constructor.
Ptr< SpectrumWifiPhy > m_tx
transmit function
Ptr< SpectrumWifiPhy > m_rx
receive function
void RxBegin(bool signalType, uint32_t senderNodeId, double rxPower, Time duration)
Callback invoked when the PHY model starts to process a signal.
void DoRun() override
Implementation to actually run this TestCase.
void CheckRxPacketCount(uint16_t expectedValue)
Event scheduled at end of simulation for validation.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint16_t m_channel
channel for packet transmission
uint32_t m_countRxBegin
count of receive events
Preamble detection test w/o frame capture.
void RxFailure(Ptr< const WifiPsdu > psdu)
Spectrum wifi receive failure function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Spectrum wifi receive success function.
void DoRun() override
Implementation to actually run this TestCase.
void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount)
Check the number of received packets.
Preamble detection test w/o frame capture.
void DoRun() override
Implementation to actually run this TestCase.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Spectrum wifi receive success function.
void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount)
Check the number of received packets.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void RxFailure(Ptr< const WifiPsdu > psdu)
Spectrum wifi receive failure function.
Unsupported Bandwidth Reception Test This test checks whether a PHY receiving a PPDU sent over a chan...
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_rxPhy
RX PHY.
std::optional< Time > m_lastRxDropped
time of last RX drop, if any
Ptr< SpectrumWifiPhy > m_txPhy
TX PHY.
std::optional< Time > m_lastRxSucceeded
time of last RX success, if any
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SendPpdu(uint16_t centerFreqMhz, uint16_t bandwidthMhz)
Function to create a PPDU.
void CheckRx(uint32_t expectedCountRxSuccess, uint32_t expectedCountRxFailure, uint32_t expectedCountRxDropped, std::optional< Time > expectedLastRxSucceeded, std::optional< Time > expectedLastRxFailed, std::optional< Time > expectedLastRxDropped)
Check the reception results.
void RxFailure(Ptr< const WifiPsdu > psdu)
Function called upon a PSDU received unsuccessfuly.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Function called upon a PSDU received successfully.
void DoRun() override
Implementation to actually run this TestCase.
std::optional< Time > m_lastRxFailed
time of last RX failure, if any
void RxDropped(Ptr< const Packet > packet, WifiPhyRxfailureReason reason)
Function called upon a PSDU dropped by the PHY.
Unsupported Modulation Reception Test This test creates a mixed network, in which an HE STA and a VHT...
void DoRun() override
Implementation to actually run this TestCase.
void CheckResults()
Check correctness of transmitted frames.
void Dropped(std::string context, Ptr< const Packet > packet, WifiPhyRxfailureReason reason)
Callback invoked when PHY drops an incoming packet.
~TestUnsupportedModulationReception() override=default
uint16_t m_dropped
number of packets dropped by the AP because it was already receiving
Wifi Phy Reception Test base class.
WifiPhyReceptionTest(std::string test_name)
Constructor.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
~WifiPhyReceptionTest() override=default
Destructor.
void DoCheckPhyState(WifiPhyState expectedState)
Check the PHY state now.
void CheckPhyState(WifiPhyState expectedState)
Schedule now to check the PHY state.
uint64_t m_uid
the UID to use for the PPDU
void SendPacket(double rxPowerDbm, uint32_t packetSize, uint8_t mcs)
Send packet function.
Ptr< SpectrumWifiPhy > m_phy
the PHY
void DoSetup() override
Implementation to do any local setup required for this TestCase.
wifi PHY reception Test Suite
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:138
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:315
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:244
void Dispose()
Dispose of this Object.
Definition: object.cc:219
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:202
Make it easy to create and manage PHY objects for the spectrum model.
void SetDevice(const Ptr< WifiNetDevice > device) override
Sets the device this PHY is associated with.
void StartRx(Ptr< SpectrumSignalParameters > rxParams, Ptr< const WifiSpectrumPhyInterface > interface)
Input method for delivering a signal from the spectrum channel and low-level PHY interface to this Sp...
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
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.
create MAC layers for a ns3::WifiNetDevice.
Ptr< WifiMac > GetMac() const
void SetPhy(const Ptr< WifiPhy > phy)
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:631
void Send(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
This function is a wrapper for the Send variant that accepts a WifiConstPsduMap as first argument.
Definition: wifi-phy.cc:1720
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:639
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:455
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:961
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1507
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:1098
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1021
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:711
void SetTxPowerEnd(double end)
Sets the maximum available transmission power level (dBm).
Definition: wifi-phy.cc:542
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:659
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:891
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:449
void SetFrameCaptureModel(const Ptr< FrameCaptureModel > frameCaptureModel)
Sets the frame capture model.
Definition: wifi-phy.cc:653
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1033
void SetTxPowerStart(double start)
Sets the minimum available transmission power level (dBm).
Definition: wifi-phy.cc:529
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: wifi-phy.cc:2227
uint16_t GetPrimaryChannelCenterFrequency(uint16_t primaryChannelWidth) const
Get the center frequency of the primary channel of the given width.
This objects implements the PHY state machine of the Wifi device.
std::vector< Ptr< WifiMpdu > >::const_iterator end() const
Return a const iterator to past-the-last MPDU.
Definition: wifi-psdu.cc:345
std::vector< Ptr< WifiMpdu > >::const_iterator begin() const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:333
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:273
bool IsAggregate() const
Return true if the PSDU is an S-MPDU or A-MPDU.
Definition: wifi-psdu.cc:83
bool IsSingle() const
Return true if the PSDU is an S-MPDU.
Definition: wifi-psdu.cc:77
std::size_t GetNMpdus() const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:327
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:890
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:974
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:144
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:251
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ UNSUPPORTED_SETTINGS
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
@ WIFI_MAC_QOSDATA
channel
Definition: third.py:88
mac
Definition: third.py:92
wifi
Definition: third.py:95
wifiApNode
Definition: third.py:86
mobility
Definition: third.py:105
wifiStaNodes
Definition: third.py:84
phy
Definition: third.py:89
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
static const uint8_t CHANNEL_NUMBER
static const uint16_t GUARD_WIDTH
static const uint16_t CHANNEL_WIDTH
static WifiPhyReceptionTestSuite wifiPhyReceptionTestSuite
the test suite
static const uint32_t FREQUENCY
WifiPhyState
The state of the PHY layer.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ RX
The PHY layer is receiving a packet.
@ IDLE
The PHY layer is IDLE.
static const uint32_t packetSize
Packet size generated at the AP.
void SendPacket(Ptr< NetDevice > sourceDevice, Address &destination)
This example (inspired from tv-trans-example) enables to generate the transmitted spectra of Wi-Fi st...