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 txParams->txWidth = CHANNEL_WIDTH;
149
150 m_phy->StartRx(txParams, nullptr);
151}
152
153void
155{
156 // This is needed to make sure PHY state will be checked as the last event if a state change
157 // occurred at the exact same time as the check
159}
160
161void
163{
164 WifiPhyState currentState;
165 PointerValue ptr;
166 m_phy->GetAttribute("State", ptr);
167 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
168 currentState = state->GetState();
169 NS_LOG_FUNCTION(this << currentState);
170 NS_TEST_ASSERT_MSG_EQ(currentState,
171 expectedState,
172 "PHY State " << currentState << " does not match expected state "
173 << expectedState << " at " << Simulator::Now());
174}
175
176void
178{
179 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
180 Ptr<Node> node = CreateObject<Node>();
181 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
182 m_phy = CreateObject<SpectrumWifiPhy>();
183 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
184 m_phy->SetInterferenceHelper(interferenceHelper);
185 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
186 m_phy->SetErrorRateModel(error);
187 m_phy->SetDevice(dev);
188 m_phy->AddChannel(spectrumChannel);
191 dev->SetPhy(m_phy);
192 node->AddDevice(dev);
193}
194
195void
197{
198 m_phy->Dispose();
199 m_phy = nullptr;
200}
201
209{
210 public:
212
213 protected:
214 void DoSetup() override;
215
224 RxSignalInfo rxSignalInfo,
225 WifiTxVector txVector,
226 std::vector<bool> statusPerMpdu);
234
235 private:
236 void DoRun() override;
237
243 void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
244};
245
249 "Threshold preamble detection model test when no frame capture model is applied")
250{
251}
252
253void
255 uint32_t expectedFailureCount)
256{
258 expectedSuccessCount,
259 "Didn't receive right number of successful packets");
261 expectedFailureCount,
262 "Didn't receive right number of unsuccessful packets");
263}
264
265void
267 RxSignalInfo rxSignalInfo,
268 WifiTxVector txVector,
269 std::vector<bool> statusPerMpdu)
270{
271 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
273}
274
275void
277{
278 NS_LOG_FUNCTION(this << *psdu);
280}
281
282void
284{
286
291
292 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
293 CreateObject<ThresholdPreambleDetectionModel>();
294 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
295 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
296 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
297}
298
299void
301{
304 int64_t streamNumber = 0;
305 m_phy->AssignStreams(streamNumber);
306
307 // RX power > CCA-ED > CCA-PD
308 double rxPowerDbm = -50;
309
310 // CASE 1: send one packet and check PHY state:
311 // All reception stages should succeed and PHY state should be RX for the duration of the packet
312 // minus the time to detect the preamble, otherwise it should be IDLE.
313
316 this,
317 rxPowerDbm,
318 1000,
319 7);
320 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
321 // CCA_BUSY
324 this,
325 WifiPhyState::IDLE);
328 this,
329 WifiPhyState::CCA_BUSY);
330 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
331 // CCA_BUSY to RX
334 this,
335 WifiPhyState::CCA_BUSY);
338 this,
339 WifiPhyState::RX);
340 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
343 this,
344 WifiPhyState::RX);
347 this,
348 WifiPhyState::IDLE);
349 // Packet should have been successfully received
352 this,
353 1,
354 0);
355
356 // CASE 2: send two packets with same power within the 4us window and check PHY state:
357 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
358 // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
359 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
360 // time to detect the preamble.
361
364 this,
365 rxPowerDbm,
366 1000,
367 7);
370 this,
371 rxPowerDbm,
372 1000,
373 7);
374 // At 4us, no preamble is successfully detected and STA PHY STATE should move from IDLE to
375 // CCA_BUSY
378 this,
379 WifiPhyState::IDLE);
382 this,
383 WifiPhyState::CCA_BUSY);
384 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
385 // = 154.8us
388 this,
389 WifiPhyState::CCA_BUSY);
392 this,
393 WifiPhyState::IDLE);
394 // No more packet should have been successfully received, and since preamble detection did not
395 // pass, the packet should not have been counted as a failure
398 this,
399 1,
400 0);
401
402 // CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY
403 // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
404 // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
405 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
406 // time to detect the preamble.
407
410 this,
411 rxPowerDbm,
412 1000,
413 7);
416 this,
417 rxPowerDbm - 3,
418 1000,
419 7);
420 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
421 // CCA_BUSY
424 this,
425 WifiPhyState::IDLE);
428 this,
429 WifiPhyState::CCA_BUSY);
430 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
431 // = 154.8us
434 this,
435 WifiPhyState::CCA_BUSY);
438 this,
439 WifiPhyState::IDLE);
440 // No more packet should have been successfully received, and since preamble detection did not
441 // pass the packet should not have been counted as a failure
444 this,
445 1,
446 0);
447
448 // CASE 4: send two packets with second one 6 dB weaker within the 4us window and check PHY
449 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
450 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
451 // decode the modulation).
452
455 this,
456 rxPowerDbm,
457 1000,
458 7);
461 this,
462 rxPowerDbm - 6,
463 1000,
464 7);
465 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
466 // CCA_BUSY
469 this,
470 WifiPhyState::IDLE);
473 this,
474 WifiPhyState::CCA_BUSY);
475 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
476 // CCA_BUSY to RX
479 this,
480 WifiPhyState::CCA_BUSY);
483 this,
484 WifiPhyState::RX);
485 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
486 // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
487 // should first be seen as CCA_BUSY for 2us.
490 this,
491 WifiPhyState::RX);
494 this,
495 WifiPhyState::CCA_BUSY);
498 this,
499 WifiPhyState::CCA_BUSY);
502 this,
503 WifiPhyState::IDLE);
504 // In this case, the first packet should be marked as a failure
507 this,
508 1,
509 1);
510
511 // CASE 5: send two packets with second one 3 dB higher within the 4us window and check PHY
512 // state: PHY preamble detection should fail because SNR is too low (around -3 dB, which is
513 // lower than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is
514 // above CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus
515 // the time to detect the preamble.
516
519 this,
520 rxPowerDbm,
521 1000,
522 7);
525 this,
526 rxPowerDbm + 3,
527 1000,
528 7);
529 // At 6us (hence 4us after the last signal is received), no preamble is successfully detected,
530 // hence STA PHY STATE should move from IDLE to CCA_BUSY
533 this,
534 WifiPhyState::IDLE);
537 this,
538 WifiPhyState::CCA_BUSY);
539 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
540 // = 154.8us
543 this,
544 WifiPhyState::CCA_BUSY);
547 this,
548 WifiPhyState::IDLE);
549 // No more packet should have been successfully received, and since preamble detection did not
550 // pass the packet should not have been counted as a failure
553 this,
554 1,
555 1);
556
557 // CCA-PD < RX power < CCA-ED
558 rxPowerDbm = -70;
559
560 // CASE 6: send one packet and check PHY state:
561 // All reception stages should succeed and PHY state should be RX for the duration of the packet
562 // minus the time to detect the preamble, otherwise it should be IDLE.
563
566 this,
567 rxPowerDbm,
568 1000,
569 7);
570 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
571 // CCA_BUSY
574 this,
575 WifiPhyState::IDLE);
578 this,
579 WifiPhyState::CCA_BUSY);
580 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
581 // CCA_BUSY to RX
584 this,
585 WifiPhyState::CCA_BUSY);
588 this,
589 WifiPhyState::RX);
590 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
593 this,
594 WifiPhyState::RX);
597 this,
598 WifiPhyState::IDLE);
599 // Packet should have been successfully received
602 this,
603 2,
604 1);
605
606 // CASE 7: send two packets with same power within the 4us window and check PHY state:
607 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
608 // the threshold of 4 dB), and PHY state should be CCA_BUSY since it should detect the start of
609 // a valid OFDM transmission at a receive level greater than or equal to the minimum modulation
610 // and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
611
614 this,
615 rxPowerDbm,
616 1000,
617 7);
620 this,
621 rxPowerDbm,
622 1000,
623 7);
624 // At 4us, STA PHY STATE should stay IDLE
627 this,
628 WifiPhyState::CCA_BUSY);
629 // No more packet should have been successfully received, and since preamble detection did not
630 // pass the packet should not have been counted as a failure
633 this,
634 2,
635 1);
636
637 // CASE 8: send two packets with second one 3 dB weaker within the 4us window and check PHY
638 // state: PHY preamble detection should fail PHY preamble detection should fail because SNR is
639 // too low (around 3 dB, which is lower than the threshold of 4 dB), and PHY state should be
640 // CCA_BUSY since it should detect the start of a valid OFDM transmission at a receive level
641 // greater than or equal to the minimum modulation and coding rate sensitivity (–82 dBm for 20
642 // MHz channel spacing).
643
646 this,
647 rxPowerDbm,
648 1000,
649 7);
652 this,
653 rxPowerDbm - 3,
654 1000,
655 7);
656 // At 4us, STA PHY STATE should stay IDLE
659 this,
660 WifiPhyState::CCA_BUSY);
661 // No more packet should have been successfully received, and since preamble detection did not
662 // pass the packet should not have been counted as a failure
665 this,
666 2,
667 1);
668
669 // CASE 9: send two packets with second one 6 dB weaker within the 4us window and check PHY
670 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
671 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
672 // decode the modulation).
673
676 this,
677 rxPowerDbm,
678 1000,
679 7);
682 this,
683 rxPowerDbm - 6,
684 1000,
685 7);
686 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
687 // CCA_BUSY
690 this,
691 WifiPhyState::IDLE);
694 this,
695 WifiPhyState::CCA_BUSY);
696 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
697 // CCA_BUSY to RX
700 this,
701 WifiPhyState::CCA_BUSY);
704 this,
705 WifiPhyState::RX);
706 // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
707 // 152.8us.
710 this,
711 WifiPhyState::RX);
714 this,
715 WifiPhyState::CCA_BUSY);
716 // In this case, the first packet should be marked as a failure
719 this,
720 2,
721 2);
722
723 // CASE 10: send two packets with second one 3 dB higher within the 4us window and check PHY
724 // state: PHY preamble detection should fail because SNR is too low (around -3 dB, which is
725 // lower than the threshold of 4 dB), and PHY state should stay IDLE since the total energy is
726 // below CCA-ED (-62 dBm).
727
730 this,
731 rxPowerDbm,
732 1000,
733 7);
736 this,
737 rxPowerDbm + 3,
738 1000,
739 7);
740 // At 4us, STA PHY STATE should stay IDLE
743 this,
744 WifiPhyState::IDLE);
745 // No more packet should have been successfully received, and since preamble detection did not
746 // pass the packet should not have been counted as a failure
749 this,
750 2,
751 2);
752
753 // CASE 11: send one packet with a power slightly above the minimum RSSI needed for the preamble
754 // detection (-82 dBm) and check PHY state: preamble detection should succeed and PHY state
755 // should move to RX.
756
757 rxPowerDbm = -81;
758
761 this,
762 rxPowerDbm,
763 1000,
764 7);
765 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
766 // CCA_BUSY
769 this,
770 WifiPhyState::IDLE);
773 this,
774 WifiPhyState::CCA_BUSY);
775 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
776 // CCA_BUSY to RX
779 this,
780 WifiPhyState::CCA_BUSY);
783 this,
784 WifiPhyState::RX);
785 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
788 this,
789 WifiPhyState::RX);
792 this,
793 WifiPhyState::IDLE);
794
795 // RX power < CCA-PD < CCA-ED
796 rxPowerDbm = -83;
797
798 // CASE 12: send one packet with a power slightly below the minimum RSSI needed for the preamble
799 // detection (-82 dBm) and check PHY state: preamble detection should fail and PHY should be
800 // kept in IDLE state.
801
804 this,
805 rxPowerDbm,
806 1000,
807 7);
808 // At 4us, STA PHY state should be IDLE
811 this,
812 WifiPhyState::IDLE);
813
816}
817
825{
826 public:
828
829 protected:
830 void DoSetup() override;
831
840 RxSignalInfo rxSignalInfo,
841 WifiTxVector txVector,
842 std::vector<bool> statusPerMpdu);
850
851 private:
852 void DoRun() override;
853
859 void CheckRxPacketCount(uint32_t expectedSuccessCount, uint32_t expectedFailureCount);
860};
861
864 "Threshold preamble detection model test when simple frame capture model is applied")
865{
866}
867
868void
870 uint32_t expectedFailureCount)
871{
873 expectedSuccessCount,
874 "Didn't receive right number of successful packets");
876 expectedFailureCount,
877 "Didn't receive right number of unsuccessful packets");
878}
879
880void
882 RxSignalInfo rxSignalInfo,
883 WifiTxVector txVector,
884 std::vector<bool> statusPerMpdu)
885{
886 NS_LOG_FUNCTION(this << *psdu << txVector);
888}
889
890void
892{
893 NS_LOG_FUNCTION(this << *psdu);
895}
896
897void
899{
901
906
907 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
908 CreateObject<ThresholdPreambleDetectionModel>();
909 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
910 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
911 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
912
913 Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
914 frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
915 frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
916 m_phy->SetFrameCaptureModel(frameCaptureModel);
917}
918
919void
921{
924 int64_t streamNumber = 1;
925 m_phy->AssignStreams(streamNumber);
926
927 // RX power > CCA-ED > CCA-PD
928 double rxPowerDbm = -50;
929
930 // CASE 1: send one packet and check PHY state:
931 // All reception stages should succeed and PHY state should be RX for the duration of the packet
932 // minus the time to detect the preamble, otherwise it should be IDLE.
933
936 this,
937 rxPowerDbm,
938 1000,
939 7);
940 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
941 // CCA_BUSY
944 this,
945 WifiPhyState::IDLE);
948 this,
949 WifiPhyState::CCA_BUSY);
950 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
951 // CCA_BUSY to RX
954 this,
955 WifiPhyState::CCA_BUSY);
958 this,
959 WifiPhyState::RX);
960 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
963 this,
964 WifiPhyState::RX);
967 this,
968 WifiPhyState::IDLE);
969 // Packet should have been successfully received
972 this,
973 1,
974 0);
975
976 // CASE 2: send two packets with same power within the 4us window and check PHY state:
977 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
978 // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
979 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
980 // time to detect the preamble.
981
984 this,
985 rxPowerDbm,
986 1000,
987 7);
990 this,
991 rxPowerDbm,
992 1000,
993 7);
994 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
995 // CCA_BUSY
998 this,
999 WifiPhyState::IDLE);
1002 this,
1003 WifiPhyState::CCA_BUSY);
1004 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1005 // = 154.8us
1008 this,
1009 WifiPhyState::CCA_BUSY);
1012 this,
1013 WifiPhyState::IDLE);
1014 // No more packet should have been successfully received, and since preamble detection did not
1015 // pass the packet should not have been counted as a failure
1018 this,
1019 1,
1020 0);
1021
1022 // CASE 3: send two packets with second one 3 dB weaker within the 4us window and check PHY
1023 // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
1024 // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1025 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1026 // time to detect the preamble.
1027
1030 this,
1031 rxPowerDbm,
1032 1000,
1033 7);
1036 this,
1037 rxPowerDbm - 3,
1038 1000,
1039 7);
1040 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1041 // CCA_BUSY
1044 this,
1045 WifiPhyState::IDLE);
1048 this,
1049 WifiPhyState::CCA_BUSY);
1050 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1051 // = 154.8us
1054 this,
1055 WifiPhyState::CCA_BUSY);
1058 this,
1059 WifiPhyState::IDLE);
1060 // No more packet should have been successfully received, and since preamble detection did not
1061 // pass the packet should not have been counted as a failure
1064 this,
1065 1,
1066 0);
1067
1068 // CASE 4: send two packets with second one 6 dB weaker within the 4us window and check PHY
1069 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1070 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1071 // decode the modulation).
1072
1075 this,
1076 rxPowerDbm,
1077 1000,
1078 7);
1081 this,
1082 rxPowerDbm - 6,
1083 1000,
1084 7);
1085 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1086 // CCA_BUSY
1089 this,
1090 WifiPhyState::IDLE);
1093 this,
1094 WifiPhyState::CCA_BUSY);
1095 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1096 // CCA_BUSY to RX
1099 this,
1100 WifiPhyState::CCA_BUSY);
1103 this,
1104 WifiPhyState::RX);
1105 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
1106 // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
1107 // should first be seen as CCA_BUSY for 2us.
1110 this,
1111 WifiPhyState::RX);
1114 this,
1115 WifiPhyState::CCA_BUSY);
1118 this,
1119 WifiPhyState::CCA_BUSY);
1122 this,
1123 WifiPhyState::IDLE);
1124 // In this case, the first packet should be marked as a failure
1127 this,
1128 1,
1129 1);
1130
1131 // CASE 5: send two packets with second one 3 dB higher within the 4us window and check PHY
1132 // state: PHY preamble detection should switch because a higher packet is received within the
1133 // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1134 // lower than the threshold of 4 dB), PHY state should be CCA_BUSY since the total energy is
1135 // above CCA-ED (-62 dBm).
1136
1139 this,
1140 rxPowerDbm,
1141 1000,
1142 7);
1145 this,
1146 rxPowerDbm + 3,
1147 1000,
1148 7);
1149 // At 4us, STA PHY STATE should stay IDLE
1152 this,
1153 WifiPhyState::IDLE);
1154 // At 6us, STA PHY STATE should move from IDLE to CCA_BUSY
1157 this,
1158 WifiPhyState::IDLE);
1161 this,
1162 WifiPhyState::CCA_BUSY);
1163 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1164 // = 154.8us
1167 this,
1168 WifiPhyState::CCA_BUSY);
1171 this,
1172 WifiPhyState::IDLE);
1173 // No more packet should have been successfully received, and since preamble detection did not
1174 // pass the packet should not have been counted as a failure
1177 this,
1178 1,
1179 1);
1180
1181 // CASE 6: send two packets with second one 6 dB higher within the 4us window and check PHY
1182 // state: PHY preamble detection should switch because a higher packet is received within the
1183 // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1184 // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1185 // decode the modulation).
1186
1189 this,
1190 rxPowerDbm,
1191 1000,
1192 7);
1195 this,
1196 rxPowerDbm + 6,
1197 1000,
1198 7);
1199 // At 4us, STA PHY STATE should stay IDLE
1202 this,
1203 WifiPhyState::IDLE);
1204 // At 6us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1205 // CCA_BUSY
1208 this,
1209 WifiPhyState::IDLE);
1212 this,
1213 WifiPhyState::CCA_BUSY);
1214 // At 46us, PHY header should be successfully received and STA PHY STATE should move from
1215 // CCA_BUSY to RX
1218 this,
1219 WifiPhyState::CCA_BUSY);
1222 this,
1223 WifiPhyState::RX);
1224 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1225 // = 154.8us
1228 this,
1229 WifiPhyState::RX);
1232 this,
1233 WifiPhyState::IDLE);
1234 // In this case, the second packet should be marked as a failure
1237 this,
1238 1,
1239 2);
1240
1241 // CASE 7: send two packets with same power at the exact same time and check PHY state:
1242 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
1243 // the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1244 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1245 // time to detect the preamble.
1246
1249 this,
1250 rxPowerDbm,
1251 1000,
1252 7);
1255 this,
1256 rxPowerDbm,
1257 1000,
1258 7);
1259 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1260 // CCA_BUSY
1263 this,
1264 WifiPhyState::IDLE);
1267 this,
1268 WifiPhyState::CCA_BUSY);
1269 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1270 // = 154.8us
1273 this,
1274 WifiPhyState::CCA_BUSY);
1277 this,
1278 WifiPhyState::IDLE);
1279 // No more packet should have been successfully received, and since preamble detection did not
1280 // pass the packet should not have been counted as a failure
1283 this,
1284 1,
1285 2);
1286
1287 // CASE 8: send two packets with second one 3 dB weaker at the exact same time and check PHY
1288 // state: PHY preamble detection should fail because SNR is too low (around 3 dB, which is lower
1289 // than the threshold of 4 dB), and PHY state should be CCA_BUSY since the total energy is above
1290 // CCA-ED (-62 dBm). CCA_BUSY state should last for the duration of the two packets minus the
1291 // time to detect the preamble.
1292
1295 this,
1296 rxPowerDbm,
1297 1000,
1298 7);
1301 this,
1302 rxPowerDbm - 3,
1303 1000,
1304 7);
1305 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1306 // CCA_BUSY
1309 this,
1310 WifiPhyState::IDLE);
1313 this,
1314 WifiPhyState::CCA_BUSY);
1315 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1318 this,
1319 WifiPhyState::CCA_BUSY);
1322 this,
1323 WifiPhyState::IDLE);
1324 // No more packet should have been successfully received, and since preamble detection did not
1325 // pass the packet should not have been counted as a failure
1328 this,
1329 1,
1330 2);
1331
1332 // CASE 9: send two packets with second one 6 dB weaker at the exact same time and check PHY
1333 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1334 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1335 // decode the modulation).
1336
1339 this,
1340 rxPowerDbm,
1341 1000,
1342 7);
1345 this,
1346 rxPowerDbm - 6,
1347 1000,
1348 7);
1349 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1350 // CCA_BUSY
1353 this,
1354 WifiPhyState::IDLE);
1357 this,
1358 WifiPhyState::CCA_BUSY);
1359 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1360 // CCA_BUSY to RX
1363 this,
1364 WifiPhyState::CCA_BUSY);
1367 this,
1368 WifiPhyState::RX);
1369 // Since it takes 152.8us to transmit the packets, PHY should be back to IDLE at time 152.8us.
1372 this,
1373 WifiPhyState::RX);
1376 this,
1377 WifiPhyState::IDLE);
1378 // In this case, the first packet should be marked as a failure
1381 this,
1382 1,
1383 3);
1384
1385 // CASE 10: send two packets with second one 3 dB higher at the exact same time and check PHY
1386 // state: PHY preamble detection should switch because a higher packet is received within the
1387 // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1388 // lower than the threshold of 4 dB), PHY state should be CCA_BUSY since the total energy is
1389 // above CCA-ED (-62 dBm).
1390
1393 this,
1394 rxPowerDbm,
1395 1000,
1396 7);
1399 this,
1400 rxPowerDbm + 3,
1401 1000,
1402 7);
1403 // At 4us, no preamble is successfully detected, hence STA PHY STATE should move from IDLE to
1404 // CCA_BUSY
1407 this,
1408 WifiPhyState::IDLE);
1411 this,
1412 WifiPhyState::CCA_BUSY);
1413 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1414 Simulator::Schedule(Seconds(10.0) + NanoSeconds(152799),
1416 this,
1417 WifiPhyState::CCA_BUSY);
1418 Simulator::Schedule(Seconds(10.0) + NanoSeconds(152800),
1420 this,
1421 WifiPhyState::IDLE);
1422 // No more packet should have been successfully received, and since preamble detection did not
1423 // pass the packet should not have been counted as a failure
1426 this,
1427 1,
1428 3);
1429
1430 // CASE 11: send two packets with second one 6 dB higher at the exact same time and check PHY
1431 // state: PHY preamble detection should switch because a higher packet is received within the
1432 // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1433 // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1434 // decode the modulation).
1435
1438 this,
1439 rxPowerDbm,
1440 1000,
1441 7);
1444 this,
1445 rxPowerDbm + 6,
1446 1000,
1447 7);
1448 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1449 // CCA_BUSY
1452 this,
1453 WifiPhyState::IDLE);
1456 this,
1457 WifiPhyState::CCA_BUSY);
1458 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1459 // CCA_BUSY to RX
1462 this,
1463 WifiPhyState::CCA_BUSY);
1466 this,
1467 WifiPhyState::RX);
1468 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 us
1469 Simulator::Schedule(Seconds(11.0) + NanoSeconds(152799),
1471 this,
1472 WifiPhyState::RX);
1473 Simulator::Schedule(Seconds(11.0) + NanoSeconds(152800),
1475 this,
1476 WifiPhyState::IDLE);
1477 // In this case, the second packet should be marked as a failure
1480 this,
1481 1,
1482 4);
1483
1484 // CCA-PD < RX power < CCA-ED
1485 rxPowerDbm = -70;
1486
1487 // CASE 12: send one packet and check PHY state:
1488 // All reception stages should succeed and PHY state should be RX for the duration of the packet
1489 // minus the time to detect the preamble, otherwise it should be IDLE.
1490
1493 this,
1494 rxPowerDbm,
1495 1000,
1496 7);
1497 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1498 // CCA_BUSY
1501 this,
1502 WifiPhyState::IDLE);
1505 this,
1506 WifiPhyState::CCA_BUSY);
1507 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1508 // CCA_BUSY to RX
1511 this,
1512 WifiPhyState::CCA_BUSY);
1515 this,
1516 WifiPhyState::RX);
1517 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us
1518 Simulator::Schedule(Seconds(12.0) + NanoSeconds(152799),
1520 this,
1521 WifiPhyState::RX);
1522 Simulator::Schedule(Seconds(12.0) + NanoSeconds(152800),
1524 this,
1525 WifiPhyState::IDLE);
1526 // Packet should have been successfully received
1529 this,
1530 2,
1531 4);
1532
1533 // CASE 13: send two packets with same power within the 4us window and check PHY state:
1534 // PHY preamble detection should fail because SNR is too low (around 0 dB, which is lower than
1535 // the threshold of 4 dB), and PHY state should be CCA_BUSY since it should detect the start of
1536 // a valid OFDM transmission at a receive level greater than or equal to the minimum modulation
1537 // and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
1538
1541 this,
1542 rxPowerDbm,
1543 1000,
1544 7);
1547 this,
1548 rxPowerDbm,
1549 1000,
1550 7);
1551 // At 4us, STA PHY STATE should stay IDLE
1554 this,
1555 WifiPhyState::CCA_BUSY);
1556 // No more packet should have been successfully received, and since preamble detection did not
1557 // pass the packet should not have been counted as a failure
1560 this,
1561 2,
1562 4);
1563
1564 // CASE 14: send two packets with second one 3 dB weaker within the 4us window and check PHY
1565 // state: PHY preamble detection should fail PHY preamble detection should fail because SNR is
1566 // too low (around 3 dB, which is lower than the threshold of 4 dB), and PHY state should be
1567 // CCA_BUSY since it should detect the start of a valid OFDM transmission at a receive level
1568 // greater than or equal to the minimum modulation and coding rate sensitivity (–82 dBm for 20
1569 // MHz channel spacing).
1570
1573 this,
1574 rxPowerDbm,
1575 1000,
1576 7);
1579 this,
1580 rxPowerDbm - 3,
1581 1000,
1582 7);
1583 // At 4us, STA PHY STATE should stay IDLE
1586 this,
1587 WifiPhyState::CCA_BUSY);
1588 // No more packet should have been successfully received, and since preamble detection did not
1589 // pass the packet should not have been counted as a failure
1592 this,
1593 2,
1594 4);
1595
1596 // CASE 15: send two packets with second one 6 dB weaker within the 4us window and check PHY
1597 // state: PHY preamble detection should succeed because SNR is high enough (around 6 dB, which
1598 // is higher than the threshold of 4 dB), but payload reception should fail (SNR too low to
1599 // decode the modulation).
1600
1603 this,
1604 rxPowerDbm,
1605 1000,
1606 7);
1609 this,
1610 rxPowerDbm - 6,
1611 1000,
1612 7);
1613 // At 4us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1614 // CCA_BUSY
1617 this,
1618 WifiPhyState::IDLE);
1621 this,
1622 WifiPhyState::CCA_BUSY);
1623 // At 44us, PHY header should be successfully received and STA PHY STATE should move from
1624 // CCA_BUSY to RX
1627 this,
1628 WifiPhyState::CCA_BUSY);
1631 this,
1632 WifiPhyState::RX);
1633 // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
1634 // 152.8us.
1635 Simulator::Schedule(Seconds(15.0) + NanoSeconds(152799),
1637 this,
1638 WifiPhyState::RX);
1639 Simulator::Schedule(Seconds(15.0) + NanoSeconds(152800),
1641 this,
1642 WifiPhyState::CCA_BUSY);
1643 // In this case, the first packet should be marked as a failure
1646 this,
1647 2,
1648 5);
1649
1650 // CASE 16: send two packets with second one 3 dB higher within the 4us window and check PHY
1651 // state: PHY preamble detection should switch because a higher packet is received within the
1652 // 4us window, but preamble detection should fail because SNR is too low (around 3 dB, which is
1653 // lower than the threshold of 4 dB). and PHY state should be CCA_BUSY since it should detect
1654 // the start of a valid OFDM transmission at a receive level greater than or equal to the
1655 // minimum modulation and coding rate sensitivity (–82 dBm for 20 MHz channel spacing).
1656
1659 this,
1660 rxPowerDbm,
1661 1000,
1662 7);
1665 this,
1666 rxPowerDbm + 3,
1667 1000,
1668 7);
1669 // At 4us, STA PHY STATE should stay IDLE
1672 this,
1673 WifiPhyState::IDLE);
1674 // At 6us, STA PHY STATE should be CCA_BUSY
1677 this,
1678 WifiPhyState::CCA_BUSY);
1679 // No more packet should have been successfully received, and since preamble detection did not
1680 // pass the packet should not have been counted as a failure
1683 this,
1684 2,
1685 5);
1686
1687 // CASE 17: send two packets with second one 6 dB higher within the 4us window and check PHY
1688 // state: PHY preamble detection should switch because a higher packet is received within the
1689 // 4us window, and preamble detection should succeed because SNR is high enough (around 6 dB,
1690 // which is higher than the threshold of 4 dB), Payload reception should fail (SNR too low to
1691 // decode the modulation).
1692
1695 this,
1696 rxPowerDbm,
1697 1000,
1698 7);
1701 this,
1702 rxPowerDbm + 6,
1703 1000,
1704 7);
1705 // At 4us, STA PHY STATE should stay IDLE
1708 this,
1709 WifiPhyState::IDLE);
1710 // At 6us, preamble should be successfully detected and STA PHY STATE should move from IDLE to
1711 // CCA_BUSY
1714 this,
1715 WifiPhyState::IDLE);
1718 this,
1719 WifiPhyState::CCA_BUSY);
1720 // At 46us, PHY header should be successfully received and STA PHY STATE should move from
1721 // CCA_BUSY to RX
1724 this,
1725 WifiPhyState::CCA_BUSY);
1728 this,
1729 WifiPhyState::RX);
1730 // Since it takes 152.8us to transmit each packet, PHY should be back to IDLE at time 152.8 + 2
1731 // = 154.8us
1732 Simulator::Schedule(Seconds(17.0) + NanoSeconds(154799),
1734 this,
1735 WifiPhyState::RX);
1736 Simulator::Schedule(Seconds(17.0) + NanoSeconds(154800),
1738 this,
1739 WifiPhyState::IDLE);
1740 // In this case, the second packet should be marked as a failure
1743 this,
1744 2,
1745 6);
1746
1747 rxPowerDbm = -50;
1748 // CASE 18: send two packets with second one 50 dB higher within the 4us window
1749
1752 this,
1753 rxPowerDbm,
1754 1000,
1755 7);
1758 this,
1759 rxPowerDbm + 50,
1760 1000,
1761 7);
1762 // The second packet should be received successfully
1765 this,
1766 3,
1767 6);
1768
1769 // CASE 19: send two packets with second one 10 dB higher within the 4us window
1770
1773 this,
1774 rxPowerDbm,
1775 1000,
1776 7);
1779 this,
1780 rxPowerDbm + 10,
1781 1000,
1782 7);
1783 // The second packet should be captured, but not decoded since SNR to low for used MCS
1786 this,
1787 3,
1788 7);
1789
1790 // CASE 20: send two packets with second one 50 dB higher in the same time
1791
1794 this,
1795 rxPowerDbm,
1796 1000,
1797 7);
1800 this,
1801 rxPowerDbm + 50,
1802 1000,
1803 7);
1804 // The second packet should be received successfully, same as in CASE 13
1807 this,
1808 4,
1809 7);
1810
1811 // CASE 21: send two packets with second one 10 dB higher in the same time
1812
1815 this,
1816 rxPowerDbm,
1817 1000,
1818 7);
1821 this,
1822 rxPowerDbm + 10,
1823 1000,
1824 7);
1825 // The second packet should be captured, but not decoded since SNR to low for used MCS, same as
1826 // in CASE 19
1829 this,
1830 4,
1831 8);
1832
1835}
1836
1844{
1845 public:
1847
1848 private:
1849 void DoSetup() override;
1850 void DoRun() override;
1851
1855 void Reset();
1864 RxSignalInfo rxSignalInfo,
1865 WifiTxVector txVector,
1866 std::vector<bool> statusPerMpdu);
1873
1890
1891 bool m_rxSuccess1000B{false};
1892 bool m_rxSuccess1500B{false};
1893 bool m_rxDropped1000B{false};
1894 bool m_rxDropped1500B{false};
1895};
1896
1898 : WifiPhyReceptionTest("Simple frame capture model test")
1899{
1900}
1901
1902void
1904 RxSignalInfo rxSignalInfo,
1905 WifiTxVector txVector,
1906 std::vector<bool> statusPerMpdu)
1907{
1908 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1909 NS_ASSERT(!psdu->IsAggregate() || psdu->IsSingle());
1910 if (psdu->GetSize() == 1030)
1911 {
1912 m_rxSuccess1000B = true;
1913 }
1914 else if (psdu->GetSize() == 1530)
1915 {
1916 m_rxSuccess1500B = true;
1917 }
1918}
1919
1920void
1922{
1923 NS_LOG_FUNCTION(this << p << reason);
1924 if (p->GetSize() == 1030)
1925 {
1926 m_rxDropped1000B = true;
1927 }
1928 else if (p->GetSize() == 1530)
1929 {
1930 m_rxDropped1500B = true;
1931 }
1932}
1933
1934void
1936{
1937 m_rxSuccess1000B = false;
1938 m_rxSuccess1500B = false;
1939 m_rxDropped1000B = false;
1940 m_rxDropped1500B = false;
1941}
1942
1943void
1945{
1946 NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1000B, true, "Didn't receive 1000B packet");
1947}
1948
1949void
1951{
1952 NS_TEST_ASSERT_MSG_EQ(m_rxSuccess1500B, true, "Didn't receive 1500B packet");
1953}
1954
1955void
1957{
1958 NS_TEST_ASSERT_MSG_EQ(m_rxDropped1000B, true, "Didn't drop 1000B packet");
1959}
1960
1961void
1963{
1964 NS_TEST_ASSERT_MSG_EQ(m_rxDropped1500B, true, "Didn't drop 1500B packet");
1965}
1966
1967void
1969{
1971
1973 m_phy->TraceConnectWithoutContext("PhyRxDrop",
1975
1976 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
1977 CreateObject<ThresholdPreambleDetectionModel>();
1978 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(2));
1979 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
1980
1981 Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
1982 frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
1983 frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
1984 m_phy->SetFrameCaptureModel(frameCaptureModel);
1985}
1986
1987void
1989{
1992 int64_t streamNumber = 2;
1993 double rxPowerDbm = -30;
1994 m_phy->AssignStreams(streamNumber);
1995
1996 // CASE 1: send two packets with same power within the capture window:
1997 // PHY should not switch reception because they have same power.
1998
2001 this,
2002 rxPowerDbm,
2003 1000,
2004 0);
2007 this,
2008 rxPowerDbm,
2009 1500,
2010 0);
2013
2014 // CASE 2: send two packets with second one 6 dB weaker within the capture window:
2015 // PHY should not switch reception because first one has higher power.
2016
2019 this,
2020 rxPowerDbm,
2021 1000,
2022 0);
2025 this,
2026 rxPowerDbm - 6,
2027 1500,
2028 0);
2031 this);
2034
2035 // CASE 3: send two packets with second one 6 dB higher within the capture window:
2036 // PHY should switch reception because the second one has a higher power.
2037
2040 this,
2041 rxPowerDbm,
2042 1000,
2043 0);
2046 this,
2047 rxPowerDbm + 6,
2048 1500,
2049 0);
2053 this);
2055
2056 // CASE 4: send two packets with second one 6 dB higher after the capture window:
2057 // PHY should not switch reception because capture window duration has elapsed when the second
2058 // packet arrives.
2059
2062 this,
2063 rxPowerDbm,
2064 1000,
2065 0);
2068 this,
2069 rxPowerDbm + 6,
2070 1500,
2071 0);
2074
2077}
2078
2086{
2087 public:
2089
2090 private:
2091 void DoRun() override;
2092};
2093
2095 : WifiPhyReceptionTest("PHY headers reception test")
2096{
2097}
2098
2099void
2101{
2104 int64_t streamNumber = 0;
2105 m_phy->AssignStreams(streamNumber);
2106
2107 // RX power > CCA-ED
2108 double rxPowerDbm = -50;
2109
2110 // CASE 1: send one packet followed by a second one with same power between the end of the 4us
2111 // preamble detection window and the start of L-SIG of the first packet: reception should be
2112 // aborted since L-SIG cannot be decoded (SNR too low).
2113
2116 this,
2117 rxPowerDbm,
2118 1000,
2119 7);
2122 this,
2123 rxPowerDbm,
2124 1000,
2125 7);
2126 // At 10 us, STA PHY STATE should be CCA_BUSY.
2129 this,
2130 WifiPhyState::CCA_BUSY);
2131 // At 44us (end of PHY header), STA PHY STATE should not have moved to RX and be kept to
2132 // CCA_BUSY.
2135 this,
2136 WifiPhyState::CCA_BUSY);
2137 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8 + 10
2138 // = 162.8us.
2141 this,
2142 WifiPhyState::CCA_BUSY);
2145 this,
2146 WifiPhyState::IDLE);
2147
2148 // CASE 2: send one packet followed by a second one 3 dB weaker between the end of the 4us
2149 // preamble detection window and the start of L-SIG of the first packet: reception should not be
2150 // aborted since L-SIG can be decoded (SNR high enough).
2151
2154 this,
2155 rxPowerDbm,
2156 1000,
2157 7);
2160 this,
2161 rxPowerDbm - 3,
2162 1000,
2163 7);
2164 // At 10 us, STA PHY STATE should be CCA_BUSY.
2167 this,
2168 WifiPhyState::CCA_BUSY);
2169 // At 44us (end of PHY header), STA PHY STATE should have moved to RX since PHY header reception
2170 // should have succeeded.
2173 this,
2174 WifiPhyState::CCA_BUSY);
2177 this,
2178 WifiPhyState::RX);
2179 // Since it takes 152.8us to transmit the packet, PHY should be back to IDLE at time 152.8us.
2180 // However, since there is a second packet transmitted with a power above CCA-ED (-62 dBm), PHY
2181 // should first be seen as CCA_BUSY for 10us.
2184 this,
2185 WifiPhyState::RX);
2188 this,
2189 WifiPhyState::CCA_BUSY);
2192 this,
2193 WifiPhyState::CCA_BUSY);
2196 this,
2197 WifiPhyState::IDLE);
2198
2199 // CASE 3: send one packet followed by a second one with same power between the end of L-SIG and
2200 // the start of HE-SIG of the first packet: PHY header reception should not succeed but PHY
2201 // should stay in RX state for the duration estimated from L-SIG.
2202
2205 this,
2206 rxPowerDbm,
2207 1000,
2208 7);
2211 this,
2212 rxPowerDbm,
2213 1000,
2214 7);
2215 // At 44us (end of PHY header), STA PHY STATE should not have moved to RX (HE-SIG failed) and be
2216 // kept to CCA_BUSY.
2219 this,
2220 WifiPhyState::CCA_BUSY);
2221 // STA PHY STATE should move back to IDLE once the duration estimated from L-SIG has elapsed,
2222 // i.e. at 152.8us. However, since there is a second packet transmitted with a power above
2223 // CCA-ED (-62 dBm), PHY should first be seen as CCA_BUSY for 25us.
2226 this,
2227 WifiPhyState::CCA_BUSY);
2230 this,
2231 WifiPhyState::CCA_BUSY);
2234 this,
2235 WifiPhyState::CCA_BUSY);
2238 this,
2239 WifiPhyState::IDLE);
2240
2241 // CASE 4: send one packet followed by a second one 3 dB weaker between the end of L-SIG and the
2242 // start of HE-SIG of the first packet: PHY header reception should succeed.
2243
2246 this,
2247 rxPowerDbm,
2248 1000,
2249 7);
2252 this,
2253 rxPowerDbm - 3,
2254 1000,
2255 7);
2256 // At 10 us, STA PHY STATE should be CCA_BUSY.
2259 this,
2260 WifiPhyState::CCA_BUSY);
2261 // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2262 // should have succeeded.
2265 this,
2266 WifiPhyState::CCA_BUSY);
2269 this,
2270 WifiPhyState::RX);
2271 // STA PHY STATE should move back to IDLE once the duration estimated from L-SIG has elapsed,
2272 // i.e. at 152.8us. However, since there is a second packet transmitted with a power above
2273 // CCA-ED (-62 dBm), PHY should first be seen as CCA_BUSY for 25us.
2276 this,
2277 WifiPhyState::RX);
2280 this,
2281 WifiPhyState::CCA_BUSY);
2284 this,
2285 WifiPhyState::CCA_BUSY);
2288 this,
2289 WifiPhyState::IDLE);
2290
2291 // RX power < CCA-ED
2292 rxPowerDbm = -70;
2293
2294 // CASE 5: send one packet followed by a second one with same power between the end of the 4us
2295 // preamble detection window and the start of L-SIG of the first packet: reception should be
2296 // aborted since L-SIG cannot be decoded (SNR too low).
2297
2300 this,
2301 rxPowerDbm,
2302 1000,
2303 7);
2306 this,
2307 rxPowerDbm,
2308 1000,
2309 7);
2310 // At 10 us, STA PHY STATE should be CCA_BUSY.
2313 this,
2314 WifiPhyState::CCA_BUSY);
2315 // At 24us (end of L-SIG), STA PHY STATE stay CCA_BUSY because L-SIG reception failed and the
2316 // start of a valid OFDM transmission has been detected
2319 this,
2320 WifiPhyState::CCA_BUSY);
2321
2322 // CASE 6: send one packet followed by a second one 3 dB weaker between the end of the 4us
2323 // preamble detection window and the start of L-SIG of the first packet: reception should not be
2324 // aborted since L-SIG can be decoded (SNR high enough).
2325
2328 this,
2329 rxPowerDbm,
2330 1000,
2331 7);
2334 this,
2335 rxPowerDbm - 3,
2336 1000,
2337 7);
2338 // At 10 us, STA PHY STATE should be CCA_BUSY.
2341 this,
2342 WifiPhyState::CCA_BUSY);
2343 // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2344 // succeeded.
2347 this,
2348 WifiPhyState::CCA_BUSY);
2349 // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2350 // should have succeeded.
2353 this,
2354 WifiPhyState::CCA_BUSY);
2357 this,
2358 WifiPhyState::RX);
2359 // Since it takes 152.8us to transmit the packet, PHY should be back to CCA_BUSY at time
2360 // 152.8us.
2363 this,
2364 WifiPhyState::RX);
2367 this,
2368 WifiPhyState::CCA_BUSY);
2369
2370 // CASE 7: send one packet followed by a second one with same power between the end of L-SIG and
2371 // the start of HE-SIG of the first packet: PHY header reception should not succeed but PHY
2372 // should stay in RX state for the duration estimated from L-SIG.
2373
2376 this,
2377 rxPowerDbm,
2378 1000,
2379 7);
2382 this,
2383 rxPowerDbm,
2384 1000,
2385 7);
2386 // At 10 us, STA PHY STATE should be CCA_BUSY.
2389 this,
2390 WifiPhyState::CCA_BUSY);
2391 // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2392 // succeeded.
2395 this,
2396 WifiPhyState::CCA_BUSY);
2397 // At 44 us (end of HE-SIG), STA PHY STATE should be not have moved to RX since reception of
2398 // HE-SIG should have failed.
2401 this,
2402 WifiPhyState::CCA_BUSY);
2403 // STA PHY STATE should keep CCA_BUSY once the duration estimated from L-SIG has elapsed, i.e.
2404 // at 152.8us.
2407 this,
2408 WifiPhyState::CCA_BUSY);
2409
2410 // CASE 8: send one packet followed by a second one 3 dB weaker between the end of L-SIG and the
2411 // start of HE-SIG of the first packet: PHY header reception should succeed.
2412
2415 this,
2416 rxPowerDbm,
2417 1000,
2418 7);
2421 this,
2422 rxPowerDbm - 3,
2423 1000,
2424 7);
2425 // At 10 us, STA PHY STATE should be CCA_BUSY.
2428 this,
2429 WifiPhyState::CCA_BUSY);
2430 // At 24us (end of L-SIG), STA PHY STATE should be unchanged because L-SIG reception should have
2431 // succeeded.
2434 this,
2435 WifiPhyState::CCA_BUSY);
2436 // At 44 us (end of HE-SIG), STA PHY STATE should move to RX since the PHY header reception
2437 // should have succeeded.
2440 this,
2441 WifiPhyState::CCA_BUSY);
2444 this,
2445 WifiPhyState::RX);
2446 // STA PHY STATE should move back to CCA_BUSY once the duration estimated from L-SIG has
2447 // elapsed, i.e. at 152.8us.
2450 this,
2451 WifiPhyState::RX);
2454 this,
2455 WifiPhyState::CCA_BUSY);
2456
2459}
2460
2468{
2469 public:
2471
2472 private:
2473 void DoSetup() override;
2474 void DoRun() override;
2475
2484 RxSignalInfo rxSignalInfo,
2485 WifiTxVector txVector,
2486 std::vector<bool> statusPerMpdu);
2491 void RxFailure(Ptr<const WifiPsdu> psdu);
2508
2512 void ResetBitmaps();
2513
2521 void SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize);
2522
2527 void CheckRxSuccessBitmapAmpdu1(uint8_t expected);
2532 void CheckRxSuccessBitmapAmpdu2(uint8_t expected);
2537 void CheckRxFailureBitmapAmpdu1(uint8_t expected);
2542 void CheckRxFailureBitmapAmpdu2(uint8_t expected);
2547 void CheckRxDroppedBitmapAmpdu1(uint8_t expected);
2552 void CheckRxDroppedBitmapAmpdu2(uint8_t expected);
2553
2558 void CheckPhyState(WifiPhyState expectedState);
2559
2562
2565
2568};
2569
2571 : WifiPhyReceptionTest("A-MPDU reception test")
2572{
2573}
2574
2575void
2577{
2584}
2585
2586void
2588 RxSignalInfo rxSignalInfo,
2589 WifiTxVector txVector,
2590 std::vector<bool> statusPerMpdu)
2591{
2592 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
2593 if (statusPerMpdu.empty()) // wait for the whole A-MPDU
2594 {
2595 return;
2596 }
2597 NS_ABORT_MSG_IF(psdu->GetNMpdus() != statusPerMpdu.size(),
2598 "Should have one receive status per MPDU");
2599 auto rxOkForMpdu = statusPerMpdu.begin();
2600 for (auto mpdu = psdu->begin(); mpdu != psdu->end(); ++mpdu)
2601 {
2602 if (*rxOkForMpdu)
2603 {
2604 IncrementSuccessBitmap((*mpdu)->GetSize());
2605 }
2606 else
2607 {
2608 IncrementFailureBitmap((*mpdu)->GetSize());
2609 }
2610 ++rxOkForMpdu;
2611 }
2612}
2613
2614void
2616{
2617 if (size == 1030) // A-MPDU 1 - MPDU #1
2618 {
2620 }
2621 else if (size == 1130) // A-MPDU 1 - MPDU #2
2622 {
2623 m_rxSuccessBitmapAmpdu1 |= (1 << 1);
2624 }
2625 else if (size == 1230) // A-MPDU 1 - MPDU #3
2626 {
2627 m_rxSuccessBitmapAmpdu1 |= (1 << 2);
2628 }
2629 else if (size == 1330) // A-MPDU 2 - MPDU #1
2630 {
2632 }
2633 else if (size == 1430) // A-MPDU 2 - MPDU #2
2634 {
2635 m_rxSuccessBitmapAmpdu2 |= (1 << 1);
2636 }
2637 else if (size == 1530) // A-MPDU 2 - MPDU #3
2638 {
2639 m_rxSuccessBitmapAmpdu2 |= (1 << 2);
2640 }
2641}
2642
2643void
2645{
2646 NS_LOG_FUNCTION(this << *psdu);
2647 for (auto mpdu = psdu->begin(); mpdu != psdu->end(); ++mpdu)
2648 {
2649 IncrementFailureBitmap((*mpdu)->GetSize());
2650 }
2651}
2652
2653void
2655{
2656 if (size == 1030) // A-MPDU 1 - MPDU #1
2657 {
2659 }
2660 else if (size == 1130) // A-MPDU 1 - MPDU #2
2661 {
2662 m_rxFailureBitmapAmpdu1 |= (1 << 1);
2663 }
2664 else if (size == 1230) // A-MPDU 1 - MPDU #3
2665 {
2666 m_rxFailureBitmapAmpdu1 |= (1 << 2);
2667 }
2668 else if (size == 1330) // A-MPDU 2 - MPDU #1
2669 {
2671 }
2672 else if (size == 1430) // A-MPDU 2 - MPDU #2
2673 {
2674 m_rxFailureBitmapAmpdu2 |= (1 << 1);
2675 }
2676 else if (size == 1530) // A-MPDU 2 - MPDU #3
2677 {
2678 m_rxFailureBitmapAmpdu2 |= (1 << 2);
2679 }
2680}
2681
2682void
2684{
2685 NS_LOG_FUNCTION(this << p << reason);
2686 if (p->GetSize() == 1030) // A-MPDU 1 - MPDU #1
2687 {
2689 }
2690 else if (p->GetSize() == 1130) // A-MPDU 1 - MPDU #2
2691 {
2692 m_rxDroppedBitmapAmpdu1 |= (1 << 1);
2693 }
2694 else if (p->GetSize() == 1230) // A-MPDU 1 - MPDU #3
2695 {
2696 m_rxDroppedBitmapAmpdu1 |= (1 << 2);
2697 }
2698 else if (p->GetSize() == 1330) // A-MPDU 2 - MPDU #1
2699 {
2701 }
2702 else if (p->GetSize() == 1430) // A-MPDU 2 - MPDU #2
2703 {
2704 m_rxDroppedBitmapAmpdu2 |= (1 << 1);
2705 }
2706 else if (p->GetSize() == 1530) // A-MPDU 2 - MPDU #3
2707 {
2708 m_rxDroppedBitmapAmpdu2 |= (1 << 2);
2709 }
2710}
2711
2712void
2714{
2716 expected,
2717 "RX success bitmap for A-MPDU 1 is not as expected");
2718}
2719
2720void
2722{
2724 expected,
2725 "RX success bitmap for A-MPDU 2 is not as expected");
2726}
2727
2728void
2730{
2732 expected,
2733 "RX failure bitmap for A-MPDU 1 is not as expected");
2734}
2735
2736void
2738{
2740 expected,
2741 "RX failure bitmap for A-MPDU 2 is not as expected");
2742}
2743
2744void
2746{
2748 expected,
2749 "RX dropped bitmap for A-MPDU 1 is not as expected");
2750}
2751
2752void
2754{
2756 expected,
2757 "RX dropped bitmap for A-MPDU 2 is not as expected");
2758}
2759
2760void
2762{
2763 WifiPhyState currentState;
2764 PointerValue ptr;
2765 m_phy->GetAttribute("State", ptr);
2766 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
2767 currentState = state->GetState();
2768 NS_TEST_ASSERT_MSG_EQ(currentState,
2769 expectedState,
2770 "PHY State " << currentState << " does not match expected state "
2771 << expectedState << " at " << Simulator::Now());
2772}
2773
2774void
2775TestAmpduReception::SendAmpduWithThreeMpdus(double rxPowerDbm, uint32_t referencePacketSize)
2776{
2777 WifiTxVector txVector =
2778 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, true);
2779
2780 WifiMacHeader hdr;
2782 hdr.SetQosTid(0);
2783
2784 std::vector<Ptr<WifiMpdu>> mpduList;
2785 for (size_t i = 0; i < 3; ++i)
2786 {
2787 Ptr<Packet> p = Create<Packet>(referencePacketSize + i * 100);
2788 mpduList.push_back(Create<WifiMpdu>(p, hdr));
2789 }
2790 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(mpduList);
2791
2792 Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
2793
2794 Ptr<WifiPpdu> ppdu =
2795 Create<HePpdu>(psdu, txVector, m_phy->GetOperatingChannel(), txDuration, m_uid++);
2796
2797 Ptr<SpectrumValue> txPowerSpectrum =
2800 DbmToW(rxPowerDbm),
2801 GUARD_WIDTH);
2802
2803 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
2804 txParams->psd = txPowerSpectrum;
2805 txParams->txPhy = nullptr;
2806 txParams->duration = txDuration;
2807 txParams->ppdu = ppdu;
2808 txParams->txWidth = CHANNEL_WIDTH;
2809
2810 m_phy->StartRx(txParams, nullptr);
2811}
2812
2813void
2815{
2817
2820 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2822
2823 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2824 CreateObject<ThresholdPreambleDetectionModel>();
2825 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(2));
2826 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2827
2828 Ptr<SimpleFrameCaptureModel> frameCaptureModel = CreateObject<SimpleFrameCaptureModel>();
2829 frameCaptureModel->SetAttribute("Margin", DoubleValue(5));
2830 frameCaptureModel->SetAttribute("CaptureWindow", TimeValue(MicroSeconds(16)));
2831 m_phy->SetFrameCaptureModel(frameCaptureModel);
2832}
2833
2834void
2836{
2839 int64_t streamNumber = 1;
2840 double rxPowerDbm = -30;
2841 m_phy->AssignStreams(streamNumber);
2842
2844 // CASE 1: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
2845 // power under RX sensitivity. The second A-MPDU is received 2 microseconds after the first
2846 // A-MPDU (i.e. during preamble detection).
2848
2849 // A-MPDU 1
2852 this,
2853 rxPowerDbm - 100,
2854 1000);
2855
2856 // A-MPDU 2
2859 this,
2860 rxPowerDbm,
2861 1300);
2862
2863 // All MPDUs of A-MPDU 1 should have been ignored.
2866 this,
2867 0b00000000);
2870 this,
2871 0b00000000);
2874 this,
2875 0b00000000);
2876
2877 // All MPDUs of A-MPDU 2 should have been successfully received.
2880 this,
2881 0b00000111);
2884 this,
2885 0b00000000);
2888 this,
2889 0b00000000);
2890
2892
2894 // CASE 2: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
2895 // with power under RX sensitivity. The second A-MPDU is received 2 microseconds after the first
2896 // A-MPDU (i.e. during preamble detection).
2898
2899 // A-MPDU 1
2902 this,
2903 rxPowerDbm,
2904 1000);
2905
2906 // A-MPDU 2
2909 this,
2910 rxPowerDbm - 100,
2911 1300);
2912
2913 // All MPDUs of A-MPDU 1 should have been received.
2916 this,
2917 0b00000111);
2920 this,
2921 0b00000000);
2924 this,
2925 0b00000000);
2926
2927 // All MPDUs of A-MPDU 2 should have been ignored.
2930 this,
2931 0b00000000);
2934 this,
2935 0b00000000);
2938 this,
2939 0b00000000);
2940
2942
2944 // CASE 3: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
2945 // power under RX sensitivity. The second A-MPDU is received 10 microseconds after the first
2946 // A-MPDU (i.e. during the frame capture window).
2948
2949 // A-MPDU 1
2952 this,
2953 rxPowerDbm - 100,
2954 1000);
2955
2956 // A-MPDU 2
2959 this,
2960 rxPowerDbm,
2961 1300);
2962
2963 // All MPDUs of A-MPDU 1 should have been ignored.
2966 this,
2967 0b00000000);
2970 this,
2971 0b00000000);
2974 this,
2975 0b00000000);
2976
2977 // All MPDUs of A-MPDU 2 should have been successfully received.
2980 this,
2981 0b00000111);
2984 this,
2985 0b00000000);
2988 this,
2989 0b00000000);
2990
2992
2994 // CASE 4: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
2995 // with power under RX sensitivity. The second A-MPDU is received 10 microseconds after the
2996 // first A-MPDU (i.e. during the frame capture window).
2998
2999 // A-MPDU 1
3002 this,
3003 rxPowerDbm,
3004 1000);
3005
3006 // A-MPDU 2
3009 this,
3010 rxPowerDbm - 100,
3011 1300);
3012
3013 // All MPDUs of A-MPDU 1 should have been received.
3016 this,
3017 0b00000111);
3020 this,
3021 0b00000000);
3024 this,
3025 0b00000000);
3026
3027 // All MPDUs of A-MPDU 2 should have been ignored.
3030 this,
3031 0b00000000);
3034 this,
3035 0b00000000);
3038 this,
3039 0b00000000);
3040
3042
3044 // CASE 5: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3045 // power under RX sensitivity. The second A-MPDU is received 100 microseconds after the first
3046 // A-MPDU (i.e. after the frame capture window, during the payload of MPDU #1).
3048
3049 // A-MPDU 1
3052 this,
3053 rxPowerDbm - 100,
3054 1000);
3055
3056 // A-MPDU 2
3059 this,
3060 rxPowerDbm,
3061 1300);
3062
3063 // All MPDUs of A-MPDU 1 should have been ignored.
3066 this,
3067 0b00000000);
3070 this,
3071 0b00000000);
3074 this,
3075 0b00000000);
3076
3077 // All MPDUs of A-MPDU 2 should have been successfully received.
3080 this,
3081 0b00000111);
3084 this,
3085 0b00000000);
3088 this,
3089 0b00000000);
3090
3092
3094 // CASE 6: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3095 // with power under RX sensitivity. The second A-MPDU is received 100 microseconds after the
3096 // first A-MPDU (i.e. after the frame capture window, during the payload of MPDU #1).
3098
3099 // A-MPDU 1
3102 this,
3103 rxPowerDbm,
3104 1000);
3105
3106 // A-MPDU 2
3109 this,
3110 rxPowerDbm - 100,
3111 1300);
3112
3113 // All MPDUs of A-MPDU 1 should have been received.
3116 this,
3117 0b00000111);
3120 this,
3121 0b00000000);
3124 this,
3125 0b00000000);
3126
3127 // All MPDUs of A-MPDU 2 should have been ignored.
3130 this,
3131 0b00000000);
3134 this,
3135 0b00000000);
3138 this,
3139 0b00000000);
3140
3142
3144 // CASE 7: receive two A-MPDUs (containing each 3 MPDUs) where the first A-MPDU is received with
3145 // power under RX sensitivity. The second A-MPDU is received during the payload of MPDU #2.
3147
3148 // A-MPDU 1
3151 this,
3152 rxPowerDbm - 100,
3153 1000);
3154
3155 // A-MPDU 2
3156 Simulator::Schedule(Seconds(7.0) + NanoSeconds(1100000),
3158 this,
3159 rxPowerDbm,
3160 1300);
3161
3162 // All MPDUs of A-MPDU 1 should have been ignored.
3165 this,
3166 0b00000000);
3169 this,
3170 0b00000000);
3173 this,
3174 0b00000000);
3175
3176 // All MPDUs of A-MPDU 2 should have been successfully received.
3179 this,
3180 0b00000111);
3183 this,
3184 0b00000000);
3187 this,
3188 0b00000000);
3189
3191
3193 // CASE 8: receive two A-MPDUs (containing each 3 MPDUs) where the second A-MPDU is received
3194 // with power under RX sensitivity. The second A-MPDU is received during the payload of MPDU #2.
3196
3197 // A-MPDU 1
3200 this,
3201 rxPowerDbm,
3202 1000);
3203
3204 // A-MPDU 2
3205 Simulator::Schedule(Seconds(8.0) + NanoSeconds(1100000),
3207 this,
3208 rxPowerDbm - 100,
3209 1300);
3210
3211 // All MPDUs of A-MPDU 1 should have been received.
3214 this,
3215 0b00000111);
3218 this,
3219 0b00000000);
3222 this,
3223 0b00000000);
3224
3225 // All MPDUs of A-MPDU 2 should have been ignored.
3228 this,
3229 0b00000000);
3232 this,
3233 0b00000000);
3236 this,
3237 0b00000000);
3238
3240
3242 // CASE 9: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power 3
3243 // dB higher. The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during
3244 // preamble detection).
3246
3247 // A-MPDU 1
3250 this,
3251 rxPowerDbm,
3252 1000);
3253
3254 // A-MPDU 2
3257 this,
3258 rxPowerDbm + 3,
3259 1300);
3260
3261 // All MPDUs of A-MPDU 1 should have been dropped.
3264 this,
3265 0b00000000);
3268 this,
3269 0b00000000);
3272 this,
3273 0b00000111);
3274
3275 // All MPDUs of A-MPDU 2 should have been received with errors.
3278 this,
3279 0b00000000);
3282 this,
3283 0b00000111);
3286 this,
3287 0b00000000);
3288
3290
3292 // CASE 10: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3293 // The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during preamble
3294 // detection).
3296
3297 // A-MPDU 1
3300 this,
3301 rxPowerDbm,
3302 1000);
3303
3304 // A-MPDU 2
3307 this,
3308 rxPowerDbm,
3309 1300);
3310
3311 // All MPDUs of A-MPDU 1 should have been dropped (preamble detection failed).
3314 this,
3315 0b00000000);
3318 this,
3319 0b00000000);
3322 this,
3323 0b00000111);
3324
3325 // All MPDUs of A-MPDU 2 should have been dropped as well.
3328 this,
3329 0b00000000);
3332 this,
3333 0b00000000);
3336 this,
3337 0b00000111);
3338
3340
3342 // CASE 11: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 3
3343 // dB higher. The second A-MPDU is received 2 microseconds after the first A-MPDU (i.e. during
3344 // preamble detection).
3346
3347 // A-MPDU 1
3350 this,
3351 rxPowerDbm + 3,
3352 1000);
3353
3354 // A-MPDU 2
3357 this,
3358 rxPowerDbm,
3359 1300);
3360
3361 // All MPDUs of A-MPDU 1 should have been received with errors.
3364 this,
3365 0b00000000);
3368 this,
3369 0b00000111);
3372 this,
3373 0b00000000);
3374
3375 // All MPDUs of A-MPDU 2 should have been dropped.
3378 this,
3379 0b00000000);
3382 this,
3383 0b00000000);
3386 this,
3387 0b00000111);
3388
3390
3392 // CASE 12: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3393 // 3 dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e.
3394 // during the frame capture window).
3396
3397 // A-MPDU 1
3400 this,
3401 rxPowerDbm,
3402 1000);
3403
3404 // A-MPDU 2
3407 this,
3408 rxPowerDbm + 3,
3409 1300);
3410
3411 // All MPDUs of A-MPDU 1 should have been received with errors (PHY header reception failed and
3412 // thus incorrect decoding of payload).
3415 this,
3416 0b00000000);
3419 this,
3420 0b00000000);
3423 this,
3424 0b00000111);
3425
3426 // All MPDUs of A-MPDU 2 should have been dropped (even though TX power is higher, it is not
3427 // high enough to get the PHY reception switched)
3430 this,
3431 0b00000000);
3434 this,
3435 0b00000000);
3438 this,
3439 0b00000111);
3440
3442
3444 // CASE 13: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3445 // The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during the frame
3446 // capture window).
3448
3449 // A-MPDU 1
3452 this,
3453 rxPowerDbm,
3454 1000);
3455
3456 // A-MPDU 2
3459 this,
3460 rxPowerDbm,
3461 1300);
3462
3463 // All MPDUs of A-MPDU 1 should have been received with errors (PHY header reception failed and
3464 // thus incorrect decoding of payload).
3467 this,
3468 0b00000000);
3471 this,
3472 0b00000000);
3475 this,
3476 0b00000111);
3477
3478 // All MPDUs of A-MPDU 2 should have been dropped as well.
3481 this,
3482 0b00000000);
3485 this,
3486 0b00000000);
3489 this,
3490 0b00000111);
3491
3493
3495 // CASE 14: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 3
3496 // dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during
3497 // the frame capture window).
3499
3500 // A-MPDU 1
3503 this,
3504 rxPowerDbm + 3,
3505 1000);
3506
3507 // A-MPDU 2
3510 this,
3511 rxPowerDbm,
3512 1300);
3513
3514 // All MPDUs of A-MPDU 1 should have been received with errors.
3517 this,
3518 0b00000000);
3521 this,
3522 0b00000111);
3525 this,
3526 0b00000000);
3527
3528 // All MPDUs of A-MPDU 2 should have been dropped.
3531 this,
3532 0b00000000);
3535 this,
3536 0b00000000);
3539 this,
3540 0b00000111);
3541
3543
3545 // CASE 15: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3546 // 6 dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e.
3547 // during the frame capture window).
3549
3550 // A-MPDU 1
3553 this,
3554 rxPowerDbm,
3555 1000);
3556
3557 // A-MPDU 2
3560 this,
3561 rxPowerDbm + 6,
3562 1300);
3563
3564 // All MPDUs of A-MPDU 1 should have been dropped because PHY reception switched to A-MPDU 2.
3567 this,
3568 0b00000000);
3571 this,
3572 0b00000000);
3575 this,
3576 0b00000111);
3577
3578 // All MPDUs of A-MPDU 2 should have been successfully received
3581 this,
3582 0b00000111);
3585 this,
3586 0b00000000);
3589 this,
3590 0b00000000);
3591
3593
3595 // CASE 16: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3596 // dB higher. The second A-MPDU is received 10 microseconds after the first A-MPDU (i.e. during
3597 // the frame capture window).
3599
3600 // A-MPDU 1
3603 this,
3604 rxPowerDbm + 6,
3605 1000);
3606
3607 // A-MPDU 2
3610 this,
3611 rxPowerDbm,
3612 1300);
3613
3614 // All MPDUs of A-MPDU 1 should have been successfully received.
3617 this,
3618 0b00000111);
3621 this,
3622 0b00000000);
3625 this,
3626 0b00000000);
3627
3628 // All MPDUs of A-MPDU 2 should have been dropped.
3631 this,
3632 0b00000000);
3635 this,
3636 0b00000000);
3639 this,
3640 0b00000111);
3641
3643
3645 // CASE 17: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3646 // 6 dB higher. The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after
3647 // the frame capture window, but still during PHY header).
3649
3650 // A-MPDU 1
3653 this,
3654 rxPowerDbm,
3655 1000);
3656
3657 // A-MPDU 2
3660 this,
3661 rxPowerDbm + 6,
3662 1300);
3663
3664 // All MPDUs of A-MPDU 1 should have been received with errors.
3667 this,
3668 0b00000000);
3671 this,
3672 0b00000000);
3675 this,
3676 0b00000111);
3677
3678 // All MPDUs of A-MPDU 2 should have been dropped (no reception switch, MPDUs dropped because
3679 // PHY is already in RX state).
3682 this,
3683 0b00000000);
3686 this,
3687 0b00000000);
3690 this,
3691 0b00000111);
3692
3694
3696 // CASE 18: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3697 // dB higher. The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after
3698 // the frame capture window, but still during PHY header).
3700
3701 // A-MPDU 1
3704 this,
3705 rxPowerDbm + 6,
3706 1000);
3707
3708 // A-MPDU 2
3711 this,
3712 rxPowerDbm,
3713 1300);
3714
3715 // All MPDUs of A-MPDU 1 should have been successfully received.
3718 this,
3719 0b00000111);
3722 this,
3723 0b00000000);
3726 this,
3727 0b00000000);
3728
3729 // All MPDUs of A-MPDU 2 should have been dropped.
3732 this,
3733 0b00000000);
3736 this,
3737 0b00000000);
3740 this,
3741 0b00000111);
3742
3744
3746 // CASE 19: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3747 // The second A-MPDU is received 25 microseconds after the first A-MPDU (i.e. after the frame
3748 // capture window, but still during PHY header).
3750
3751 // A-MPDU 1
3754 this,
3755 rxPowerDbm,
3756 1000);
3757
3758 // A-MPDU 2
3761 this,
3762 rxPowerDbm,
3763 1300);
3764
3765 // All MPDUs of A-MPDU 1 should have been received with errors.
3768 this,
3769 0b00000000);
3772 this,
3773 0b00000000);
3776 this,
3777 0b00000111);
3778
3779 // All MPDUs of A-MPDU 2 should have been dropped.
3782 this,
3783 0b00000000);
3786 this,
3787 0b00000000);
3790 this,
3791 0b00000111);
3792
3794
3796 // CASE 20: receive two A-MPDUs (containing each 3 MPDUs) with the second A-MPDU having a power
3797 // 6 dB higher. The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e.
3798 // during the payload of MPDU #1).
3800
3801 // A-MPDU 1
3804 this,
3805 rxPowerDbm,
3806 1000);
3807
3808 // A-MPDU 2
3811 this,
3812 rxPowerDbm + 6,
3813 1300);
3814
3815 // All MPDUs of A-MPDU 1 should have been received with errors.
3818 this,
3819 0b00000000);
3822 this,
3823 0b00000111);
3826 this,
3827 0b00000000);
3828
3829 // All MPDUs of A-MPDU 2 should have been dropped (no reception switch, MPDUs dropped because
3830 // PHY is already in RX state).
3833 this,
3834 0b00000000);
3837 this,
3838 0b00000000);
3841 this,
3842 0b00000111);
3843
3845
3847 // CASE 21: receive two A-MPDUs (containing each 3 MPDUs) with the first A-MPDU having a power 6
3848 // dB higher. The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e. during
3849 // the payload of MPDU #1).
3851
3852 // A-MPDU 1
3855 this,
3856 rxPowerDbm + 6,
3857 1000);
3858
3859 // A-MPDU 2
3862 this,
3863 rxPowerDbm,
3864 1300);
3865
3866 // All MPDUs of A-MPDU 1 should have been successfully received.
3869 this,
3870 0b00000111);
3873 this,
3874 0b00000000);
3877 this,
3878 0b00000000);
3879
3880 // All MPDUs of A-MPDU 2 should have been dropped.
3883 this,
3884 0b00000000);
3887 this,
3888 0b00000000);
3891 this,
3892 0b00000111);
3893
3895
3897 // CASE 22: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3898 // The second A-MPDU is received 100 microseconds after the first A-MPDU (i.e. during the
3899 // payload of MPDU #1).
3901
3902 // A-MPDU 1
3905 this,
3906 rxPowerDbm,
3907 1000);
3908
3909 // A-MPDU 2
3912 this,
3913 rxPowerDbm,
3914 1300);
3915
3916 // All MPDUs of A-MPDU 1 should have been received with errors.
3919 this,
3920 0b00000000);
3923 this,
3924 0b00000111);
3927 this,
3928 0b00000000);
3929
3930 // All MPDUs of A-MPDU 2 should have been dropped.
3933 this,
3934 0b00000000);
3937 this,
3938 0b00000000);
3941 this,
3942 0b00000111);
3943
3945
3947 // CASE 23: receive two A-MPDUs (containing each 3 MPDUs) with the same power.
3948 // The second A-MPDU is received during the payload of MPDU #2.
3950
3951 // A-MPDU 1
3954 this,
3955 rxPowerDbm,
3956 1000);
3957
3958 // A-MPDU 2
3959 Simulator::Schedule(Seconds(23.0) + NanoSeconds(1100000),
3961 this,
3962 rxPowerDbm,
3963 1300);
3964
3965 // The first MPDU of A-MPDU 1 should have been successfully received (no interference).
3966 // The two other MPDUs failed due to interference and are marked as failure (and dropped).
3969 this,
3970 0b00000001);
3973 this,
3974 0b00000110);
3977 this,
3978 0b00000000);
3979
3980 // The two first MPDUs of A-MPDU 2 are dropped because PHY is already in RX state (receiving
3981 // A-MPDU 1). The last MPDU of A-MPDU 2 is interference free (A-MPDU 1 transmission is finished)
3982 // but is dropped because its PHY preamble and header were not received.
3985 this,
3986 0b00000000);
3989 this,
3990 0b00000000);
3993 this,
3994 0b00000111);
3995
3997
4000}
4001
4023{
4024 public:
4027
4028 private:
4029 void DoRun() override;
4030
4037 void Dropped(std::string context, Ptr<const Packet> packet, WifiPhyRxfailureReason reason);
4041 void CheckResults();
4042
4043 uint16_t m_dropped{0};
4044};
4045
4047 : TestCase("Check correct behavior when a STA is receiving a transmission using an unsupported "
4048 "modulation")
4049{
4050}
4051
4052void
4054 Ptr<const Packet> packet,
4056{
4057 // Print if the test is executed through test-runner
4058 if (reason == RXING)
4059 {
4060 std::cout << "Dropped a packet because already receiving" << std::endl;
4061 m_dropped++;
4062 }
4063}
4064
4065void
4067{
4068 uint16_t m_nStations = 2;
4069 NetDeviceContainer m_staDevices;
4070 NetDeviceContainer m_apDevices;
4071
4072 int64_t streamNumber = 100;
4073
4074 NodeContainer wifiApNode;
4075 wifiApNode.Create(1);
4076
4077 NodeContainer wifiStaNodes;
4078 wifiStaNodes.Create(m_nStations);
4079
4080 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
4081 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
4082 spectrumChannel->AddPropagationLossModel(lossModel);
4084 CreateObject<ConstantSpeedPropagationDelayModel>();
4085 spectrumChannel->SetPropagationDelayModel(delayModel);
4086
4088 phy.SetChannel(spectrumChannel);
4089
4090 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue(65535));
4091
4092 WifiHelper wifi;
4093 wifi.SetRemoteStationManager("ns3::IdealWifiManager");
4094
4095 WifiMacHelper mac;
4096 mac.SetType("ns3::StaWifiMac",
4097 "QosSupported",
4098 BooleanValue(true),
4099 "Ssid",
4100 SsidValue(Ssid("non-existent-ssid")));
4101
4102 wifi.SetStandard(WIFI_STANDARD_80211ax);
4103 m_staDevices.Add(wifi.Install(phy, mac, wifiStaNodes.Get(0)));
4104 wifi.SetStandard(WIFI_STANDARD_80211ac);
4105 m_staDevices.Add(wifi.Install(phy, mac, wifiStaNodes.Get(1)));
4106
4107 wifi.SetStandard(WIFI_STANDARD_80211ax);
4108 mac.SetType("ns3::ApWifiMac",
4109 "QosSupported",
4110 BooleanValue(true),
4111 "Ssid",
4112 SsidValue(Ssid("wifi-backoff-ssid")),
4113 "BeaconInterval",
4114 TimeValue(MicroSeconds(102400)),
4115 "EnableBeaconJitter",
4116 BooleanValue(false));
4117
4118 m_apDevices = wifi.Install(phy, mac, wifiApNode);
4119
4120 // schedule association requests at different times
4121 Time init = MilliSeconds(100);
4123
4124 for (uint16_t i = 0; i < m_nStations; i++)
4125 {
4126 dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
4127 Simulator::Schedule(init + i * MicroSeconds(102400),
4129 dev->GetMac(),
4130 Ssid("wifi-backoff-ssid"));
4131 }
4132
4133 // Assign fixed streams to random variables in use
4134 wifi.AssignStreams(m_apDevices, streamNumber);
4135
4136 MobilityHelper mobility;
4137 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
4138
4139 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
4140 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
4141 positionAlloc->Add(Vector(0.0, 1.0, 0.0));
4142 positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
4143 mobility.SetPositionAllocator(positionAlloc);
4144
4145 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
4146 mobility.Install(wifiApNode);
4147 mobility.Install(wifiStaNodes);
4148
4149 // set the TXOP limit on BE AC
4150 dev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
4151 PointerValue ptr;
4152 dev->GetMac()->GetAttribute("BE_Txop", ptr);
4153
4154 PacketSocketHelper packetSocket;
4155 packetSocket.Install(wifiApNode);
4156 packetSocket.Install(wifiStaNodes);
4157
4158 // UL Traffic
4159 for (uint16_t i = 0; i < m_nStations; i++)
4160 {
4161 PacketSocketAddress socket;
4162 socket.SetSingleDevice(m_staDevices.Get(0)->GetIfIndex());
4163 socket.SetPhysicalAddress(m_apDevices.Get(0)->GetAddress());
4164 socket.SetProtocol(1);
4165 Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
4166 client->SetAttribute("PacketSize", UintegerValue(1500));
4167 client->SetAttribute("MaxPackets", UintegerValue(200));
4168 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
4169 client->SetRemote(socket);
4170 wifiStaNodes.Get(i)->AddApplication(client);
4171 client->SetStartTime(MicroSeconds(400000));
4172 client->SetStopTime(Seconds(1.0));
4173 Ptr<PacketSocketClient> legacyStaClient = CreateObject<PacketSocketClient>();
4174 legacyStaClient->SetAttribute("PacketSize", UintegerValue(1500));
4175 legacyStaClient->SetAttribute("MaxPackets", UintegerValue(200));
4176 legacyStaClient->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
4177 legacyStaClient->SetRemote(socket);
4178 wifiStaNodes.Get(i)->AddApplication(legacyStaClient);
4179 legacyStaClient->SetStartTime(MicroSeconds(400000));
4180 legacyStaClient->SetStopTime(Seconds(1.0));
4181 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
4182 server->SetLocal(socket);
4183 wifiApNode.Get(0)->AddApplication(server);
4184 server->SetStartTime(Seconds(0.0));
4185 server->SetStopTime(Seconds(1.0));
4186 }
4187
4188 // Trace dropped packets
4189 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxDrop",
4191
4194
4195 CheckResults();
4196
4198}
4199
4200void
4202{
4203 NS_TEST_EXPECT_MSG_EQ(m_dropped, 0, "Dropped some packets unexpectedly");
4204}
4205
4218{
4219 public:
4221
4222 private:
4223 void DoSetup() override;
4224 void DoTeardown() override;
4225 void DoRun() override;
4226
4233 void SendPpdu(uint16_t centerFreqMhz, uint16_t bandwidthMhz);
4234
4243 RxSignalInfo rxSignalInfo,
4244 WifiTxVector txVector,
4245 std::vector<bool> statusPerMpdu);
4246
4251 void RxFailure(Ptr<const WifiPsdu> psdu);
4252
4259
4271 void CheckRx(uint32_t expectedCountRxSuccess,
4272 uint32_t expectedCountRxFailure,
4273 uint32_t expectedCountRxDropped,
4274 std::optional<Time> expectedLastRxSucceeded,
4275 std::optional<Time> expectedLastRxFailed,
4276 std::optional<Time> expectedLastRxDropped);
4277
4281
4282 std::optional<Time> m_lastRxSucceeded;
4283 std::optional<Time> m_lastRxFailed;
4284 std::optional<Time> m_lastRxDropped;
4285
4288};
4289
4291 : TestCase("Check correct behavior when a STA is receiving a transmission using an unsupported "
4292 "bandwidth"),
4293 m_countRxSuccess(0),
4294 m_countRxFailure(0),
4295 m_countRxDropped(0),
4296 m_lastRxSucceeded(std::nullopt),
4297 m_lastRxFailed(std::nullopt),
4298 m_lastRxDropped(std::nullopt)
4299{
4300}
4301
4302void
4303TestUnsupportedBandwidthReception::SendPpdu(uint16_t centerFreqMhz, uint16_t bandwidthMhz)
4304{
4305 auto txVector =
4306 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, bandwidthMhz, false);
4307
4308 auto pkt = Create<Packet>(1000);
4309 WifiMacHeader hdr;
4310
4312 hdr.SetQosTid(0);
4313
4314 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4315 Time txDuration =
4316 m_rxPhy->CalculateTxDuration(psdu->GetSize(), txVector, m_rxPhy->GetPhyBand());
4317
4318 auto ppdu = Create<HePpdu>(psdu, txVector, m_txPhy->GetOperatingChannel(), txDuration, 0);
4319
4320 auto txPowerSpectrum =
4322 bandwidthMhz,
4323 DbmToW(-50),
4324 bandwidthMhz);
4325
4326 auto txParams = Create<WifiSpectrumSignalParameters>();
4327 txParams->psd = txPowerSpectrum;
4328 txParams->txPhy = nullptr;
4329 txParams->duration = txDuration;
4330 txParams->ppdu = ppdu;
4331 txParams->txWidth = bandwidthMhz;
4332
4333 m_rxPhy->StartRx(txParams, nullptr);
4334}
4335
4336void
4338 RxSignalInfo rxSignalInfo,
4339 WifiTxVector txVector,
4340 std::vector<bool> statusPerMpdu)
4341{
4342 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
4345}
4346
4347void
4349{
4350 NS_LOG_FUNCTION(this << *psdu);
4353}
4354
4355void
4357{
4358 NS_LOG_FUNCTION(this << p << reason);
4362}
4363
4364void
4366 uint32_t expectedCountRxFailure,
4367 uint32_t expectedCountRxDropped,
4368 std::optional<Time> expectedLastRxSucceeded,
4369 std::optional<Time> expectedLastRxFailed,
4370 std::optional<Time> expectedLastRxDropped)
4371{
4373 expectedCountRxSuccess,
4374 "Didn't receive right number of successful packets");
4375
4377 expectedCountRxFailure,
4378 "Didn't receive right number of unsuccessful packets");
4379
4381 expectedCountRxDropped,
4382 "Didn't receive right number of dropped packets");
4383
4384 if (expectedCountRxSuccess > 0)
4385 {
4386 NS_ASSERT(m_lastRxSucceeded.has_value());
4387 NS_ASSERT(expectedLastRxSucceeded.has_value());
4389 expectedLastRxSucceeded.value(),
4390 "Didn't receive the last successful packet at the expected time");
4391 }
4392
4393 if (expectedCountRxFailure > 0)
4394 {
4395 NS_ASSERT(m_lastRxFailed.has_value());
4396 NS_ASSERT(expectedLastRxFailed.has_value());
4398 expectedLastRxFailed.value(),
4399 "Didn't receive the last unsuccessful packet at the expected time");
4400 }
4401
4402 if (expectedCountRxDropped > 0)
4403 {
4404 NS_ASSERT(m_lastRxDropped.has_value());
4405 NS_ASSERT(expectedLastRxDropped.has_value());
4407 expectedLastRxDropped.value(),
4408 "Didn't drop the last filtered packet at the expected time");
4409 }
4410}
4411
4412void
4414{
4415 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
4416 Ptr<Node> node = CreateObject<Node>();
4417 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
4418 m_rxPhy = CreateObject<SpectrumWifiPhy>();
4419 auto rxInterferenceHelper = CreateObject<InterferenceHelper>();
4420 m_rxPhy->SetInterferenceHelper(rxInterferenceHelper);
4421 auto rxErrorRateModel = CreateObject<NistErrorRateModel>();
4422 m_rxPhy->SetErrorRateModel(rxErrorRateModel);
4423 m_rxPhy->SetDevice(dev);
4424 m_rxPhy->AddChannel(spectrumChannel);
4426 dev->SetPhy(m_rxPhy);
4427 node->AddDevice(dev);
4428
4434 "PhyRxDrop",
4436
4437 m_txPhy = CreateObject<SpectrumWifiPhy>();
4438 auto txInterferenceHelper = CreateObject<InterferenceHelper>();
4439 m_txPhy->SetInterferenceHelper(txInterferenceHelper);
4440 auto txErrorRateModel = CreateObject<NistErrorRateModel>();
4441 m_txPhy->SetErrorRateModel(txErrorRateModel);
4442 m_txPhy->AddChannel(spectrumChannel);
4444}
4445
4446void
4448{
4449 m_rxPhy->Dispose();
4450 m_rxPhy = nullptr;
4451
4452 m_txPhy->Dispose();
4453 m_txPhy = nullptr;
4454}
4455
4456void
4458{
4461
4462 int64_t streamNumber = 0;
4463 m_rxPhy->AssignStreams(streamNumber);
4464
4465 // Case 1: the PHY is operating on channel 36 (20 MHz) and receives a 40 MHz PPDU (channel 38).
4466 // The PPDU should be dropped once HE-SIG-A is successfully received, since it contains
4467 // indication about the BW used for the transmission and the PHY shall detect it is larger than
4468 // its operating BW.
4471
4473
4474 auto heSigAExpectedRxTime = Seconds(1.0) + MicroSeconds(32);
4477 this,
4478 0,
4479 0,
4480 1,
4481 std::nullopt,
4482 std::nullopt,
4483 heSigAExpectedRxTime);
4484
4485 // TODO: this test can be extended with other scenarios
4486
4489}
4490
4500{
4501 public:
4503
4504 private:
4505 void DoSetup() override;
4506 void DoRun() override;
4507 void DoTeardown() override;
4508
4515 Ptr<HePpdu> CreatePpdu(uint16_t ppduCenterFreqMhz);
4516
4529 void RunOne(WifiPhyBand band,
4530 uint16_t phyCenterFreqMhz,
4531 uint8_t p20Index,
4532 uint16_t ppduCenterFreqMhz,
4533 bool expectedP20Overlap,
4534 bool expectedP20Covered);
4535
4538};
4539
4541 : TestCase("Check correct detection of whether P20 is fully covered (hence it can be received) "
4542 "or overlaps with the bandwidth of an incoming PPDU")
4543{
4544}
4545
4548{
4549 [[maybe_unused]] auto [channelNumber, centerFreq, channelWidth, type, phyBand] =
4551 ppduCenterFreqMhz,
4552 0,
4554 m_rxPhy->GetPhyBand()));
4555 m_txPhy->SetOperatingChannel(WifiPhy::ChannelTuple{channelNumber, channelWidth, phyBand, 0});
4556 auto txVector =
4557 WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, channelWidth, false);
4558
4559 auto pkt = Create<Packet>(1000);
4561
4562 auto psdu = Create<WifiPsdu>(pkt, hdr);
4563 auto txDuration = m_txPhy->CalculateTxDuration(psdu->GetSize(), txVector, phyBand);
4564
4565 return Create<HePpdu>(psdu, txVector, m_txPhy->GetOperatingChannel(), txDuration, 0);
4566}
4567
4568void
4570{
4571 m_rxPhy = CreateObject<SpectrumWifiPhy>();
4572 auto rxInterferenceHelper = CreateObject<InterferenceHelper>();
4573 m_rxPhy->SetInterferenceHelper(rxInterferenceHelper);
4574 auto rxErrorRateModel = CreateObject<NistErrorRateModel>();
4575 m_rxPhy->SetErrorRateModel(rxErrorRateModel);
4576 m_rxPhy->AddChannel(CreateObject<MultiModelSpectrumChannel>());
4578
4579 m_txPhy = CreateObject<SpectrumWifiPhy>();
4580 auto txInterferenceHelper = CreateObject<InterferenceHelper>();
4581 m_txPhy->SetInterferenceHelper(txInterferenceHelper);
4582 auto txErrorRateModel = CreateObject<NistErrorRateModel>();
4583 m_txPhy->SetErrorRateModel(txErrorRateModel);
4584 m_txPhy->AddChannel(CreateObject<MultiModelSpectrumChannel>());
4586}
4587
4588void
4590{
4591 m_rxPhy->Dispose();
4592 m_rxPhy = nullptr;
4593 m_txPhy->Dispose();
4594 m_txPhy = nullptr;
4595}
4596
4597void
4599 uint16_t phyCenterFreqMhz,
4600 uint8_t p20Index,
4601 uint16_t ppduCenterFreqMhz,
4602 bool expectedP20Overlap,
4603 bool expectedP20Covered)
4604{
4605 [[maybe_unused]] const auto [channelNumber, centerFreq, channelWidth, type, phyBand] =
4606 (*WifiPhyOperatingChannel::FindFirst(0, phyCenterFreqMhz, 0, WIFI_STANDARD_80211ax, band));
4607
4609 WifiPhy::ChannelTuple{channelNumber, channelWidth, band, p20Index});
4611 auto p20MinFreq = p20CenterFreq - 10;
4612 auto p20MaxFreq = p20CenterFreq + 10;
4613
4614 auto ppdu = CreatePpdu(ppduCenterFreqMhz);
4615
4616 auto p20Overlap = ppdu->DoesOverlapChannel(p20MinFreq, p20MaxFreq);
4617 NS_TEST_ASSERT_MSG_EQ(p20Overlap,
4618 expectedP20Overlap,
4619 "PPDU is " << (expectedP20Overlap ? "expected" : "not expected")
4620 << " to overlap with the P20");
4621
4622 auto p20Covered =
4624 ->CanStartRx(
4625 ppdu,
4626 ppdu->GetTxVector()
4627 .GetChannelWidth()); // CanStartRx returns true is the P20 is fully covered
4628 NS_TEST_ASSERT_MSG_EQ(p20Covered,
4629 expectedP20Covered,
4630 "PPDU is " << (expectedP20Covered ? "expected" : "not expected")
4631 << " to cover the whole P20");
4632}
4633
4634void
4636{
4637 /*
4638 * Receiver PHY Operating Channel: 2.4 GHz Channel 4 (2417 MHz – 2437 MHz)
4639 * Transmitted 20 MHz PPDU: 2.4 GHz Channel 4 (2417 MHz – 2437 MHz)
4640 * Overlap with primary 20 MHz: yes
4641 * Primary 20 MHz fully covered: yes
4642 */
4643 RunOne(WIFI_PHY_BAND_2_4GHZ, 2427, 0, 2427, true, true);
4644
4645 /*
4646 * Receiver PHY Operating Channel: 2.4 GHz Channel 4 (2417 MHz – 2437 MHz)
4647 * Transmitted 20 MHz PPDU: 2.4 GHz Channel 6 (2427 MHz – 2447 MHz)
4648 * Overlap with primary 20 MHz: yes
4649 * Primary 20 MHz fully covered: no
4650 */
4651 RunOne(WIFI_PHY_BAND_2_4GHZ, 2427, 0, 2437, true, false);
4652
4653 /*
4654 * Receiver PHY Operating Channel: 5 GHz Channel 36 (5170 MHz – 5190 MHz)
4655 * Transmitted 40 MHz PPDU: 5 GHz Channel 38 (5170 MHz – 5210 MHz)
4656 * Overlap with primary 20 MHz: yes
4657 * Primary 20 MHz fully covered: yes
4658 */
4659 RunOne(WIFI_PHY_BAND_5GHZ, 5180, 0, 5190, true, true);
4660
4661 /*
4662 * Receiver PHY Operating Channel: 5 GHz Channel 36 (5170 MHz–5190 MHz)
4663 * Transmitted 20 MHz PPDU: 5 GHz Channel 40 (5190 MHz – 5210 MHz)
4664 * Overlap with primary 20 MHz: no
4665 * Primary 20 MHz fully covered: no
4666 */
4667 RunOne(WIFI_PHY_BAND_5GHZ, 5180, 0, 5200, false, false);
4668
4669 /*
4670 * Receiver PHY Operating Channel: 5 GHz Channel 38 (5170 MHz – 5210 MHz) with P20 index 0
4671 * Transmitted 20 MHz PPDU: 5 GHz Channel 36 (5170 MHz – 5190 MHz)
4672 * Overlap with primary 20 MHz: yes
4673 * Primary 20 MHz fully covered: yes
4674 */
4675 RunOne(WIFI_PHY_BAND_5GHZ, 5190, 0, 5180, true, true);
4676
4677 /*
4678 * Receiver PHY Operating Channel: 5 GHz Channel 38 (5170 MHz – 5210 MHz) with P20 index 1
4679 * Transmitted 20 MHz PPDU: 5 GHz Channel 36 (5170 MHz – 5190 MHz)
4680 * Overlap with primary 20 MHz: no
4681 * Primary 20 MHz fully covered: no
4682 */
4683 RunOne(WIFI_PHY_BAND_5GHZ, 5190, 1, 5180, false, false);
4684
4686}
4687
4698{
4699 public:
4706 TestSpectrumChannelWithBandwidthFilter(uint16_t channel, uint16_t expectedValue);
4707
4708 protected:
4709 void DoSetup() override;
4710 void DoTeardown() override;
4711
4712 private:
4721 void RxBegin(bool signalType, uint32_t senderNodeId, double rxPower, Time duration);
4722
4726 void Send() const;
4727
4733 void CheckRxPacketCount(uint16_t expectedValue);
4734
4735 void DoRun() override;
4736
4740 uint16_t m_channel{36};
4741 uint16_t m_expectedValue{0};
4742};
4743
4745 uint16_t channel,
4746 uint16_t expectedValue)
4747 : TestCase("Test for early discard of signal in single-model-spectrum-channel::StartTx()"),
4748 m_channel(channel),
4749 m_expectedValue(expectedValue)
4750{
4751}
4752
4753void
4755{
4756 WifiTxVector txVector =
4757 WifiTxVector(HePhy::GetHeMcs7(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false);
4758
4759 Ptr<Packet> pkt = Create<Packet>(1000);
4760 WifiMacHeader hdr;
4761
4763 hdr.SetQosTid(0);
4764
4765 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4766 m_tx->Send(psdu, txVector);
4767}
4768
4769void
4771{
4773 expectedValue,
4774 "Received a different amount of packets than expected.");
4775}
4776
4777void
4779 uint32_t senderNodeId [[maybe_unused]],
4780 double rxPower [[maybe_unused]],
4781 Time duration [[maybe_unused]])
4782{
4783 NS_LOG_FUNCTION(this << signalType << senderNodeId << rxPower << duration);
4785}
4786
4787void
4789{
4790 NS_LOG_FUNCTION(this);
4791 Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel>();
4792
4793 Ptr<WifiBandwidthFilter> wifiFilter = CreateObject<WifiBandwidthFilter>();
4794 channel->AddSpectrumTransmitFilter(wifiFilter);
4795
4796 Ptr<Node> node = CreateObject<Node>();
4797 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
4798 m_tx = CreateObject<SpectrumWifiPhy>();
4799 m_tx->SetDevice(dev);
4800 m_tx->SetTxPowerStart(20);
4801 m_tx->SetTxPowerEnd(20);
4802
4803 Ptr<Node> nodeRx = CreateObject<Node>();
4804 Ptr<WifiNetDevice> devRx = CreateObject<WifiNetDevice>();
4805 m_rx = CreateObject<SpectrumWifiPhy>();
4806 m_rx->SetDevice(devRx);
4807
4808 Ptr<InterferenceHelper> interferenceTx = CreateObject<InterferenceHelper>();
4809 m_tx->SetInterferenceHelper(interferenceTx);
4810 Ptr<ErrorRateModel> errorTx = CreateObject<NistErrorRateModel>();
4811 m_tx->SetErrorRateModel(errorTx);
4812
4813 Ptr<InterferenceHelper> interferenceRx = CreateObject<InterferenceHelper>();
4814 m_rx->SetInterferenceHelper(interferenceRx);
4815 Ptr<ErrorRateModel> errorRx = CreateObject<NistErrorRateModel>();
4816 m_rx->SetErrorRateModel(errorRx);
4817
4818 m_tx->AddChannel(channel);
4819 m_rx->AddChannel(channel);
4820
4823
4824 dev->SetPhy(m_tx);
4825 node->AddDevice(dev);
4826 devRx->SetPhy(m_rx);
4827 nodeRx->AddDevice(devRx);
4828
4830 "SignalArrival",
4832}
4833
4834void
4836{
4837 m_tx->Dispose();
4838 m_rx->Dispose();
4839}
4840
4841void
4843{
4844 NS_LOG_FUNCTION(this);
4847
4851 this,
4853
4856}
4857
4865{
4866 public:
4868};
4869
4871 : TestSuite("wifi-phy-reception", UNIT)
4872{
4881 // The below three test cases are related. The test involves a receiver tuned to
4882 // channel 36 and a transmitter sending on channels 36, 40, and 44, respectively.
4883 // The second argument corresponds to the number of signals expected to be received.
4884 // Signals on channel 36 and 40 will fall within the receiver bandwidth, while
4885 // a signal on channel 44 will fall completely outside and will be filtered.
4889}
4890
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.