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/spectrum-wifi-helper.h"
41 #include "ns3/spectrum-wifi-phy.h"
42 #include "ns3/test.h"
43 #include "ns3/threshold-preamble-detection-model.h"
44 #include "ns3/wifi-mac-header.h"
45 #include "ns3/wifi-mpdu.h"
46 #include "ns3/wifi-net-device.h"
47 #include "ns3/wifi-psdu.h"
48 #include "ns3/wifi-spectrum-signal-parameters.h"
49 #include "ns3/wifi-spectrum-value-helper.h"
50 #include "ns3/wifi-utils.h"
51 
52 #include <optional>
53 
54 using namespace ns3;
55 
56 NS_LOG_COMPONENT_DEFINE("WifiPhyReceptionTest");
57 
58 static const uint8_t CHANNEL_NUMBER = 36;
59 static const uint32_t FREQUENCY = 5180; // MHz
60 static const uint16_t CHANNEL_WIDTH = 20; // MHz
61 static const uint16_t GUARD_WIDTH =
62  CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
63 
71 {
72  public:
75 
76  protected:
77  void DoSetup() override;
78  void DoTeardown() override;
84  void SendPacket(double rxPowerDbm);
92  void RxSuccess(Ptr<const WifiPsdu> psdu,
93  RxSignalInfo rxSignalInfo,
94  WifiTxVector txVector,
95  std::vector<bool> statusPerMpdu);
100  void RxFailure(Ptr<const WifiPsdu> psdu);
101  uint32_t m_countRxSuccess;
102  uint32_t m_countRxFailure;
103 
104  private:
105  void DoRun() override;
106 
111  void CheckPhyState(WifiPhyState expectedState);
116  void DoCheckPhyState(WifiPhyState expectedState);
122  void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
123 
124  uint64_t m_uid;
125 };
126 
129  : TestCase("Threshold preamble detection model test when no frame capture model is applied"),
130  m_countRxSuccess(0),
131  m_countRxFailure(0),
132  m_uid(0)
133 {
134 }
135 
136 void
138 {
139  WifiTxVector txVector =
140  WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
141 
142  Ptr<Packet> pkt = Create<Packet>(1000);
143  WifiMacHeader hdr;
144 
146  hdr.SetQosTid(0);
147 
148  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
149  Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
150 
151  Ptr<WifiPpdu> ppdu =
152  Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
153 
154  Ptr<SpectrumValue> txPowerSpectrum =
155  WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
157  DbmToW(rxPowerDbm),
158  GUARD_WIDTH);
159 
160  Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
161  txParams->psd = txPowerSpectrum;
162  txParams->txPhy = nullptr;
163  txParams->duration = txDuration;
164  txParams->ppdu = ppdu;
165  txParams->txWidth = CHANNEL_WIDTH;
166 
167  m_phy->StartRx(txParams);
168 }
169 
170 void
172 {
173  // This is needed to make sure PHY state will be checked as the last event if a state change
174  // occurred at the exact same time as the check
176  this,
177  expectedState);
178 }
179 
180 void
182 {
183  WifiPhyState currentState;
184  PointerValue ptr;
185  m_phy->GetAttribute("State", ptr);
186  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
187  currentState = state->GetState();
188  NS_LOG_FUNCTION(this << currentState);
189  NS_TEST_ASSERT_MSG_EQ(currentState,
190  expectedState,
191  "PHY State " << currentState << " does not match expected state "
192  << expectedState << " at " << Simulator::Now());
193 }
194 
195 void
197  uint32_t expectedFailureCount)
198 {
200  expectedSuccessCount,
201  "Didn't receive right number of successful packets");
203  expectedFailureCount,
204  "Didn't receive right number of unsuccessful packets");
205 }
206 
207 void
209  RxSignalInfo rxSignalInfo,
210  WifiTxVector txVector,
211  std::vector<bool> statusPerMpdu)
212 {
213  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
215 }
216 
217 void
219 {
220  NS_LOG_FUNCTION(this << *psdu);
222 }
223 
226 {
227  m_phy = nullptr;
228 }
229 
230 void
232 {
233  m_phy = CreateObject<SpectrumWifiPhy>();
235  Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
236  m_phy->SetInterferenceHelper(interferenceHelper);
237  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
238  m_phy->SetErrorRateModel(error);
244 
245  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
246  CreateObject<ThresholdPreambleDetectionModel>();
247  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
248  preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
249  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
250 }
251 
252 void
254 {
255  m_phy->Dispose();
256  m_phy = nullptr;
257 }
258 
259 void
261 {
262  RngSeedManager::SetSeed(1);
263  RngSeedManager::SetRun(1);
264  int64_t streamNumber = 0;
265  m_phy->AssignStreams(streamNumber);
266 
267  // RX power > CCA-ED > CCA-PD
268  double rxPowerDbm = -50;
269 
270  // CASE 1: send one packet and check PHY state:
271  // All reception stages should succeed and PHY state should be RX for the duration of the packet
272  // minus the time to detect the preamble, otherwise it should be IDLE.
273 
274  Simulator::Schedule(Seconds(1.0),
276  this,
277  rxPowerDbm);
278  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
279  // CCA_BUSY
280  Simulator::Schedule(Seconds(1.0) + NanoSeconds(3999),
282  this,
284  Simulator::Schedule(Seconds(1.0) + NanoSeconds(4000),
286  this,
288  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
289  // CCA_BUSY to RX
290  Simulator::Schedule(Seconds(1.0) + NanoSeconds(43999),
292  this,
294  Simulator::Schedule(Seconds(1.0) + NanoSeconds(44000),
296  this,
298  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
299  Simulator::Schedule(Seconds(1.0) + NanoSeconds(152799),
301  this,
303  Simulator::Schedule(Seconds(1.0) + NanoSeconds(152800),
305  this,
307  // Packet should have been successfully received
308  Simulator::Schedule(Seconds(1.1),
310  this,
311  1,
312  0);
313 
314  // CASE 2: send two packets with same power within the 4us window and check PHY state:
315  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
316  // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
317  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
318  // time to detect the preamble.
319 
320  Simulator::Schedule(Seconds(2.0),
322  this,
323  rxPowerDbm);
324  Simulator::Schedule(Seconds(2.0) + MicroSeconds(2.0),
326  this,
327  rxPowerDbm);
328  // At 4us, no preamble is successfully detected and STA PHY STATE should move from IDLE to
329  // CCA_BUSY
330  Simulator::Schedule(Seconds(2.0) + NanoSeconds(3999),
332  this,
334  Simulator::Schedule(Seconds(2.0) + NanoSeconds(4000),
336  this,
338  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
339  // = 154.8us
340  Simulator::Schedule(Seconds(2.0) + NanoSeconds(154799),
342  this,
344  Simulator::Schedule(Seconds(2.0) + NanoSeconds(154800),
346  this,
348  // No more packet should have been successfully received, and since preamble detection did not
349  // pass, the packet should not have been counted as a failure
350  Simulator::Schedule(Seconds(2.1),
352  this,
353  1,
354  0);
355 
356  // CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY
357  // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
358  // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
359  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
360  // time to detect the preamble.
361 
362  Simulator::Schedule(Seconds(3.0),
364  this,
365  rxPowerDbm);
366  Simulator::Schedule(Seconds(3.0) + MicroSeconds(2.0),
368  this,
369  rxPowerDbm - 3);
370  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
371  // CCA_BUSY
372  Simulator::Schedule(Seconds(3.0) + NanoSeconds(3999),
374  this,
376  Simulator::Schedule(Seconds(3.0) + NanoSeconds(4000),
378  this,
380  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
381  // = 154.8us
382  Simulator::Schedule(Seconds(3.0) + NanoSeconds(154799),
384  this,
386  Simulator::Schedule(Seconds(3.0) + NanoSeconds(154800),
388  this,
390  // No more packet should have been successfully received, and since preamble detection did not
391  // pass the packet should not have been counted as a failure
392  Simulator::Schedule(Seconds(3.1),
394  this,
395  1,
396  0);
397 
398  // CASE 4: send two packets with second one 6 dB weaker within the 4us window and check PHY
399  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
400  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
401  // decode the modulation).
402 
403  Simulator::Schedule(Seconds(4.0),
405  this,
406  rxPowerDbm);
407  Simulator::Schedule(Seconds(4.0) + MicroSeconds(2.0),
409  this,
410  rxPowerDbm - 6);
411  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
412  // CCA_BUSY
413  Simulator::Schedule(Seconds(4.0) + NanoSeconds(3999),
415  this,
417  Simulator::Schedule(Seconds(4.0) + NanoSeconds(4000),
419  this,
421  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
422  // CCA_BUSY to RX
423  Simulator::Schedule(Seconds(4.0) + NanoSeconds(43999),
425  this,
427  Simulator::Schedule(Seconds(4.0) + NanoSeconds(44000),
429  this,
431  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
432  // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
433  // should first be seen as CCA_BUSY for 2us.
434  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152799),
436  this,
438  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152800),
440  this,
442  Simulator::Schedule(Seconds(4.0) + NanoSeconds(154799),
444  this,
446  Simulator::Schedule(Seconds(4.0) + NanoSeconds(154800),
448  this,
450  // In this case, the first packet should be marked as a failure
451  Simulator::Schedule(Seconds(4.1),
453  this,
454  1,
455  1);
456 
457  // CASE 5: send two packets with second one 3 dB higher within the 4us window and check PHY
458  // state: PHY preamble detection should fail because SNR is too low (around -3 dB, which is
459  // lower than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is
460  // above CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus
461  // the time to detect the preamble.
462 
463  Simulator::Schedule(Seconds(5.0),
465  this,
466  rxPowerDbm);
467  Simulator::Schedule(Seconds(5.0) + MicroSeconds(2.0),
469  this,
470  rxPowerDbm + 3);
471  // At 6us (hence 4us after the last signal is received), no preamble is successfully detected,
472  // hence STA PHY STATE should move from IDLE to CCA_BUSY
473  Simulator::Schedule(Seconds(5.0) + NanoSeconds(5999),
475  this,
477  Simulator::Schedule(Seconds(5.0) + NanoSeconds(6000),
479  this,
481  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
482  // = 154.8us
483  Simulator::Schedule(Seconds(5.0) + NanoSeconds(154799),
485  this,
487  Simulator::Schedule(Seconds(5.0) + NanoSeconds(154800),
489  this,
491  // No more packet should have been successfully received, and since preamble detection did not
492  // pass the packet should not have been counted as a failure
493  Simulator::Schedule(Seconds(5.1),
495  this,
496  1,
497  1);
498 
499  // CCA-PD < RX power < CCA-ED
500  rxPowerDbm = -70;
501 
502  // CASE 6: send one packet and check PHY state:
503  // All reception stages should succeed and PHY state should be RX for the duration of the packet
504  // minus the time to detect the preamble, otherwise it should be IDLE.
505 
506  Simulator::Schedule(Seconds(6.0),
508  this,
509  rxPowerDbm);
510  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
511  // CCA_BUSY
512  Simulator::Schedule(Seconds(6.0) + NanoSeconds(3999),
514  this,
516  Simulator::Schedule(Seconds(6.0) + NanoSeconds(4000),
518  this,
520  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
521  // CCA_BUSY to RX
522  Simulator::Schedule(Seconds(6.0) + NanoSeconds(43999),
524  this,
526  Simulator::Schedule(Seconds(6.0) + NanoSeconds(44000),
528  this,
530  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
531  Simulator::Schedule(Seconds(6.0) + NanoSeconds(152799),
533  this,
535  Simulator::Schedule(Seconds(6.0) + NanoSeconds(152800),
537  this,
539  // Packet should have been successfully received
540  Simulator::Schedule(Seconds(6.1),
542  this,
543  2,
544  1);
545 
546  // CASE 7: send two packets with same power within the 4us window and check PHY state:
547  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
548  // the threshold of 4 dB), and PHY state should be CCA_BUSY since it should detect the start of
549  // a valid OFDM transmission at a receive level greater than or equal to the minimum modulation
550  // and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
551 
552  Simulator::Schedule(Seconds(7.0),
554  this,
555  rxPowerDbm);
556  Simulator::Schedule(Seconds(7.0) + MicroSeconds(2.0),
558  this,
559  rxPowerDbm);
560  // At 4us, STA PHY STATE should stay IDLE
561  Simulator::Schedule(Seconds(7.0) + MicroSeconds(4.0),
563  this,
565  // No more packet should have been successfully received, and since preamble detection did not
566  // pass the packet should not have been counted as a failure
567  Simulator::Schedule(Seconds(7.1),
569  this,
570  2,
571  1);
572 
573  // CASE 8: send two packets with second one 3 dB weaker within the 4us window and check PHY
574  // state: PHY preamble detection should fail PHY preamble detection should fail because SNR is
575  // too low (around 3 dB, which is lower than the threshold of 4 dB), and PHY state should be
576  // CCA_BUSY since it should detect the start of a valid OFDM transmission at a receive level
577  // greater than or equal to the minimum modulation and coding rate sensitivity (–82 dBm for 20
578  // MHz channel spacing).
579 
580  Simulator::Schedule(Seconds(8.0),
582  this,
583  rxPowerDbm);
584  Simulator::Schedule(Seconds(8.0) + MicroSeconds(2.0),
586  this,
587  rxPowerDbm - 3);
588  // At 4us, STA PHY STATE should stay IDLE
589  Simulator::Schedule(Seconds(8.0) + MicroSeconds(4.0),
591  this,
593  // No more packet should have been successfully received, and since preamble detection did not
594  // pass the packet should not have been counted as a failure
595  Simulator::Schedule(Seconds(8.1),
597  this,
598  2,
599  1);
600 
601  // CASE 9: send two packets with second one 6 dB weaker within the 4us window and check PHY
602  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
603  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
604  // decode the modulation).
605 
606  Simulator::Schedule(Seconds(9.0),
608  this,
609  rxPowerDbm);
610  Simulator::Schedule(Seconds(9.0) + MicroSeconds(2.0),
612  this,
613  rxPowerDbm - 6);
614  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
615  // CCA_BUSY
616  Simulator::Schedule(Seconds(9.0) + NanoSeconds(3999),
618  this,
620  Simulator::Schedule(Seconds(9.0) + NanoSeconds(4000),
622  this,
624  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
625  // CCA_BUSY to RX
626  Simulator::Schedule(Seconds(9.0) + NanoSeconds(43999),
628  this,
630  Simulator::Schedule(Seconds(9.0) + NanoSeconds(44000),
632  this,
634  // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
635  // 152.8us.
636  Simulator::Schedule(Seconds(9.0) + NanoSeconds(152799),
638  this,
640  Simulator::Schedule(Seconds(9.0) + NanoSeconds(152800),
642  this,
644  // In this case, the first packet should be marked as a failure
645  Simulator::Schedule(Seconds(9.1),
647  this,
648  2,
649  2);
650 
651  // CASE 10: send two packets with second one 3 dB higher within the 4us window and check PHY
652  // state: PHY preamble detection should fail because SNR is too low (around -3 dB, which is
653  // lower than the threshold of 4 dB), and PHY state should stay IDLE since the total energy is
654  // below CCA-ED (-62 dBm).
655 
656  Simulator::Schedule(Seconds(10.0),
658  this,
659  rxPowerDbm);
660  Simulator::Schedule(Seconds(10.0) + MicroSeconds(2.0),
662  this,
663  rxPowerDbm + 3);
664  // At 4us, STA PHY STATE should stay IDLE
665  Simulator::Schedule(Seconds(10.0) + MicroSeconds(4.0),
667  this,
669  // No more packet should have been successfully received, and since preamble detection did not
670  // pass the packet should not have been counted as a failure
671  Simulator::Schedule(Seconds(10.1),
673  this,
674  2,
675  2);
676 
677  // CASE 11: send one packet with a power slightly above the minimum RSSI needed for the preamble
678  // detection (-82 dBm) and check PHY state: preamble detection should succeed and PHY state
679  // should move to RX.
680 
681  rxPowerDbm = -81;
682 
683  Simulator::Schedule(Seconds(11.0),
685  this,
686  rxPowerDbm);
687  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
688  // CCA_BUSY
689  Simulator::Schedule(Seconds(11.0) + NanoSeconds(3999),
691  this,
693  Simulator::Schedule(Seconds(11.0) + NanoSeconds(4000),
695  this,
697  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
698  // CCA_BUSY to RX
699  Simulator::Schedule(Seconds(11.0) + NanoSeconds(43999),
701  this,
703  Simulator::Schedule(Seconds(11.0) + NanoSeconds(44000),
705  this,
707  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
708  Simulator::Schedule(Seconds(11.0) + NanoSeconds(152799),
710  this,
712  Simulator::Schedule(Seconds(11.0) + NanoSeconds(152800),
714  this,
716 
717  // RX power < CCA-PD < CCA-ED
718  rxPowerDbm = -83;
719 
720  // CASE 12: send one packet with a power slightly below the minimum RSSI needed for the preamble
721  // detection (-82 dBm) and check PHY state: preamble detection should fail and PHY should be
722  // kept in IDLE state.
723 
724  Simulator::Schedule(Seconds(12.0),
726  this,
727  rxPowerDbm);
728  // At 4us, STA PHY state should be IDLE
729  Simulator::Schedule(Seconds(12.0) + MicroSeconds(4.0),
731  this,
733 
734  Simulator::Run();
735  Simulator::Destroy();
736 }
737 
745 {
746  public:
749 
750  protected:
751  void DoSetup() override;
752  void DoTeardown() override;
758  void SendPacket(double rxPowerDbm);
766  void RxSuccess(Ptr<const WifiPsdu> psdu,
767  RxSignalInfo rxSignalInfo,
768  WifiTxVector txVector,
769  std::vector<bool> statusPerMpdu);
774  void RxFailure(Ptr<const WifiPsdu> psdu);
775  uint32_t m_countRxSuccess;
776  uint32_t m_countRxFailure;
777 
778  private:
779  void DoRun() override;
780 
785  void CheckPhyState(WifiPhyState expectedState);
790  void DoCheckPhyState(WifiPhyState expectedState);
796  void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
797 
798  uint64_t m_uid;
799 };
800 
802  : TestCase(
803  "Threshold preamble detection model test when simple frame capture model is applied"),
804  m_countRxSuccess(0),
805  m_countRxFailure(0),
806  m_uid(0)
807 {
808 }
809 
810 void
812 {
813  WifiTxVector txVector =
814  WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
815 
816  Ptr<Packet> pkt = Create<Packet>(1000);
817  WifiMacHeader hdr;
818 
820  hdr.SetQosTid(0);
821 
822  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
823  Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
824 
825  Ptr<WifiPpdu> ppdu =
826  Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
827 
828  Ptr<SpectrumValue> txPowerSpectrum =
829  WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
831  DbmToW(rxPowerDbm),
832  GUARD_WIDTH);
833 
834  Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
835  txParams->psd = txPowerSpectrum;
836  txParams->txPhy = nullptr;
837  txParams->duration = txDuration;
838  txParams->ppdu = ppdu;
839 
840  m_phy->StartRx(txParams);
841 }
842 
843 void
845 {
846  // This is needed to make sure PHY state will be checked as the last event if a state change
847  // occurred at the exact same time as the check
849  this,
850  expectedState);
851 }
852 
853 void
855 {
856  WifiPhyState currentState;
857  PointerValue ptr;
858  m_phy->GetAttribute("State", ptr);
859  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
860  currentState = state->GetState();
861  NS_LOG_FUNCTION(this << currentState);
862  NS_TEST_ASSERT_MSG_EQ(currentState,
863  expectedState,
864  "PHY State " << currentState << " does not match expected state "
865  << expectedState << " at " << Simulator::Now());
866 }
867 
868 void
870  uint32_t expectedFailureCount)
871 {
873  expectedSuccessCount,
874  "Didn't receive right number of successful packets");
876  expectedFailureCount,
877  "Didn't receive right number of unsuccessful packets");
878 }
879 
880 void
882  RxSignalInfo rxSignalInfo,
883  WifiTxVector txVector,
884  std::vector<bool> statusPerMpdu)
885 {
886  NS_LOG_FUNCTION(this << *psdu << txVector);
888 }
889 
890 void
892 {
893  NS_LOG_FUNCTION(this << *psdu);
895 }
896 
898 {
899  m_phy = nullptr;
900 }
901 
902 void
904 {
905  m_phy = CreateObject<SpectrumWifiPhy>();
907  Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
908  m_phy->SetInterferenceHelper(interferenceHelper);
909  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
910  m_phy->SetErrorRateModel(error);
916 
917  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
918  CreateObject<ThresholdPreambleDetectionModel>();
919  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
920  preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
921  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
922 
923  Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
924  frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
925  frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
926  m_phy->SetFrameCaptureModel(frameCaptureModel);
927 }
928 
929 void
931 {
932  m_phy->Dispose();
933  m_phy = nullptr;
934 }
935 
936 void
938 {
939  RngSeedManager::SetSeed(1);
940  RngSeedManager::SetRun(1);
941  int64_t streamNumber = 1;
942  m_phy->AssignStreams(streamNumber);
943 
944  // RX power > CCA-ED > CCA-PD
945  double rxPowerDbm = -50;
946 
947  // CASE 1: send one packet and check PHY state:
948  // All reception stages should succeed and PHY state should be RX for the duration of the packet
949  // minus the time to detect the preamble, otherwise it should be IDLE.
950 
951  Simulator::Schedule(Seconds(1.0),
953  this,
954  rxPowerDbm);
955  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
956  // CCA_BUSY
957  Simulator::Schedule(Seconds(1.0) + NanoSeconds(3999),
959  this,
961  Simulator::Schedule(Seconds(1.0) + NanoSeconds(4000),
963  this,
965  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
966  // CCA_BUSY to RX
967  Simulator::Schedule(Seconds(1.0) + NanoSeconds(43999),
969  this,
971  Simulator::Schedule(Seconds(1.0) + NanoSeconds(44000),
973  this,
975  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
976  Simulator::Schedule(Seconds(1.0) + NanoSeconds(152799),
978  this,
980  Simulator::Schedule(Seconds(1.0) + NanoSeconds(152800),
982  this,
984  // Packet should have been successfully received
985  Simulator::Schedule(Seconds(1.1),
987  this,
988  1,
989  0);
990 
991  // CASE 2: send two packets with same power within the 4us window and check PHY state:
992  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
993  // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
994  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
995  // time to detect the preamble.
996 
997  Simulator::Schedule(Seconds(2.0),
999  this,
1000  rxPowerDbm);
1001  Simulator::Schedule(Seconds(2.0) + MicroSeconds(2.0),
1003  this,
1004  rxPowerDbm);
1005  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1006  // CCA_BUSY
1007  Simulator::Schedule(Seconds(2.0) + NanoSeconds(3999),
1009  this,
1011  Simulator::Schedule(Seconds(2.0) + NanoSeconds(4000),
1013  this,
1015  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1016  // = 154.8us
1017  Simulator::Schedule(Seconds(2.0) + NanoSeconds(154799),
1019  this,
1021  Simulator::Schedule(Seconds(2.0) + NanoSeconds(154800),
1023  this,
1025  // No more packet should have been successfully received, and since preamble detection did not
1026  // pass the packet should not have been counted as a failure
1027  Simulator::Schedule(Seconds(2.1),
1029  this,
1030  1,
1031  0);
1032 
1033  // CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY
1034  // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
1035  // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1036  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1037  // time to detect the preamble.
1038 
1039  Simulator::Schedule(Seconds(3.0),
1041  this,
1042  rxPowerDbm);
1043  Simulator::Schedule(Seconds(3.0) + MicroSeconds(2.0),
1045  this,
1046  rxPowerDbm - 3);
1047  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1048  // CCA_BUSY
1049  Simulator::Schedule(Seconds(3.0) + NanoSeconds(3999),
1051  this,
1053  Simulator::Schedule(Seconds(3.0) + NanoSeconds(4000),
1055  this,
1057  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1058  // = 154.8us
1059  Simulator::Schedule(Seconds(3.0) + NanoSeconds(154799),
1061  this,
1063  Simulator::Schedule(Seconds(3.0) + NanoSeconds(154800),
1065  this,
1067  // No more packet should have been successfully received, and since preamble detection did not
1068  // pass the packet should not have been counted as a failure
1069  Simulator::Schedule(Seconds(3.1),
1071  this,
1072  1,
1073  0);
1074 
1075  // CASE 4: send two packets with second one 6 dB weaker within the 4us window and check PHY
1076  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1077  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1078  // decode the modulation).
1079 
1080  Simulator::Schedule(Seconds(4.0),
1082  this,
1083  rxPowerDbm);
1084  Simulator::Schedule(Seconds(4.0) + MicroSeconds(2.0),
1086  this,
1087  rxPowerDbm - 6);
1088  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1089  // CCA_BUSY
1090  Simulator::Schedule(Seconds(4.0) + NanoSeconds(3999),
1092  this,
1094  Simulator::Schedule(Seconds(4.0) + NanoSeconds(4000),
1096  this,
1098  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1099  // CCA_BUSY to RX
1100  Simulator::Schedule(Seconds(4.0) + NanoSeconds(43999),
1102  this,
1104  Simulator::Schedule(Seconds(4.0) + NanoSeconds(44000),
1106  this,
1108  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
1109  // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
1110  // should first be seen as CCA_BUSY for 2us.
1111  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152799),
1113  this,
1115  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152800),
1117  this,
1119  Simulator::Schedule(Seconds(4.0) + NanoSeconds(154799),
1121  this,
1123  Simulator::Schedule(Seconds(4.0) + NanoSeconds(154800),
1125  this,
1127  // In this case, the first packet should be marked as a failure
1128  Simulator::Schedule(Seconds(4.1),
1130  this,
1131  1,
1132  1);
1133 
1134  // CASE 5: send two packets with second one 3 dB higher within the 4us window and check PHY
1135  // state: PHY preamble detection should switch because a higher packet is received within the
1136  // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1137  // lower than the threshold of 4 dB), PHY state should be CCA_BUSY since the total energy is
1138  // above CCA-ED (-62 dBm).
1139 
1140  Simulator::Schedule(Seconds(5.0),
1142  this,
1143  rxPowerDbm);
1144  Simulator::Schedule(Seconds(5.0) + MicroSeconds(2.0),
1146  this,
1147  rxPowerDbm + 3);
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  Simulator::Schedule(Seconds(6.0) + MicroSeconds(2.0),
1192  this,
1193  rxPowerDbm + 6);
1194  // At 4us, STA PHY STATE should stay IDLE
1195  Simulator::Schedule(Seconds(6.0) + MicroSeconds(4.0),
1197  this,
1199  // At 6us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1200  // CCA_BUSY
1201  Simulator::Schedule(Seconds(6.0) + NanoSeconds(5999),
1203  this,
1205  Simulator::Schedule(Seconds(6.0) + NanoSeconds(6000),
1207  this,
1209  // At 46us, PHY header should be successfully received and STA PHY STATE should move from
1210  // CCA_BUSY to RX
1211  Simulator::Schedule(Seconds(6.0) + NanoSeconds(45999),
1213  this,
1215  Simulator::Schedule(Seconds(6.0) + NanoSeconds(46000),
1217  this,
1219  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1220  // = 154.8us
1221  Simulator::Schedule(Seconds(6.0) + NanoSeconds(154799),
1223  this,
1225  Simulator::Schedule(Seconds(6.0) + NanoSeconds(154800),
1227  this,
1229  // In this case, the second packet should be marked as a failure
1230  Simulator::Schedule(Seconds(6.1),
1232  this,
1233  1,
1234  2);
1235 
1236  // CASE 7: send two packets with same power at the exact same time and check PHY state:
1237  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
1238  // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1239  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1240  // time to detect the preamble.
1241 
1242  Simulator::Schedule(Seconds(7.0),
1244  this,
1245  rxPowerDbm);
1246  Simulator::Schedule(Seconds(7.0),
1248  this,
1249  rxPowerDbm);
1250  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1251  // CCA_BUSY
1252  Simulator::Schedule(Seconds(7.0) + NanoSeconds(3999),
1254  this,
1256  Simulator::Schedule(Seconds(7.0) + NanoSeconds(4000),
1258  this,
1260  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1261  // = 154.8us
1262  Simulator::Schedule(Seconds(7.0) + NanoSeconds(152799),
1264  this,
1266  Simulator::Schedule(Seconds(7.0) + NanoSeconds(152800),
1268  this,
1270  // No more packet should have been successfully received, and since preamble detection did not
1271  // pass the packet should not have been counted as a failure
1272  Simulator::Schedule(Seconds(7.1),
1274  this,
1275  1,
1276  2);
1277 
1278  // CASE 8: send two packets with second one 3 dB weaker at the exact same time and check PHY
1279  // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
1280  // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1281  // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1282  // time to detect the preamble.
1283 
1284  Simulator::Schedule(Seconds(8.0),
1286  this,
1287  rxPowerDbm);
1288  Simulator::Schedule(Seconds(8.0),
1290  this,
1291  rxPowerDbm - 3);
1292  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1293  // CCA_BUSY
1294  Simulator::Schedule(Seconds(8.0) + NanoSeconds(3999),
1296  this,
1298  Simulator::Schedule(Seconds(8.0) + NanoSeconds(4000),
1300  this,
1302  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1303  Simulator::Schedule(Seconds(8.0) + NanoSeconds(152799),
1305  this,
1307  Simulator::Schedule(Seconds(8.0) + NanoSeconds(152800),
1309  this,
1311  // No more packet should have been successfully received, and since preamble detection did not
1312  // pass the packet should not have been counted as a failure
1313  Simulator::Schedule(Seconds(8.1),
1315  this,
1316  1,
1317  2);
1318 
1319  // CASE 9: send two packets with second one 6 dB weaker at the exact same time and check PHY
1320  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1321  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1322  // decode the modulation).
1323 
1324  Simulator::Schedule(Seconds(9.0),
1326  this,
1327  rxPowerDbm);
1328  Simulator::Schedule(Seconds(9.0),
1330  this,
1331  rxPowerDbm - 6);
1332  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1333  // CCA_BUSY
1334  Simulator::Schedule(Seconds(9.0) + NanoSeconds(3999),
1336  this,
1338  Simulator::Schedule(Seconds(9.0) + NanoSeconds(4000),
1340  this,
1342  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1343  // CCA_BUSY to RX
1344  Simulator::Schedule(Seconds(9.0) + NanoSeconds(43999),
1346  this,
1348  Simulator::Schedule(Seconds(9.0) + NanoSeconds(44000),
1350  this,
1352  // Since it takes 152.8us to transmit the packets, PHY should be back to IDLE at time 152.8us.
1353  Simulator::Schedule(Seconds(9.0) + NanoSeconds(152799),
1355  this,
1357  Simulator::Schedule(Seconds(9.0) + NanoSeconds(152800),
1359  this,
1361  // In this case, the first packet should be marked as a failure
1362  Simulator::Schedule(Seconds(9.1),
1364  this,
1365  1,
1366  3);
1367 
1368  // CASE 10: send two packets with second one 3 dB higher at the exact same time and check PHY
1369  // state: PHY preamble detection should switch because a higher packet is received within the
1370  // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1371  // lower than the threshold of 4 dB), PHY state should be CCA_BUSY since the total energy is
1372  // above CCA-ED (-62 dBm).
1373 
1374  Simulator::Schedule(Seconds(10.0),
1376  this,
1377  rxPowerDbm);
1378  Simulator::Schedule(Seconds(10.0),
1380  this,
1381  rxPowerDbm + 3);
1382  // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1383  // CCA_BUSY
1384  Simulator::Schedule(Seconds(10.0) + NanoSeconds(3999),
1386  this,
1388  Simulator::Schedule(Seconds(10.0) + NanoSeconds(4000),
1390  this,
1392  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1393  Simulator::Schedule(Seconds(10.0) + NanoSeconds(152799),
1395  this,
1397  Simulator::Schedule(Seconds(10.0) + NanoSeconds(152800),
1399  this,
1401  // No more packet should have been successfully received, and since preamble detection did not
1402  // pass the packet should not have been counted as a failure
1403  Simulator::Schedule(Seconds(10.1),
1405  this,
1406  1,
1407  3);
1408 
1409  // CASE 11: send two packets with second one 6 dB higher at the exact same time and check PHY
1410  // state: PHY preamble detection should switch because a higher packet is received within the
1411  // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1412  // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1413  // decode the modulation).
1414 
1415  Simulator::Schedule(Seconds(11.0),
1417  this,
1418  rxPowerDbm);
1419  Simulator::Schedule(Seconds(11.0),
1421  this,
1422  rxPowerDbm + 6);
1423  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1424  // CCA_BUSY
1425  Simulator::Schedule(Seconds(11.0) + NanoSeconds(3999),
1427  this,
1429  Simulator::Schedule(Seconds(11.0) + NanoSeconds(4000),
1431  this,
1433  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1434  // CCA_BUSY to RX
1435  Simulator::Schedule(Seconds(11.0) + NanoSeconds(43999),
1437  this,
1439  Simulator::Schedule(Seconds(11.0) + NanoSeconds(44000),
1441  this,
1443  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1444  Simulator::Schedule(Seconds(11.0) + NanoSeconds(152799),
1446  this,
1448  Simulator::Schedule(Seconds(11.0) + NanoSeconds(152800),
1450  this,
1452  // In this case, the second packet should be marked as a failure
1453  Simulator::Schedule(Seconds(11.1),
1455  this,
1456  1,
1457  4);
1458 
1459  // CCA-PD < RX power < CCA-ED
1460  rxPowerDbm = -70;
1461 
1462  // CASE 12: send one packet and check PHY state:
1463  // All reception stages should succeed and PHY state should be RX for the duration of the packet
1464  // minus the time to detect the preamble, otherwise it should be IDLE.
1465 
1466  Simulator::Schedule(Seconds(12.0),
1468  this,
1469  rxPowerDbm);
1470  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1471  // CCA_BUSY
1472  Simulator::Schedule(Seconds(12.0) + NanoSeconds(3999),
1474  this,
1476  Simulator::Schedule(Seconds(12.0) + NanoSeconds(4000),
1478  this,
1480  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1481  // CCA_BUSY to RX
1482  Simulator::Schedule(Seconds(12.0) + NanoSeconds(43999),
1484  this,
1486  Simulator::Schedule(Seconds(12.0) + NanoSeconds(44000),
1488  this,
1490  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
1491  Simulator::Schedule(Seconds(12.0) + NanoSeconds(152799),
1493  this,
1495  Simulator::Schedule(Seconds(12.0) + NanoSeconds(152800),
1497  this,
1499  // Packet should have been successfully received
1500  Simulator::Schedule(Seconds(12.1),
1502  this,
1503  2,
1504  4);
1505 
1506  // CASE 13: send two packets with same power within the 4us window and check PHY state:
1507  // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
1508  // the threshold of 4 dB), and PHY state should be CCA_BUSY since it should detect the start of
1509  // a valid OFDM transmission at a receive level greater than or equal to the minimum modulation
1510  // and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
1511 
1512  Simulator::Schedule(Seconds(13.0),
1514  this,
1515  rxPowerDbm);
1516  Simulator::Schedule(Seconds(13.0) + MicroSeconds(2.0),
1518  this,
1519  rxPowerDbm);
1520  // At 4us, STA PHY STATE should stay IDLE
1521  Simulator::Schedule(Seconds(13.0) + MicroSeconds(4.0),
1523  this,
1525  // No more packet should have been successfully received, and since preamble detection did not
1526  // pass the packet should not have been counted as a failure
1527  Simulator::Schedule(Seconds(13.1),
1529  this,
1530  2,
1531  4);
1532 
1533  // CASE 14: send two packets with second one 3 dB weaker within the 4us window and check PHY
1534  // state: PHY preamble detection should fail PHY preamble detection should fail because SNR is
1535  // too low (around 3 dB, which is lower than the threshold of 4 dB), and PHY state should be
1536  // CCA_BUSY since it should detect the start of a valid OFDM transmission at a receive level
1537  // greater than or equal to the minimum modulation and coding rate sensitivity (–82 dBm for 20
1538  // MHz channel spacing).
1539 
1540  Simulator::Schedule(Seconds(14.0),
1542  this,
1543  rxPowerDbm);
1544  Simulator::Schedule(Seconds(14.0) + MicroSeconds(2.0),
1546  this,
1547  rxPowerDbm - 3);
1548  // At 4us, STA PHY STATE should stay IDLE
1549  Simulator::Schedule(Seconds(14.0) + MicroSeconds(4.0),
1551  this,
1553  // No more packet should have been successfully received, and since preamble detection did not
1554  // pass the packet should not have been counted as a failure
1555  Simulator::Schedule(Seconds(14.1),
1557  this,
1558  2,
1559  4);
1560 
1561  // CASE 15: send two packets with second one 6 dB weaker within the 4us window and check PHY
1562  // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1563  // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1564  // decode the modulation).
1565 
1566  Simulator::Schedule(Seconds(15.0),
1568  this,
1569  rxPowerDbm);
1570  Simulator::Schedule(Seconds(15.0) + MicroSeconds(2.0),
1572  this,
1573  rxPowerDbm - 6);
1574  // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1575  // CCA_BUSY
1576  Simulator::Schedule(Seconds(15.0) + NanoSeconds(3999),
1578  this,
1580  Simulator::Schedule(Seconds(15.0) + NanoSeconds(4000),
1582  this,
1584  // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1585  // CCA_BUSY to RX
1586  Simulator::Schedule(Seconds(15.0) + NanoSeconds(43999),
1588  this,
1590  Simulator::Schedule(Seconds(15.0) + NanoSeconds(44000),
1592  this,
1594  // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
1595  // 152.8us.
1596  Simulator::Schedule(Seconds(15.0) + NanoSeconds(152799),
1598  this,
1600  Simulator::Schedule(Seconds(15.0) + NanoSeconds(152800),
1602  this,
1604  // In this case, the first packet should be marked as a failure
1605  Simulator::Schedule(Seconds(15.1),
1607  this,
1608  2,
1609  5);
1610 
1611  // CASE 16: send two packets with second one 3 dB higher within the 4us window and check PHY
1612  // state: PHY preamble detection should switch because a higher packet is received within the
1613  // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1614  // lower than the threshold of 4 dB). and PHY state should be CCA_BUSY since it should detect
1615  // the start of a valid OFDM transmission at a receive level greater than or equal to the
1616  // minimum modulation and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
1617 
1618  Simulator::Schedule(Seconds(16.0),
1620  this,
1621  rxPowerDbm);
1622  Simulator::Schedule(Seconds(16.0) + MicroSeconds(2.0),
1624  this,
1625  rxPowerDbm + 3);
1626  // At 4us, STA PHY STATE should stay IDLE
1627  Simulator::Schedule(Seconds(16.0) + MicroSeconds(4.0),
1629  this,
1631  // At 6us, STA PHY STATE should be CCA_BUSY
1632  Simulator::Schedule(Seconds(16.0) + MicroSeconds(6.0),
1634  this,
1636  // No more packet should have been successfully received, and since preamble detection did not
1637  // pass the packet should not have been counted as a failure
1638  Simulator::Schedule(Seconds(16.1),
1640  this,
1641  2,
1642  5);
1643 
1644  // CASE 17: send two packets with second one 6 dB higher within the 4us window and check PHY
1645  // state: PHY preamble detection should switch because a higher packet is received within the
1646  // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1647  // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1648  // decode the modulation).
1649 
1650  Simulator::Schedule(Seconds(17.0),
1652  this,
1653  rxPowerDbm);
1654  Simulator::Schedule(Seconds(17.0) + MicroSeconds(2.0),
1656  this,
1657  rxPowerDbm + 6);
1658  // At 4us, STA PHY STATE should stay IDLE
1659  Simulator::Schedule(Seconds(17.0) + MicroSeconds(4.0),
1661  this,
1663  // At 6us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1664  // CCA_BUSY
1665  Simulator::Schedule(Seconds(17.0) + NanoSeconds(5999),
1667  this,
1669  Simulator::Schedule(Seconds(17.0) + NanoSeconds(6000),
1671  this,
1673  // At 46us, PHY header should be successfully received and STA PHY STATE should move from
1674  // CCA_BUSY to RX
1675  Simulator::Schedule(Seconds(17.0) + NanoSeconds(45999),
1677  this,
1679  Simulator::Schedule(Seconds(17.0) + NanoSeconds(46000),
1681  this,
1683  // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1684  // = 154.8us
1685  Simulator::Schedule(Seconds(17.0) + NanoSeconds(154799),
1687  this,
1689  Simulator::Schedule(Seconds(17.0) + NanoSeconds(154800),
1691  this,
1693  // In this case, the second packet should be marked as a failure
1694  Simulator::Schedule(Seconds(17.1),
1696  this,
1697  2,
1698  6);
1699 
1700  rxPowerDbm = -50;
1701  // CASE 18: send two packets with second one 50 dB higher within the 4us window
1702 
1703  Simulator::Schedule(Seconds(18.0),
1705  this,
1706  rxPowerDbm);
1707  Simulator::Schedule(Seconds(18.0) + MicroSeconds(2.0),
1709  this,
1710  rxPowerDbm + 50);
1711  // The second packet should be received successfully
1712  Simulator::Schedule(Seconds(18.1),
1714  this,
1715  3,
1716  6);
1717 
1718  // CASE 19: send two packets with second one 10 dB higher within the 4us window
1719 
1720  Simulator::Schedule(Seconds(19.0),
1722  this,
1723  rxPowerDbm);
1724  Simulator::Schedule(Seconds(19.0) + MicroSeconds(2.0),
1726  this,
1727  rxPowerDbm + 10);
1728  // The second packet should be captured, but not decoded since SNR to low for used MCS
1729  Simulator::Schedule(Seconds(19.1),
1731  this,
1732  3,
1733  7);
1734 
1735  // CASE 20: send two packets with second one 50 dB higher in the same time
1736 
1737  Simulator::Schedule(Seconds(20.0),
1739  this,
1740  rxPowerDbm);
1741  Simulator::Schedule(Seconds(20.0),
1743  this,
1744  rxPowerDbm + 50);
1745  // The second packet should be received successfully, same as in CASE 13
1746  Simulator::Schedule(Seconds(20.1),
1748  this,
1749  4,
1750  7);
1751 
1752  // CASE 21: send two packets with second one 10 dB higher in the same time
1753 
1754  Simulator::Schedule(Seconds(21.0),
1756  this,
1757  rxPowerDbm);
1758  Simulator::Schedule(Seconds(21.0),
1760  this,
1761  rxPowerDbm + 10);
1762  // The second packet should be captured, but not decoded since SNR to low for used MCS, same as
1763  // in CASE 19
1764  Simulator::Schedule(Seconds(21.1),
1766  this,
1767  4,
1768  8);
1769 
1770  Simulator::Run();
1771  Simulator::Destroy();
1772 }
1773 
1781 {
1782  public:
1784  ~TestSimpleFrameCaptureModel() override;
1785 
1786  protected:
1787  void DoSetup() override;
1788  void DoTeardown() override;
1789 
1790  private:
1791  void DoRun() override;
1792 
1796  void Reset();
1802  void SendPacket(double rxPowerDbm, uint32_t packetSize);
1810  void RxSuccess(Ptr<const WifiPsdu> psdu,
1811  RxSignalInfo rxSignalInfo,
1812  WifiTxVector txVector,
1813  std::vector<bool> statusPerMpdu);
1820 
1832  void Expect1000BPacketDropped();
1836  void Expect1500BPacketDropped();
1837 
1839 
1844 
1845  uint64_t m_uid;
1846 };
1847 
1849  : TestCase("Simple frame capture model test"),
1850  m_rxSuccess1000B(false),
1851  m_rxSuccess1500B(false),
1852  m_rxDropped1000B(false),
1853  m_rxDropped1500B(false),
1854  m_uid(0)
1855 {
1856 }
1857 
1858 void
1860 {
1861  WifiTxVector txVector =
1862  WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
1863 
1864  Ptr<Packet> pkt = Create<Packet>(packetSize);
1865  WifiMacHeader hdr;
1866 
1868  hdr.SetQosTid(0);
1869 
1870  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
1871  Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
1872 
1873  Ptr<WifiPpdu> ppdu =
1874  Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
1875 
1876  Ptr<SpectrumValue> txPowerSpectrum =
1877  WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
1878  CHANNEL_WIDTH,
1879  DbmToW(rxPowerDbm),
1880  GUARD_WIDTH);
1881 
1882  Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
1883  txParams->psd = txPowerSpectrum;
1884  txParams->txPhy = nullptr;
1885  txParams->duration = txDuration;
1886  txParams->ppdu = ppdu;
1887 
1888  m_phy->StartRx(txParams);
1889 }
1890 
1891 void
1893  RxSignalInfo rxSignalInfo,
1894  WifiTxVector txVector,
1895  std::vector<bool> statusPerMpdu)
1896 {
1897  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1898  NS_ASSERT(!psdu->IsAggregate() || psdu->IsSingle());
1899  if (psdu->GetSize() == 1030)
1900  {
1901  m_rxSuccess1000B = true;
1902  }
1903  else if (psdu->GetSize() == 1530)
1904  {
1905  m_rxSuccess1500B = true;
1906  }
1907 }
1908 
1909 void
1911 {
1912  NS_LOG_FUNCTION(this << p << reason);
1913  if (p->GetSize() == 1030)
1914  {
1915  m_rxDropped1000B = true;
1916  }
1917  else if (p->GetSize() == 1530)
1918  {
1919  m_rxDropped1500B = true;
1920  }
1921 }
1922 
1923 void
1925 {
1926  m_rxSuccess1000B = false;
1927  m_rxSuccess1500B = false;
1928  m_rxDropped1000B = false;
1929  m_rxDropped1500B = false;
1930 }
1931 
1932 void
1934 {
1935  NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1000B, true, "Didn't receive 1000B packet");
1936 }
1937 
1938 void
1940 {
1941  NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1500B, true, "Didn't receive 1500B packet");
1942 }
1943 
1944 void
1946 {
1947  NS_TEST_ASSERT_MSG_EQ(m_rxDropped1000B, true, "Didn't drop 1000B packet");
1948 }
1949 
1950 void
1952 {
1953  NS_TEST_ASSERT_MSG_EQ(m_rxDropped1500B, true, "Didn't drop 1500B packet");
1954 }
1955 
1957 {
1958  m_phy = nullptr;
1959 }
1960 
1961 void
1963 {
1964  m_phy = CreateObject<SpectrumWifiPhy>();
1966  Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
1967  m_phy->SetInterferenceHelper(interferenceHelper);
1968  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
1969  m_phy->SetErrorRateModel(error);
1971 
1973  m_phy->TraceConnectWithoutContext("PhyRxDrop",
1975 
1976  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
1977  CreateObject<ThresholdPreambleDetectionModel>();
1978  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(2));
1979  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
1980 
1981  Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
1982  frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
1983  frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
1984  m_phy->SetFrameCaptureModel(frameCaptureModel);
1985 }
1986 
1987 void
1989 {
1990  m_phy->Dispose();
1991  m_phy = nullptr;
1992 }
1993 
1994 void
1996 {
1997  RngSeedManager::SetSeed(1);
1998  RngSeedManager::SetRun(1);
1999  int64_t streamNumber = 2;
2000  double rxPowerDbm = -30;
2001  m_phy->AssignStreams(streamNumber);
2002 
2003  // CASE 1: send two packets with same power within the capture window:
2004  // PHY should not switch reception because they have same power.
2005 
2006  Simulator::Schedule(Seconds(1.0),
2008  this,
2009  rxPowerDbm,
2010  1000);
2011  Simulator::Schedule(Seconds(1.0) + MicroSeconds(10.0),
2013  this,
2014  rxPowerDbm,
2015  1500);
2016  Simulator::Schedule(Seconds(1.1), &TestSimpleFrameCaptureModel::Expect1500BPacketDropped, this);
2017  Simulator::Schedule(Seconds(1.2), &TestSimpleFrameCaptureModel::Reset, this);
2018 
2019  // CASE 2: send two packets with second one 6 dB weaker within the capture window:
2020  // PHY should not switch reception because first one has higher power.
2021 
2022  Simulator::Schedule(Seconds(2.0),
2024  this,
2025  rxPowerDbm,
2026  1000);
2027  Simulator::Schedule(Seconds(2.0) + MicroSeconds(10.0),
2029  this,
2030  rxPowerDbm - 6,
2031  1500);
2032  Simulator::Schedule(Seconds(2.1),
2034  this);
2035  Simulator::Schedule(Seconds(2.1), &TestSimpleFrameCaptureModel::Expect1500BPacketDropped, this);
2036  Simulator::Schedule(Seconds(2.2), &TestSimpleFrameCaptureModel::Reset, this);
2037 
2038  // CASE 3: send two packets with second one 6 dB higher within the capture window:
2039  // PHY should switch reception because the second one has a higher power.
2040 
2041  Simulator::Schedule(Seconds(3.0),
2043  this,
2044  rxPowerDbm,
2045  1000);
2046  Simulator::Schedule(Seconds(3.0) + MicroSeconds(10.0),
2048  this,
2049  rxPowerDbm + 6,
2050  1500);
2051  Simulator::Schedule(Seconds(3.1), &TestSimpleFrameCaptureModel::Expect1000BPacketDropped, this);
2052  Simulator::Schedule(Seconds(3.1),
2054  this);
2055  Simulator::Schedule(Seconds(3.2), &TestSimpleFrameCaptureModel::Reset, this);
2056 
2057  // CASE 4: send two packets with second one 6 dB higher after the capture window:
2058  // PHY should not switch reception because capture window duration has elapsed when the second
2059  // packet arrives.
2060 
2061  Simulator::Schedule(Seconds(4.0),
2063  this,
2064  rxPowerDbm,
2065  1000);
2066  Simulator::Schedule(Seconds(4.0) + MicroSeconds(25.0),
2068  this,
2069  rxPowerDbm + 6,
2070  1500);
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  ~TestPhyHeadersReception() override;
2089 
2090  protected:
2091  void DoSetup() override;
2092  void DoTeardown() override;
2098  void SendPacket(double rxPowerDbm);
2099 
2100  private:
2101  void DoRun() override;
2102 
2107  void CheckPhyState(WifiPhyState expectedState);
2112  void DoCheckPhyState(WifiPhyState expectedState);
2113 
2114  uint64_t m_uid;
2115 };
2116 
2118  : TestCase("PHY headers reception test"),
2119  m_uid(0)
2120 {
2121 }
2122 
2123 void
2125 {
2126  WifiTxVector txVector =
2127  WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
2128 
2129  Ptr<Packet> pkt = Create<Packet>(1000);
2130  WifiMacHeader hdr;
2131 
2133  hdr.SetQosTid(0);
2134 
2135  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2136  Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
2137 
2138  Ptr<WifiPpdu> ppdu =
2139  Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
2140 
2141  Ptr<SpectrumValue> txPowerSpectrum =
2142  WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
2143  CHANNEL_WIDTH,
2144  DbmToW(rxPowerDbm),
2145  GUARD_WIDTH);
2146 
2147  Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
2148  txParams->psd = txPowerSpectrum;
2149  txParams->txPhy = nullptr;
2150  txParams->duration = txDuration;
2151  txParams->ppdu = ppdu;
2152 
2153  m_phy->StartRx(txParams);
2154 }
2155 
2156 void
2158 {
2159  // This is needed to make sure PHY state will be checked as the last event if a state change
2160  // occurred at the exact same time as the check
2161  Simulator::ScheduleNow(&TestPhyHeadersReception::DoCheckPhyState, this, expectedState);
2162 }
2163 
2164 void
2166 {
2167  WifiPhyState currentState;
2168  PointerValue ptr;
2169  m_phy->GetAttribute("State", ptr);
2170  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
2171  currentState = state->GetState();
2172  NS_LOG_FUNCTION(this << currentState);
2173  NS_TEST_ASSERT_MSG_EQ(currentState,
2174  expectedState,
2175  "PHY State " << currentState << " does not match expected state "
2176  << expectedState << " at " << Simulator::Now());
2177 }
2178 
2180 {
2181  m_phy = nullptr;
2182 }
2183 
2184 void
2186 {
2187  m_phy = CreateObject<SpectrumWifiPhy>();
2189  Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2190  m_phy->SetInterferenceHelper(interferenceHelper);
2191  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2192  m_phy->SetErrorRateModel(error);
2194 }
2195 
2196 void
2198 {
2199  m_phy->Dispose();
2200  m_phy = nullptr;
2201 }
2202 
2203 void
2205 {
2206  RngSeedManager::SetSeed(1);
2207  RngSeedManager::SetRun(1);
2208  int64_t streamNumber = 0;
2209  m_phy->AssignStreams(streamNumber);
2210 
2211  // RX power > CCA-ED
2212  double rxPowerDbm = -50;
2213 
2214  // CASE 1: send one packet followed by a second one with same power between the end of the 4us
2215  // preamble detection window and the start of L-SIG of the first packet: reception should be
2216  // aborted since L-SIG cannot be decoded (SNR too low).
2217 
2218  Simulator::Schedule(Seconds(1.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2219  Simulator::Schedule(Seconds(1.0) + MicroSeconds(10),
2221  this,
2222  rxPowerDbm);
2223  // At 10 us, STA PHY STATE should be CCA_BUSY.
2224  Simulator::Schedule(Seconds(1.0) + MicroSeconds(10.0),
2226  this,
2228  // At 44us (end of PHY header), STA PHY STATE should not have moved to RX and be kept to
2229  // CCA_BUSY.
2230  Simulator::Schedule(Seconds(1.0) + NanoSeconds(44000),
2232  this,
2234  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8 + 10
2235  // = 162.8us.
2236  Simulator::Schedule(Seconds(1.0) + NanoSeconds(162799),
2238  this,
2240  Simulator::Schedule(Seconds(1.0) + NanoSeconds(162800),
2242  this,
2244 
2245  // CASE 2: send one packet followed by a second one 3 dB weaker between the end of the 4us
2246  // preamble detection window and the start of L-SIG of the first packet: reception should not be
2247  // aborted since L-SIG can be decoded (SNR high enough).
2248 
2249  Simulator::Schedule(Seconds(2.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2250  Simulator::Schedule(Seconds(2.0) + MicroSeconds(10),
2252  this,
2253  rxPowerDbm - 3);
2254  // At 10 us, STA PHY STATE should be CCA_BUSY.
2255  Simulator::Schedule(Seconds(2.0) + MicroSeconds(10.0),
2257  this,
2259  // At 44us (end of PHY header), STA PHY STATE should have moved to RX since PHY header reception
2260  // should have succeeded.
2261  Simulator::Schedule(Seconds(2.0) + NanoSeconds(43999),
2263  this,
2265  Simulator::Schedule(Seconds(2.0) + NanoSeconds(44000),
2267  this,
2269  // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
2270  // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
2271  // should first be seen as CCA_BUSY for 10us.
2272  Simulator::Schedule(Seconds(2.0) + NanoSeconds(152799),
2274  this,
2276  Simulator::Schedule(Seconds(2.0) + NanoSeconds(152800),
2278  this,
2280  Simulator::Schedule(Seconds(2.0) + NanoSeconds(162799),
2282  this,
2284  Simulator::Schedule(Seconds(2.0) + NanoSeconds(162800),
2286  this,
2288 
2289  // CASE 3: send one packet followed by a second one with same power between the end of L-SIG and
2290  // the start of HE-SIG of the first packet: PHY header reception should not succeed but PHY
2291  // should stay in RX state for the duration estimated from L-SIG.
2292 
2293  Simulator::Schedule(Seconds(3.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2294  Simulator::Schedule(Seconds(3.0) + MicroSeconds(25),
2296  this,
2297  rxPowerDbm);
2298  // At 44us (end of PHY header), STA PHY STATE should not have moved to RX (HE-SIG failed) and be
2299  // kept to CCA_BUSY.
2300  Simulator::Schedule(Seconds(3.0) + MicroSeconds(44.0),
2302  this,
2304  // STA PHY STATE should move back to IDLE once the duration estimated from L-SIG has elapsed,
2305  // i.e. at 152.8us. However, since there is a second packet transmitted with a power above
2306  // CCA-ED (-62 dBm), PHY should first be seen as CCA_BUSY for 25us.
2307  Simulator::Schedule(Seconds(3.0) + NanoSeconds(152799),
2309  this,
2311  Simulator::Schedule(Seconds(3.0) + NanoSeconds(152800),
2313  this,
2315  Simulator::Schedule(Seconds(3.0) + NanoSeconds(177799),
2317  this,
2319  Simulator::Schedule(Seconds(3.0) + NanoSeconds(177800),
2321  this,
2323 
2324  // CASE 4: send one packet followed by a second one 3 dB weaker between the end of L-SIG and the
2325  // start of HE-SIG of the first packet: PHY header reception should succeed.
2326 
2327  Simulator::Schedule(Seconds(4.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2328  Simulator::Schedule(Seconds(4.0) + MicroSeconds(25),
2330  this,
2331  rxPowerDbm - 3);
2332  // At 10 us, STA PHY STATE should be CCA_BUSY.
2333  Simulator::Schedule(Seconds(4.0) + MicroSeconds(10.0),
2335  this,
2337  // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2338  // should have succeeded.
2339  Simulator::Schedule(Seconds(4.0) + NanoSeconds(43999),
2341  this,
2343  Simulator::Schedule(Seconds(4.0) + NanoSeconds(44000),
2345  this,
2347  // STA PHY STATE should move back to IDLE once the duration estimated from L-SIG has elapsed,
2348  // i.e. at 152.8us. However, since there is a second packet transmitted with a power above
2349  // CCA-ED (-62 dBm), PHY should first be seen as CCA_BUSY for 25us.
2350  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152799),
2352  this,
2354  Simulator::Schedule(Seconds(4.0) + NanoSeconds(152800),
2356  this,
2358  Simulator::Schedule(Seconds(4.0) + NanoSeconds(177799),
2360  this,
2362  Simulator::Schedule(Seconds(4.0) + NanoSeconds(177800),
2364  this,
2366 
2367  // RX power < CCA-ED
2368  rxPowerDbm = -70;
2369 
2370  // CASE 5: send one packet followed by a second one with same power between the end of the 4us
2371  // preamble detection window and the start of L-SIG of the first packet: reception should be
2372  // aborted since L-SIG cannot be decoded (SNR too low).
2373 
2374  Simulator::Schedule(Seconds(5.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2375  Simulator::Schedule(Seconds(5.0) + MicroSeconds(10),
2377  this,
2378  rxPowerDbm);
2379  // At 10 us, STA PHY STATE should be CCA_BUSY.
2380  Simulator::Schedule(Seconds(5.0) + MicroSeconds(10.0),
2382  this,
2384  // At 24us (end of L-SIG), STA PHY STATE stay CCA_BUSY because L-SIG reception failed and the
2385  // start of a valid OFDM transmission has been detected
2386  Simulator::Schedule(Seconds(5.0) + NanoSeconds(24000),
2388  this,
2390 
2391  // CASE 6: send one packet followed by a second one 3 dB weaker between the end of the 4us
2392  // preamble detection window and the start of L-SIG of the first packet: reception should not be
2393  // aborted since L-SIG can be decoded (SNR high enough).
2394 
2395  Simulator::Schedule(Seconds(6.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2396  Simulator::Schedule(Seconds(6.0) + MicroSeconds(10),
2398  this,
2399  rxPowerDbm - 3);
2400  // At 10 us, STA PHY STATE should be CCA_BUSY.
2401  Simulator::Schedule(Seconds(6.0) + MicroSeconds(10.0),
2403  this,
2405  // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2406  // succeeded.
2407  Simulator::Schedule(Seconds(6.0) + MicroSeconds(24.0),
2409  this,
2411  // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2412  // should have succeeded.
2413  Simulator::Schedule(Seconds(6.0) + NanoSeconds(43999),
2415  this,
2417  Simulator::Schedule(Seconds(6.0) + NanoSeconds(44000),
2419  this,
2421  // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
2422  // 152.8us.
2423  Simulator::Schedule(Seconds(6.0) + NanoSeconds(152799),
2425  this,
2427  Simulator::Schedule(Seconds(6.0) + NanoSeconds(152800),
2429  this,
2431 
2432  // CASE 7: send one packet followed by a second one with same power between the end of L-SIG and
2433  // the start of HE-SIG of the first packet: PHY header reception should not succeed but PHY
2434  // should stay in RX state for the duration estimated from L-SIG.
2435 
2436  Simulator::Schedule(Seconds(7.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2437  Simulator::Schedule(Seconds(7.0) + MicroSeconds(25),
2439  this,
2440  rxPowerDbm);
2441  // At 10 us, STA PHY STATE should be CCA_BUSY.
2442  Simulator::Schedule(Seconds(7.0) + MicroSeconds(10.0),
2444  this,
2446  // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2447  // succeeded.
2448  Simulator::Schedule(Seconds(7.0) + MicroSeconds(24.0),
2450  this,
2452  // At 44 us (end of HE-SIG), STA PHY STATE should be not have moved to RX since reception of
2453  // HE-SIG should have failed.
2454  Simulator::Schedule(Seconds(7.0) + MicroSeconds(44.0),
2456  this,
2458  // STA PHY STATE should keep CCA_BUSY once the duration estimated from L-SIG has elapsed, i.e.
2459  // at 152.8us.
2460  Simulator::Schedule(Seconds(7.0) + NanoSeconds(152800),
2462  this,
2464 
2465  // CASE 8: send one packet followed by a second one 3 dB weaker between the end of L-SIG and the
2466  // start of HE-SIG of the first packet: PHY header reception should succeed.
2467 
2468  Simulator::Schedule(Seconds(8.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2469  Simulator::Schedule(Seconds(8.0) + MicroSeconds(25),
2471  this,
2472  rxPowerDbm - 3);
2473  // At 10 us, STA PHY STATE should be CCA_BUSY.
2474  Simulator::Schedule(Seconds(8.0) + MicroSeconds(10.0),
2476  this,
2478  // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2479  // succeeded.
2480  Simulator::Schedule(Seconds(8.0) + MicroSeconds(24.0),
2482  this,
2484  // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2485  // should have succeeded.
2486  Simulator::Schedule(Seconds(8.0) + NanoSeconds(43999),
2488  this,
2490  Simulator::Schedule(Seconds(8.0) + NanoSeconds(44000),
2492  this,
2494  // STA PHY STATE should move back to CCA_BUSY once the duration estimated from L-SIG has
2495  // elapsed, i.e. at 152.8us.
2496  Simulator::Schedule(Seconds(8.0) + NanoSeconds(152799),
2498  this,
2500  Simulator::Schedule(Seconds(8.0) + NanoSeconds(152800),
2502  this,
2504 
2505  Simulator::Run();
2506  Simulator::Destroy();
2507 }
2508 
2516 {
2517  public:
2519  ~TestAmpduReception() override;
2520 
2521  protected:
2522  void DoSetup() override;
2523  void DoTeardown() override;
2524 
2525  private:
2526  void DoRun() override;
2527 
2535  void RxSuccess(Ptr<const WifiPsdu> psdu,
2536  RxSignalInfo rxSignalInfo,
2537  WifiTxVector txVector,
2538  std::vector<bool> statusPerMpdu);
2543  void RxFailure(Ptr<const WifiPsdu> psdu);
2554  void IncrementSuccessBitmap(uint32_t size);
2559  void IncrementFailureBitmap(uint32_t size);
2560 
2564  void ResetBitmaps();
2565 
2573  void SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize);
2574 
2579  void CheckRxSuccessBitmapAmpdu1(uint8_t expected);
2584  void CheckRxSuccessBitmapAmpdu2(uint8_t expected);
2589  void CheckRxFailureBitmapAmpdu1(uint8_t expected);
2594  void CheckRxFailureBitmapAmpdu2(uint8_t expected);
2599  void CheckRxDroppedBitmapAmpdu1(uint8_t expected);
2604  void CheckRxDroppedBitmapAmpdu2(uint8_t expected);
2605 
2610  void CheckPhyState(WifiPhyState expectedState);
2611 
2613 
2616 
2619 
2622 
2623  uint64_t m_uid;
2624 };
2625 
2627  : TestCase("A-MPDU reception test"),
2628  m_rxSuccessBitmapAmpdu1(0),
2629  m_rxSuccessBitmapAmpdu2(0),
2630  m_rxFailureBitmapAmpdu1(0),
2631  m_rxFailureBitmapAmpdu2(0),
2632  m_rxDroppedBitmapAmpdu1(0),
2633  m_rxDroppedBitmapAmpdu2(0),
2634  m_uid(0)
2635 {
2636 }
2637 
2639 {
2640  m_phy = nullptr;
2641 }
2642 
2643 void
2645 {
2652 }
2653 
2654 void
2656  RxSignalInfo rxSignalInfo,
2657  WifiTxVector txVector,
2658  std::vector<bool> statusPerMpdu)
2659 {
2660  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
2661  if (statusPerMpdu.empty()) // wait for the whole A-MPDU
2662  {
2663  return;
2664  }
2665  NS_ABORT_MSG_IF(psdu->GetNMpdus() != statusPerMpdu.size(),
2666  "Should have one receive status per MPDU");
2667  auto rxOkForMpdu = statusPerMpdu.begin();
2668  for (auto mpdu = psdu->begin(); mpdu != psdu->end(); ++mpdu)
2669  {
2670  if (*rxOkForMpdu)
2671  {
2672  IncrementSuccessBitmap((*mpdu)->GetSize());
2673  }
2674  else
2675  {
2676  IncrementFailureBitmap((*mpdu)->GetSize());
2677  }
2678  ++rxOkForMpdu;
2679  }
2680 }
2681 
2682 void
2684 {
2685  if (size == 1030) // A-MPDU 1 - MPDU #1
2686  {
2688  }
2689  else if (size == 1130) // A-MPDU 1 - MPDU #2
2690  {
2691  m_rxSuccessBitmapAmpdu1 |= (1 << 1);
2692  }
2693  else if (size == 1230) // A-MPDU 1 - MPDU #3
2694  {
2695  m_rxSuccessBitmapAmpdu1 |= (1 << 2);
2696  }
2697  else if (size == 1330) // A-MPDU 2 - MPDU #1
2698  {
2700  }
2701  else if (size == 1430) // A-MPDU 2 - MPDU #2
2702  {
2703  m_rxSuccessBitmapAmpdu2 |= (1 << 1);
2704  }
2705  else if (size == 1530) // A-MPDU 2 - MPDU #3
2706  {
2707  m_rxSuccessBitmapAmpdu2 |= (1 << 2);
2708  }
2709 }
2710 
2711 void
2713 {
2714  NS_LOG_FUNCTION(this << *psdu);
2715  for (auto mpdu = psdu->begin(); mpdu != psdu->end(); ++mpdu)
2716  {
2717  IncrementFailureBitmap((*mpdu)->GetSize());
2718  }
2719 }
2720 
2721 void
2723 {
2724  if (size == 1030) // A-MPDU 1 - MPDU #1
2725  {
2727  }
2728  else if (size == 1130) // A-MPDU 1 - MPDU #2
2729  {
2730  m_rxFailureBitmapAmpdu1 |= (1 << 1);
2731  }
2732  else if (size == 1230) // A-MPDU 1 - MPDU #3
2733  {
2734  m_rxFailureBitmapAmpdu1 |= (1 << 2);
2735  }
2736  else if (size == 1330) // A-MPDU 2 - MPDU #1
2737  {
2739  }
2740  else if (size == 1430) // A-MPDU 2 - MPDU #2
2741  {
2742  m_rxFailureBitmapAmpdu2 |= (1 << 1);
2743  }
2744  else if (size == 1530) // A-MPDU 2 - MPDU #3
2745  {
2746  m_rxFailureBitmapAmpdu2 |= (1 << 2);
2747  }
2748 }
2749 
2750 void
2752 {
2753  NS_LOG_FUNCTION(this << p << reason);
2754  if (p->GetSize() == 1030) // A-MPDU 1 - MPDU #1
2755  {
2757  }
2758  else if (p->GetSize() == 1130) // A-MPDU 1 - MPDU #2
2759  {
2760  m_rxDroppedBitmapAmpdu1 |= (1 << 1);
2761  }
2762  else if (p->GetSize() == 1230) // A-MPDU 1 - MPDU #3
2763  {
2764  m_rxDroppedBitmapAmpdu1 |= (1 << 2);
2765  }
2766  else if (p->GetSize() == 1330) // A-MPDU 2 - MPDU #1
2767  {
2769  }
2770  else if (p->GetSize() == 1430) // A-MPDU 2 - MPDU #2
2771  {
2772  m_rxDroppedBitmapAmpdu2 |= (1 << 1);
2773  }
2774  else if (p->GetSize() == 1530) // A-MPDU 2 - MPDU #3
2775  {
2776  m_rxDroppedBitmapAmpdu2 |= (1 << 2);
2777  }
2778 }
2779 
2780 void
2782 {
2784  expected,
2785  "RX success bitmap for A-MPDU 1 is not as expected");
2786 }
2787 
2788 void
2790 {
2792  expected,
2793  "RX success bitmap for A-MPDU 2 is not as expected");
2794 }
2795 
2796 void
2798 {
2800  expected,
2801  "RX failure bitmap for A-MPDU 1 is not as expected");
2802 }
2803 
2804 void
2806 {
2808  expected,
2809  "RX failure bitmap for A-MPDU 2 is not as expected");
2810 }
2811 
2812 void
2814 {
2816  expected,
2817  "RX dropped bitmap for A-MPDU 1 is not as expected");
2818 }
2819 
2820 void
2822 {
2824  expected,
2825  "RX dropped bitmap for A-MPDU 2 is not as expected");
2826 }
2827 
2828 void
2830 {
2831  WifiPhyState currentState;
2832  PointerValue ptr;
2833  m_phy->GetAttribute("State", ptr);
2834  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
2835  currentState = state->GetState();
2836  NS_TEST_ASSERT_MSG_EQ(currentState,
2837  expectedState,
2838  "PHY State " << currentState << " does not match expected state "
2839  << expectedState << " at " << Simulator::Now());
2840 }
2841 
2842 void
2843 TestAmpduReception::SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize)
2844 {
2845  WifiTxVector txVector =
2846  WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, true);
2847 
2848  WifiMacHeader hdr;
2850  hdr.SetQosTid(0);
2851 
2852  std::vector<Ptr<WifiMpdu>> mpduList;
2853  for (size_t i = 0; i < 3; ++i)
2854  {
2855  Ptr<Packet> p = Create<Packet>(referencePacketSize + i * 100);
2856  mpduList.push_back(Create<WifiMpdu>(p, hdr));
2857  }
2858  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(mpduList);
2859 
2860  Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
2861 
2862  Ptr<WifiPpdu> ppdu =
2863  Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
2864 
2865  Ptr<SpectrumValue> txPowerSpectrum =
2866  WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
2867  CHANNEL_WIDTH,
2868  DbmToW(rxPowerDbm),
2869  GUARD_WIDTH);
2870 
2871  Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
2872  txParams->psd = txPowerSpectrum;
2873  txParams->txPhy = nullptr;
2874  txParams->duration = txDuration;
2875  txParams->ppdu = ppdu;
2876  txParams->txWidth = CHANNEL_WIDTH;
2877 
2878  m_phy->StartRx(txParams);
2879 }
2880 
2881 void
2883 {
2884  m_phy = CreateObject<SpectrumWifiPhy>();
2886  Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2887  m_phy->SetInterferenceHelper(interferenceHelper);
2888  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2889  m_phy->SetErrorRateModel(error);
2891 
2894  m_phy->TraceConnectWithoutContext("PhyRxDrop",
2896 
2897  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2898  CreateObject<ThresholdPreambleDetectionModel>();
2899  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(2));
2900  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2901 
2902  Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
2903  frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
2904  frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
2905  m_phy->SetFrameCaptureModel(frameCaptureModel);
2906 }
2907 
2908 void
2910 {
2911  m_phy->Dispose();
2912  m_phy = nullptr;
2913 }
2914 
2915 void
2917 {
2918  RngSeedManager::SetSeed(1);
2919  RngSeedManager::SetRun(2);
2920  int64_t streamNumber = 1;
2921  double rxPowerDbm = -30;
2922  m_phy->AssignStreams(streamNumber);
2923 
2925  // CASE 1: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
2926  // power under RX sensitivity. The second A-MPDU is received 2 microseconds after the first
2927  // A-MPDU (i.e. during preamble detection).
2929 
2930  // A-MPDU 1
2931  Simulator::Schedule(Seconds(1.0),
2933  this,
2934  rxPowerDbm - 100,
2935  1000);
2936 
2937  // A-MPDU 2
2938  Simulator::Schedule(Seconds(1.0) + MicroSeconds(2),
2940  this,
2941  rxPowerDbm,
2942  1300);
2943 
2944  // All MPDUs of A-MPDU 1 should have been ignored.
2945  Simulator::Schedule(Seconds(1.1),
2947  this,
2948  0b00000000);
2949  Simulator::Schedule(Seconds(1.1),
2951  this,
2952  0b00000000);
2953  Simulator::Schedule(Seconds(1.1),
2955  this,
2956  0b00000000);
2957 
2958  // All MPDUs of A-MPDU 2 should have been successfully received.
2959  Simulator::Schedule(Seconds(1.1),
2961  this,
2962  0b00000111);
2963  Simulator::Schedule(Seconds(1.1),
2965  this,
2966  0b00000000);
2967  Simulator::Schedule(Seconds(1.1),
2969  this,
2970  0b00000000);
2971 
2972  Simulator::Schedule(Seconds(1.2), &TestAmpduReception::ResetBitmaps, this);
2973 
2975  // CASE 2: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
2976  // with power under RX sensitivity. The second A-MPDU is received 2 microseconds after the first
2977  // A-MPDU (i.e. during preamble detection).
2979 
2980  // A-MPDU 1
2981  Simulator::Schedule(Seconds(2.0),
2983  this,
2984  rxPowerDbm,
2985  1000);
2986 
2987  // A-MPDU 2
2988  Simulator::Schedule(Seconds(2.0) + MicroSeconds(2),
2990  this,
2991  rxPowerDbm - 100,
2992  1300);
2993 
2994  // All MPDUs of A-MPDU 1 should have been received.
2995  Simulator::Schedule(Seconds(2.1),
2997  this,
2998  0b00000111);
2999  Simulator::Schedule(Seconds(2.1),
3001  this,
3002  0b00000000);
3003  Simulator::Schedule(Seconds(2.1),
3005  this,
3006  0b00000000);
3007 
3008  // All MPDUs of A-MPDU 2 should have been ignored.
3009  Simulator::Schedule(Seconds(2.1),
3011  this,
3012  0b00000000);
3013  Simulator::Schedule(Seconds(2.1),
3015  this,
3016  0b00000000);
3017  Simulator::Schedule(Seconds(2.1),
3019  this,
3020  0b00000000);
3021 
3022  Simulator::Schedule(Seconds(2.2), &TestAmpduReception::ResetBitmaps, this);
3023 
3025  // CASE 3: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3026  // power under RX sensitivity. The second A-MPDU is received 10 microseconds after the first
3027  // A-MPDU (i.e. during the frame capture window).
3029 
3030  // A-MPDU 1
3031  Simulator::Schedule(Seconds(3.0),
3033  this,
3034  rxPowerDbm - 100,
3035  1000);
3036 
3037  // A-MPDU 2
3038  Simulator::Schedule(Seconds(3.0) + MicroSeconds(10),
3040  this,
3041  rxPowerDbm,
3042  1300);
3043 
3044  // All MPDUs of A-MPDU 1 should have been ignored.
3045  Simulator::Schedule(Seconds(3.1),
3047  this,
3048  0b00000000);
3049  Simulator::Schedule(Seconds(3.1),
3051  this,
3052  0b00000000);
3053  Simulator::Schedule(Seconds(3.1),
3055  this,
3056  0b00000000);
3057 
3058  // All MPDUs of A-MPDU 2 should have been successfully received.
3059  Simulator::Schedule(Seconds(3.1),
3061  this,
3062  0b00000111);
3063  Simulator::Schedule(Seconds(3.1),
3065  this,
3066  0b00000000);
3067  Simulator::Schedule(Seconds(3.1),
3069  this,
3070  0b00000000);
3071 
3072  Simulator::Schedule(Seconds(3.2), &TestAmpduReception::ResetBitmaps, this);
3073 
3075  // CASE 4: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3076  // with power under RX sensitivity. The second A-MPDU is received 10 microseconds after the
3077  // first A-MPDU (i.e. during the frame capture window).
3079 
3080  // A-MPDU 1
3081  Simulator::Schedule(Seconds(4.0),
3083  this,
3084  rxPowerDbm,
3085  1000);
3086 
3087  // A-MPDU 2
3088  Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
3090  this,
3091  rxPowerDbm - 100,
3092  1300);
3093 
3094  // All MPDUs of A-MPDU 1 should have been received.
3095  Simulator::Schedule(Seconds(4.1),
3097  this,
3098  0b00000111);
3099  Simulator::Schedule(Seconds(4.1),
3101  this,
3102  0b00000000);
3103  Simulator::Schedule(Seconds(4.1),
3105  this,
3106  0b00000000);
3107 
3108  // All MPDUs of A-MPDU 2 should have been ignored.
3109  Simulator::Schedule(Seconds(4.1),
3111  this,
3112  0b00000000);
3113  Simulator::Schedule(Seconds(4.1),
3115  this,
3116  0b00000000);
3117  Simulator::Schedule(Seconds(4.1),
3119  this,
3120  0b00000000);
3121 
3122  Simulator::Schedule(Seconds(4.2), &TestAmpduReception::ResetBitmaps, this);
3123 
3125  // CASE 5: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3126  // power under RX sensitivity. The second A-MPDU is received 100 microseconds after the first
3127  // A-MPDU (i.e. after the frame capture window, during the payload of MPDU #1).
3129 
3130  // A-MPDU 1
3131  Simulator::Schedule(Seconds(5.0),
3133  this,
3134  rxPowerDbm - 100,
3135  1000);
3136 
3137  // A-MPDU 2
3138  Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
3140  this,
3141  rxPowerDbm,
3142  1300);
3143 
3144  // All MPDUs of A-MPDU 1 should have been ignored.
3145  Simulator::Schedule(Seconds(5.1),
3147  this,
3148  0b00000000);
3149  Simulator::Schedule(Seconds(5.1),
3151  this,
3152  0b00000000);
3153  Simulator::Schedule(Seconds(5.1),
3155  this,
3156  0b00000000);
3157 
3158  // All MPDUs of A-MPDU 2 should have been successfully received.
3159  Simulator::Schedule(Seconds(5.1),
3161  this,
3162  0b00000111);
3163  Simulator::Schedule(Seconds(5.1),
3165  this,
3166  0b00000000);
3167  Simulator::Schedule(Seconds(5.1),
3169  this,
3170  0b00000000);
3171 
3172  Simulator::Schedule(Seconds(5.2), &TestAmpduReception::ResetBitmaps, this);
3173 
3175  // CASE 6: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3176  // with power under RX sensitivity. The second A-MPDU is received 100 microseconds after the
3177  // first A-MPDU (i.e. after the frame capture window, during the payload of MPDU #1).
3179 
3180  // A-MPDU 1
3181  Simulator::Schedule(Seconds(6.0),
3183  this,
3184  rxPowerDbm,
3185  1000);
3186 
3187  // A-MPDU 2
3188  Simulator::Schedule(Seconds(6.0) + MicroSeconds(100),
3190  this,
3191  rxPowerDbm - 100,
3192  1300);
3193 
3194  // All MPDUs of A-MPDU 1 should have been received.
3195  Simulator::Schedule(Seconds(6.1),
3197  this,
3198  0b00000111);
3199  Simulator::Schedule(Seconds(6.1),
3201  this,
3202  0b00000000);
3203  Simulator::Schedule(Seconds(6.1),
3205  this,
3206  0b00000000);
3207 
3208  // All MPDUs of A-MPDU 2 should have been ignored.
3209  Simulator::Schedule(Seconds(6.1),
3211  this,
3212  0b00000000);
3213  Simulator::Schedule(Seconds(6.1),
3215  this,
3216  0b00000000);
3217  Simulator::Schedule(Seconds(6.1),
3219  this,
3220  0b00000000);
3221 
3222  Simulator::Schedule(Seconds(6.2), &TestAmpduReception::ResetBitmaps, this);
3223 
3225  // CASE 7: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3226  // power under RX sensitivity. The second A-MPDU is received during the payload of MPDU #2.
3228 
3229  // A-MPDU 1
3230  Simulator::Schedule(Seconds(7.0),
3232  this,
3233  rxPowerDbm - 100,
3234  1000);
3235 
3236  // A-MPDU 2
3237  Simulator::Schedule(Seconds(7.0) + NanoSeconds(1100000),
3239  this,
3240  rxPowerDbm,
3241  1300);
3242 
3243  // All MPDUs of A-MPDU 1 should have been ignored.
3244  Simulator::Schedule(Seconds(7.1),
3246  this,
3247  0b00000000);
3248  Simulator::Schedule(Seconds(7.1),
3250  this,
3251  0b00000000);
3252  Simulator::Schedule(Seconds(7.1),
3254  this,
3255  0b00000000);
3256 
3257  // All MPDUs of A-MPDU 2 should have been successfully received.
3258  Simulator::Schedule(Seconds(7.1),
3260  this,
3261  0b00000111);
3262  Simulator::Schedule(Seconds(7.1),
3264  this,
3265  0b00000000);
3266  Simulator::Schedule(Seconds(7.1),
3268  this,
3269  0b00000000);
3270 
3271  Simulator::Schedule(Seconds(7.2), &TestAmpduReception::ResetBitmaps, this);
3272 
3274  // CASE 8: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3275  // with power under RX sensitivity. The second A-MPDU is received during the payload of MPDU #2.
3277 
3278  // A-MPDU 1
3279  Simulator::Schedule(Seconds(8.0),
3281  this,
3282  rxPowerDbm,
3283  1000);
3284 
3285  // A-MPDU 2
3286  Simulator::Schedule(Seconds(8.0) + NanoSeconds(1100000),
3288  this,
3289  rxPowerDbm - 100,
3290  1300);
3291 
3292  // All MPDUs of A-MPDU 1 should have been received.
3293  Simulator::Schedule(Seconds(8.1),
3295  this,
3296  0b00000111);
3297  Simulator::Schedule(Seconds(8.1),
3299  this,
3300  0b00000000);
3301  Simulator::Schedule(Seconds(8.1),
3303  this,
3304  0b00000000);
3305 
3306  // All MPDUs of A-MPDU 2 should have been ignored.
3307  Simulator::Schedule(Seconds(8.1),
3309  this,
3310  0b00000000);
3311  Simulator::Schedule(Seconds(8.1),
3313  this,
3314  0b00000000);
3315  Simulator::Schedule(Seconds(8.1),
3317  this,
3318  0b00000000);
3319 
3320  Simulator::Schedule(Seconds(8.2), &TestAmpduReception::ResetBitmaps, this);
3321 
3323  // CASE 9: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power 3
3324  // dB higher. The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during
3325  // preamble detection).
3327 
3328  // A-MPDU 1
3329  Simulator::Schedule(Seconds(9.0),
3331  this,
3332  rxPowerDbm,
3333  1000);
3334 
3335  // A-MPDU 2
3336  Simulator::Schedule(Seconds(9.0) + MicroSeconds(2),
3338  this,
3339  rxPowerDbm + 3,
3340  1300);
3341 
3342  // All MPDUs of A-MPDU 1 should have been dropped.
3343  Simulator::Schedule(Seconds(9.1),
3345  this,
3346  0b00000000);
3347  Simulator::Schedule(Seconds(9.1),
3349  this,
3350  0b00000000);
3351  Simulator::Schedule(Seconds(9.1),
3353  this,
3354  0b00000111);
3355 
3356  // All MPDUs of A-MPDU 2 should have been received with errors.
3357  Simulator::Schedule(Seconds(9.1),
3359  this,
3360  0b00000000);
3361  Simulator::Schedule(Seconds(9.1),
3363  this,
3364  0b00000111);
3365  Simulator::Schedule(Seconds(9.1),
3367  this,
3368  0b00000000);
3369 
3370  Simulator::Schedule(Seconds(9.2), &TestAmpduReception::ResetBitmaps, this);
3371 
3373  // CASE 10: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3374  // The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during preamble
3375  // detection).
3377 
3378  // A-MPDU 1
3379  Simulator::Schedule(Seconds(10.0),
3381  this,
3382  rxPowerDbm,
3383  1000);
3384 
3385  // A-MPDU 2
3386  Simulator::Schedule(Seconds(10.0) + MicroSeconds(2),
3388  this,
3389  rxPowerDbm,
3390  1300);
3391 
3392  // All MPDUs of A-MPDU 1 should have been dropped (preamble detection failed).
3393  Simulator::Schedule(Seconds(10.1),
3395  this,
3396  0b00000000);
3397  Simulator::Schedule(Seconds(10.1),
3399  this,
3400  0b00000000);
3401  Simulator::Schedule(Seconds(10.1),
3403  this,
3404  0b00000111);
3405 
3406  // All MPDUs of A-MPDU 2 should have been dropped as well.
3407  Simulator::Schedule(Seconds(10.1),
3409  this,
3410  0b00000000);
3411  Simulator::Schedule(Seconds(10.1),
3413  this,
3414  0b00000000);
3415  Simulator::Schedule(Seconds(10.1),
3417  this,
3418  0b00000111);
3419 
3420  Simulator::Schedule(Seconds(10.2), &TestAmpduReception::ResetBitmaps, this);
3421 
3423  // CASE 11: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 3
3424  // dB higher. The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during
3425  // preamble detection).
3427 
3428  // A-MPDU 1
3429  Simulator::Schedule(Seconds(11.0),
3431  this,
3432  rxPowerDbm + 3,
3433  1000);
3434 
3435  // A-MPDU 2
3436  Simulator::Schedule(Seconds(11.0) + MicroSeconds(2),
3438  this,
3439  rxPowerDbm,
3440  1300);
3441 
3442  // All MPDUs of A-MPDU 1 should have been received with errors.
3443  Simulator::Schedule(Seconds(11.1),
3445  this,
3446  0b00000000);
3447  Simulator::Schedule(Seconds(11.1),
3449  this,
3450  0b00000111);
3451  Simulator::Schedule(Seconds(11.1),
3453  this,
3454  0b00000000);
3455 
3456  // All MPDUs of A-MPDU 2 should have been dropped.
3457  Simulator::Schedule(Seconds(11.1),
3459  this,
3460  0b00000000);
3461  Simulator::Schedule(Seconds(11.1),
3463  this,
3464  0b00000000);
3465  Simulator::Schedule(Seconds(11.1),
3467  this,
3468  0b00000111);
3469 
3470  Simulator::Schedule(Seconds(11.2), &TestAmpduReception::ResetBitmaps, this);
3471 
3473  // CASE 12: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3474  // 3 dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e.
3475  // during the frame capture window).
3477 
3478  // A-MPDU 1
3479  Simulator::Schedule(Seconds(12.0),
3481  this,
3482  rxPowerDbm,
3483  1000);
3484 
3485  // A-MPDU 2
3486  Simulator::Schedule(Seconds(12.0) + MicroSeconds(10),
3488  this,
3489  rxPowerDbm + 3,
3490  1300);
3491 
3492  // All MPDUs of A-MPDU 1 should have been received with errors (PHY header reception failed and
3493  // thus incorrect decoding of payload).
3494  Simulator::Schedule(Seconds(12.1),
3496  this,
3497  0b00000000);
3498  Simulator::Schedule(Seconds(12.1),
3500  this,
3501  0b00000000);
3502  Simulator::Schedule(Seconds(12.1),
3504  this,
3505  0b00000111);
3506 
3507  // All MPDUs of A-MPDU 2 should have been dropped (even though TX power is higher, it is not
3508  // high enough to get the PHY reception switched)
3509  Simulator::Schedule(Seconds(12.1),
3511  this,
3512  0b00000000);
3513  Simulator::Schedule(Seconds(12.1),
3515  this,
3516  0b00000000);
3517  Simulator::Schedule(Seconds(12.1),
3519  this,
3520  0b00000111);
3521 
3522  Simulator::Schedule(Seconds(12.2), &TestAmpduReception::ResetBitmaps, this);
3523 
3525  // CASE 13: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3526  // The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during the frame
3527  // capture window).
3529 
3530  // A-MPDU 1
3531  Simulator::Schedule(Seconds(13.0),
3533  this,
3534  rxPowerDbm,
3535  1000);
3536 
3537  // A-MPDU 2
3538  Simulator::Schedule(Seconds(13.0) + MicroSeconds(10),
3540  this,
3541  rxPowerDbm,
3542  1300);
3543 
3544  // All MPDUs of A-MPDU 1 should have been received with errors (PHY header reception failed and
3545  // thus incorrect decoding of payload).
3546  Simulator::Schedule(Seconds(13.1),
3548  this,
3549  0b00000000);
3550  Simulator::Schedule(Seconds(13.1),
3552  this,
3553  0b00000000);
3554  Simulator::Schedule(Seconds(13.1),
3556  this,
3557  0b00000111);
3558 
3559  // All MPDUs of A-MPDU 2 should have been dropped as well.
3560  Simulator::Schedule(Seconds(13.1),
3562  this,
3563  0b00000000);
3564  Simulator::Schedule(Seconds(13.1),
3566  this,
3567  0b00000000);
3568  Simulator::Schedule(Seconds(13.1),
3570  this,
3571  0b00000111);
3572 
3573  Simulator::Schedule(Seconds(13.2), &TestAmpduReception::ResetBitmaps, this);
3574 
3576  // CASE 14: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 3
3577  // dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during
3578  // the frame capture window).
3580 
3581  // A-MPDU 1
3582  Simulator::Schedule(Seconds(14.0),
3584  this,
3585  rxPowerDbm + 3,
3586  1000);
3587 
3588  // A-MPDU 2
3589  Simulator::Schedule(Seconds(14.0) + MicroSeconds(10),
3591  this,
3592  rxPowerDbm,
3593  1300);
3594 
3595  // All MPDUs of A-MPDU 1 should have been received with errors.
3596  Simulator::Schedule(Seconds(14.1),
3598  this,
3599  0b00000000);
3600  Simulator::Schedule(Seconds(14.1),
3602  this,
3603  0b00000111);
3604  Simulator::Schedule(Seconds(14.1),
3606  this,
3607  0b00000000);
3608 
3609  // All MPDUs of A-MPDU 2 should have been dropped.
3610  Simulator::Schedule(Seconds(14.1),
3612  this,
3613  0b00000000);
3614  Simulator::Schedule(Seconds(14.1),
3616  this,
3617  0b00000000);
3618  Simulator::Schedule(Seconds(14.1),
3620  this,
3621  0b00000111);
3622 
3623  Simulator::Schedule(Seconds(14.2), &TestAmpduReception::ResetBitmaps, this);
3624 
3626  // CASE 15: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3627  // 6 dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e.
3628  // during the frame capture window).
3630 
3631  // A-MPDU 1
3632  Simulator::Schedule(Seconds(15.0),
3634  this,
3635  rxPowerDbm,
3636  1000);
3637 
3638  // A-MPDU 2
3639  Simulator::Schedule(Seconds(15.0) + MicroSeconds(10),
3641  this,
3642  rxPowerDbm + 6,
3643  1300);
3644 
3645  // All MPDUs of A-MPDU 1 should have been dropped because PHY reception switched to A-MPDU 2.
3646  Simulator::Schedule(Seconds(15.1),
3648  this,
3649  0b00000000);
3650  Simulator::Schedule(Seconds(15.1),
3652  this,
3653  0b00000000);
3654  Simulator::Schedule(Seconds(15.1),
3656  this,
3657  0b00000111);
3658 
3659  // All MPDUs of A-MPDU 2 should have been successfully received
3660  Simulator::Schedule(Seconds(15.1),
3662  this,
3663  0b00000111);
3664  Simulator::Schedule(Seconds(15.1),
3666  this,
3667  0b00000000);
3668  Simulator::Schedule(Seconds(15.1),
3670  this,
3671  0b00000000);
3672 
3673  Simulator::Schedule(Seconds(15.2), &TestAmpduReception::ResetBitmaps, this);
3674 
3676  // CASE 16: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3677  // dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during
3678  // the frame capture window).
3680 
3681  // A-MPDU 1
3682  Simulator::Schedule(Seconds(16.0),
3684  this,
3685  rxPowerDbm + 6,
3686  1000);
3687 
3688  // A-MPDU 2
3689  Simulator::Schedule(Seconds(16.0) + MicroSeconds(10),
3691  this,
3692  rxPowerDbm,
3693  1300);
3694 
3695  // All MPDUs of A-MPDU 1 should have been successfully received.
3696  Simulator::Schedule(Seconds(16.1),
3698  this,
3699  0b00000111);
3700  Simulator::Schedule(Seconds(16.1),
3702  this,
3703  0b00000000);
3704  Simulator::Schedule(Seconds(16.1),
3706  this,
3707  0b00000000);
3708 
3709  // All MPDUs of A-MPDU 2 should have been dropped.
3710  Simulator::Schedule(Seconds(16.1),
3712  this,
3713  0b00000000);
3714  Simulator::Schedule(Seconds(16.1),
3716  this,
3717  0b00000000);
3718  Simulator::Schedule(Seconds(16.1),
3720  this,
3721  0b00000111);
3722 
3723  Simulator::Schedule(Seconds(16.2), &TestAmpduReception::ResetBitmaps, this);
3724 
3726  // CASE 17: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3727  // 6 dB higher. The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after
3728  // the frame capture window, but still during PHY header).
3730 
3731  // A-MPDU 1
3732  Simulator::Schedule(Seconds(17.0),
3734  this,
3735  rxPowerDbm,
3736  1000);
3737 
3738  // A-MPDU 2
3739  Simulator::Schedule(Seconds(17.0) + MicroSeconds(25),
3741  this,
3742  rxPowerDbm + 6,
3743  1300);
3744 
3745  // All MPDUs of A-MPDU 1 should have been received with errors.
3746  Simulator::Schedule(Seconds(17.1),
3748  this,
3749  0b00000000);
3750  Simulator::Schedule(Seconds(17.1),
3752  this,
3753  0b00000000);
3754  Simulator::Schedule(Seconds(17.1),
3756  this,
3757  0b00000111);
3758 
3759  // All MPDUs of A-MPDU 2 should have been dropped (no reception switch, MPDUs dropped because
3760  // PHY is already in RX state).
3761  Simulator::Schedule(Seconds(17.1),
3763  this,
3764  0b00000000);
3765  Simulator::Schedule(Seconds(17.1),
3767  this,
3768  0b00000000);
3769  Simulator::Schedule(Seconds(17.1),
3771  this,
3772  0b00000111);
3773 
3774  Simulator::Schedule(Seconds(17.2), &TestAmpduReception::ResetBitmaps, this);
3775 
3777  // CASE 18: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3778  // dB higher. The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after
3779  // the frame capture window, but still during PHY header).
3781 
3782  // A-MPDU 1
3783  Simulator::Schedule(Seconds(18.0),
3785  this,
3786  rxPowerDbm + 6,
3787  1000);
3788 
3789  // A-MPDU 2
3790  Simulator::Schedule(Seconds(18.0) + MicroSeconds(25),
3792  this,
3793  rxPowerDbm,
3794  1300);
3795 
3796  // All MPDUs of A-MPDU 1 should have been successfully received.
3797  Simulator::Schedule(Seconds(18.1),
3799  this,
3800  0b00000111);
3801  Simulator::Schedule(Seconds(18.1),
3803  this,
3804  0b00000000);
3805  Simulator::Schedule(Seconds(18.1),
3807  this,
3808  0b00000000);
3809 
3810  // All MPDUs of A-MPDU 2 should have been dropped.
3811  Simulator::Schedule(Seconds(18.1),
3813  this,
3814  0b00000000);
3815  Simulator::Schedule(Seconds(18.1),
3817  this,
3818  0b00000000);
3819  Simulator::Schedule(Seconds(18.1),
3821  this,
3822  0b00000111);
3823 
3824  Simulator::Schedule(Seconds(18.2), &TestAmpduReception::ResetBitmaps, this);
3825 
3827  // CASE 19: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3828  // The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after the frame
3829  // capture window, but still during PHY header).
3831 
3832  // A-MPDU 1
3833  Simulator::Schedule(Seconds(19.0),
3835  this,
3836  rxPowerDbm,
3837  1000);
3838 
3839  // A-MPDU 2
3840  Simulator::Schedule(Seconds(19.0) + MicroSeconds(25),
3842  this,
3843  rxPowerDbm,
3844  1300);
3845 
3846  // All MPDUs of A-MPDU 1 should have been received with errors.
3847  Simulator::Schedule(Seconds(19.1),
3849  this,
3850  0b00000000);
3851  Simulator::Schedule(Seconds(19.1),
3853  this,
3854  0b00000000);
3855  Simulator::Schedule(Seconds(19.1),
3857  this,
3858  0b00000111);
3859 
3860  // All MPDUs of A-MPDU 2 should have been dropped.
3861  Simulator::Schedule(Seconds(19.1),
3863  this,
3864  0b00000000);
3865  Simulator::Schedule(Seconds(19.1),
3867  this,
3868  0b00000000);
3869  Simulator::Schedule(Seconds(19.1),
3871  this,
3872  0b00000111);
3873 
3874  Simulator::Schedule(Seconds(19.2), &TestAmpduReception::ResetBitmaps, this);
3875 
3877  // CASE 20: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3878  // 6 dB higher. The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e.
3879  // during the payload of MPDU #1).
3881 
3882  // A-MPDU 1
3883  Simulator::Schedule(Seconds(20.0),
3885  this,
3886  rxPowerDbm,
3887  1000);
3888 
3889  // A-MPDU 2
3890  Simulator::Schedule(Seconds(20.0) + MicroSeconds(100),
3892  this,
3893  rxPowerDbm + 6,
3894  1300);
3895 
3896  // All MPDUs of A-MPDU 1 should have been received with errors.
3897  Simulator::Schedule(Seconds(20.1),
3899  this,
3900  0b00000000);
3901  Simulator::Schedule(Seconds(20.1),
3903  this,
3904  0b00000111);
3905  Simulator::Schedule(Seconds(20.1),
3907  this,
3908  0b00000000);
3909 
3910  // All MPDUs of A-MPDU 2 should have been dropped (no reception switch, MPDUs dropped because
3911  // PHY is already in RX state).
3912  Simulator::Schedule(Seconds(20.1),
3914  this,
3915  0b00000000);
3916  Simulator::Schedule(Seconds(20.1),
3918  this,
3919  0b00000000);
3920  Simulator::Schedule(Seconds(20.1),
3922  this,
3923  0b00000111);
3924 
3925  Simulator::Schedule(Seconds(20.2), &TestAmpduReception::ResetBitmaps, this);
3926 
3928  // CASE 21: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3929  // dB higher. The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e. during
3930  // the payload of MPDU #1).
3932 
3933  // A-MPDU 1
3934  Simulator::Schedule(Seconds(21.0),
3936  this,
3937  rxPowerDbm + 6,
3938  1000);
3939 
3940  // A-MPDU 2
3941  Simulator::Schedule(Seconds(21.0) + MicroSeconds(100),
3943  this,
3944  rxPowerDbm,
3945  1300);
3946 
3947  // All MPDUs of A-MPDU 1 should have been successfully received.
3948  Simulator::Schedule(Seconds(21.1),
3950  this,
3951  0b00000111);
3952  Simulator::Schedule(Seconds(21.1),
3954  this,
3955  0b00000000);
3956  Simulator::Schedule(Seconds(21.1),
3958  this,
3959  0b00000000);
3960 
3961  // All MPDUs of A-MPDU 2 should have been dropped.
3962  Simulator::Schedule(Seconds(21.1),
3964  this,
3965  0b00000000);
3966  Simulator::Schedule(Seconds(21.1),
3968  this,
3969  0b00000000);
3970  Simulator::Schedule(Seconds(21.1),
3972  this,
3973  0b00000111);
3974 
3975  Simulator::Schedule(Seconds(21.2), &TestAmpduReception::ResetBitmaps, this);
3976 
3978  // CASE 22: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3979  // The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e. during the
3980  // payload of MPDU #1).
3982 
3983  // A-MPDU 1
3984  Simulator::Schedule(Seconds(22.0),
3986  this,
3987  rxPowerDbm,
3988  1000);
3989 
3990  // A-MPDU 2
3991  Simulator::Schedule(Seconds(22.0) + MicroSeconds(100),
3993  this,
3994  rxPowerDbm,
3995  1300);
3996 
3997  // All MPDUs of A-MPDU 1 should have been received with errors.
3998  Simulator::Schedule(Seconds(22.1),
4000  this,
4001  0b00000000);
4002  Simulator::Schedule(Seconds(22.1),
4004  this,
4005  0b00000111);
4006  Simulator::Schedule(Seconds(22.1),
4008  this,
4009  0b00000000);
4010 
4011  // All MPDUs of A-MPDU 2 should have been dropped.
4012  Simulator::Schedule(Seconds(22.1),
4014  this,
4015  0b00000000);
4016  Simulator::Schedule(Seconds(22.1),
4018  this,
4019  0b00000000);
4020  Simulator::Schedule(Seconds(22.1),
4022  this,
4023  0b00000111);
4024 
4025  Simulator::Schedule(Seconds(22.2), &TestAmpduReception::ResetBitmaps, this);
4026 
4028  // CASE 23: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
4029  // The second A-MPDU is received during the payload of MPDU #2.
4031 
4032  // A-MPDU 1
4033  Simulator::Schedule(Seconds(23.0),
4035  this,
4036  rxPowerDbm,
4037  1000);
4038 
4039  // A-MPDU 2
4040  Simulator::Schedule(Seconds(23.0) + NanoSeconds(1100000),
4042  this,
4043  rxPowerDbm,
4044  1300);
4045 
4046  // The first MPDU of A-MPDU 1 should have been successfully received (no interference).
4047  // The two other MPDUs failed due to interference and are marked as failure (and dropped).
4048  Simulator::Schedule(Seconds(23.1),
4050  this,
4051  0b00000001);
4052  Simulator::Schedule(Seconds(23.1),
4054  this,
4055  0b00000110);
4056  Simulator::Schedule(Seconds(23.1),
4058  this,
4059  0b00000000);
4060 
4061  // The two first MPDUs of A-MPDU 2 are dropped because PHY is already in RX state (receiving
4062  // A-MPDU 1). The last MPDU of A-MPDU 2 is interference free (A-MPDU 1 transmission is finished)
4063  // but is dropped because its PHY preamble and header were not received.
4064  Simulator::Schedule(Seconds(23.1),
4066  this,
4067  0b00000000);
4068  Simulator::Schedule(Seconds(23.1),
4070  this,
4071  0b00000000);
4072  Simulator::Schedule(Seconds(23.1),
4074  this,
4075  0b00000111);
4076 
4077  Simulator::Schedule(Seconds(23.2), &TestAmpduReception::ResetBitmaps, this);
4078 
4079  Simulator::Run();
4080  Simulator::Destroy();
4081 }
4082 
4104 {
4105  public:
4111 
4118  void Dropped(std::string context, Ptr<const Packet> packet, WifiPhyRxfailureReason reason);
4122  void CheckResults();
4123 
4124  private:
4125  void DoRun() override;
4126  uint16_t m_dropped;
4127 };
4128 
4130  : TestCase("Check correct behavior when a STA is receiving a transmission using an unsupported "
4131  "modulation"),
4132  m_dropped(0)
4133 {
4134 }
4135 
4137 {
4138 }
4139 
4140 void
4142  Ptr<const Packet> packet,
4143  WifiPhyRxfailureReason reason)
4144 {
4145  // Print if the test is executed through test-runner
4146  if (reason == RXING)
4147  {
4148  std::cout << "Dropped a packet because already receiving" << std::endl;
4149  m_dropped++;
4150  }
4151 }
4152 
4153 void
4155 {
4156  uint16_t m_nStations = 2;
4157  NetDeviceContainer m_staDevices;
4158  NetDeviceContainer m_apDevices;
4159 
4160  // RngSeedManager::SetSeed (1);
4161  // RngSeedManager::SetRun (40);
4162  int64_t streamNumber = 100;
4163 
4165  wifiApNode.Create(1);
4166 
4168  wifiStaNodes.Create(m_nStations);
4169 
4170  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
4171  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
4172  spectrumChannel->AddPropagationLossModel(lossModel);
4174  CreateObject<ConstantSpeedPropagationDelayModel>();
4175  spectrumChannel->SetPropagationDelayModel(delayModel);
4176 
4178  phy.SetChannel(spectrumChannel);
4179 
4180  Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue(65535));
4181 
4182  WifiHelper wifi;
4183  wifi.SetRemoteStationManager("ns3::IdealWifiManager");
4184 
4186  mac.SetType("ns3::StaWifiMac",
4187  "QosSupported",
4188  BooleanValue(true),
4189  "Ssid",
4190  SsidValue(Ssid("non-existent-ssid")));
4191 
4192  wifi.SetStandard(WIFI_STANDARD_80211ax);
4193  m_staDevices.Add(wifi.Install(phy, mac, wifiStaNodes.Get(0)));
4194  wifi.SetStandard(WIFI_STANDARD_80211ac);
4195  m_staDevices.Add(wifi.Install(phy, mac, wifiStaNodes.Get(1)));
4196 
4197  wifi.SetStandard(WIFI_STANDARD_80211ax);
4198  mac.SetType("ns3::ApWifiMac",
4199  "QosSupported",
4200  BooleanValue(true),
4201  "Ssid",
4202  SsidValue(Ssid("wifi-backoff-ssid")),
4203  "BeaconInterval",
4204  TimeValue(MicroSeconds(102400)),
4205  "EnableBeaconJitter",
4206  BooleanValue(false));
4207 
4208  m_apDevices = wifi.Install(phy, mac, wifiApNode);
4209 
4210  // schedule association requests at different times
4211  Time init = MilliSeconds(100);
4212  Ptr<WifiNetDevice> dev;
4213 
4214  for (uint16_t i = 0; i < m_nStations; i++)
4215  {
4216  dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
4217  Simulator::Schedule(init + i * MicroSeconds(102400),
4218  &WifiMac::SetSsid,
4219  dev->GetMac(),
4220  Ssid("wifi-backoff-ssid"));
4221  }
4222 
4223  // Assign fixed streams to random variables in use
4224  wifi.AssignStreams(m_apDevices, streamNumber);
4225 
4227  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
4228 
4229  positionAlloc->Add(Vector(0.0, 0.0, 0.0));
4230  positionAlloc->Add(Vector(1.0, 0.0, 0.0));
4231  positionAlloc->Add(Vector(0.0, 1.0, 0.0));
4232  positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
4233  mobility.SetPositionAllocator(positionAlloc);
4234 
4235  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
4236  mobility.Install(wifiApNode);
4237  mobility.Install(wifiStaNodes);
4238 
4239  // set the TXOP limit on BE AC
4240  dev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
4241  PointerValue ptr;
4242  dev->GetMac()->GetAttribute("BE_Txop", ptr);
4243 
4244  PacketSocketHelper packetSocket;
4245  packetSocket.Install(wifiApNode);
4246  packetSocket.Install(wifiStaNodes);
4247 
4248  // UL Traffic
4249  for (uint16_t i = 0; i < m_nStations; i++)
4250  {
4251  PacketSocketAddress socket;
4252  socket.SetSingleDevice(m_staDevices.Get(0)->GetIfIndex());
4253  socket.SetPhysicalAddress(m_apDevices.Get(0)->GetAddress());
4254  socket.SetProtocol(1);
4255  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
4256  client->SetAttribute("PacketSize", UintegerValue(1500));
4257  client->SetAttribute("MaxPackets", UintegerValue(200));
4258  client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
4259  client->SetRemote(socket);
4260  wifiStaNodes.Get(i)->AddApplication(client);
4261  client->SetStartTime(MicroSeconds(400000));
4262  client->SetStopTime(Seconds(1.0));
4263  Ptr<PacketSocketClient> legacyStaClient = CreateObject<PacketSocketClient>();
4264  legacyStaClient->SetAttribute("PacketSize", UintegerValue(1500));
4265  legacyStaClient->SetAttribute("MaxPackets", UintegerValue(200));
4266  legacyStaClient->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
4267  legacyStaClient->SetRemote(socket);
4268  wifiStaNodes.Get(i)->AddApplication(legacyStaClient);
4269  legacyStaClient->SetStartTime(MicroSeconds(400000));
4270  legacyStaClient->SetStopTime(Seconds(1.0));
4271  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
4272  server->SetLocal(socket);
4273  wifiApNode.Get(0)->AddApplication(server);
4274  server->SetStartTime(Seconds(0.0));
4275  server->SetStopTime(Seconds(1.0));
4276  }
4277 
4278  // Trace dropped packets
4279  Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxDrop",
4281 
4282  Simulator::Stop(Seconds(1));
4283  Simulator::Run();
4284 
4285  CheckResults();
4286 
4287  Simulator::Destroy();
4288 }
4289 
4290 void
4292 {
4293  NS_TEST_EXPECT_MSG_EQ(m_dropped, 0, "Dropped some packets unexpectedly");
4294 }
4295 
4308 {
4309  public:
4311 
4312  private:
4313  void DoSetup() override;
4314  void DoTeardown() override;
4315  void DoRun() override;
4316 
4324  void SendPpdu(WifiPhyBand band, uint16_t centerFreqMhz, uint16_t bandwidthMhz);
4325 
4333  void RxSuccess(Ptr<const WifiPsdu> psdu,
4334  RxSignalInfo rxSignalInfo,
4335  WifiTxVector txVector,
4336  std::vector<bool> statusPerMpdu);
4337 
4342  void RxFailure(Ptr<const WifiPsdu> psdu);
4343 
4349  void RxDropped(Ptr<const Packet> packet, WifiPhyRxfailureReason reason);
4350 
4362  void 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 
4369  uint32_t m_countRxSuccess;
4370  uint32_t m_countRxFailure;
4371  uint32_t m_countRxDropped;
4372 
4373  std::optional<Time> m_lastRxSucceeded;
4374  std::optional<Time> m_lastRxFailed;
4375  std::optional<Time> m_lastRxDropped;
4376 
4378 };
4379 
4381  : TestCase("Check correct behavior when a STA is receiving a transmission using an unsupported "
4382  "bandwidth"),
4383  m_countRxSuccess(0),
4384  m_countRxFailure(0),
4385  m_countRxDropped(0),
4386  m_lastRxSucceeded(std::nullopt),
4387  m_lastRxFailed(std::nullopt),
4388  m_lastRxDropped(std::nullopt)
4389 {
4390 }
4391 
4392 void
4394  uint16_t centerFreqMhz,
4395  uint16_t bandwidthMhz)
4396 {
4397  auto txVector =
4398  WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, bandwidthMhz, false);
4399 
4400  auto pkt = Create<Packet>(1000);
4401  WifiMacHeader hdr;
4402 
4404  hdr.SetQosTid(0);
4405 
4406  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4407  Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
4408 
4409  auto ppdu = Create<HePpdu>(psdu, txVector, centerFreqMhz, txDuration, WIFI_PHY_BAND_5GHZ, 0);
4410 
4411  auto txPowerSpectrum =
4412  WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(centerFreqMhz,
4413  bandwidthMhz,
4414  DbmToW(-50),
4415  bandwidthMhz);
4416 
4417  auto txParams = Create<WifiSpectrumSignalParameters>();
4418  txParams->psd = txPowerSpectrum;
4419  txParams->txPhy = nullptr;
4420  txParams->duration = txDuration;
4421  txParams->ppdu = ppdu;
4422  txParams->txWidth = bandwidthMhz;
4423 
4424  m_phy->StartRx(txParams);
4425 }
4426 
4427 void
4429  RxSignalInfo rxSignalInfo,
4430  WifiTxVector txVector,
4431  std::vector<bool> statusPerMpdu)
4432 {
4433  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
4434  m_countRxSuccess++;
4436 }
4437 
4438 void
4440 {
4441  NS_LOG_FUNCTION(this << *psdu);
4442  m_countRxFailure++;
4444 }
4445 
4446 void
4448 {
4449  NS_LOG_FUNCTION(this << p << reason);
4450  NS_ASSERT(reason == UNSUPPORTED_SETTINGS);
4451  m_countRxDropped++;
4453 }
4454 
4455 void
4456 TestUnsupportedBandwidthReception::CheckRx(uint32_t expectedCountRxSuccess,
4457  uint32_t expectedCountRxFailure,
4458  uint32_t expectedCountRxDropped,
4459  std::optional<Time> expectedLastRxSucceeded,
4460  std::optional<Time> expectedLastRxFailed,
4461  std::optional<Time> expectedLastRxDropped)
4462 {
4464  expectedCountRxSuccess,
4465  "Didn't receive right number of successful packets");
4466 
4468  expectedCountRxFailure,
4469  "Didn't receive right number of unsuccessful packets");
4470 
4472  expectedCountRxDropped,
4473  "Didn't receive right number of dropped packets");
4474 
4475  if (expectedCountRxSuccess > 0)
4476  {
4477  NS_ASSERT(m_lastRxSucceeded.has_value());
4478  NS_ASSERT(expectedLastRxSucceeded.has_value());
4480  expectedLastRxSucceeded.value(),
4481  "Didn't receive the last successful packet at the expected time");
4482  }
4483 
4484  if (expectedCountRxFailure > 0)
4485  {
4486  NS_ASSERT(m_lastRxFailed.has_value());
4487  NS_ASSERT(expectedLastRxFailed.has_value());
4489  expectedLastRxFailed.value(),
4490  "Didn't receive the last unsuccessful packet at the expected time");
4491  }
4492 
4493  if (expectedCountRxDropped > 0)
4494  {
4495  NS_ASSERT(m_lastRxDropped.has_value());
4496  NS_ASSERT(expectedLastRxDropped.has_value());
4498  expectedLastRxDropped.value(),
4499  "Didn't drop the last filtered packet at the expected time");
4500  }
4501 }
4502 
4503 void
4505 {
4506  m_phy = CreateObject<SpectrumWifiPhy>();
4508  auto interferenceHelper = CreateObject<InterferenceHelper>();
4509  m_phy->SetInterferenceHelper(interferenceHelper);
4510  auto error = CreateObject<NistErrorRateModel>();
4511  m_phy->SetErrorRateModel(error);
4512 
4517  "PhyRxDrop",
4519 }
4520 
4521 void
4523 {
4524  m_phy->Dispose();
4525  m_phy = nullptr;
4526 }
4527 
4528 void
4530 {
4531  RngSeedManager::SetSeed(1);
4532  RngSeedManager::SetRun(1);
4533 
4534  int64_t streamNumber = 0;
4535  m_phy->AssignStreams(streamNumber);
4536 
4537  // Case 1: the PHY is operating on channel 36 (20 MHz) and receives a 40 MHz PPDU (channel 38).
4538  // The PPDU should be dropped once HE-SIG-A is successfully received, since it contains
4539  // indication about the BW used for the transmission and the PHY shall detect it is larger than
4540  // its operating BW.
4542 
4543  Simulator::Schedule(Seconds(1.0),
4545  this,
4547  5190,
4548  40);
4549 
4550  auto heSigAExpectedRxTime = Seconds(1.0) + MicroSeconds(32);
4551  Simulator::Schedule(Seconds(1.5),
4553  this,
4554  0,
4555  0,
4556  1,
4557  std::nullopt,
4558  std::nullopt,
4559  heSigAExpectedRxTime);
4560 
4561  // TODO: this test can be extended with other scenarios
4562 
4563  Simulator::Run();
4564  Simulator::Destroy();
4565 }
4566 
4576 {
4577  public:
4579 
4580  private:
4581  void DoSetup() override;
4582  void DoRun() override;
4583  void DoTeardown() override;
4584 
4592  Ptr<HePpdu> CreatePpdu(WifiPhyBand band, uint16_t ppduCenterFreqMhz);
4593 
4606  void RunOne(WifiPhyBand band,
4607  uint16_t phyCenterFreqMhz,
4608  uint8_t p20Index,
4609  uint16_t ppduCenterFreqMhz,
4610  bool expectedP20Overlap,
4611  bool expectedP20Covered);
4612 
4614 };
4615 
4617  : TestCase("Check correct detection of whether P20 is fully covered (hence it can be received) "
4618  "or overlaps with the bandwidth of an incoming PPDU")
4619 {
4620 }
4621 
4623 TestPrimary20CoveredByPpdu::CreatePpdu(WifiPhyBand band, uint16_t ppduCenterFreqMhz)
4624 {
4625  [[maybe_unused]] auto [channelNumber, centerFreq, channelWidth, type, phyBand] =
4626  (*WifiPhyOperatingChannel::FindFirst(0, ppduCenterFreqMhz, 0, WIFI_STANDARD_80211ax, band));
4627 
4628  auto txVector =
4629  WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, channelWidth, false);
4630 
4631  auto pkt = Create<Packet>(1000);
4633 
4634  auto psdu = Create<WifiPsdu>(pkt, hdr);
4635  auto txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, band);
4636 
4637  return Create<HePpdu>(psdu, txVector, ppduCenterFreqMhz, txDuration, band, 0);
4638 }
4639 
4640 void
4642 {
4643  m_phy = CreateObject<SpectrumWifiPhy>();
4645  auto interferenceHelper = CreateObject<InterferenceHelper>();
4646  m_phy->SetInterferenceHelper(interferenceHelper);
4647  auto error = CreateObject<NistErrorRateModel>();
4648  m_phy->SetErrorRateModel(error);
4649 }
4650 
4651 void
4653 {
4654  m_phy->Dispose();
4655  m_phy = nullptr;
4656 }
4657 
4658 void
4660  uint16_t phyCenterFreqMhz,
4661  uint8_t p20Index,
4662  uint16_t ppduCenterFreqMhz,
4663  bool expectedP20Overlap,
4664  bool expectedP20Covered)
4665 {
4666  [[maybe_unused]] const auto [channelNumber, centerFreq, channelWidth, type, phyBand] =
4667  (*WifiPhyOperatingChannel::FindFirst(0, phyCenterFreqMhz, 0, WIFI_STANDARD_80211ax, band));
4668 
4669  m_phy->SetOperatingChannel(WifiPhy::ChannelTuple{channelNumber, channelWidth, band, p20Index});
4670  auto p20CenterFreq = m_phy->GetOperatingChannel().GetPrimaryChannelCenterFrequency(20);
4671  auto p20MinFreq = p20CenterFreq - 10;
4672  auto p20MaxFreq = p20CenterFreq + 10;
4673 
4674  auto ppdu = CreatePpdu(band, ppduCenterFreqMhz);
4675 
4676  auto p20Overlap = ppdu->DoesOverlapChannel(p20MinFreq, p20MaxFreq);
4677  NS_TEST_ASSERT_MSG_EQ(p20Overlap,
4678  expectedP20Overlap,
4679  "PPDU is " << (expectedP20Overlap ? "expected" : "not expected")
4680  << " to overlap with the P20");
4681 
4682  auto p20Covered =
4684  ->CanStartRx(
4685  ppdu,
4686  ppdu->GetTxVector()
4687  .GetChannelWidth()); // CanStartRx returns true is the P20 is fully covered
4688  NS_TEST_ASSERT_MSG_EQ(p20Covered,
4689  expectedP20Covered,
4690  "PPDU is " << (expectedP20Covered ? "expected" : "not expected")
4691  << " to cover the whole P20");
4692 }
4693 
4694 void
4696 {
4697  /*
4698  * Receiver PHY Operating Channel: 2.4 GHz Channel 4 (2417 MHz – 2437 MHz)
4699  * Transmitted 20 MHz PPDU: 2.4 GHz Channel 4 (2417 MHz – 2437 MHz)
4700  * Overlap with primary 20 MHz: yes
4701  * Primary 20 MHz fully covered: yes
4702  */
4703  RunOne(WIFI_PHY_BAND_2_4GHZ, 2427, 0, 2427, true, true);
4704 
4705  /*
4706  * Receiver PHY Operating Channel: 2.4 GHz Channel 4 (2417 MHz – 2437 MHz)
4707  * Transmitted 40 MHz PPDU: 2.4 GHz Channel 6 (2427 MHz – 2447 MHz)
4708  * Overlap with primary 20 MHz: yes
4709  * Primary 20 MHz fully covered: no
4710  */
4711  RunOne(WIFI_PHY_BAND_2_4GHZ, 2427, 0, 2437, true, false);
4712 
4713  /*
4714  * Receiver PHY Operating Channel: 5 GHz Channel 36 (5170 MHz – 5190 MHz)
4715  * Transmitted 40 MHz PPDU: 5 GHz Channel 38 (5170 MHz – 5210 MHz)
4716  * Overlap with primary 20 MHz: yes
4717  * Primary 20 MHz fully covered: yes
4718  */
4719  RunOne(WIFI_PHY_BAND_5GHZ, 5180, 0, 5190, true, true);
4720 
4721  /*
4722  * Receiver PHY Operating Channel: 5 GHz Channel 36 (5170 MHz–5190 MHz)
4723  * Transmitted 20 MHz PPDU: 5 GHz Channel 40 (5190 MHz – 5210 MHz)
4724  * Overlap with primary 20 MHz: no
4725  * Primary 20 MHz fully covered: no
4726  */
4727  RunOne(WIFI_PHY_BAND_5GHZ, 5180, 0, 5200, false, false);
4728 
4729  /*
4730  * Receiver PHY Operating Channel: 5 GHz Channel 38 (5170 MHz – 5210 MHz) with P20 index 0
4731  * Transmitted 20 MHz PPDU: 5 GHz Channel 36 (5170 MHz – 5190 MHz)
4732  * Overlap with primary 20 MHz: yes
4733  * Primary 20 MHz fully covered: yes
4734  */
4735  RunOne(WIFI_PHY_BAND_5GHZ, 5190, 0, 5180, true, true);
4736 
4737  /*
4738  * Receiver PHY Operating Channel: 5 GHz Channel 38 (5170 MHz – 5210 MHz) with P20 index 1
4739  * Transmitted 20 MHz PPDU: 5 GHz Channel 36 (5170 MHz – 5190 MHz)
4740  * Overlap with primary 20 MHz: no
4741  * Primary 20 MHz fully covered: no
4742  */
4743  RunOne(WIFI_PHY_BAND_5GHZ, 5190, 1, 5180, false, false);
4744 
4745  Simulator::Destroy();
4746 }
4747 
4755 {
4756  public:
4758 };
4759 
4761  : TestSuite("wifi-phy-reception", UNIT)
4762 {
4765  AddTestCase(new TestSimpleFrameCaptureModel, TestCase::QUICK);
4766  AddTestCase(new TestPhyHeadersReception, TestCase::QUICK);
4767  AddTestCase(new TestAmpduReception, TestCase::QUICK);
4768  AddTestCase(new TestUnsupportedModulationReception(), TestCase::QUICK);
4769  AddTestCase(new TestUnsupportedBandwidthReception(), TestCase::QUICK);
4770  AddTestCase(new TestPrimary20CoveredByPpdu(), TestCase::QUICK);
4771 }
4772 
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 unsuccessfuly received MPDUs in A-MPDU #1
uint8_t m_rxFailureBitmapAmpdu2
bitmap of unsuccessfuly 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 DoTeardown() override
Implementation to do any local setup required for this TestCase.
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
Ptr< SpectrumWifiPhy > m_phy
Phy.
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.
void SendPacket(double rxPowerDbm)
Send packet function.
Ptr< SpectrumWifiPhy > m_phy
Phy.
void CheckPhyState(WifiPhyState expectedState)
Schedule now to check the PHY state.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void DoCheckPhyState(WifiPhyState expectedState)
Check the PHY state now.
uint64_t m_uid
the UID to use for the PPDU
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Primary 20 MHz Covered By Ppdu Test This test checks whether the functions WifiPpdu::DoesOverlapChann...
void RunOne(WifiPhyBand band, uint16_t phyCenterFreqMhz, uint8_t p20Index, uint16_t ppduCenterFreqMhz, bool expectedP20Overlap, bool expectedP20Covered)
Run one function.
Ptr< SpectrumWifiPhy > m_phy
PHY.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< HePpdu > CreatePpdu(WifiPhyBand band, uint16_t ppduCenterFreqMhz)
Function to create a PPDU.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
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 SendPacket(double rxPowerDbm, uint32_t packetSize)
Send packet function.
Ptr< SpectrumWifiPhy > m_phy
Phy.
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.
uint64_t m_uid
the UID to use for the PPDU
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
bool m_rxDropped1000B
count dropped packets with 1000B payload
Preamble detection test w/o frame capture.
void CheckPhyState(WifiPhyState expectedState)
Schedule now to check the PHY state.
void SendPacket(double rxPowerDbm)
Send packet function.
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 DoTeardown() 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 DoCheckPhyState(WifiPhyState expectedState)
Check the PHY state now.
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 DoCheckPhyState(WifiPhyState expectedState)
Check the PHY state now.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendPacket(double rxPowerDbm)
Send packet function.
void CheckPhyState(WifiPhyState expectedState)
Schedule now to check the PHY state.
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.
std::optional< Time > m_lastRxDropped
time of last RX drop, if any
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 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 SendPpdu(WifiPhyBand band, uint16_t centerFreqMhz, uint16_t bandwidthMhz)
Function to create a PPDU.
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.
uint16_t m_dropped
number of packets dropped by the AP because it was already receiving
wifi PHY reception Test Suite
AttributeValue implementation for Boolean.
Definition: boolean.h:37
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.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:311
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:240
void 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:863
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:206
Make it easy to create and manage PHY objects for the spectrum model.
void StartRx(Ptr< SpectrumSignalParameters > rxParams)
Input method for delivering a signal from the spectrum channel and low-level PHY interface to this Sp...
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1423
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:325
Implements the IEEE 802.11 MAC header.
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
create MAC layers for a ns3::WifiNetDevice.
Ptr< WifiMac > GetMac() const
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:624
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:632
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:448
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:941
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1480
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:1062
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:996
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:704
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:652
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:442
void SetFrameCaptureModel(const Ptr< FrameCaptureModel > frameCaptureModel)
Sets the frame capture model.
Definition: wifi-phy.cc:646
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:870
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1008
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: wifi-phy.cc:2184
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:891
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:975
#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:296
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:144
#define NS_TEST_EXPECT_MSG_EQ(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:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
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:707
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
@ WIFI_MAC_QOSDATA
mac
Definition: third.py:85
wifi
Definition: third.py:88
wifiApNode
Definition: third.py:79
mobility
Definition: third.py:96
wifiStaNodes
Definition: third.py:77
phy
Definition: third.py:82
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:70
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...