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