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
54using namespace ns3;
55
56NS_LOG_COMPONENT_DEFINE("WifiPhyReceptionTest");
57
58static const uint8_t CHANNEL_NUMBER = 36;
59static const uint32_t FREQUENCY = 5180; // MHz
60static const uint16_t CHANNEL_WIDTH = 20; // MHz
61static 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);
93 RxSignalInfo rxSignalInfo,
94 WifiTxVector txVector,
95 std::vector<bool> statusPerMpdu);
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
136void
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),
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
170void
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
180void
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
195void
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
207void
209 RxSignalInfo rxSignalInfo,
210 WifiTxVector txVector,
211 std::vector<bool> statusPerMpdu)
212{
213 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
215}
216
217void
219{
220 NS_LOG_FUNCTION(this << *psdu);
222}
223
226{
227 m_phy = nullptr;
228}
229
230void
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
252void
254{
255 m_phy->Dispose();
256 m_phy = nullptr;
257}
258
259void
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);
767 RxSignalInfo rxSignalInfo,
768 WifiTxVector txVector,
769 std::vector<bool> statusPerMpdu);
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
810void
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),
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
843void
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
853void
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
868void
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
880void
882 RxSignalInfo rxSignalInfo,
883 WifiTxVector txVector,
884 std::vector<bool> statusPerMpdu)
885{
886 NS_LOG_FUNCTION(this << *psdu << txVector);
888}
889
890void
892{
893 NS_LOG_FUNCTION(this << *psdu);
895}
896
898{
899 m_phy = nullptr;
900}
901
902void
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
929void
931{
932 m_phy->Dispose();
933 m_phy = nullptr;
934}
935
936void
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:
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);
1811 RxSignalInfo rxSignalInfo,
1812 WifiTxVector txVector,
1813 std::vector<bool> statusPerMpdu);
1820
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
1858void
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,
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
1891void
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
1909void
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
1923void
1925{
1926 m_rxSuccess1000B = false;
1927 m_rxSuccess1500B = false;
1928 m_rxDropped1000B = false;
1929 m_rxDropped1500B = false;
1930}
1931
1932void
1934{
1935 NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1000B, true, "Didn't receive 1000B packet");
1936}
1937
1938void
1940{
1941 NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1500B, true, "Didn't receive 1500B packet");
1942}
1943
1944void
1946{
1947 NS_TEST_ASSERT_MSG_EQ(m_rxDropped1000B, true, "Didn't drop 1000B packet");
1948}
1949
1950void
1952{
1953 NS_TEST_ASSERT_MSG_EQ(m_rxDropped1500B, true, "Didn't drop 1500B packet");
1954}
1955
1957{
1958 m_phy = nullptr;
1959}
1960
1961void
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
1987void
1989{
1990 m_phy->Dispose();
1991 m_phy = nullptr;
1992}
1993
1994void
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
2123void
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,
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
2156void
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
2164void
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
2184void
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
2196void
2198{
2199 m_phy->Dispose();
2200 m_phy = nullptr;
2201}
2202
2203void
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
2536 RxSignalInfo rxSignalInfo,
2537 WifiTxVector txVector,
2538 std::vector<bool> statusPerMpdu);
2543 void RxFailure(Ptr<const WifiPsdu> psdu);
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
2643void
2645{
2652}
2653
2654void
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
2682void
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
2711void
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
2721void
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
2750void
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
2780void
2782{
2784 expected,
2785 "RX success bitmap for A-MPDU 1 is not as expected");
2786}
2787
2788void
2790{
2792 expected,
2793 "RX success bitmap for A-MPDU 2 is not as expected");
2794}
2795
2796void
2798{
2800 expected,
2801 "RX failure bitmap for A-MPDU 1 is not as expected");
2802}
2803
2804void
2806{
2808 expected,
2809 "RX failure bitmap for A-MPDU 2 is not as expected");
2810}
2811
2812void
2814{
2816 expected,
2817 "RX dropped bitmap for A-MPDU 1 is not as expected");
2818}
2819
2820void
2822{
2824 expected,
2825 "RX dropped bitmap for A-MPDU 2 is not as expected");
2826}
2827
2828void
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
2842void
2843TestAmpduReception::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,
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
2881void
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
2908void
2910{
2911 m_phy->Dispose();
2912 m_phy = nullptr;
2913}
2914
2915void
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
4140void
4142 Ptr<const Packet> packet,
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
4153void
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
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);
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
4290void
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
4334 RxSignalInfo rxSignalInfo,
4335 WifiTxVector txVector,
4336 std::vector<bool> statusPerMpdu);
4337
4342 void RxFailure(Ptr<const WifiPsdu> psdu);
4343
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
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
4392void
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
4427void
4429 RxSignalInfo rxSignalInfo,
4430 WifiTxVector txVector,
4431 std::vector<bool> statusPerMpdu)
4432{
4433 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
4436}
4437
4438void
4440{
4441 NS_LOG_FUNCTION(this << *psdu);
4444}
4445
4446void
4448{
4449 NS_LOG_FUNCTION(this << p << reason);
4453}
4454
4455void
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
4503void
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
4521void
4523{
4524 m_phy->Dispose();
4525 m_phy = nullptr;
4526}
4527
4528void
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
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
4640void
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
4651void
4653{
4654 m_phy->Dispose();
4655 m_phy = nullptr;
4656}
4657
4658void
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});
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
4694void
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:862
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:324
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
STL namespace.
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.