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
52using namespace ns3;
53
54NS_LOG_COMPONENT_DEFINE("WifiPhyReceptionTest");
55
56static const uint8_t CHANNEL_NUMBER = 36;
57static const uint32_t FREQUENCY = 5180; // MHz
58static const uint16_t CHANNEL_WIDTH = 20; // MHz
59static const uint16_t GUARD_WIDTH =
60 CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
61
69{
70 public:
73
74 protected:
75 void DoSetup() override;
76 void DoTeardown() override;
82 void SendPacket(double rxPowerDbm);
91 RxSignalInfo rxSignalInfo,
92 WifiTxVector txVector,
93 std::vector<bool> statusPerMpdu);
101
102 private:
103 void DoRun() override;
104
109 void CheckPhyState(WifiPhyState expectedState);
114 void DoCheckPhyState(WifiPhyState expectedState);
120 void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
121
122 uint64_t m_uid;
123};
124
127 : TestCase("Threshold preamble detection model test when no frame capture model is applied"),
128 m_countRxSuccess(0),
129 m_countRxFailure(0),
130 m_uid(0)
131{
132}
133
134void
136{
137 WifiTxVector txVector =
138 WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
139
140 Ptr<Packet> pkt = Create<Packet>(1000);
141 WifiMacHeader hdr;
142
144 hdr.SetQosTid(0);
145
146 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
147 Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
148
149 Ptr<WifiPpdu> ppdu =
150 Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
151
152 Ptr<SpectrumValue> txPowerSpectrum =
153 WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
155 DbmToW(rxPowerDbm),
157
158 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
159 txParams->psd = txPowerSpectrum;
160 txParams->txPhy = nullptr;
161 txParams->duration = txDuration;
162 txParams->ppdu = ppdu;
163
164 m_phy->StartRx(txParams);
165}
166
167void
169{
170 // This is needed to make sure PHY state will be checked as the last event if a state change
171 // occured at the exact same time as the check
173 this,
174 expectedState);
175}
176
177void
179{
180 WifiPhyState currentState;
181 PointerValue ptr;
182 m_phy->GetAttribute("State", ptr);
183 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
184 currentState = state->GetState();
185 NS_LOG_FUNCTION(this << currentState);
186 NS_TEST_ASSERT_MSG_EQ(currentState,
187 expectedState,
188 "PHY State " << currentState << " does not match expected state "
189 << expectedState << " at " << Simulator::Now());
190}
191
192void
194 uint32_t expectedFailureCount)
195{
197 expectedSuccessCount,
198 "Didn't receive right number of successful packets");
200 expectedFailureCount,
201 "Didn't receive right number of unsuccessful packets");
202}
203
204void
206 RxSignalInfo rxSignalInfo,
207 WifiTxVector txVector,
208 std::vector<bool> statusPerMpdu)
209{
210 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
212}
213
214void
216{
217 NS_LOG_FUNCTION(this << *psdu);
219}
220
223{
224 m_phy = nullptr;
225}
226
227void
229{
230 m_phy = CreateObject<SpectrumWifiPhy>();
232 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
233 m_phy->SetInterferenceHelper(interferenceHelper);
234 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
235 m_phy->SetErrorRateModel(error);
241
242 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
243 CreateObject<ThresholdPreambleDetectionModel>();
244 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
245 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
246 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
247}
248
249void
251{
252 m_phy->Dispose();
253 m_phy = nullptr;
254}
255
256void
258{
259 RngSeedManager::SetSeed(1);
260 RngSeedManager::SetRun(1);
261 int64_t streamNumber = 0;
262 m_phy->AssignStreams(streamNumber);
263
264 // RX power > CCA-ED > CCA-PD
265 double rxPowerDbm = -50;
266
267 // CASE 1: send one packet and check PHY state:
268 // All reception stages should succeed and PHY state should be RX for the duration of the packet
269 // minus the time to detect the preamble, otherwise it should be IDLE.
270
271 Simulator::Schedule(Seconds(1.0),
273 this,
274 rxPowerDbm);
275 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
276 // CCA_BUSY
277 Simulator::Schedule(Seconds(1.0) + NanoSeconds(3999),
279 this,
281 Simulator::Schedule(Seconds(1.0) + NanoSeconds(4000),
283 this,
285 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
286 // CCA_BUSY to RX
287 Simulator::Schedule(Seconds(1.0) + NanoSeconds(43999),
289 this,
291 Simulator::Schedule(Seconds(1.0) + NanoSeconds(44000),
293 this,
295 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
296 Simulator::Schedule(Seconds(1.0) + NanoSeconds(152799),
298 this,
300 Simulator::Schedule(Seconds(1.0) + NanoSeconds(152800),
302 this,
304 // Packet should have been successfully received
305 Simulator::Schedule(Seconds(1.1),
307 this,
308 1,
309 0);
310
311 // CASE 2: send two packets with same power within the 4us window and check PHY state:
312 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
313 // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
314 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
315 // time to detect the preamble.
316
317 Simulator::Schedule(Seconds(2.0),
319 this,
320 rxPowerDbm);
321 Simulator::Schedule(Seconds(2.0) + MicroSeconds(2.0),
323 this,
324 rxPowerDbm);
325 // At 4us, no preamble is successfully detected and STA PHY STATE should move from IDLE to
326 // CCA_BUSY
327 Simulator::Schedule(Seconds(2.0) + NanoSeconds(3999),
329 this,
331 Simulator::Schedule(Seconds(2.0) + NanoSeconds(4000),
333 this,
335 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
336 // = 154.8us
337 Simulator::Schedule(Seconds(2.0) + NanoSeconds(154799),
339 this,
341 Simulator::Schedule(Seconds(2.0) + NanoSeconds(154800),
343 this,
345 // No more packet should have been successfully received, and since preamble detection did not
346 // pass, the packet should not have been counted as a failure
347 Simulator::Schedule(Seconds(2.1),
349 this,
350 1,
351 0);
352
353 // CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY
354 // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
355 // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
356 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
357 // time to detect the preamble.
358
359 Simulator::Schedule(Seconds(3.0),
361 this,
362 rxPowerDbm);
363 Simulator::Schedule(Seconds(3.0) + MicroSeconds(2.0),
365 this,
366 rxPowerDbm - 3);
367 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
368 // CCA_BUSY
369 Simulator::Schedule(Seconds(3.0) + NanoSeconds(3999),
371 this,
373 Simulator::Schedule(Seconds(3.0) + NanoSeconds(4000),
375 this,
377 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
378 // = 154.8us
379 Simulator::Schedule(Seconds(3.0) + NanoSeconds(154799),
381 this,
383 Simulator::Schedule(Seconds(3.0) + NanoSeconds(154800),
385 this,
387 // No more packet should have been successfully received, and since preamble detection did not
388 // pass the packet should not have been counted as a failure
389 Simulator::Schedule(Seconds(3.1),
391 this,
392 1,
393 0);
394
395 // CASE 4: send two packets with second one 6 dB weaker within the 4us window and check PHY
396 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
397 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
398 // decode the modulation).
399
400 Simulator::Schedule(Seconds(4.0),
402 this,
403 rxPowerDbm);
404 Simulator::Schedule(Seconds(4.0) + MicroSeconds(2.0),
406 this,
407 rxPowerDbm - 6);
408 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
409 // CCA_BUSY
410 Simulator::Schedule(Seconds(4.0) + NanoSeconds(3999),
412 this,
414 Simulator::Schedule(Seconds(4.0) + NanoSeconds(4000),
416 this,
418 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
419 // CCA_BUSY to RX
420 Simulator::Schedule(Seconds(4.0) + NanoSeconds(43999),
422 this,
424 Simulator::Schedule(Seconds(4.0) + NanoSeconds(44000),
426 this,
428 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
429 // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
430 // should first be seen as CCA_BUSY for 2us.
431 Simulator::Schedule(Seconds(4.0) + NanoSeconds(152799),
433 this,
435 Simulator::Schedule(Seconds(4.0) + NanoSeconds(152800),
437 this,
439 Simulator::Schedule(Seconds(4.0) + NanoSeconds(154799),
441 this,
443 Simulator::Schedule(Seconds(4.0) + NanoSeconds(154800),
445 this,
447 // In this case, the first packet should be marked as a failure
448 Simulator::Schedule(Seconds(4.1),
450 this,
451 1,
452 1);
453
454 // CASE 5: send two packets with second one 3 dB higher within the 4us window and check PHY
455 // state: PHY preamble detection should fail because SNR is too low (around -3 dB, which is
456 // lower than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is
457 // above CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus
458 // the time to detect the preamble.
459
460 Simulator::Schedule(Seconds(5.0),
462 this,
463 rxPowerDbm);
464 Simulator::Schedule(Seconds(5.0) + MicroSeconds(2.0),
466 this,
467 rxPowerDbm + 3);
468 // At 6us (hence 4us after the last signal is received), no preamble is successfully detected,
469 // hence STA PHY STATE should move from IDLE to CCA_BUSY
470 Simulator::Schedule(Seconds(5.0) + NanoSeconds(5999),
472 this,
474 Simulator::Schedule(Seconds(5.0) + NanoSeconds(6000),
476 this,
478 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
479 // = 154.8us
480 Simulator::Schedule(Seconds(5.0) + NanoSeconds(154799),
482 this,
484 Simulator::Schedule(Seconds(5.0) + NanoSeconds(154800),
486 this,
488 // No more packet should have been successfully received, and since preamble detection did not
489 // pass the packet should not have been counted as a failure
490 Simulator::Schedule(Seconds(5.1),
492 this,
493 1,
494 1);
495
496 // CCA-PD < RX power < CCA-ED
497 rxPowerDbm = -70;
498
499 // CASE 6: send one packet and check PHY state:
500 // All reception stages should succeed and PHY state should be RX for the duration of the packet
501 // minus the time to detect the preamble, otherwise it should be IDLE.
502
503 Simulator::Schedule(Seconds(6.0),
505 this,
506 rxPowerDbm);
507 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
508 // CCA_BUSY
509 Simulator::Schedule(Seconds(6.0) + NanoSeconds(3999),
511 this,
513 Simulator::Schedule(Seconds(6.0) + NanoSeconds(4000),
515 this,
517 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
518 // CCA_BUSY to RX
519 Simulator::Schedule(Seconds(6.0) + NanoSeconds(43999),
521 this,
523 Simulator::Schedule(Seconds(6.0) + NanoSeconds(44000),
525 this,
527 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
528 Simulator::Schedule(Seconds(6.0) + NanoSeconds(152799),
530 this,
532 Simulator::Schedule(Seconds(6.0) + NanoSeconds(152800),
534 this,
536 // Packet should have been successfully received
537 Simulator::Schedule(Seconds(6.1),
539 this,
540 2,
541 1);
542
543 // CASE 7: send two packets with same power within the 4us window and check PHY state:
544 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
545 // the threshold of 4 dB), and PHY state should be CCA_BUSY since it should detect the start of
546 // a valid OFDM transmission at a receive level greater than or equal to the minimum modulation
547 // and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
548
549 Simulator::Schedule(Seconds(7.0),
551 this,
552 rxPowerDbm);
553 Simulator::Schedule(Seconds(7.0) + MicroSeconds(2.0),
555 this,
556 rxPowerDbm);
557 // At 4us, STA PHY STATE should stay IDLE
558 Simulator::Schedule(Seconds(7.0) + MicroSeconds(4.0),
560 this,
562 // No more packet should have been successfully received, and since preamble detection did not
563 // pass the packet should not have been counted as a failure
564 Simulator::Schedule(Seconds(7.1),
566 this,
567 2,
568 1);
569
570 // CASE 8: send two packets with second one 3 dB weaker within the 4us window and check PHY
571 // state: PHY preamble detection should fail PHY preamble detection should fail because SNR is
572 // too low (around 3 dB, which is lower than the threshold of 4 dB), and PHY state should be
573 // CCA_BUSY since it should detect the start of a valid OFDM transmission at a receive level
574 // greater than or equal to the minimum modulation and coding rate sensitivity (–82 dBm for 20
575 // MHz channel spacing).
576
577 Simulator::Schedule(Seconds(8.0),
579 this,
580 rxPowerDbm);
581 Simulator::Schedule(Seconds(8.0) + MicroSeconds(2.0),
583 this,
584 rxPowerDbm - 3);
585 // At 4us, STA PHY STATE should stay IDLE
586 Simulator::Schedule(Seconds(8.0) + MicroSeconds(4.0),
588 this,
590 // No more packet should have been successfully received, and since preamble detection did not
591 // pass the packet should not have been counted as a failure
592 Simulator::Schedule(Seconds(8.1),
594 this,
595 2,
596 1);
597
598 // CASE 9: send two packets with second one 6 dB weaker within the 4us window and check PHY
599 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
600 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
601 // decode the modulation).
602
603 Simulator::Schedule(Seconds(9.0),
605 this,
606 rxPowerDbm);
607 Simulator::Schedule(Seconds(9.0) + MicroSeconds(2.0),
609 this,
610 rxPowerDbm - 6);
611 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
612 // CCA_BUSY
613 Simulator::Schedule(Seconds(9.0) + NanoSeconds(3999),
615 this,
617 Simulator::Schedule(Seconds(9.0) + NanoSeconds(4000),
619 this,
621 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
622 // CCA_BUSY to RX
623 Simulator::Schedule(Seconds(9.0) + NanoSeconds(43999),
625 this,
627 Simulator::Schedule(Seconds(9.0) + NanoSeconds(44000),
629 this,
631 // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
632 // 152.8us.
633 Simulator::Schedule(Seconds(9.0) + NanoSeconds(152799),
635 this,
637 Simulator::Schedule(Seconds(9.0) + NanoSeconds(152800),
639 this,
641 // In this case, the first packet should be marked as a failure
642 Simulator::Schedule(Seconds(9.1),
644 this,
645 2,
646 2);
647
648 // CASE 10: send two packets with second one 3 dB higher within the 4us window and check PHY
649 // state: PHY preamble detection should fail because SNR is too low (around -3 dB, which is
650 // lower than the threshold of 4 dB), and PHY state should stay IDLE since the total energy is
651 // below CCA-ED (-62 dBm).
652
653 Simulator::Schedule(Seconds(10.0),
655 this,
656 rxPowerDbm);
657 Simulator::Schedule(Seconds(10.0) + MicroSeconds(2.0),
659 this,
660 rxPowerDbm + 3);
661 // At 4us, STA PHY STATE should stay IDLE
662 Simulator::Schedule(Seconds(10.0) + MicroSeconds(4.0),
664 this,
666 // No more packet should have been successfully received, and since preamble detection did not
667 // pass the packet should not have been counted as a failure
668 Simulator::Schedule(Seconds(10.1),
670 this,
671 2,
672 2);
673
674 // CASE 11: send one packet with a power slightly above the minimum RSSI needed for the preamble
675 // detection (-82 dBm) and check PHY state: preamble detection should succeed and PHY state
676 // should move to RX.
677
678 rxPowerDbm = -81;
679
680 Simulator::Schedule(Seconds(11.0),
682 this,
683 rxPowerDbm);
684 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
685 // CCA_BUSY
686 Simulator::Schedule(Seconds(11.0) + NanoSeconds(3999),
688 this,
690 Simulator::Schedule(Seconds(11.0) + NanoSeconds(4000),
692 this,
694 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
695 // CCA_BUSY to RX
696 Simulator::Schedule(Seconds(11.0) + NanoSeconds(43999),
698 this,
700 Simulator::Schedule(Seconds(11.0) + NanoSeconds(44000),
702 this,
704 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
705 Simulator::Schedule(Seconds(11.0) + NanoSeconds(152799),
707 this,
709 Simulator::Schedule(Seconds(11.0) + NanoSeconds(152800),
711 this,
713
714 // RX power < CCA-PD < CCA-ED
715 rxPowerDbm = -83;
716
717 // CASE 12: send one packet with a power slightly below the minimum RSSI needed for the preamble
718 // detection (-82 dBm) and check PHY state: preamble detection should fail and PHY should be
719 // kept in IDLE state.
720
721 Simulator::Schedule(Seconds(12.0),
723 this,
724 rxPowerDbm);
725 // At 4us, STA PHY state should be IDLE
726 Simulator::Schedule(Seconds(12.0) + MicroSeconds(4.0),
728 this,
730
731 Simulator::Run();
732 Simulator::Destroy();
733}
734
742{
743 public:
746
747 protected:
748 void DoSetup() override;
749 void DoTeardown() override;
755 void SendPacket(double rxPowerDbm);
764 RxSignalInfo rxSignalInfo,
765 WifiTxVector txVector,
766 std::vector<bool> statusPerMpdu);
774
775 private:
776 void DoRun() override;
777
782 void CheckPhyState(WifiPhyState expectedState);
787 void DoCheckPhyState(WifiPhyState expectedState);
793 void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
794
795 uint64_t m_uid;
796};
797
799 : TestCase(
800 "Threshold preamble detection model test when simple frame capture model is applied"),
801 m_countRxSuccess(0),
802 m_countRxFailure(0),
803 m_uid(0)
804{
805}
806
807void
809{
810 WifiTxVector txVector =
811 WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
812
813 Ptr<Packet> pkt = Create<Packet>(1000);
814 WifiMacHeader hdr;
815
817 hdr.SetQosTid(0);
818
819 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
820 Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
821
822 Ptr<WifiPpdu> ppdu =
823 Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
824
825 Ptr<SpectrumValue> txPowerSpectrum =
826 WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
828 DbmToW(rxPowerDbm),
830
831 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
832 txParams->psd = txPowerSpectrum;
833 txParams->txPhy = nullptr;
834 txParams->duration = txDuration;
835 txParams->ppdu = ppdu;
836
837 m_phy->StartRx(txParams);
838}
839
840void
842{
843 // This is needed to make sure PHY state will be checked as the last event if a state change
844 // occured at the exact same time as the check
846 this,
847 expectedState);
848}
849
850void
852{
853 WifiPhyState currentState;
854 PointerValue ptr;
855 m_phy->GetAttribute("State", ptr);
856 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
857 currentState = state->GetState();
858 NS_LOG_FUNCTION(this << currentState);
859 NS_TEST_ASSERT_MSG_EQ(currentState,
860 expectedState,
861 "PHY State " << currentState << " does not match expected state "
862 << expectedState << " at " << Simulator::Now());
863}
864
865void
867 uint32_t expectedFailureCount)
868{
870 expectedSuccessCount,
871 "Didn't receive right number of successful packets");
873 expectedFailureCount,
874 "Didn't receive right number of unsuccessful packets");
875}
876
877void
879 RxSignalInfo rxSignalInfo,
880 WifiTxVector txVector,
881 std::vector<bool> statusPerMpdu)
882{
883 NS_LOG_FUNCTION(this << *psdu << txVector);
885}
886
887void
889{
890 NS_LOG_FUNCTION(this << *psdu);
892}
893
895{
896 m_phy = nullptr;
897}
898
899void
901{
902 m_phy = CreateObject<SpectrumWifiPhy>();
904 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
905 m_phy->SetInterferenceHelper(interferenceHelper);
906 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
907 m_phy->SetErrorRateModel(error);
913
914 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
915 CreateObject<ThresholdPreambleDetectionModel>();
916 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
917 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
918 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
919
920 Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
921 frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
922 frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
923 m_phy->SetFrameCaptureModel(frameCaptureModel);
924}
925
926void
928{
929 m_phy->Dispose();
930 m_phy = nullptr;
931}
932
933void
935{
936 RngSeedManager::SetSeed(1);
937 RngSeedManager::SetRun(1);
938 int64_t streamNumber = 1;
939 m_phy->AssignStreams(streamNumber);
940
941 // RX power > CCA-ED > CCA-PD
942 double rxPowerDbm = -50;
943
944 // CASE 1: send one packet and check PHY state:
945 // All reception stages should succeed and PHY state should be RX for the duration of the packet
946 // minus the time to detect the preamble, otherwise it should be IDLE.
947
948 Simulator::Schedule(Seconds(1.0),
950 this,
951 rxPowerDbm);
952 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
953 // CCA_BUSY
954 Simulator::Schedule(Seconds(1.0) + NanoSeconds(3999),
956 this,
958 Simulator::Schedule(Seconds(1.0) + NanoSeconds(4000),
960 this,
962 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
963 // CCA_BUSY to RX
964 Simulator::Schedule(Seconds(1.0) + NanoSeconds(43999),
966 this,
968 Simulator::Schedule(Seconds(1.0) + NanoSeconds(44000),
970 this,
972 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
973 Simulator::Schedule(Seconds(1.0) + NanoSeconds(152799),
975 this,
977 Simulator::Schedule(Seconds(1.0) + NanoSeconds(152800),
979 this,
981 // Packet should have been successfully received
982 Simulator::Schedule(Seconds(1.1),
984 this,
985 1,
986 0);
987
988 // CASE 2: send two packets with same power within the 4us window and check PHY state:
989 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
990 // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
991 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
992 // time to detect the preamble.
993
994 Simulator::Schedule(Seconds(2.0),
996 this,
997 rxPowerDbm);
998 Simulator::Schedule(Seconds(2.0) + MicroSeconds(2.0),
1000 this,
1001 rxPowerDbm);
1002 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1003 // CCA_BUSY
1004 Simulator::Schedule(Seconds(2.0) + NanoSeconds(3999),
1006 this,
1008 Simulator::Schedule(Seconds(2.0) + NanoSeconds(4000),
1010 this,
1012 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1013 // = 154.8us
1014 Simulator::Schedule(Seconds(2.0) + NanoSeconds(154799),
1016 this,
1018 Simulator::Schedule(Seconds(2.0) + NanoSeconds(154800),
1020 this,
1022 // No more packet should have been successfully received, and since preamble detection did not
1023 // pass the packet should not have been counted as a failure
1024 Simulator::Schedule(Seconds(2.1),
1026 this,
1027 1,
1028 0);
1029
1030 // CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY
1031 // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
1032 // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1033 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1034 // time to detect the preamble.
1035
1036 Simulator::Schedule(Seconds(3.0),
1038 this,
1039 rxPowerDbm);
1040 Simulator::Schedule(Seconds(3.0) + MicroSeconds(2.0),
1042 this,
1043 rxPowerDbm - 3);
1044 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1045 // CCA_BUSY
1046 Simulator::Schedule(Seconds(3.0) + NanoSeconds(3999),
1048 this,
1050 Simulator::Schedule(Seconds(3.0) + NanoSeconds(4000),
1052 this,
1054 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1055 // = 154.8us
1056 Simulator::Schedule(Seconds(3.0) + NanoSeconds(154799),
1058 this,
1060 Simulator::Schedule(Seconds(3.0) + NanoSeconds(154800),
1062 this,
1064 // No more packet should have been successfully received, and since preamble detection did not
1065 // pass the packet should not have been counted as a failure
1066 Simulator::Schedule(Seconds(3.1),
1068 this,
1069 1,
1070 0);
1071
1072 // CASE 4: send two packets with second one 6 dB weaker within the 4us window and check PHY
1073 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1074 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1075 // decode the modulation).
1076
1077 Simulator::Schedule(Seconds(4.0),
1079 this,
1080 rxPowerDbm);
1081 Simulator::Schedule(Seconds(4.0) + MicroSeconds(2.0),
1083 this,
1084 rxPowerDbm - 6);
1085 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1086 // CCA_BUSY
1087 Simulator::Schedule(Seconds(4.0) + NanoSeconds(3999),
1089 this,
1091 Simulator::Schedule(Seconds(4.0) + NanoSeconds(4000),
1093 this,
1095 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1096 // CCA_BUSY to RX
1097 Simulator::Schedule(Seconds(4.0) + NanoSeconds(43999),
1099 this,
1101 Simulator::Schedule(Seconds(4.0) + NanoSeconds(44000),
1103 this,
1105 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
1106 // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
1107 // should first be seen as CCA_BUSY for 2us.
1108 Simulator::Schedule(Seconds(4.0) + NanoSeconds(152799),
1110 this,
1112 Simulator::Schedule(Seconds(4.0) + NanoSeconds(152800),
1114 this,
1116 Simulator::Schedule(Seconds(4.0) + NanoSeconds(154799),
1118 this,
1120 Simulator::Schedule(Seconds(4.0) + NanoSeconds(154800),
1122 this,
1124 // In this case, the first packet should be marked as a failure
1125 Simulator::Schedule(Seconds(4.1),
1127 this,
1128 1,
1129 1);
1130
1131 // CASE 5: send two packets with second one 3 dB higher within the 4us window and check PHY
1132 // state: PHY preamble detection should switch because a higher packet is received within the
1133 // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1134 // lower than the threshold of 4 dB), PHY state should be CCA_BUSY since the total energy is
1135 // above CCA-ED (-62 dBm).
1136
1137 Simulator::Schedule(Seconds(5.0),
1139 this,
1140 rxPowerDbm);
1141 Simulator::Schedule(Seconds(5.0) + MicroSeconds(2.0),
1143 this,
1144 rxPowerDbm + 3);
1145 // At 4us, STA PHY STATE should stay IDLE
1146 Simulator::Schedule(Seconds(5.0) + MicroSeconds(4.0),
1148 this,
1150 // At 6us, STA PHY STATE should move from IDLE to CCA_BUSY
1151 Simulator::Schedule(Seconds(5.0) + NanoSeconds(5999),
1153 this,
1155 Simulator::Schedule(Seconds(5.0) + NanoSeconds(6000),
1157 this,
1159 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1160 // = 154.8us
1161 Simulator::Schedule(Seconds(5.0) + NanoSeconds(154799),
1163 this,
1165 Simulator::Schedule(Seconds(5.0) + NanoSeconds(154800),
1167 this,
1169 // No more packet should have been successfully received, and since preamble detection did not
1170 // pass the packet should not have been counted as a failure
1171 Simulator::Schedule(Seconds(5.1),
1173 this,
1174 1,
1175 1);
1176
1177 // CASE 6: send two packets with second one 6 dB higher within the 4us window and check PHY
1178 // state: PHY preamble detection should switch because a higher packet is received within the
1179 // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1180 // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1181 // decode the modulation).
1182
1183 Simulator::Schedule(Seconds(6.0),
1185 this,
1186 rxPowerDbm);
1187 Simulator::Schedule(Seconds(6.0) + MicroSeconds(2.0),
1189 this,
1190 rxPowerDbm + 6);
1191 // At 4us, STA PHY STATE should stay IDLE
1192 Simulator::Schedule(Seconds(6.0) + MicroSeconds(4.0),
1194 this,
1196 // At 6us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1197 // CCA_BUSY
1198 Simulator::Schedule(Seconds(6.0) + NanoSeconds(5999),
1200 this,
1202 Simulator::Schedule(Seconds(6.0) + NanoSeconds(6000),
1204 this,
1206 // At 46us, PHY header should be successfully received and STA PHY STATE should move from
1207 // CCA_BUSY to RX
1208 Simulator::Schedule(Seconds(6.0) + NanoSeconds(45999),
1210 this,
1212 Simulator::Schedule(Seconds(6.0) + NanoSeconds(46000),
1214 this,
1216 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1217 // = 154.8us
1218 Simulator::Schedule(Seconds(6.0) + NanoSeconds(154799),
1220 this,
1222 Simulator::Schedule(Seconds(6.0) + NanoSeconds(154800),
1224 this,
1226 // In this case, the second packet should be marked as a failure
1227 Simulator::Schedule(Seconds(6.1),
1229 this,
1230 1,
1231 2);
1232
1233 // CASE 7: send two packets with same power at the exact same time and check PHY state:
1234 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
1235 // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1236 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1237 // time to detect the preamble.
1238
1239 Simulator::Schedule(Seconds(7.0),
1241 this,
1242 rxPowerDbm);
1243 Simulator::Schedule(Seconds(7.0),
1245 this,
1246 rxPowerDbm);
1247 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1248 // CCA_BUSY
1249 Simulator::Schedule(Seconds(7.0) + NanoSeconds(3999),
1251 this,
1253 Simulator::Schedule(Seconds(7.0) + NanoSeconds(4000),
1255 this,
1257 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1258 // = 154.8us
1259 Simulator::Schedule(Seconds(7.0) + NanoSeconds(152799),
1261 this,
1263 Simulator::Schedule(Seconds(7.0) + NanoSeconds(152800),
1265 this,
1267 // No more packet should have been successfully received, and since preamble detection did not
1268 // pass the packet should not have been counted as a failure
1269 Simulator::Schedule(Seconds(7.1),
1271 this,
1272 1,
1273 2);
1274
1275 // CASE 8: send two packets with second one 3 dB weaker at the exact same time and check PHY
1276 // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
1277 // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1278 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1279 // time to detect the preamble.
1280
1281 Simulator::Schedule(Seconds(8.0),
1283 this,
1284 rxPowerDbm);
1285 Simulator::Schedule(Seconds(8.0),
1287 this,
1288 rxPowerDbm - 3);
1289 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1290 // CCA_BUSY
1291 Simulator::Schedule(Seconds(8.0) + NanoSeconds(3999),
1293 this,
1295 Simulator::Schedule(Seconds(8.0) + NanoSeconds(4000),
1297 this,
1299 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1300 Simulator::Schedule(Seconds(8.0) + NanoSeconds(152799),
1302 this,
1304 Simulator::Schedule(Seconds(8.0) + NanoSeconds(152800),
1306 this,
1308 // No more packet should have been successfully received, and since preamble detection did not
1309 // pass the packet should not have been counted as a failure
1310 Simulator::Schedule(Seconds(8.1),
1312 this,
1313 1,
1314 2);
1315
1316 // CASE 9: send two packets with second one 6 dB weaker at the exact same time and check PHY
1317 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1318 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1319 // decode the modulation).
1320
1321 Simulator::Schedule(Seconds(9.0),
1323 this,
1324 rxPowerDbm);
1325 Simulator::Schedule(Seconds(9.0),
1327 this,
1328 rxPowerDbm - 6);
1329 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1330 // CCA_BUSY
1331 Simulator::Schedule(Seconds(9.0) + NanoSeconds(3999),
1333 this,
1335 Simulator::Schedule(Seconds(9.0) + NanoSeconds(4000),
1337 this,
1339 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1340 // CCA_BUSY to RX
1341 Simulator::Schedule(Seconds(9.0) + NanoSeconds(43999),
1343 this,
1345 Simulator::Schedule(Seconds(9.0) + NanoSeconds(44000),
1347 this,
1349 // Since it takes 152.8us to transmit the packets, PHY should be back to IDLE at time 152.8us.
1350 Simulator::Schedule(Seconds(9.0) + NanoSeconds(152799),
1352 this,
1354 Simulator::Schedule(Seconds(9.0) + NanoSeconds(152800),
1356 this,
1358 // In this case, the first packet should be marked as a failure
1359 Simulator::Schedule(Seconds(9.1),
1361 this,
1362 1,
1363 3);
1364
1365 // CASE 10: send two packets with second one 3 dB higher at the exact same time and check PHY
1366 // state: PHY preamble detection should switch because a higher packet is received within the
1367 // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1368 // lower than the threshold of 4 dB), PHY state should be CCA_BUSY since the total energy is
1369 // above CCA-ED (-62 dBm).
1370
1371 Simulator::Schedule(Seconds(10.0),
1373 this,
1374 rxPowerDbm);
1375 Simulator::Schedule(Seconds(10.0),
1377 this,
1378 rxPowerDbm + 3);
1379 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1380 // CCA_BUSY
1381 Simulator::Schedule(Seconds(10.0) + NanoSeconds(3999),
1383 this,
1385 Simulator::Schedule(Seconds(10.0) + NanoSeconds(4000),
1387 this,
1389 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1390 Simulator::Schedule(Seconds(10.0) + NanoSeconds(152799),
1392 this,
1394 Simulator::Schedule(Seconds(10.0) + NanoSeconds(152800),
1396 this,
1398 // No more packet should have been successfully received, and since preamble detection did not
1399 // pass the packet should not have been counted as a failure
1400 Simulator::Schedule(Seconds(10.1),
1402 this,
1403 1,
1404 3);
1405
1406 // CASE 11: send two packets with second one 6 dB higher at the exact same time and check PHY
1407 // state: PHY preamble detection should switch because a higher packet is received within the
1408 // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1409 // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1410 // decode the modulation).
1411
1412 Simulator::Schedule(Seconds(11.0),
1414 this,
1415 rxPowerDbm);
1416 Simulator::Schedule(Seconds(11.0),
1418 this,
1419 rxPowerDbm + 6);
1420 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1421 // CCA_BUSY
1422 Simulator::Schedule(Seconds(11.0) + NanoSeconds(3999),
1424 this,
1426 Simulator::Schedule(Seconds(11.0) + NanoSeconds(4000),
1428 this,
1430 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1431 // CCA_BUSY to RX
1432 Simulator::Schedule(Seconds(11.0) + NanoSeconds(43999),
1434 this,
1436 Simulator::Schedule(Seconds(11.0) + NanoSeconds(44000),
1438 this,
1440 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1441 Simulator::Schedule(Seconds(11.0) + NanoSeconds(152799),
1443 this,
1445 Simulator::Schedule(Seconds(11.0) + NanoSeconds(152800),
1447 this,
1449 // In this case, the second packet should be marked as a failure
1450 Simulator::Schedule(Seconds(11.1),
1452 this,
1453 1,
1454 4);
1455
1456 // CCA-PD < RX power < CCA-ED
1457 rxPowerDbm = -70;
1458
1459 // CASE 12: send one packet and check PHY state:
1460 // All reception stages should succeed and PHY state should be RX for the duration of the packet
1461 // minus the time to detect the preamble, otherwise it should be IDLE.
1462
1463 Simulator::Schedule(Seconds(12.0),
1465 this,
1466 rxPowerDbm);
1467 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1468 // CCA_BUSY
1469 Simulator::Schedule(Seconds(12.0) + NanoSeconds(3999),
1471 this,
1473 Simulator::Schedule(Seconds(12.0) + NanoSeconds(4000),
1475 this,
1477 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1478 // CCA_BUSY to RX
1479 Simulator::Schedule(Seconds(12.0) + NanoSeconds(43999),
1481 this,
1483 Simulator::Schedule(Seconds(12.0) + NanoSeconds(44000),
1485 this,
1487 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
1488 Simulator::Schedule(Seconds(12.0) + NanoSeconds(152799),
1490 this,
1492 Simulator::Schedule(Seconds(12.0) + NanoSeconds(152800),
1494 this,
1496 // Packet should have been successfully received
1497 Simulator::Schedule(Seconds(12.1),
1499 this,
1500 2,
1501 4);
1502
1503 // CASE 13: send two packets with same power within the 4us window and check PHY state:
1504 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
1505 // the threshold of 4 dB), and PHY state should be CCA_BUSY since it should detect the start of
1506 // a valid OFDM transmission at a receive level greater than or equal to the minimum modulation
1507 // and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
1508
1509 Simulator::Schedule(Seconds(13.0),
1511 this,
1512 rxPowerDbm);
1513 Simulator::Schedule(Seconds(13.0) + MicroSeconds(2.0),
1515 this,
1516 rxPowerDbm);
1517 // At 4us, STA PHY STATE should stay IDLE
1518 Simulator::Schedule(Seconds(13.0) + MicroSeconds(4.0),
1520 this,
1522 // No more packet should have been successfully received, and since preamble detection did not
1523 // pass the packet should not have been counted as a failure
1524 Simulator::Schedule(Seconds(13.1),
1526 this,
1527 2,
1528 4);
1529
1530 // CASE 14: send two packets with second one 3 dB weaker within the 4us window and check PHY
1531 // state: PHY preamble detection should fail PHY preamble detection should fail because SNR is
1532 // too low (around 3 dB, which is lower than the threshold of 4 dB), and PHY state should be
1533 // CCA_BUSY since it should detect the start of a valid OFDM transmission at a receive level
1534 // greater than or equal to the minimum modulation and coding rate sensitivity (–82 dBm for 20
1535 // MHz channel spacing).
1536
1537 Simulator::Schedule(Seconds(14.0),
1539 this,
1540 rxPowerDbm);
1541 Simulator::Schedule(Seconds(14.0) + MicroSeconds(2.0),
1543 this,
1544 rxPowerDbm - 3);
1545 // At 4us, STA PHY STATE should stay IDLE
1546 Simulator::Schedule(Seconds(14.0) + MicroSeconds(4.0),
1548 this,
1550 // No more packet should have been successfully received, and since preamble detection did not
1551 // pass the packet should not have been counted as a failure
1552 Simulator::Schedule(Seconds(14.1),
1554 this,
1555 2,
1556 4);
1557
1558 // CASE 15: send two packets with second one 6 dB weaker within the 4us window and check PHY
1559 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1560 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1561 // decode the modulation).
1562
1563 Simulator::Schedule(Seconds(15.0),
1565 this,
1566 rxPowerDbm);
1567 Simulator::Schedule(Seconds(15.0) + MicroSeconds(2.0),
1569 this,
1570 rxPowerDbm - 6);
1571 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1572 // CCA_BUSY
1573 Simulator::Schedule(Seconds(15.0) + NanoSeconds(3999),
1575 this,
1577 Simulator::Schedule(Seconds(15.0) + NanoSeconds(4000),
1579 this,
1581 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1582 // CCA_BUSY to RX
1583 Simulator::Schedule(Seconds(15.0) + NanoSeconds(43999),
1585 this,
1587 Simulator::Schedule(Seconds(15.0) + NanoSeconds(44000),
1589 this,
1591 // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
1592 // 152.8us.
1593 Simulator::Schedule(Seconds(15.0) + NanoSeconds(152799),
1595 this,
1597 Simulator::Schedule(Seconds(15.0) + NanoSeconds(152800),
1599 this,
1601 // In this case, the first packet should be marked as a failure
1602 Simulator::Schedule(Seconds(15.1),
1604 this,
1605 2,
1606 5);
1607
1608 // CASE 16: send two packets with second one 3 dB higher within the 4us window and check PHY
1609 // state: PHY preamble detection should switch because a higher packet is received within the
1610 // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1611 // lower than the threshold of 4 dB). and PHY state should be CCA_BUSY since it should detect
1612 // the start of a valid OFDM transmission at a receive level greater than or equal to the
1613 // minimum modulation and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
1614
1615 Simulator::Schedule(Seconds(16.0),
1617 this,
1618 rxPowerDbm);
1619 Simulator::Schedule(Seconds(16.0) + MicroSeconds(2.0),
1621 this,
1622 rxPowerDbm + 3);
1623 // At 4us, STA PHY STATE should stay IDLE
1624 Simulator::Schedule(Seconds(16.0) + MicroSeconds(4.0),
1626 this,
1628 // At 6us, STA PHY STATE should be CCA_BUSY
1629 Simulator::Schedule(Seconds(16.0) + MicroSeconds(6.0),
1631 this,
1633 // No more packet should have been successfully received, and since preamble detection did not
1634 // pass the packet should not have been counted as a failure
1635 Simulator::Schedule(Seconds(16.1),
1637 this,
1638 2,
1639 5);
1640
1641 // CASE 17: send two packets with second one 6 dB higher within the 4us window and check PHY
1642 // state: PHY preamble detection should switch because a higher packet is received within the
1643 // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1644 // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1645 // decode the modulation).
1646
1647 Simulator::Schedule(Seconds(17.0),
1649 this,
1650 rxPowerDbm);
1651 Simulator::Schedule(Seconds(17.0) + MicroSeconds(2.0),
1653 this,
1654 rxPowerDbm + 6);
1655 // At 4us, STA PHY STATE should stay IDLE
1656 Simulator::Schedule(Seconds(17.0) + MicroSeconds(4.0),
1658 this,
1660 // At 6us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1661 // CCA_BUSY
1662 Simulator::Schedule(Seconds(17.0) + NanoSeconds(5999),
1664 this,
1666 Simulator::Schedule(Seconds(17.0) + NanoSeconds(6000),
1668 this,
1670 // At 46us, PHY header should be successfully received and STA PHY STATE should move from
1671 // CCA_BUSY to RX
1672 Simulator::Schedule(Seconds(17.0) + NanoSeconds(45999),
1674 this,
1676 Simulator::Schedule(Seconds(17.0) + NanoSeconds(46000),
1678 this,
1680 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1681 // = 154.8us
1682 Simulator::Schedule(Seconds(17.0) + NanoSeconds(154799),
1684 this,
1686 Simulator::Schedule(Seconds(17.0) + NanoSeconds(154800),
1688 this,
1690 // In this case, the second packet should be marked as a failure
1691 Simulator::Schedule(Seconds(17.1),
1693 this,
1694 2,
1695 6);
1696
1697 rxPowerDbm = -50;
1698 // CASE 18: send two packets with second one 50 dB higher within the 4us window
1699
1700 Simulator::Schedule(Seconds(18.0),
1702 this,
1703 rxPowerDbm);
1704 Simulator::Schedule(Seconds(18.0) + MicroSeconds(2.0),
1706 this,
1707 rxPowerDbm + 50);
1708 // The second packet should be received successfully
1709 Simulator::Schedule(Seconds(18.1),
1711 this,
1712 3,
1713 6);
1714
1715 // CASE 19: send two packets with second one 10 dB higher within the 4us window
1716
1717 Simulator::Schedule(Seconds(19.0),
1719 this,
1720 rxPowerDbm);
1721 Simulator::Schedule(Seconds(19.0) + MicroSeconds(2.0),
1723 this,
1724 rxPowerDbm + 10);
1725 // The second packet should be captured, but not decoded since SNR to low for used MCS
1726 Simulator::Schedule(Seconds(19.1),
1728 this,
1729 3,
1730 7);
1731
1732 // CASE 20: send two packets with second one 50 dB higher in the same time
1733
1734 Simulator::Schedule(Seconds(20.0),
1736 this,
1737 rxPowerDbm);
1738 Simulator::Schedule(Seconds(20.0),
1740 this,
1741 rxPowerDbm + 50);
1742 // The second packet should be received successfully, same as in CASE 13
1743 Simulator::Schedule(Seconds(20.1),
1745 this,
1746 4,
1747 7);
1748
1749 // CASE 21: send two packets with second one 10 dB higher in the same time
1750
1751 Simulator::Schedule(Seconds(21.0),
1753 this,
1754 rxPowerDbm);
1755 Simulator::Schedule(Seconds(21.0),
1757 this,
1758 rxPowerDbm + 10);
1759 // The second packet should be captured, but not decoded since SNR to low for used MCS, same as
1760 // in CASE 19
1761 Simulator::Schedule(Seconds(21.1),
1763 this,
1764 4,
1765 8);
1766
1767 Simulator::Run();
1768 Simulator::Destroy();
1769}
1770
1778{
1779 public:
1782
1783 protected:
1784 void DoSetup() override;
1785 void DoTeardown() override;
1786
1787 private:
1788 void DoRun() override;
1789
1793 void Reset();
1799 void SendPacket(double rxPowerDbm, uint32_t packetSize);
1808 RxSignalInfo rxSignalInfo,
1809 WifiTxVector txVector,
1810 std::vector<bool> statusPerMpdu);
1817
1834
1836
1841
1842 uint64_t m_uid;
1843};
1844
1846 : TestCase("Simple frame capture model test"),
1847 m_rxSuccess1000B(false),
1848 m_rxSuccess1500B(false),
1849 m_rxDropped1000B(false),
1850 m_rxDropped1500B(false),
1851 m_uid(0)
1852{
1853}
1854
1855void
1857{
1858 WifiTxVector txVector =
1859 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
1860
1861 Ptr<Packet> pkt = Create<Packet>(packetSize);
1862 WifiMacHeader hdr;
1863
1865 hdr.SetQosTid(0);
1866
1867 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
1868 Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
1869
1870 Ptr<WifiPpdu> ppdu =
1871 Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
1872
1873 Ptr<SpectrumValue> txPowerSpectrum =
1874 WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
1876 DbmToW(rxPowerDbm),
1877 GUARD_WIDTH);
1878
1879 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
1880 txParams->psd = txPowerSpectrum;
1881 txParams->txPhy = nullptr;
1882 txParams->duration = txDuration;
1883 txParams->ppdu = ppdu;
1884
1885 m_phy->StartRx(txParams);
1886}
1887
1888void
1890 RxSignalInfo rxSignalInfo,
1891 WifiTxVector txVector,
1892 std::vector<bool> statusPerMpdu)
1893{
1894 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1895 NS_ASSERT(!psdu->IsAggregate() || psdu->IsSingle());
1896 if (psdu->GetSize() == 1030)
1897 {
1898 m_rxSuccess1000B = true;
1899 }
1900 else if (psdu->GetSize() == 1530)
1901 {
1902 m_rxSuccess1500B = true;
1903 }
1904}
1905
1906void
1908{
1909 NS_LOG_FUNCTION(this << p << reason);
1910 if (p->GetSize() == 1030)
1911 {
1912 m_rxDropped1000B = true;
1913 }
1914 else if (p->GetSize() == 1530)
1915 {
1916 m_rxDropped1500B = true;
1917 }
1918}
1919
1920void
1922{
1923 m_rxSuccess1000B = false;
1924 m_rxSuccess1500B = false;
1925 m_rxDropped1000B = false;
1926 m_rxDropped1500B = false;
1927}
1928
1929void
1931{
1932 NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1000B, true, "Didn't receive 1000B packet");
1933}
1934
1935void
1937{
1938 NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1500B, true, "Didn't receive 1500B packet");
1939}
1940
1941void
1943{
1944 NS_TEST_ASSERT_MSG_EQ(m_rxDropped1000B, true, "Didn't drop 1000B packet");
1945}
1946
1947void
1949{
1950 NS_TEST_ASSERT_MSG_EQ(m_rxDropped1500B, true, "Didn't drop 1500B packet");
1951}
1952
1954{
1955 m_phy = nullptr;
1956}
1957
1958void
1960{
1961 m_phy = CreateObject<SpectrumWifiPhy>();
1963 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
1964 m_phy->SetInterferenceHelper(interferenceHelper);
1965 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
1966 m_phy->SetErrorRateModel(error);
1968
1970 m_phy->TraceConnectWithoutContext("PhyRxDrop",
1972
1973 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
1974 CreateObject<ThresholdPreambleDetectionModel>();
1975 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(2));
1976 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
1977
1978 Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
1979 frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
1980 frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
1981 m_phy->SetFrameCaptureModel(frameCaptureModel);
1982}
1983
1984void
1986{
1987 m_phy->Dispose();
1988 m_phy = nullptr;
1989}
1990
1991void
1993{
1994 RngSeedManager::SetSeed(1);
1995 RngSeedManager::SetRun(1);
1996 int64_t streamNumber = 2;
1997 double rxPowerDbm = -30;
1998 m_phy->AssignStreams(streamNumber);
1999
2000 // CASE 1: send two packets with same power within the capture window:
2001 // PHY should not switch reception because they have same power.
2002
2003 Simulator::Schedule(Seconds(1.0),
2005 this,
2006 rxPowerDbm,
2007 1000);
2008 Simulator::Schedule(Seconds(1.0) + MicroSeconds(10.0),
2010 this,
2011 rxPowerDbm,
2012 1500);
2013 Simulator::Schedule(Seconds(1.1), &TestSimpleFrameCaptureModel::Expect1500BPacketDropped, this);
2014 Simulator::Schedule(Seconds(1.2), &TestSimpleFrameCaptureModel::Reset, this);
2015
2016 // CASE 2: send two packets with second one 6 dB weaker within the capture window:
2017 // PHY should not switch reception because first one has higher power.
2018
2019 Simulator::Schedule(Seconds(2.0),
2021 this,
2022 rxPowerDbm,
2023 1000);
2024 Simulator::Schedule(Seconds(2.0) + MicroSeconds(10.0),
2026 this,
2027 rxPowerDbm - 6,
2028 1500);
2029 Simulator::Schedule(Seconds(2.1),
2031 this);
2032 Simulator::Schedule(Seconds(2.1), &TestSimpleFrameCaptureModel::Expect1500BPacketDropped, this);
2033 Simulator::Schedule(Seconds(2.2), &TestSimpleFrameCaptureModel::Reset, this);
2034
2035 // CASE 3: send two packets with second one 6 dB higher within the capture window:
2036 // PHY should switch reception because the second one has a higher power.
2037
2038 Simulator::Schedule(Seconds(3.0),
2040 this,
2041 rxPowerDbm,
2042 1000);
2043 Simulator::Schedule(Seconds(3.0) + MicroSeconds(10.0),
2045 this,
2046 rxPowerDbm + 6,
2047 1500);
2048 Simulator::Schedule(Seconds(3.1), &TestSimpleFrameCaptureModel::Expect1000BPacketDropped, this);
2049 Simulator::Schedule(Seconds(3.1),
2051 this);
2052 Simulator::Schedule(Seconds(3.2), &TestSimpleFrameCaptureModel::Reset, this);
2053
2054 // CASE 4: send two packets with second one 6 dB higher after the capture window:
2055 // PHY should not switch reception because capture window duration has elapsed when the second
2056 // packet arrives.
2057
2058 Simulator::Schedule(Seconds(4.0),
2060 this,
2061 rxPowerDbm,
2062 1000);
2063 Simulator::Schedule(Seconds(4.0) + MicroSeconds(25.0),
2065 this,
2066 rxPowerDbm + 6,
2067 1500);
2068 Simulator::Schedule(Seconds(4.1), &TestSimpleFrameCaptureModel::Expect1500BPacketDropped, this);
2069 Simulator::Schedule(Seconds(4.2), &TestSimpleFrameCaptureModel::Reset, this);
2070
2071 Simulator::Run();
2072 Simulator::Destroy();
2073}
2074
2082{
2083 public:
2085 ~TestPhyHeadersReception() override;
2086
2087 protected:
2088 void DoSetup() override;
2089 void DoTeardown() override;
2095 void SendPacket(double rxPowerDbm);
2096
2097 private:
2098 void DoRun() override;
2099
2104 void CheckPhyState(WifiPhyState expectedState);
2109 void DoCheckPhyState(WifiPhyState expectedState);
2110
2111 uint64_t m_uid;
2112};
2113
2115 : TestCase("PHY headers reception test"),
2116 m_uid(0)
2117{
2118}
2119
2120void
2122{
2123 WifiTxVector txVector =
2124 WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
2125
2126 Ptr<Packet> pkt = Create<Packet>(1000);
2127 WifiMacHeader hdr;
2128
2130 hdr.SetQosTid(0);
2131
2132 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2133 Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
2134
2135 Ptr<WifiPpdu> ppdu =
2136 Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
2137
2138 Ptr<SpectrumValue> txPowerSpectrum =
2139 WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
2141 DbmToW(rxPowerDbm),
2142 GUARD_WIDTH);
2143
2144 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
2145 txParams->psd = txPowerSpectrum;
2146 txParams->txPhy = nullptr;
2147 txParams->duration = txDuration;
2148 txParams->ppdu = ppdu;
2149
2150 m_phy->StartRx(txParams);
2151}
2152
2153void
2155{
2156 // This is needed to make sure PHY state will be checked as the last event if a state change
2157 // occured at the exact same time as the check
2158 Simulator::ScheduleNow(&TestPhyHeadersReception::DoCheckPhyState, this, expectedState);
2159}
2160
2161void
2163{
2164 WifiPhyState currentState;
2165 PointerValue ptr;
2166 m_phy->GetAttribute("State", ptr);
2167 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
2168 currentState = state->GetState();
2169 NS_LOG_FUNCTION(this << currentState);
2170 NS_TEST_ASSERT_MSG_EQ(currentState,
2171 expectedState,
2172 "PHY State " << currentState << " does not match expected state "
2173 << expectedState << " at " << Simulator::Now());
2174}
2175
2177{
2178 m_phy = nullptr;
2179}
2180
2181void
2183{
2184 m_phy = CreateObject<SpectrumWifiPhy>();
2186 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2187 m_phy->SetInterferenceHelper(interferenceHelper);
2188 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2189 m_phy->SetErrorRateModel(error);
2191}
2192
2193void
2195{
2196 m_phy->Dispose();
2197 m_phy = nullptr;
2198}
2199
2200void
2202{
2203 RngSeedManager::SetSeed(1);
2204 RngSeedManager::SetRun(1);
2205 int64_t streamNumber = 0;
2206 m_phy->AssignStreams(streamNumber);
2207
2208 // RX power > CCA-ED
2209 double rxPowerDbm = -50;
2210
2211 // CASE 1: send one packet followed by a second one with same power between the end of the 4us
2212 // preamble detection window and the start of L-SIG of the first packet: reception should be
2213 // aborted since L-SIG cannot be decoded (SNR too low).
2214
2215 Simulator::Schedule(Seconds(1.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2216 Simulator::Schedule(Seconds(1.0) + MicroSeconds(10),
2218 this,
2219 rxPowerDbm);
2220 // At 10 us, STA PHY STATE should be CCA_BUSY.
2221 Simulator::Schedule(Seconds(1.0) + MicroSeconds(10.0),
2223 this,
2225 // At 44us (end of PHY header), STA PHY STATE should not have moved to RX and be kept to
2226 // CCA_BUSY.
2227 Simulator::Schedule(Seconds(1.0) + NanoSeconds(44000),
2229 this,
2231 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8 + 10
2232 // = 162.8us.
2233 Simulator::Schedule(Seconds(1.0) + NanoSeconds(162799),
2235 this,
2237 Simulator::Schedule(Seconds(1.0) + NanoSeconds(162800),
2239 this,
2241
2242 // CASE 2: send one packet followed by a second one 3 dB weaker between the end of the 4us
2243 // preamble detection window and the start of L-SIG of the first packet: reception should not be
2244 // aborted since L-SIG can be decoded (SNR high enough).
2245
2246 Simulator::Schedule(Seconds(2.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2247 Simulator::Schedule(Seconds(2.0) + MicroSeconds(10),
2249 this,
2250 rxPowerDbm - 3);
2251 // At 10 us, STA PHY STATE should be CCA_BUSY.
2252 Simulator::Schedule(Seconds(2.0) + MicroSeconds(10.0),
2254 this,
2256 // At 44us (end of PHY header), STA PHY STATE should have moved to RX since PHY header reception
2257 // should have succeeded.
2258 Simulator::Schedule(Seconds(2.0) + NanoSeconds(43999),
2260 this,
2262 Simulator::Schedule(Seconds(2.0) + NanoSeconds(44000),
2264 this,
2266 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
2267 // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
2268 // should first be seen as CCA_BUSY for 10us.
2269 Simulator::Schedule(Seconds(2.0) + NanoSeconds(152799),
2271 this,
2273 Simulator::Schedule(Seconds(2.0) + NanoSeconds(152800),
2275 this,
2277 Simulator::Schedule(Seconds(2.0) + NanoSeconds(162799),
2279 this,
2281 Simulator::Schedule(Seconds(2.0) + NanoSeconds(162800),
2283 this,
2285
2286 // CASE 3: send one packet followed by a second one with same power between the end of L-SIG and
2287 // the start of HE-SIG of the first packet: PHY header reception should not succeed but PHY
2288 // should stay in RX state for the duration estimated from L-SIG.
2289
2290 Simulator::Schedule(Seconds(3.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2291 Simulator::Schedule(Seconds(3.0) + MicroSeconds(25),
2293 this,
2294 rxPowerDbm);
2295 // At 44us (end of PHY header), STA PHY STATE should not have moved to RX (HE-SIG failed) and be
2296 // kept to CCA_BUSY.
2297 Simulator::Schedule(Seconds(3.0) + MicroSeconds(44.0),
2299 this,
2301 // STA PHY STATE should move back to IDLE once the duration estimated from L-SIG has elapsed,
2302 // i.e. at 152.8us. However, since there is a second packet transmitted with a power above
2303 // CCA-ED (-62 dBm), PHY should first be seen as CCA_BUSY for 25us.
2304 Simulator::Schedule(Seconds(3.0) + NanoSeconds(152799),
2306 this,
2308 Simulator::Schedule(Seconds(3.0) + NanoSeconds(152800),
2310 this,
2312 Simulator::Schedule(Seconds(3.0) + NanoSeconds(177799),
2314 this,
2316 Simulator::Schedule(Seconds(3.0) + NanoSeconds(177800),
2318 this,
2320
2321 // CASE 4: send one packet followed by a second one 3 dB weaker between the end of L-SIG and the
2322 // start of HE-SIG of the first packet: PHY header reception should succeed.
2323
2324 Simulator::Schedule(Seconds(4.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2325 Simulator::Schedule(Seconds(4.0) + MicroSeconds(25),
2327 this,
2328 rxPowerDbm - 3);
2329 // At 10 us, STA PHY STATE should be CCA_BUSY.
2330 Simulator::Schedule(Seconds(4.0) + MicroSeconds(10.0),
2332 this,
2334 // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2335 // should have succeeded.
2336 Simulator::Schedule(Seconds(4.0) + NanoSeconds(43999),
2338 this,
2340 Simulator::Schedule(Seconds(4.0) + NanoSeconds(44000),
2342 this,
2344 // STA PHY STATE should move back to IDLE once the duration estimated from L-SIG has elapsed,
2345 // i.e. at 152.8us. However, since there is a second packet transmitted with a power above
2346 // CCA-ED (-62 dBm), PHY should first be seen as CCA_BUSY for 25us.
2347 Simulator::Schedule(Seconds(4.0) + NanoSeconds(152799),
2349 this,
2351 Simulator::Schedule(Seconds(4.0) + NanoSeconds(152800),
2353 this,
2355 Simulator::Schedule(Seconds(4.0) + NanoSeconds(177799),
2357 this,
2359 Simulator::Schedule(Seconds(4.0) + NanoSeconds(177800),
2361 this,
2363
2364 // RX power < CCA-ED
2365 rxPowerDbm = -70;
2366
2367 // CASE 5: send one packet followed by a second one with same power between the end of the 4us
2368 // preamble detection window and the start of L-SIG of the first packet: reception should be
2369 // aborted since L-SIG cannot be decoded (SNR too low).
2370
2371 Simulator::Schedule(Seconds(5.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2372 Simulator::Schedule(Seconds(5.0) + MicroSeconds(10),
2374 this,
2375 rxPowerDbm);
2376 // At 10 us, STA PHY STATE should be CCA_BUSY.
2377 Simulator::Schedule(Seconds(5.0) + MicroSeconds(10.0),
2379 this,
2381 // At 24us (end of L-SIG), STA PHY STATE stay CCA_BUSY because L-SIG reception failed and the
2382 // start of a valid OFDM transmission has been detected
2383 Simulator::Schedule(Seconds(5.0) + NanoSeconds(24000),
2385 this,
2387
2388 // CASE 6: send one packet followed by a second one 3 dB weaker between the end of the 4us
2389 // preamble detection window and the start of L-SIG of the first packet: reception should not be
2390 // aborted since L-SIG can be decoded (SNR high enough).
2391
2392 Simulator::Schedule(Seconds(6.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2393 Simulator::Schedule(Seconds(6.0) + MicroSeconds(10),
2395 this,
2396 rxPowerDbm - 3);
2397 // At 10 us, STA PHY STATE should be CCA_BUSY.
2398 Simulator::Schedule(Seconds(6.0) + MicroSeconds(10.0),
2400 this,
2402 // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2403 // succeeded.
2404 Simulator::Schedule(Seconds(6.0) + MicroSeconds(24.0),
2406 this,
2408 // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2409 // should have succeeded.
2410 Simulator::Schedule(Seconds(6.0) + NanoSeconds(43999),
2412 this,
2414 Simulator::Schedule(Seconds(6.0) + NanoSeconds(44000),
2416 this,
2418 // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
2419 // 152.8us.
2420 Simulator::Schedule(Seconds(6.0) + NanoSeconds(152799),
2422 this,
2424 Simulator::Schedule(Seconds(6.0) + NanoSeconds(152800),
2426 this,
2428
2429 // CASE 7: send one packet followed by a second one with same power between the end of L-SIG and
2430 // the start of HE-SIG of the first packet: PHY header reception should not succeed but PHY
2431 // should stay in RX state for the duration estimated from L-SIG.
2432
2433 Simulator::Schedule(Seconds(7.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2434 Simulator::Schedule(Seconds(7.0) + MicroSeconds(25),
2436 this,
2437 rxPowerDbm);
2438 // At 10 us, STA PHY STATE should be CCA_BUSY.
2439 Simulator::Schedule(Seconds(7.0) + MicroSeconds(10.0),
2441 this,
2443 // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2444 // succeeded.
2445 Simulator::Schedule(Seconds(7.0) + MicroSeconds(24.0),
2447 this,
2449 // At 44 us (end of HE-SIG), STA PHY STATE should be not have moved to RX since reception of
2450 // HE-SIG should have failed.
2451 Simulator::Schedule(Seconds(7.0) + MicroSeconds(44.0),
2453 this,
2455 // STA PHY STATE should keep CCA_BUSY once the duration estimated from L-SIG has elapsed, i.e.
2456 // at 152.8us.
2457 Simulator::Schedule(Seconds(7.0) + NanoSeconds(152800),
2459 this,
2461
2462 // CASE 8: send one packet followed by a second one 3 dB weaker between the end of L-SIG and the
2463 // start of HE-SIG of the first packet: PHY header reception should succeed.
2464
2465 Simulator::Schedule(Seconds(8.0), &TestPhyHeadersReception::SendPacket, this, rxPowerDbm);
2466 Simulator::Schedule(Seconds(8.0) + MicroSeconds(25),
2468 this,
2469 rxPowerDbm - 3);
2470 // At 10 us, STA PHY STATE should be CCA_BUSY.
2471 Simulator::Schedule(Seconds(8.0) + MicroSeconds(10.0),
2473 this,
2475 // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2476 // succeeded.
2477 Simulator::Schedule(Seconds(8.0) + MicroSeconds(24.0),
2479 this,
2481 // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2482 // should have succeeded.
2483 Simulator::Schedule(Seconds(8.0) + NanoSeconds(43999),
2485 this,
2487 Simulator::Schedule(Seconds(8.0) + NanoSeconds(44000),
2489 this,
2491 // STA PHY STATE should move back to CCA_BUSY once the duration estimated from L-SIG has
2492 // elapsed, i.e. at 152.8us.
2493 Simulator::Schedule(Seconds(8.0) + NanoSeconds(152799),
2495 this,
2497 Simulator::Schedule(Seconds(8.0) + NanoSeconds(152800),
2499 this,
2501
2502 Simulator::Run();
2503 Simulator::Destroy();
2504}
2505
2513{
2514 public:
2516 ~TestAmpduReception() override;
2517
2518 protected:
2519 void DoSetup() override;
2520 void DoTeardown() override;
2521
2522 private:
2523 void DoRun() override;
2524
2533 RxSignalInfo rxSignalInfo,
2534 WifiTxVector txVector,
2535 std::vector<bool> statusPerMpdu);
2540 void RxFailure(Ptr<const WifiPsdu> psdu);
2557
2561 void ResetBitmaps();
2562
2570 void SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize);
2571
2576 void CheckRxSuccessBitmapAmpdu1(uint8_t expected);
2581 void CheckRxSuccessBitmapAmpdu2(uint8_t expected);
2586 void CheckRxFailureBitmapAmpdu1(uint8_t expected);
2591 void CheckRxFailureBitmapAmpdu2(uint8_t expected);
2596 void CheckRxDroppedBitmapAmpdu1(uint8_t expected);
2601 void CheckRxDroppedBitmapAmpdu2(uint8_t expected);
2602
2607 void CheckPhyState(WifiPhyState expectedState);
2608
2610
2613
2616
2619
2620 uint64_t m_uid;
2621};
2622
2624 : TestCase("A-MPDU reception test"),
2625 m_rxSuccessBitmapAmpdu1(0),
2626 m_rxSuccessBitmapAmpdu2(0),
2627 m_rxFailureBitmapAmpdu1(0),
2628 m_rxFailureBitmapAmpdu2(0),
2629 m_rxDroppedBitmapAmpdu1(0),
2630 m_rxDroppedBitmapAmpdu2(0),
2631 m_uid(0)
2632{
2633}
2634
2636{
2637 m_phy = nullptr;
2638}
2639
2640void
2642{
2649}
2650
2651void
2653 RxSignalInfo rxSignalInfo,
2654 WifiTxVector txVector,
2655 std::vector<bool> statusPerMpdu)
2656{
2657 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
2658 if (statusPerMpdu.empty()) // wait for the whole A-MPDU
2659 {
2660 return;
2661 }
2662 NS_ABORT_MSG_IF(psdu->GetNMpdus() != statusPerMpdu.size(),
2663 "Should have one receive status per MPDU");
2664 auto rxOkForMpdu = statusPerMpdu.begin();
2665 for (auto mpdu = psdu->begin(); mpdu != psdu->end(); ++mpdu)
2666 {
2667 if (*rxOkForMpdu)
2668 {
2669 IncrementSuccessBitmap((*mpdu)->GetSize());
2670 }
2671 else
2672 {
2673 IncrementFailureBitmap((*mpdu)->GetSize());
2674 }
2675 ++rxOkForMpdu;
2676 }
2677}
2678
2679void
2681{
2682 if (size == 1030) // A-MPDU 1 - MPDU #1
2683 {
2685 }
2686 else if (size == 1130) // A-MPDU 1 - MPDU #2
2687 {
2688 m_rxSuccessBitmapAmpdu1 |= (1 << 1);
2689 }
2690 else if (size == 1230) // A-MPDU 1 - MPDU #3
2691 {
2692 m_rxSuccessBitmapAmpdu1 |= (1 << 2);
2693 }
2694 else if (size == 1330) // A-MPDU 2 - MPDU #1
2695 {
2697 }
2698 else if (size == 1430) // A-MPDU 2 - MPDU #2
2699 {
2700 m_rxSuccessBitmapAmpdu2 |= (1 << 1);
2701 }
2702 else if (size == 1530) // A-MPDU 2 - MPDU #3
2703 {
2704 m_rxSuccessBitmapAmpdu2 |= (1 << 2);
2705 }
2706}
2707
2708void
2710{
2711 NS_LOG_FUNCTION(this << *psdu);
2712 for (auto mpdu = psdu->begin(); mpdu != psdu->end(); ++mpdu)
2713 {
2714 IncrementFailureBitmap((*mpdu)->GetSize());
2715 }
2716}
2717
2718void
2720{
2721 if (size == 1030) // A-MPDU 1 - MPDU #1
2722 {
2724 }
2725 else if (size == 1130) // A-MPDU 1 - MPDU #2
2726 {
2727 m_rxFailureBitmapAmpdu1 |= (1 << 1);
2728 }
2729 else if (size == 1230) // A-MPDU 1 - MPDU #3
2730 {
2731 m_rxFailureBitmapAmpdu1 |= (1 << 2);
2732 }
2733 else if (size == 1330) // A-MPDU 2 - MPDU #1
2734 {
2736 }
2737 else if (size == 1430) // A-MPDU 2 - MPDU #2
2738 {
2739 m_rxFailureBitmapAmpdu2 |= (1 << 1);
2740 }
2741 else if (size == 1530) // A-MPDU 2 - MPDU #3
2742 {
2743 m_rxFailureBitmapAmpdu2 |= (1 << 2);
2744 }
2745}
2746
2747void
2749{
2750 NS_LOG_FUNCTION(this << p << reason);
2751 if (p->GetSize() == 1030) // A-MPDU 1 - MPDU #1
2752 {
2754 }
2755 else if (p->GetSize() == 1130) // A-MPDU 1 - MPDU #2
2756 {
2757 m_rxDroppedBitmapAmpdu1 |= (1 << 1);
2758 }
2759 else if (p->GetSize() == 1230) // A-MPDU 1 - MPDU #3
2760 {
2761 m_rxDroppedBitmapAmpdu1 |= (1 << 2);
2762 }
2763 else if (p->GetSize() == 1330) // A-MPDU 2 - MPDU #1
2764 {
2766 }
2767 else if (p->GetSize() == 1430) // A-MPDU 2 - MPDU #2
2768 {
2769 m_rxDroppedBitmapAmpdu2 |= (1 << 1);
2770 }
2771 else if (p->GetSize() == 1530) // A-MPDU 2 - MPDU #3
2772 {
2773 m_rxDroppedBitmapAmpdu2 |= (1 << 2);
2774 }
2775}
2776
2777void
2779{
2781 expected,
2782 "RX success bitmap for A-MPDU 1 is not as expected");
2783}
2784
2785void
2787{
2789 expected,
2790 "RX success bitmap for A-MPDU 2 is not as expected");
2791}
2792
2793void
2795{
2797 expected,
2798 "RX failure bitmap for A-MPDU 1 is not as expected");
2799}
2800
2801void
2803{
2805 expected,
2806 "RX failure bitmap for A-MPDU 2 is not as expected");
2807}
2808
2809void
2811{
2813 expected,
2814 "RX dropped bitmap for A-MPDU 1 is not as expected");
2815}
2816
2817void
2819{
2821 expected,
2822 "RX dropped bitmap for A-MPDU 2 is not as expected");
2823}
2824
2825void
2827{
2828 WifiPhyState currentState;
2829 PointerValue ptr;
2830 m_phy->GetAttribute("State", ptr);
2831 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
2832 currentState = state->GetState();
2833 NS_TEST_ASSERT_MSG_EQ(currentState,
2834 expectedState,
2835 "PHY State " << currentState << " does not match expected state "
2836 << expectedState << " at " << Simulator::Now());
2837}
2838
2839void
2840TestAmpduReception::SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize)
2841{
2842 WifiTxVector txVector =
2843 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, true);
2844
2845 WifiMacHeader hdr;
2847 hdr.SetQosTid(0);
2848
2849 std::vector<Ptr<WifiMpdu>> mpduList;
2850 for (size_t i = 0; i < 3; ++i)
2851 {
2852 Ptr<Packet> p = Create<Packet>(referencePacketSize + i * 100);
2853 mpduList.push_back(Create<WifiMpdu>(p, hdr));
2854 }
2855 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(mpduList);
2856
2857 Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
2858
2859 Ptr<WifiPpdu> ppdu =
2860 Create<HePpdu>(psdu, txVector, FREQUENCY, txDuration, WIFI_PHY_BAND_5GHZ, m_uid++);
2861
2862 Ptr<SpectrumValue> txPowerSpectrum =
2863 WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(FREQUENCY,
2865 DbmToW(rxPowerDbm),
2866 GUARD_WIDTH);
2867
2868 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
2869 txParams->psd = txPowerSpectrum;
2870 txParams->txPhy = nullptr;
2871 txParams->duration = txDuration;
2872 txParams->ppdu = ppdu;
2873
2874 m_phy->StartRx(txParams);
2875}
2876
2877void
2879{
2880 m_phy = CreateObject<SpectrumWifiPhy>();
2882 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2883 m_phy->SetInterferenceHelper(interferenceHelper);
2884 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2885 m_phy->SetErrorRateModel(error);
2887
2890 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2892
2893 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2894 CreateObject<ThresholdPreambleDetectionModel>();
2895 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(2));
2896 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2897
2898 Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
2899 frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
2900 frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
2901 m_phy->SetFrameCaptureModel(frameCaptureModel);
2902}
2903
2904void
2906{
2907 m_phy->Dispose();
2908 m_phy = nullptr;
2909}
2910
2911void
2913{
2914 RngSeedManager::SetSeed(1);
2915 RngSeedManager::SetRun(2);
2916 int64_t streamNumber = 1;
2917 double rxPowerDbm = -30;
2918 m_phy->AssignStreams(streamNumber);
2919
2921 // CASE 1: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
2922 // power under RX sensitivity. The second A-MPDU is received 2 microseconds after the first
2923 // A-MPDU (i.e. during preamble detection).
2925
2926 // A-MPDU 1
2927 Simulator::Schedule(Seconds(1.0),
2929 this,
2930 rxPowerDbm - 100,
2931 1000);
2932
2933 // A-MPDU 2
2934 Simulator::Schedule(Seconds(1.0) + MicroSeconds(2),
2936 this,
2937 rxPowerDbm,
2938 1300);
2939
2940 // All MPDUs of A-MPDU 1 should have been ignored.
2941 Simulator::Schedule(Seconds(1.1),
2943 this,
2944 0b00000000);
2945 Simulator::Schedule(Seconds(1.1),
2947 this,
2948 0b00000000);
2949 Simulator::Schedule(Seconds(1.1),
2951 this,
2952 0b00000000);
2953
2954 // All MPDUs of A-MPDU 2 should have been successfully received.
2955 Simulator::Schedule(Seconds(1.1),
2957 this,
2958 0b00000111);
2959 Simulator::Schedule(Seconds(1.1),
2961 this,
2962 0b00000000);
2963 Simulator::Schedule(Seconds(1.1),
2965 this,
2966 0b00000000);
2967
2968 Simulator::Schedule(Seconds(1.2), &TestAmpduReception::ResetBitmaps, this);
2969
2971 // CASE 2: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
2972 // with power under RX sensitivity. The second A-MPDU is received 2 microseconds after the first
2973 // A-MPDU (i.e. during preamble detection).
2975
2976 // A-MPDU 1
2977 Simulator::Schedule(Seconds(2.0),
2979 this,
2980 rxPowerDbm,
2981 1000);
2982
2983 // A-MPDU 2
2984 Simulator::Schedule(Seconds(2.0) + MicroSeconds(2),
2986 this,
2987 rxPowerDbm - 100,
2988 1300);
2989
2990 // All MPDUs of A-MPDU 1 should have been received.
2991 Simulator::Schedule(Seconds(2.1),
2993 this,
2994 0b00000111);
2995 Simulator::Schedule(Seconds(2.1),
2997 this,
2998 0b00000000);
2999 Simulator::Schedule(Seconds(2.1),
3001 this,
3002 0b00000000);
3003
3004 // All MPDUs of A-MPDU 2 should have been ignored.
3005 Simulator::Schedule(Seconds(2.1),
3007 this,
3008 0b00000000);
3009 Simulator::Schedule(Seconds(2.1),
3011 this,
3012 0b00000000);
3013 Simulator::Schedule(Seconds(2.1),
3015 this,
3016 0b00000000);
3017
3018 Simulator::Schedule(Seconds(2.2), &TestAmpduReception::ResetBitmaps, this);
3019
3021 // CASE 3: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3022 // power under RX sensitivity. The second A-MPDU is received 10 microseconds after the first
3023 // A-MPDU (i.e. during the frame capture window).
3025
3026 // A-MPDU 1
3027 Simulator::Schedule(Seconds(3.0),
3029 this,
3030 rxPowerDbm - 100,
3031 1000);
3032
3033 // A-MPDU 2
3034 Simulator::Schedule(Seconds(3.0) + MicroSeconds(10),
3036 this,
3037 rxPowerDbm,
3038 1300);
3039
3040 // All MPDUs of A-MPDU 1 should have been ignored.
3041 Simulator::Schedule(Seconds(3.1),
3043 this,
3044 0b00000000);
3045 Simulator::Schedule(Seconds(3.1),
3047 this,
3048 0b00000000);
3049 Simulator::Schedule(Seconds(3.1),
3051 this,
3052 0b00000000);
3053
3054 // All MPDUs of A-MPDU 2 should have been successfully received.
3055 Simulator::Schedule(Seconds(3.1),
3057 this,
3058 0b00000111);
3059 Simulator::Schedule(Seconds(3.1),
3061 this,
3062 0b00000000);
3063 Simulator::Schedule(Seconds(3.1),
3065 this,
3066 0b00000000);
3067
3068 Simulator::Schedule(Seconds(3.2), &TestAmpduReception::ResetBitmaps, this);
3069
3071 // CASE 4: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3072 // with power under RX sensitivity. The second A-MPDU is received 10 microseconds after the
3073 // first A-MPDU (i.e. during the frame capture window).
3075
3076 // A-MPDU 1
3077 Simulator::Schedule(Seconds(4.0),
3079 this,
3080 rxPowerDbm,
3081 1000);
3082
3083 // A-MPDU 2
3084 Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
3086 this,
3087 rxPowerDbm - 100,
3088 1300);
3089
3090 // All MPDUs of A-MPDU 1 should have been received.
3091 Simulator::Schedule(Seconds(4.1),
3093 this,
3094 0b00000111);
3095 Simulator::Schedule(Seconds(4.1),
3097 this,
3098 0b00000000);
3099 Simulator::Schedule(Seconds(4.1),
3101 this,
3102 0b00000000);
3103
3104 // All MPDUs of A-MPDU 2 should have been ignored.
3105 Simulator::Schedule(Seconds(4.1),
3107 this,
3108 0b00000000);
3109 Simulator::Schedule(Seconds(4.1),
3111 this,
3112 0b00000000);
3113 Simulator::Schedule(Seconds(4.1),
3115 this,
3116 0b00000000);
3117
3118 Simulator::Schedule(Seconds(4.2), &TestAmpduReception::ResetBitmaps, this);
3119
3121 // CASE 5: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3122 // power under RX sensitivity. The second A-MPDU is received 100 microseconds after the first
3123 // A-MPDU (i.e. after the frame capture window, during the payload of MPDU #1).
3125
3126 // A-MPDU 1
3127 Simulator::Schedule(Seconds(5.0),
3129 this,
3130 rxPowerDbm - 100,
3131 1000);
3132
3133 // A-MPDU 2
3134 Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
3136 this,
3137 rxPowerDbm,
3138 1300);
3139
3140 // All MPDUs of A-MPDU 1 should have been ignored.
3141 Simulator::Schedule(Seconds(5.1),
3143 this,
3144 0b00000000);
3145 Simulator::Schedule(Seconds(5.1),
3147 this,
3148 0b00000000);
3149 Simulator::Schedule(Seconds(5.1),
3151 this,
3152 0b00000000);
3153
3154 // All MPDUs of A-MPDU 2 should have been successfully received.
3155 Simulator::Schedule(Seconds(5.1),
3157 this,
3158 0b00000111);
3159 Simulator::Schedule(Seconds(5.1),
3161 this,
3162 0b00000000);
3163 Simulator::Schedule(Seconds(5.1),
3165 this,
3166 0b00000000);
3167
3168 Simulator::Schedule(Seconds(5.2), &TestAmpduReception::ResetBitmaps, this);
3169
3171 // CASE 6: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3172 // with power under RX sensitivity. The second A-MPDU is received 100 microseconds after the
3173 // first A-MPDU (i.e. after the frame capture window, during the payload of MPDU #1).
3175
3176 // A-MPDU 1
3177 Simulator::Schedule(Seconds(6.0),
3179 this,
3180 rxPowerDbm,
3181 1000);
3182
3183 // A-MPDU 2
3184 Simulator::Schedule(Seconds(6.0) + MicroSeconds(100),
3186 this,
3187 rxPowerDbm - 100,
3188 1300);
3189
3190 // All MPDUs of A-MPDU 1 should have been received.
3191 Simulator::Schedule(Seconds(6.1),
3193 this,
3194 0b00000111);
3195 Simulator::Schedule(Seconds(6.1),
3197 this,
3198 0b00000000);
3199 Simulator::Schedule(Seconds(6.1),
3201 this,
3202 0b00000000);
3203
3204 // All MPDUs of A-MPDU 2 should have been ignored.
3205 Simulator::Schedule(Seconds(6.1),
3207 this,
3208 0b00000000);
3209 Simulator::Schedule(Seconds(6.1),
3211 this,
3212 0b00000000);
3213 Simulator::Schedule(Seconds(6.1),
3215 this,
3216 0b00000000);
3217
3218 Simulator::Schedule(Seconds(6.2), &TestAmpduReception::ResetBitmaps, this);
3219
3221 // CASE 7: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3222 // power under RX sensitivity. The second A-MPDU is received during the payload of MPDU #2.
3224
3225 // A-MPDU 1
3226 Simulator::Schedule(Seconds(7.0),
3228 this,
3229 rxPowerDbm - 100,
3230 1000);
3231
3232 // A-MPDU 2
3233 Simulator::Schedule(Seconds(7.0) + NanoSeconds(1100000),
3235 this,
3236 rxPowerDbm,
3237 1300);
3238
3239 // All MPDUs of A-MPDU 1 should have been ignored.
3240 Simulator::Schedule(Seconds(7.1),
3242 this,
3243 0b00000000);
3244 Simulator::Schedule(Seconds(7.1),
3246 this,
3247 0b00000000);
3248 Simulator::Schedule(Seconds(7.1),
3250 this,
3251 0b00000000);
3252
3253 // All MPDUs of A-MPDU 2 should have been successfully received.
3254 Simulator::Schedule(Seconds(7.1),
3256 this,
3257 0b00000111);
3258 Simulator::Schedule(Seconds(7.1),
3260 this,
3261 0b00000000);
3262 Simulator::Schedule(Seconds(7.1),
3264 this,
3265 0b00000000);
3266
3267 Simulator::Schedule(Seconds(7.2), &TestAmpduReception::ResetBitmaps, this);
3268
3270 // CASE 8: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3271 // with power under RX sensitivity. The second A-MPDU is received during the payload of MPDU #2.
3273
3274 // A-MPDU 1
3275 Simulator::Schedule(Seconds(8.0),
3277 this,
3278 rxPowerDbm,
3279 1000);
3280
3281 // A-MPDU 2
3282 Simulator::Schedule(Seconds(8.0) + NanoSeconds(1100000),
3284 this,
3285 rxPowerDbm - 100,
3286 1300);
3287
3288 // All MPDUs of A-MPDU 1 should have been received.
3289 Simulator::Schedule(Seconds(8.1),
3291 this,
3292 0b00000111);
3293 Simulator::Schedule(Seconds(8.1),
3295 this,
3296 0b00000000);
3297 Simulator::Schedule(Seconds(8.1),
3299 this,
3300 0b00000000);
3301
3302 // All MPDUs of A-MPDU 2 should have been ignored.
3303 Simulator::Schedule(Seconds(8.1),
3305 this,
3306 0b00000000);
3307 Simulator::Schedule(Seconds(8.1),
3309 this,
3310 0b00000000);
3311 Simulator::Schedule(Seconds(8.1),
3313 this,
3314 0b00000000);
3315
3316 Simulator::Schedule(Seconds(8.2), &TestAmpduReception::ResetBitmaps, this);
3317
3319 // CASE 9: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power 3
3320 // dB higher. The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during
3321 // preamble detection).
3323
3324 // A-MPDU 1
3325 Simulator::Schedule(Seconds(9.0),
3327 this,
3328 rxPowerDbm,
3329 1000);
3330
3331 // A-MPDU 2
3332 Simulator::Schedule(Seconds(9.0) + MicroSeconds(2),
3334 this,
3335 rxPowerDbm + 3,
3336 1300);
3337
3338 // All MPDUs of A-MPDU 1 should have been dropped.
3339 Simulator::Schedule(Seconds(9.1),
3341 this,
3342 0b00000000);
3343 Simulator::Schedule(Seconds(9.1),
3345 this,
3346 0b00000000);
3347 Simulator::Schedule(Seconds(9.1),
3349 this,
3350 0b00000111);
3351
3352 // All MPDUs of A-MPDU 2 should have been received with errors.
3353 Simulator::Schedule(Seconds(9.1),
3355 this,
3356 0b00000000);
3357 Simulator::Schedule(Seconds(9.1),
3359 this,
3360 0b00000111);
3361 Simulator::Schedule(Seconds(9.1),
3363 this,
3364 0b00000000);
3365
3366 Simulator::Schedule(Seconds(9.2), &TestAmpduReception::ResetBitmaps, this);
3367
3369 // CASE 10: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3370 // The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during preamble
3371 // detection).
3373
3374 // A-MPDU 1
3375 Simulator::Schedule(Seconds(10.0),
3377 this,
3378 rxPowerDbm,
3379 1000);
3380
3381 // A-MPDU 2
3382 Simulator::Schedule(Seconds(10.0) + MicroSeconds(2),
3384 this,
3385 rxPowerDbm,
3386 1300);
3387
3388 // All MPDUs of A-MPDU 1 should have been dropped (preamble detection failed).
3389 Simulator::Schedule(Seconds(10.1),
3391 this,
3392 0b00000000);
3393 Simulator::Schedule(Seconds(10.1),
3395 this,
3396 0b00000000);
3397 Simulator::Schedule(Seconds(10.1),
3399 this,
3400 0b00000111);
3401
3402 // All MPDUs of A-MPDU 2 should have been dropped as well.
3403 Simulator::Schedule(Seconds(10.1),
3405 this,
3406 0b00000000);
3407 Simulator::Schedule(Seconds(10.1),
3409 this,
3410 0b00000000);
3411 Simulator::Schedule(Seconds(10.1),
3413 this,
3414 0b00000111);
3415
3416 Simulator::Schedule(Seconds(10.2), &TestAmpduReception::ResetBitmaps, this);
3417
3419 // CASE 11: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 3
3420 // dB higher. The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during
3421 // preamble detection).
3423
3424 // A-MPDU 1
3425 Simulator::Schedule(Seconds(11.0),
3427 this,
3428 rxPowerDbm + 3,
3429 1000);
3430
3431 // A-MPDU 2
3432 Simulator::Schedule(Seconds(11.0) + MicroSeconds(2),
3434 this,
3435 rxPowerDbm,
3436 1300);
3437
3438 // All MPDUs of A-MPDU 1 should have been received with errors.
3439 Simulator::Schedule(Seconds(11.1),
3441 this,
3442 0b00000000);
3443 Simulator::Schedule(Seconds(11.1),
3445 this,
3446 0b00000111);
3447 Simulator::Schedule(Seconds(11.1),
3449 this,
3450 0b00000000);
3451
3452 // All MPDUs of A-MPDU 2 should have been dropped.
3453 Simulator::Schedule(Seconds(11.1),
3455 this,
3456 0b00000000);
3457 Simulator::Schedule(Seconds(11.1),
3459 this,
3460 0b00000000);
3461 Simulator::Schedule(Seconds(11.1),
3463 this,
3464 0b00000111);
3465
3466 Simulator::Schedule(Seconds(11.2), &TestAmpduReception::ResetBitmaps, this);
3467
3469 // CASE 12: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3470 // 3 dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e.
3471 // during the frame capture window).
3473
3474 // A-MPDU 1
3475 Simulator::Schedule(Seconds(12.0),
3477 this,
3478 rxPowerDbm,
3479 1000);
3480
3481 // A-MPDU 2
3482 Simulator::Schedule(Seconds(12.0) + MicroSeconds(10),
3484 this,
3485 rxPowerDbm + 3,
3486 1300);
3487
3488 // All MPDUs of A-MPDU 1 should have been received with errors (PHY header reception failed and
3489 // thus incorrect decoding of payload).
3490 Simulator::Schedule(Seconds(12.1),
3492 this,
3493 0b00000000);
3494 Simulator::Schedule(Seconds(12.1),
3496 this,
3497 0b00000000);
3498 Simulator::Schedule(Seconds(12.1),
3500 this,
3501 0b00000111);
3502
3503 // All MPDUs of A-MPDU 2 should have been dropped (even though TX power is higher, it is not
3504 // high enough to get the PHY reception switched)
3505 Simulator::Schedule(Seconds(12.1),
3507 this,
3508 0b00000000);
3509 Simulator::Schedule(Seconds(12.1),
3511 this,
3512 0b00000000);
3513 Simulator::Schedule(Seconds(12.1),
3515 this,
3516 0b00000111);
3517
3518 Simulator::Schedule(Seconds(12.2), &TestAmpduReception::ResetBitmaps, this);
3519
3521 // CASE 13: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3522 // The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during the frame
3523 // capture window).
3525
3526 // A-MPDU 1
3527 Simulator::Schedule(Seconds(13.0),
3529 this,
3530 rxPowerDbm,
3531 1000);
3532
3533 // A-MPDU 2
3534 Simulator::Schedule(Seconds(13.0) + MicroSeconds(10),
3536 this,
3537 rxPowerDbm,
3538 1300);
3539
3540 // All MPDUs of A-MPDU 1 should have been received with errors (PHY header reception failed and
3541 // thus incorrect decoding of payload).
3542 Simulator::Schedule(Seconds(13.1),
3544 this,
3545 0b00000000);
3546 Simulator::Schedule(Seconds(13.1),
3548 this,
3549 0b00000000);
3550 Simulator::Schedule(Seconds(13.1),
3552 this,
3553 0b00000111);
3554
3555 // All MPDUs of A-MPDU 2 should have been dropped as well.
3556 Simulator::Schedule(Seconds(13.1),
3558 this,
3559 0b00000000);
3560 Simulator::Schedule(Seconds(13.1),
3562 this,
3563 0b00000000);
3564 Simulator::Schedule(Seconds(13.1),
3566 this,
3567 0b00000111);
3568
3569 Simulator::Schedule(Seconds(13.2), &TestAmpduReception::ResetBitmaps, this);
3570
3572 // CASE 14: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 3
3573 // dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during
3574 // the frame capture window).
3576
3577 // A-MPDU 1
3578 Simulator::Schedule(Seconds(14.0),
3580 this,
3581 rxPowerDbm + 3,
3582 1000);
3583
3584 // A-MPDU 2
3585 Simulator::Schedule(Seconds(14.0) + MicroSeconds(10),
3587 this,
3588 rxPowerDbm,
3589 1300);
3590
3591 // All MPDUs of A-MPDU 1 should have been received with errors.
3592 Simulator::Schedule(Seconds(14.1),
3594 this,
3595 0b00000000);
3596 Simulator::Schedule(Seconds(14.1),
3598 this,
3599 0b00000111);
3600 Simulator::Schedule(Seconds(14.1),
3602 this,
3603 0b00000000);
3604
3605 // All MPDUs of A-MPDU 2 should have been dropped.
3606 Simulator::Schedule(Seconds(14.1),
3608 this,
3609 0b00000000);
3610 Simulator::Schedule(Seconds(14.1),
3612 this,
3613 0b00000000);
3614 Simulator::Schedule(Seconds(14.1),
3616 this,
3617 0b00000111);
3618
3619 Simulator::Schedule(Seconds(14.2), &TestAmpduReception::ResetBitmaps, this);
3620
3622 // CASE 15: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3623 // 6 dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e.
3624 // during the frame capture window).
3626
3627 // A-MPDU 1
3628 Simulator::Schedule(Seconds(15.0),
3630 this,
3631 rxPowerDbm,
3632 1000);
3633
3634 // A-MPDU 2
3635 Simulator::Schedule(Seconds(15.0) + MicroSeconds(10),
3637 this,
3638 rxPowerDbm + 6,
3639 1300);
3640
3641 // All MPDUs of A-MPDU 1 should have been dropped because PHY reception switched to A-MPDU 2.
3642 Simulator::Schedule(Seconds(15.1),
3644 this,
3645 0b00000000);
3646 Simulator::Schedule(Seconds(15.1),
3648 this,
3649 0b00000000);
3650 Simulator::Schedule(Seconds(15.1),
3652 this,
3653 0b00000111);
3654
3655 // All MPDUs of A-MPDU 2 should have been successfully received
3656 Simulator::Schedule(Seconds(15.1),
3658 this,
3659 0b00000111);
3660 Simulator::Schedule(Seconds(15.1),
3662 this,
3663 0b00000000);
3664 Simulator::Schedule(Seconds(15.1),
3666 this,
3667 0b00000000);
3668
3669 Simulator::Schedule(Seconds(15.2), &TestAmpduReception::ResetBitmaps, this);
3670
3672 // CASE 16: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3673 // dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during
3674 // the frame capture window).
3676
3677 // A-MPDU 1
3678 Simulator::Schedule(Seconds(16.0),
3680 this,
3681 rxPowerDbm + 6,
3682 1000);
3683
3684 // A-MPDU 2
3685 Simulator::Schedule(Seconds(16.0) + MicroSeconds(10),
3687 this,
3688 rxPowerDbm,
3689 1300);
3690
3691 // All MPDUs of A-MPDU 1 should have been successfully received.
3692 Simulator::Schedule(Seconds(16.1),
3694 this,
3695 0b00000111);
3696 Simulator::Schedule(Seconds(16.1),
3698 this,
3699 0b00000000);
3700 Simulator::Schedule(Seconds(16.1),
3702 this,
3703 0b00000000);
3704
3705 // All MPDUs of A-MPDU 2 should have been dropped.
3706 Simulator::Schedule(Seconds(16.1),
3708 this,
3709 0b00000000);
3710 Simulator::Schedule(Seconds(16.1),
3712 this,
3713 0b00000000);
3714 Simulator::Schedule(Seconds(16.1),
3716 this,
3717 0b00000111);
3718
3719 Simulator::Schedule(Seconds(16.2), &TestAmpduReception::ResetBitmaps, this);
3720
3722 // CASE 17: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3723 // 6 dB higher. The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after
3724 // the frame capture window, but still during PHY header).
3726
3727 // A-MPDU 1
3728 Simulator::Schedule(Seconds(17.0),
3730 this,
3731 rxPowerDbm,
3732 1000);
3733
3734 // A-MPDU 2
3735 Simulator::Schedule(Seconds(17.0) + MicroSeconds(25),
3737 this,
3738 rxPowerDbm + 6,
3739 1300);
3740
3741 // All MPDUs of A-MPDU 1 should have been received with errors.
3742 Simulator::Schedule(Seconds(17.1),
3744 this,
3745 0b00000000);
3746 Simulator::Schedule(Seconds(17.1),
3748 this,
3749 0b00000000);
3750 Simulator::Schedule(Seconds(17.1),
3752 this,
3753 0b00000111);
3754
3755 // All MPDUs of A-MPDU 2 should have been dropped (no reception switch, MPDUs dropped because
3756 // PHY is already in RX state).
3757 Simulator::Schedule(Seconds(17.1),
3759 this,
3760 0b00000000);
3761 Simulator::Schedule(Seconds(17.1),
3763 this,
3764 0b00000000);
3765 Simulator::Schedule(Seconds(17.1),
3767 this,
3768 0b00000111);
3769
3770 Simulator::Schedule(Seconds(17.2), &TestAmpduReception::ResetBitmaps, this);
3771
3773 // CASE 18: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3774 // dB higher. The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after
3775 // the frame capture window, but still during PHY header).
3777
3778 // A-MPDU 1
3779 Simulator::Schedule(Seconds(18.0),
3781 this,
3782 rxPowerDbm + 6,
3783 1000);
3784
3785 // A-MPDU 2
3786 Simulator::Schedule(Seconds(18.0) + MicroSeconds(25),
3788 this,
3789 rxPowerDbm,
3790 1300);
3791
3792 // All MPDUs of A-MPDU 1 should have been successfully received.
3793 Simulator::Schedule(Seconds(18.1),
3795 this,
3796 0b00000111);
3797 Simulator::Schedule(Seconds(18.1),
3799 this,
3800 0b00000000);
3801 Simulator::Schedule(Seconds(18.1),
3803 this,
3804 0b00000000);
3805
3806 // All MPDUs of A-MPDU 2 should have been dropped.
3807 Simulator::Schedule(Seconds(18.1),
3809 this,
3810 0b00000000);
3811 Simulator::Schedule(Seconds(18.1),
3813 this,
3814 0b00000000);
3815 Simulator::Schedule(Seconds(18.1),
3817 this,
3818 0b00000111);
3819
3820 Simulator::Schedule(Seconds(18.2), &TestAmpduReception::ResetBitmaps, this);
3821
3823 // CASE 19: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3824 // The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after the frame
3825 // capture window, but still during PHY header).
3827
3828 // A-MPDU 1
3829 Simulator::Schedule(Seconds(19.0),
3831 this,
3832 rxPowerDbm,
3833 1000);
3834
3835 // A-MPDU 2
3836 Simulator::Schedule(Seconds(19.0) + MicroSeconds(25),
3838 this,
3839 rxPowerDbm,
3840 1300);
3841
3842 // All MPDUs of A-MPDU 1 should have been received with errors.
3843 Simulator::Schedule(Seconds(19.1),
3845 this,
3846 0b00000000);
3847 Simulator::Schedule(Seconds(19.1),
3849 this,
3850 0b00000000);
3851 Simulator::Schedule(Seconds(19.1),
3853 this,
3854 0b00000111);
3855
3856 // All MPDUs of A-MPDU 2 should have been dropped.
3857 Simulator::Schedule(Seconds(19.1),
3859 this,
3860 0b00000000);
3861 Simulator::Schedule(Seconds(19.1),
3863 this,
3864 0b00000000);
3865 Simulator::Schedule(Seconds(19.1),
3867 this,
3868 0b00000111);
3869
3870 Simulator::Schedule(Seconds(19.2), &TestAmpduReception::ResetBitmaps, this);
3871
3873 // CASE 20: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3874 // 6 dB higher. The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e.
3875 // during the payload of MPDU #1).
3877
3878 // A-MPDU 1
3879 Simulator::Schedule(Seconds(20.0),
3881 this,
3882 rxPowerDbm,
3883 1000);
3884
3885 // A-MPDU 2
3886 Simulator::Schedule(Seconds(20.0) + MicroSeconds(100),
3888 this,
3889 rxPowerDbm + 6,
3890 1300);
3891
3892 // All MPDUs of A-MPDU 1 should have been received with errors.
3893 Simulator::Schedule(Seconds(20.1),
3895 this,
3896 0b00000000);
3897 Simulator::Schedule(Seconds(20.1),
3899 this,
3900 0b00000111);
3901 Simulator::Schedule(Seconds(20.1),
3903 this,
3904 0b00000000);
3905
3906 // All MPDUs of A-MPDU 2 should have been dropped (no reception switch, MPDUs dropped because
3907 // PHY is already in RX state).
3908 Simulator::Schedule(Seconds(20.1),
3910 this,
3911 0b00000000);
3912 Simulator::Schedule(Seconds(20.1),
3914 this,
3915 0b00000000);
3916 Simulator::Schedule(Seconds(20.1),
3918 this,
3919 0b00000111);
3920
3921 Simulator::Schedule(Seconds(20.2), &TestAmpduReception::ResetBitmaps, this);
3922
3924 // CASE 21: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3925 // dB higher. The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e. during
3926 // the payload of MPDU #1).
3928
3929 // A-MPDU 1
3930 Simulator::Schedule(Seconds(21.0),
3932 this,
3933 rxPowerDbm + 6,
3934 1000);
3935
3936 // A-MPDU 2
3937 Simulator::Schedule(Seconds(21.0) + MicroSeconds(100),
3939 this,
3940 rxPowerDbm,
3941 1300);
3942
3943 // All MPDUs of A-MPDU 1 should have been successfully received.
3944 Simulator::Schedule(Seconds(21.1),
3946 this,
3947 0b00000111);
3948 Simulator::Schedule(Seconds(21.1),
3950 this,
3951 0b00000000);
3952 Simulator::Schedule(Seconds(21.1),
3954 this,
3955 0b00000000);
3956
3957 // All MPDUs of A-MPDU 2 should have been dropped.
3958 Simulator::Schedule(Seconds(21.1),
3960 this,
3961 0b00000000);
3962 Simulator::Schedule(Seconds(21.1),
3964 this,
3965 0b00000000);
3966 Simulator::Schedule(Seconds(21.1),
3968 this,
3969 0b00000111);
3970
3971 Simulator::Schedule(Seconds(21.2), &TestAmpduReception::ResetBitmaps, this);
3972
3974 // CASE 22: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3975 // The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e. during the
3976 // payload of MPDU #1).
3978
3979 // A-MPDU 1
3980 Simulator::Schedule(Seconds(22.0),
3982 this,
3983 rxPowerDbm,
3984 1000);
3985
3986 // A-MPDU 2
3987 Simulator::Schedule(Seconds(22.0) + MicroSeconds(100),
3989 this,
3990 rxPowerDbm,
3991 1300);
3992
3993 // All MPDUs of A-MPDU 1 should have been received with errors.
3994 Simulator::Schedule(Seconds(22.1),
3996 this,
3997 0b00000000);
3998 Simulator::Schedule(Seconds(22.1),
4000 this,
4001 0b00000111);
4002 Simulator::Schedule(Seconds(22.1),
4004 this,
4005 0b00000000);
4006
4007 // All MPDUs of A-MPDU 2 should have been dropped.
4008 Simulator::Schedule(Seconds(22.1),
4010 this,
4011 0b00000000);
4012 Simulator::Schedule(Seconds(22.1),
4014 this,
4015 0b00000000);
4016 Simulator::Schedule(Seconds(22.1),
4018 this,
4019 0b00000111);
4020
4021 Simulator::Schedule(Seconds(22.2), &TestAmpduReception::ResetBitmaps, this);
4022
4024 // CASE 23: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
4025 // The second A-MPDU is received during the payload of MPDU #2.
4027
4028 // A-MPDU 1
4029 Simulator::Schedule(Seconds(23.0),
4031 this,
4032 rxPowerDbm,
4033 1000);
4034
4035 // A-MPDU 2
4036 Simulator::Schedule(Seconds(23.0) + NanoSeconds(1100000),
4038 this,
4039 rxPowerDbm,
4040 1300);
4041
4042 // The first MPDU of A-MPDU 1 should have been successfully received (no interference).
4043 // The two other MPDUs failed due to interference and are marked as failure (and dropped).
4044 Simulator::Schedule(Seconds(23.1),
4046 this,
4047 0b00000001);
4048 Simulator::Schedule(Seconds(23.1),
4050 this,
4051 0b00000110);
4052 Simulator::Schedule(Seconds(23.1),
4054 this,
4055 0b00000000);
4056
4057 // The two first MPDUs of A-MPDU 2 are dropped because PHY is already in RX state (receiving
4058 // A-MPDU 1). The last MPDU of A-MPDU 2 is interference free (A-MPDU 1 transmission is finished)
4059 // but is dropped because its PHY preamble and header were not received.
4060 Simulator::Schedule(Seconds(23.1),
4062 this,
4063 0b00000000);
4064 Simulator::Schedule(Seconds(23.1),
4066 this,
4067 0b00000000);
4068 Simulator::Schedule(Seconds(23.1),
4070 this,
4071 0b00000111);
4072
4073 Simulator::Schedule(Seconds(23.2), &TestAmpduReception::ResetBitmaps, this);
4074
4075 Simulator::Run();
4076 Simulator::Destroy();
4077}
4078
4100{
4101 public:
4107
4114 void Dropped(std::string context, Ptr<const Packet> packet, WifiPhyRxfailureReason reason);
4118 void CheckResults();
4119
4120 private:
4121 void DoRun() override;
4122 uint16_t m_dropped;
4123};
4124
4126 : TestCase("Check correct behavior when a STA is receiving a transmission using an unsupported "
4127 "modulation"),
4128 m_dropped(0)
4129{
4130}
4131
4133{
4134}
4135
4136void
4138 Ptr<const Packet> packet,
4140{
4141 // Print if the test is executed through test-runner
4142 if (reason == RXING)
4143 {
4144 std::cout << "Dropped a packet because already receiving" << std::endl;
4145 m_dropped++;
4146 }
4147}
4148
4149void
4151{
4152 uint16_t m_nStations = 2;
4153 NetDeviceContainer m_staDevices;
4154 NetDeviceContainer m_apDevices;
4155
4156 // RngSeedManager::SetSeed (1);
4157 // RngSeedManager::SetRun (40);
4158 int64_t streamNumber = 100;
4159
4161 wifiApNode.Create(1);
4162
4164 wifiStaNodes.Create(m_nStations);
4165
4166 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
4167 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
4168 spectrumChannel->AddPropagationLossModel(lossModel);
4170 CreateObject<ConstantSpeedPropagationDelayModel>();
4171 spectrumChannel->SetPropagationDelayModel(delayModel);
4172
4174 phy.SetChannel(spectrumChannel);
4175
4176 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue(65535));
4177
4179 wifi.SetRemoteStationManager("ns3::IdealWifiManager");
4180
4182 mac.SetType("ns3::StaWifiMac",
4183 "QosSupported",
4184 BooleanValue(true),
4185 "Ssid",
4186 SsidValue(Ssid("non-existent-ssid")));
4187
4188 wifi.SetStandard(WIFI_STANDARD_80211ax);
4189 m_staDevices.Add(wifi.Install(phy, mac, wifiStaNodes.Get(0)));
4190 wifi.SetStandard(WIFI_STANDARD_80211ac);
4191 m_staDevices.Add(wifi.Install(phy, mac, wifiStaNodes.Get(1)));
4192
4193 wifi.SetStandard(WIFI_STANDARD_80211ax);
4194 mac.SetType("ns3::ApWifiMac",
4195 "QosSupported",
4196 BooleanValue(true),
4197 "Ssid",
4198 SsidValue(Ssid("wifi-backoff-ssid")),
4199 "BeaconInterval",
4200 TimeValue(MicroSeconds(102400)),
4201 "EnableBeaconJitter",
4202 BooleanValue(false));
4203
4204 m_apDevices = wifi.Install(phy, mac, wifiApNode);
4205
4206 // schedule association requests at different times
4207 Time init = MilliSeconds(100);
4209
4210 for (uint16_t i = 0; i < m_nStations; i++)
4211 {
4212 dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
4213 Simulator::Schedule(init + i * MicroSeconds(102400),
4214 &WifiMac::SetSsid,
4215 dev->GetMac(),
4216 Ssid("wifi-backoff-ssid"));
4217 }
4218
4219 // Assign fixed streams to random variables in use
4220 wifi.AssignStreams(m_apDevices, streamNumber);
4221
4223 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
4224
4225 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
4226 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
4227 positionAlloc->Add(Vector(0.0, 1.0, 0.0));
4228 positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
4229 mobility.SetPositionAllocator(positionAlloc);
4230
4231 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
4232 mobility.Install(wifiApNode);
4233 mobility.Install(wifiStaNodes);
4234
4235 // set the TXOP limit on BE AC
4236 dev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
4237 PointerValue ptr;
4238 dev->GetMac()->GetAttribute("BE_Txop", ptr);
4239
4240 PacketSocketHelper packetSocket;
4241 packetSocket.Install(wifiApNode);
4242 packetSocket.Install(wifiStaNodes);
4243
4244 // UL Traffic
4245 for (uint16_t i = 0; i < m_nStations; i++)
4246 {
4247 PacketSocketAddress socket;
4248 socket.SetSingleDevice(m_staDevices.Get(0)->GetIfIndex());
4249 socket.SetPhysicalAddress(m_apDevices.Get(0)->GetAddress());
4250 socket.SetProtocol(1);
4251 Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
4252 client->SetAttribute("PacketSize", UintegerValue(1500));
4253 client->SetAttribute("MaxPackets", UintegerValue(200));
4254 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
4255 client->SetRemote(socket);
4256 wifiStaNodes.Get(i)->AddApplication(client);
4257 client->SetStartTime(MicroSeconds(400000));
4258 client->SetStopTime(Seconds(1.0));
4259 Ptr<PacketSocketClient> legacyStaClient = CreateObject<PacketSocketClient>();
4260 legacyStaClient->SetAttribute("PacketSize", UintegerValue(1500));
4261 legacyStaClient->SetAttribute("MaxPackets", UintegerValue(200));
4262 legacyStaClient->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
4263 legacyStaClient->SetRemote(socket);
4264 wifiStaNodes.Get(i)->AddApplication(legacyStaClient);
4265 legacyStaClient->SetStartTime(MicroSeconds(400000));
4266 legacyStaClient->SetStopTime(Seconds(1.0));
4267 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
4268 server->SetLocal(socket);
4269 wifiApNode.Get(0)->AddApplication(server);
4270 server->SetStartTime(Seconds(0.0));
4271 server->SetStopTime(Seconds(1.0));
4272 }
4273
4274 // Trace dropped packets
4275 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxDrop",
4277
4278 Simulator::Stop(Seconds(1));
4279 Simulator::Run();
4280
4281 CheckResults();
4282
4283 Simulator::Destroy();
4284}
4285
4286void
4288{
4289 NS_TEST_EXPECT_MSG_EQ(m_dropped, 0, "Dropped some packets unexpectedly");
4290}
4291
4299{
4300 public:
4302};
4303
4305 : TestSuite("wifi-phy-reception", UNIT)
4306{
4309 AddTestCase(new TestSimpleFrameCaptureModel, TestCase::QUICK);
4310 AddTestCase(new TestPhyHeadersReception, TestCase::QUICK);
4311 AddTestCase(new TestAmpduReception, TestCase::QUICK);
4312 AddTestCase(new TestUnsupportedModulationReception(), TestCase::QUICK);
4313}
4314
A-MPDU reception test.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
RX success function.
void IncrementSuccessBitmap(uint32_t size)
Increment reception success bitmap.
uint8_t m_rxDroppedBitmapAmpdu2
bitmap of dropped MPDUs in A-MPDU #2
void CheckRxSuccessBitmapAmpdu2(uint8_t expected)
Check the RX success bitmap for A-MPDU 2.
void DoRun() override
Implementation to actually run this TestCase.
void CheckRxDroppedBitmapAmpdu1(uint8_t expected)
Check the RX dropped bitmap for A-MPDU 1.
uint8_t m_rxSuccessBitmapAmpdu1
bitmap of successfully received MPDUs in A-MPDU #1
uint8_t m_rxFailureBitmapAmpdu1
bitmap of unsuccessfully received MPDUs in A-MPDU #1
uint8_t m_rxFailureBitmapAmpdu2
bitmap of unsuccessfully received MPDUs in A-MPDU #2
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize)
Send A-MPDU with 3 MPDUs of different size (i-th MSDU will have 100 bytes more than (i-1)-th).
void RxFailure(Ptr< const WifiPsdu > psdu)
RX failure function.
void 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.
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 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:369
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:298
void Dispose()
Dispose of this Object.
Definition: object.cc:219
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:205
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:1425
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:325
Implements the IEEE 802.11 MAC header.
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
create MAC layers for a ns3::WifiNetDevice.
Ptr< WifiMac > GetMac() const
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:606
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:614
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:423
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:895
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1422
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:1004
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:950
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:634
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:417
void SetFrameCaptureModel(const Ptr< FrameCaptureModel > frameCaptureModel)
Sets the frame capture model.
Definition: wifi-phy.cc:628
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:869
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:2124
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:335
std::vector< Ptr< WifiMpdu > >::const_iterator begin() const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:323
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:263
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:317
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:1362
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1374
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ WIFI_PREAMBLE_HE_SU
@ 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:691
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
@ WIFI_MAC_QOSDATA
mac
Definition: third.py:85
wifi
Definition: third.py:88
wifiApNode
Definition: third.py:79
mobility
Definition: third.py:96
wifiStaNodes
Definition: third.py:77
phy
Definition: third.py:82
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:70
static const uint8_t CHANNEL_NUMBER
static const uint16_t GUARD_WIDTH
static const uint16_t CHANNEL_WIDTH
static WifiPhyReceptionTestSuite wifiPhyReceptionTestSuite
the test suite
static const uint32_t FREQUENCY
WifiPhyState
The state of the PHY layer.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ RX
The PHY layer is receiving a packet.
@ IDLE
The PHY layer is IDLE.
static const uint32_t packetSize
Packet size generated at the AP.