A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-phy-rx-trace-helper-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 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#include "ns3/ampdu-tag.h"
18#include "ns3/ap-wifi-mac.h"
19#include "ns3/boolean.h"
20#include "ns3/config.h"
21#include "ns3/constant-position-mobility-model.h"
22#include "ns3/double.h"
23#include "ns3/eht-configuration.h"
24#include "ns3/he-phy.h"
25#include "ns3/he-ppdu.h"
26#include "ns3/interference-helper.h"
27#include "ns3/log.h"
28#include "ns3/mobility-helper.h"
29#include "ns3/mpdu-aggregator.h"
30#include "ns3/multi-model-spectrum-channel.h"
31#include "ns3/nist-error-rate-model.h"
32#include "ns3/ofdm-ppdu.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-phy-rx-trace-helper.h"
50#include "ns3/wifi-psdu.h"
51#include "ns3/wifi-spectrum-phy-interface.h"
52#include "ns3/wifi-spectrum-signal-parameters.h"
53#include "ns3/wifi-spectrum-value-helper.h"
54#include "ns3/wifi-utils.h"
55#include "ns3/yans-wifi-channel.h"
56#include "ns3/yans-wifi-phy.h"
57#include <ns3/propagation-loss-model.h>
58
59#include <optional>
60
61using namespace ns3;
62
63NS_LOG_COMPONENT_DEFINE("WifiPhyRxTraceHelperTest");
64
65/**
66 * \ingroup wifi-test
67 * \brief Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY)
68 * frames (PPDU) with multiple MAC Protocol Data Units (MPDUs).
69 *
70 * This class extends the TestCase class to simulate and analyze the reception of PPDUs containing
71 * either one or two MPDUs. It specifically tests the PHY layer's capability to handle multiple
72 * MPDUs addressed to specific receivers, measuring success and failure rates. The simulation setup
73 * includes configuring transmit and receive power levels, and the class provides functionality to
74 * check statistics related to PPDU and MPDU reception success and failure, as well as overlap
75 * handling.
76 */
78{
79 public:
80 /**
81 * Constructs a TestWifiPhyRxTraceHelper instance with a given test name.
82 * \param test_name The name of the test case.
83 */
84 TestWifiPhyRxTraceHelper(std::string test_name);
85
86 /**
87 * Destructor.
88 */
89 ~TestWifiPhyRxTraceHelper() override = default;
90
91 private:
92 void DoSetup() override;
93 void DoRun() override;
94 void DoTeardown() override;
95
96 /**
97 * Sends a PPDU containing two MPDUs addressed to specific receivers.
98 * \param rxPowerDbm The transmit power in dBm.
99 * \param add1 The MAC address of the first receiver.
100 * \param add2 The MAC address of the second receiver.
101 * \param tx_phy The transmitting PHY object.
102 */
103 void SendPpduWithTwoMpdus(double rxPowerDbm,
104 Mac48Address add1,
105 Mac48Address add2,
107
108 /**
109 * Sends a PPDU containing one MPDU addressed to a specific receiver.
110 * \param rxPowerDbm The transmit power in dBm.
111 * \param add1 The MAC address of the receiver.
112 * \param tx_phy The transmitting PHY object.
113 */
114 void SendPpduWithOneMpdu(double rxPowerDbm,
115 Mac48Address add1,
117
118 /**
119 * Checks the statistics of PPDU and MPDU reception success and failure.
120 * \param expectedPpduSuccess The expected number of successful PPDU receptions.
121 * \param expectedPpduFailure The expected number of failed PPDU receptions.
122 * \param expectedMpduSuccess The expected number of successful MPDU receptions within PPDUs.
123 * \param expectedMpduFailure The expected number of failed MPDU receptions within PPDUs.
124 * \param expectedOverlaps The expected number of overlapping reception events.
125 * \param expectedNonOverlaps The expected number of non-overlapping reception events.
126 */
127 void CheckAllStats(uint64_t expectedPpduSuccess,
128 uint64_t expectedPpduFailure,
129 uint64_t expectedMpduSuccess,
130 uint64_t expectedMpduFailure,
131 uint64_t expectedOverlaps,
132 uint64_t expectedNonOverlaps);
133
134 /**
135 * Checks the statistics of PPDU and MPDU reception success and failure.
136 * \param expectedStats The expected counts for PPDU and MPDU reception.
137 * @param nodeId The node ID for which to check the received stats.
138 * @param deviceId The device ID for which to check the received stats.
139 * @param linkId The link ID for which to check the received stats.
140 */
141 void CheckStats(WifiPhyTraceStatistics expectedStats,
142 uint32_t nodeId,
143 uint32_t deviceId,
144 uint32_t linkId);
145
146 /**
147 * Checks the statistics of PPDU and MPDU reception success and failure.
148 * \param expectedRecordCount The expected number of records.
149 */
150 void CheckRecords(uint64_t expectedRecordCount);
151
153 Mac48Address("00:00:00:00:00:01"); ///< The MAC address representing an incorrect receiver,
154 ///< used for testing.
156 Mac48Address("00:00:00:00:00:03"); ///< The MAC address representing the correct receiver,
157 ///< used for testing.
158
159 std::map<ns3::Mac48Address, uint32_t> MacToNodeId = {
160 {Mac48Address("00:00:00:00:00:04"), 0},
161 {Mac48Address("00:00:00:00:00:05"), 1},
162 {correctReceiver, 2},
163 {wrongReceiver, 3}}; ///< Maps MAC addresses to node IDs. This is done since there is no MAC
164 ///< layer configured and therefore the helper cannot obtain the MAC
165 ///< addresses automatically.
166
167 Ptr<Node> nodeRx; ///< The receiving node
168 Ptr<SpectrumWifiPhy> m_txA{nullptr}; ///< The transmit function for node A.
169 Ptr<SpectrumWifiPhy> m_txB{nullptr}; ///< The transmit function for node B.
170 Ptr<SpectrumWifiPhy> m_rx{nullptr}; ///< The receive function for testing.
171
173 m_rxTraceHelper; ///< The helper being tested for tracking PHY reception events.
174};
175
177 : TestCase{test_name}
178{
179}
180
181void
183{
184 double txPower = 20;
185
186 auto spectrumChannel = CreateObject<SingleModelSpectrumChannel>();
187
188 auto nodeA = CreateObject<Node>();
189 auto devA = CreateObject<WifiNetDevice>();
190 m_txA = CreateObject<SpectrumWifiPhy>();
191 m_txA->SetDevice(devA);
192 m_txA->SetTxPowerStart(txPower);
193 m_txA->SetTxPowerEnd(txPower);
194
195 auto nodeB = CreateObject<Node>();
196 auto devB = CreateObject<WifiNetDevice>();
197 m_txB = CreateObject<SpectrumWifiPhy>();
198 m_txB->SetDevice(devB);
199 m_txB->SetTxPowerStart(txPower);
200 m_txB->SetTxPowerEnd(txPower);
201
202 nodeRx = CreateObject<Node>();
203 auto devRx = CreateObject<WifiNetDevice>();
204 m_rx = CreateObject<SpectrumWifiPhy>();
205 m_rx->SetDevice(devRx);
206
207 Ptr<InterferenceHelper> interferenceTxA = CreateObject<InterferenceHelper>();
208 m_txA->SetInterferenceHelper(interferenceTxA);
209 auto errorTxA = CreateObject<NistErrorRateModel>();
210 m_txA->SetErrorRateModel(errorTxA);
211
212 auto interferenceTxB = CreateObject<InterferenceHelper>();
213 m_txB->SetInterferenceHelper(interferenceTxB);
214 auto errorTxB = CreateObject<NistErrorRateModel>();
215 m_txB->SetErrorRateModel(errorTxB);
216
217 auto interferenceRx = CreateObject<InterferenceHelper>();
218 m_rx->SetInterferenceHelper(interferenceRx);
219 auto errorRx = CreateObject<NistErrorRateModel>();
220 m_rx->SetErrorRateModel(errorRx);
221
222 m_txA->AddChannel(spectrumChannel);
223 m_txB->AddChannel(spectrumChannel);
224 m_rx->AddChannel(spectrumChannel);
225
229
233
234 devA->SetPhy(m_txA);
235 nodeA->AddDevice(devA);
236 devB->SetPhy(m_txB);
237 nodeB->AddDevice(devB);
238 devRx->SetPhy(m_rx);
239 nodeRx->AddDevice(devRx);
240
242 nodes.Add(nodeA);
243 nodes.Add(nodeB);
245
247
248 auto preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel>();
249 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
250 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
251 m_rx->SetPreambleDetectionModel(preambleDetectionModel);
252}
253
254void
256{
257 m_txA->Dispose();
258 m_txB->Dispose();
259 m_rx->Dispose();
260}
261
262void
264 Mac48Address receiver1,
265 Mac48Address receiver2,
267{
268 double txPower = rxPowerDbm;
269 tx_phy->SetTxPowerStart(txPower);
270 tx_phy->SetTxPowerEnd(txPower);
271
272 WifiTxVector txVector =
273 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, true);
274
275 std::vector<Ptr<WifiMpdu>> mpduList;
276
277 WifiMacHeader hdr1;
279 hdr1.SetQosTid(0);
280 hdr1.SetAddr1(receiver1); // Changing the expected receiver
281 auto p1 = Create<Packet>(750);
282 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
283
284 WifiMacHeader hdr2;
286 hdr2.SetQosTid(0);
287 hdr2.SetAddr1(receiver2); // Changing the expected receiver
288 auto p2 = Create<Packet>(750);
289 mpduList.emplace_back(Create<WifiMpdu>(p2, hdr2));
290
291 auto psdu = Create<WifiPsdu>(mpduList);
292
293 tx_phy->Send(psdu, txVector);
294}
295
296void
298 Mac48Address receiver1,
300{
301 double txPower = rxPowerDbm;
302 tx_phy->SetTxPowerStart(txPower);
303 tx_phy->SetTxPowerEnd(txPower);
304
305 WifiTxVector txVector =
306 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, true);
307
308 std::vector<Ptr<WifiMpdu>> mpduList;
309
310 WifiMacHeader hdr1;
312 hdr1.SetQosTid(0);
313 hdr1.SetAddr1(receiver1); // Changing the expected receiver
314 auto p1 = Create<Packet>(750);
315 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
316
317 auto psdu = Create<WifiPsdu>(mpduList);
318 tx_phy->Send(psdu, txVector);
319}
320
321void
322TestWifiPhyRxTraceHelper::CheckAllStats(uint64_t expectedPpduSuccess,
323 uint64_t expectedPpduFailure,
324 uint64_t expectedMpduSuccess,
325 uint64_t expectedMpduFailure,
326 uint64_t expectedOverlaps,
327 uint64_t expectedNonOverlaps)
328{
330
332 expectedPpduSuccess,
333 "Didn't receive right number of successful PPDUs");
335 expectedPpduFailure,
336 "Didn't receive right number of unsuccessful PPDUs");
338 expectedMpduSuccess,
339 "Didn't receive right number of successful MPDUs");
341 expectedMpduFailure,
342 "Didn't receive right number of unsuccessful MPDUs");
344 expectedOverlaps,
345 "Didn't receive right number of overlapping PPDUs");
347 expectedNonOverlaps,
348 "Didn't receive right number of nonoverlapping PPDUs");
350}
351
352void
354 uint32_t nodeId,
355 uint32_t deviceId,
356 uint32_t linkId)
357{
358 WifiPhyTraceStatistics stats = m_rxTraceHelper.GetStatistics(nodeId, deviceId, linkId);
359
361 expectedStats.m_receivedPpdus,
362 "Didn't receive right number of successful PPDUs");
364 expectedStats.m_failedPpdus,
365 "Didn't receive right number of unsuccessful PPDUs");
367 expectedStats.m_receivedMpdus,
368 "Didn't receive right number of successful MPDUs");
370 expectedStats.m_failedMpdus,
371 "Didn't receive right number of unsuccessful MPDUs");
373 expectedStats.m_overlappingPpdus,
374 "Didn't receive right number of overlapping PPDUs");
376 expectedStats.m_nonOverlappingPpdus,
377 "Didn't receive right number of nonoverlapping PPDUs");
378}
379
380void
381TestWifiPhyRxTraceHelper::CheckRecords(uint64_t expectedRecordCount)
382{
383 auto records = m_rxTraceHelper.GetPpduRecords();
384 NS_TEST_ASSERT_MSG_EQ(records.size(),
385 expectedRecordCount,
386 "Didn't produce the right number of Records");
387}
388
389void
391{
394 int64_t streamNumber = 1;
395 double rxPowerDbm = -80;
396 streamNumber += m_txA->AssignStreams(streamNumber);
397 streamNumber += m_txB->AssignStreams(streamNumber);
398 streamNumber += m_rx->AssignStreams(streamNumber);
399 WifiPhyTraceStatistics expectedStats;
400
402
403 // CASE 1: PPDU Reception with Sufficient RSSI With SOME Frames Addressed to Receiver
404 expectedStats.m_receivedPpdus = 1;
405 expectedStats.m_failedPpdus = 0;
406 expectedStats.m_receivedMpdus = 1;
407 expectedStats.m_failedMpdus = 0;
408 expectedStats.m_overlappingPpdus = 0;
409 expectedStats.m_nonOverlappingPpdus = 1;
410
411 // A-MPDU 1
414 this,
415 rxPowerDbm,
416 correctReceiver, // One MPDU addressed to
417 wrongReceiver, // One MPDU addressed to
418 m_txA);
419
422 this,
423 2); // Total Records
424
427 this,
428 expectedStats,
429 nodeRx->GetId(),
430 0,
431 0);
432
435 this,
436 expectedStats.m_receivedPpdus,
437 expectedStats.m_failedPpdus,
438 expectedStats.m_receivedMpdus,
439 expectedStats.m_failedMpdus,
440 expectedStats.m_overlappingPpdus,
441 expectedStats.m_nonOverlappingPpdus);
442
443 // CASE 2: PPDU Reception with inSufficient RSSI With SOME Frames Addressed to Receiver
444 expectedStats.m_receivedPpdus = 0;
445 expectedStats.m_failedPpdus = 1;
446 expectedStats.m_receivedMpdus = 0;
447 expectedStats.m_failedMpdus = 1;
448 expectedStats.m_overlappingPpdus = 0;
449 expectedStats.m_nonOverlappingPpdus = 1;
450 rxPowerDbm = -83;
451 // A-MPDU 1
454 this,
455 rxPowerDbm,
456 correctReceiver, // One MPDU addressed to
457 wrongReceiver, // One MPDU addressed to
458 m_txA);
459
462 this,
463 2); // TotalRecords
464
467 this,
468 expectedStats,
469 nodeRx->GetId(),
470 0,
471 0);
472
475 this,
476 expectedStats.m_receivedPpdus,
477 expectedStats.m_failedPpdus,
478 expectedStats.m_receivedMpdus,
479 expectedStats.m_failedMpdus,
480 expectedStats.m_overlappingPpdus,
481 expectedStats.m_nonOverlappingPpdus);
482
483 // CASE 3: PPDU Reception with Sufficient RSSI/SNR With NO Frames Addressed to Receiver
484 expectedStats.m_receivedPpdus = 0;
485 expectedStats.m_failedPpdus = 0;
486 expectedStats.m_receivedMpdus = 0;
487 expectedStats.m_failedMpdus = 0;
488 expectedStats.m_overlappingPpdus = 0;
489 expectedStats.m_nonOverlappingPpdus = 0;
490 rxPowerDbm = -80;
491 // A-MPDU 1
494 this,
495 rxPowerDbm,
496 wrongReceiver, // One MPDU addressed to
497 wrongReceiver, // One MPDU addressed to
498 m_txA);
499
502 this,
503 2); // TotalRecords
504
507 this,
508 expectedStats,
509 nodeRx->GetId(),
510 0,
511 0);
512
515 this,
516 expectedStats.m_receivedPpdus,
517 expectedStats.m_failedPpdus,
518 expectedStats.m_receivedMpdus,
519 expectedStats.m_failedMpdus,
520 expectedStats.m_overlappingPpdus,
521 expectedStats.m_nonOverlappingPpdus);
522
523 // CASE 4: PPDU Reception with Insufficient RSSI/SNR With NO Frames Addressed to Receiver
524 expectedStats.m_receivedPpdus = 0;
525 expectedStats.m_failedPpdus = 0;
526 expectedStats.m_receivedMpdus = 0;
527 expectedStats.m_failedMpdus = 0;
528 expectedStats.m_overlappingPpdus = 0;
529 expectedStats.m_nonOverlappingPpdus = 0;
530 rxPowerDbm = -83;
531 // A-MPDU 1
534 this,
535 rxPowerDbm,
536 wrongReceiver, // One MPDU addressed to
537 wrongReceiver, // One MPDU addressed to
538 m_txA);
539
542 this,
543 2); // TotalRecords
544
547 this,
548 expectedStats,
549 nodeRx->GetId(),
550 0,
551 0);
552
555 this,
556 expectedStats.m_receivedPpdus,
557 expectedStats.m_failedPpdus,
558 expectedStats.m_receivedMpdus,
559 expectedStats.m_failedMpdus,
560 expectedStats.m_overlappingPpdus,
561 expectedStats.m_nonOverlappingPpdus);
562
563 // CASE 5: PPDU Overlapping Reception with sufficient RSSI/SNR With ALL Frames Addressed to
564 // Receiver
565 expectedStats.m_receivedPpdus = 0;
566 expectedStats.m_failedPpdus = 2;
567 expectedStats.m_receivedMpdus = 0;
568 expectedStats.m_failedMpdus = 2;
569 expectedStats.m_overlappingPpdus = 2;
570 expectedStats.m_nonOverlappingPpdus = 0;
571 rxPowerDbm = -80;
572 // A-MPDU 1
575 this,
576 rxPowerDbm,
577 correctReceiver, // One MPDU addressed to
578 m_txA);
579 // A-MPDU 2
582 this,
583 rxPowerDbm,
584 correctReceiver, // One MPDU addressed to
585 m_txB);
586
589 this,
590 4); // TotalRecords
591
594 this,
595 expectedStats,
596 nodeRx->GetId(),
597 0,
598 0);
599
602 this,
603 expectedStats.m_receivedPpdus,
604 expectedStats.m_failedPpdus,
605 expectedStats.m_receivedMpdus,
606 expectedStats.m_failedMpdus,
607 expectedStats.m_overlappingPpdus,
608 expectedStats.m_nonOverlappingPpdus);
609
610 // CASE 6: PPDU Overlapping Reception with sufficient RSSI/SNR With SOME Frames Addressed to
611 // Receiver
612 expectedStats.m_receivedPpdus = 0;
613 expectedStats.m_failedPpdus = 1;
614 expectedStats.m_receivedMpdus = 0;
615 expectedStats.m_failedMpdus = 1;
616 expectedStats.m_overlappingPpdus = 1;
617 expectedStats.m_nonOverlappingPpdus = 0;
618 rxPowerDbm = -80;
619 // A-MPDU 1
622 this,
623 rxPowerDbm,
624 correctReceiver, // One MPDU addressed to
625 m_txA);
626 // A-MPDU 2
629 this,
630 rxPowerDbm,
631 wrongReceiver, // One MPDU addressed to
632 m_txB);
633
636 this,
637 4); // TotalRecords
638
641 this,
642 expectedStats,
643 nodeRx->GetId(),
644 0,
645 0);
646
649 this,
650 expectedStats.m_receivedPpdus,
651 expectedStats.m_failedPpdus,
652 expectedStats.m_receivedMpdus,
653 expectedStats.m_failedMpdus,
654 expectedStats.m_overlappingPpdus,
655 expectedStats.m_nonOverlappingPpdus);
656
657 // Stop Statistics Collection Period Since following testcases evaluate the Start and Stop
658 // methods
660
661 // CASE 7: Execution of "Start()" Before Signal Injection
662 expectedStats.m_receivedPpdus = 1;
663 expectedStats.m_failedPpdus = 0;
664 expectedStats.m_receivedMpdus = 1;
665 expectedStats.m_failedMpdus = 0;
666 expectedStats.m_overlappingPpdus = 0;
667 expectedStats.m_nonOverlappingPpdus = 1;
668 rxPowerDbm = -80;
670
671 // A-MPDU 1
674 this,
675 rxPowerDbm,
676 correctReceiver, // One MPDU addressed to
677 m_txA);
678
681 this,
682 2); // TotalRecords
683
686 this,
687 expectedStats,
688 nodeRx->GetId(),
689 0,
690 0);
691
694 this,
695 expectedStats.m_receivedPpdus,
696 expectedStats.m_failedPpdus,
697 expectedStats.m_receivedMpdus,
698 expectedStats.m_failedMpdus,
699 expectedStats.m_overlappingPpdus,
700 expectedStats.m_nonOverlappingPpdus);
701
703
704 // CASE 8: Activation of "Start()" Followed by "Stop()" Before Signal Injection
705 expectedStats.m_receivedPpdus = 0;
706 expectedStats.m_failedPpdus = 0;
707 expectedStats.m_receivedMpdus = 0;
708 expectedStats.m_failedMpdus = 0;
709 expectedStats.m_overlappingPpdus = 0;
710 expectedStats.m_nonOverlappingPpdus = 0;
711 rxPowerDbm = -80;
712
714
716
717 // A-MPDU 1
720 this,
721 rxPowerDbm,
722 correctReceiver, // One MPDU addressed to
723 m_txA);
724
727 this,
728 0); // TotalRecords
729
732 this,
733 expectedStats,
734 nodeRx->GetId(),
735 0,
736 0);
737
740 this,
741 expectedStats.m_receivedPpdus,
742 expectedStats.m_failedPpdus,
743 expectedStats.m_receivedMpdus,
744 expectedStats.m_failedMpdus,
745 expectedStats.m_overlappingPpdus,
746 expectedStats.m_nonOverlappingPpdus);
747
748 // CASE 9: "Start()" Method Initiated During Ongoing PPDU Reception
749 expectedStats.m_receivedPpdus = 1;
750 expectedStats.m_failedPpdus = 0;
751 expectedStats.m_receivedMpdus = 1;
752 expectedStats.m_failedMpdus = 0;
753 expectedStats.m_overlappingPpdus = 0;
754 expectedStats.m_nonOverlappingPpdus = 1;
755 rxPowerDbm = -80;
756
757 // A-MPDU 1
760 this,
761 rxPowerDbm,
762 correctReceiver, // One MPDU addressed to
763 m_txA);
764
766
769 this,
770 2); // TotalRecords
771
774 this,
775 expectedStats,
776 nodeRx->GetId(),
777 0,
778 0);
779
782 this,
783 expectedStats.m_receivedPpdus,
784 expectedStats.m_failedPpdus,
785 expectedStats.m_receivedMpdus,
786 expectedStats.m_failedMpdus,
787 expectedStats.m_overlappingPpdus,
788 expectedStats.m_nonOverlappingPpdus);
789
791
792 // CASE 10: Execution of "Stop()" During Ongoing PPDU Reception
793 expectedStats.m_receivedPpdus = 0;
794 expectedStats.m_failedPpdus = 0;
795 expectedStats.m_receivedMpdus = 0;
796 expectedStats.m_failedMpdus = 0;
797 expectedStats.m_overlappingPpdus = 0;
798 expectedStats.m_nonOverlappingPpdus = 0;
799 rxPowerDbm = -80;
800
802
803 // A-MPDU 1
806 this,
807 rxPowerDbm,
808 correctReceiver, // One MPDU addressed to
809 m_txA);
810
812
815 this,
816 0); // TotalRecords
817
820 this,
821 expectedStats,
822 nodeRx->GetId(),
823 0,
824 0);
825
828 this,
829 expectedStats.m_receivedPpdus,
830 expectedStats.m_failedPpdus,
831 expectedStats.m_receivedMpdus,
832 expectedStats.m_failedMpdus,
833 expectedStats.m_overlappingPpdus,
834 expectedStats.m_nonOverlappingPpdus);
835
838}
839
840/**
841 * \ingroup wifi-test
842 * \brief Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY)
843 * frames (PPDU) containing multiple MAC Protocol Data Units (MPDUs) in Multi-Link Operation (MLO)
844 * contexts.
845 *
846 * This class extends the TestCase class to simulate and analyze the reception of PPDUs containing
847 * either one or two MPDUs in MLO setups. It specifically assesses the WifiPhyRxTraceHelper
848 * ability to manage MLO by handling multiple MPDUs addressed to specific receivers across different
849 * links, measuring success and failure rates. The simulation setup includes configuring transmit
850 * and receive power levels and provides functionality to check statistics related to PPDU and MPDU
851 * reception success and failure, as well overlaps and non-overlaps in reception
852 * events.
853 */
855{
856 public:
857 /**
858 * Constructs a TestWifiPhyRxTraceHelperMloStr instance for MLO reception testing.
859 */
861
862 private:
863 void DoSetup() override;
864 void DoRun() override;
865
866 void DoTeardown() override;
867
868 /**
869 * Sends a PPDU containing two MPDUs addressed to specific receivers, simulating an MLO
870 * scenario.
871 * \param rxPowerDbm The transmit power in dBm.
872 * \param add1 The MAC address of the first receiver.
873 * \param add2 The MAC address of the second receiver.
874 * \param tx_phy The transmitting PHY object for MLO.
875 */
876 void SendPpduWithTwoMpdus(double rxPowerDbm,
877 Mac48Address add1,
878 Mac48Address add2,
880
881 /**
882 * Sends a PPDU containing one MPDU addressed to a specific receiver, within an MLO setup.
883 * \param rxPowerDbm The transmit power in dBm.
884 * \param add1 The MAC address of the receiver.
885 * \param tx_phy The transmitting PHY object for MLO.
886 */
887 void SendPpduWithOneMpdu(double rxPowerDbm,
888 Mac48Address add1,
890
891 /**
892 * Checks the statistics of PPDU and MPDU reception success and failure.
893 * \param expectedStats The expected counts for PPDU and MPDU reception.
894 * @param nodeId The node ID for which to check the received stats.
895 */
896 void CheckStats(WifiPhyTraceStatistics expectedStats, uint32_t nodeId);
897
898 /**
899 * Checks the statistics of PPDU and MPDU reception success and failure.
900 * \param expectedStats The expected counts for PPDU and MPDU reception.
901 * @param nodeId The node ID for which to check the received stats.
902 * @param deviceId The device ID for which to check the received stats.
903 */
904 void CheckStats(WifiPhyTraceStatistics expectedStats, uint32_t nodeId, uint32_t deviceId);
905
906 /**
907 * Checks the statistics of PPDU and MPDU reception success and failure.
908 * \param expectedStats The expected counts for PPDU and MPDU reception.
909 * @param nodeId The node ID for which to check the received stats.
910 * @param deviceId The device ID for which to check the received stats.
911 * @param linkId The link ID for which to check the received stats.
912 */
913 void CheckStats(WifiPhyTraceStatistics expectedStats,
914 uint32_t nodeId,
915 uint32_t deviceId,
916 uint32_t linkId);
917
918 /**
919 * Checks the statistics of PPDU and MPDU reception success and failure in MLO scenarios.
920 * \param expectedPpduSuccess The expected number of successful PPDU receptions.
921 * \param expectedPpduFailure The expected number of failed PPDU receptions.
922 * \param expectedMpduSuccess The expected number of successful MPDU receptions within PPDUs.
923 * \param expectedMpduFailure The expected number of failed MPDU receptions within PPDUs.
924 * \param expectedOverlaps The expected number of overlapping reception events.
925 * \param expectedNonOverlaps The expected number of non-overlapping reception events.
926 */
927 void CheckAllStats(uint64_t expectedPpduSuccess,
928 uint64_t expectedPpduFailure,
929 uint64_t expectedMpduSuccess,
930 uint64_t expectedMpduFailure,
931 uint64_t expectedOverlaps,
932 uint64_t expectedNonOverlaps);
933
934 /**
935 * Checks the statistics of PPDU and MPDU reception success and failure.
936 * \param expectedRecordCount The expected number of records.
937 */
938 void CheckRecords(uint64_t expectedRecordCount);
939
941 Mac48Address("00:00:00:00:00:01"); ///< The MAC address representing an incorrect receiver,
942 ///< used for testing in MLO.
944 Mac48Address("00:00:00:00:00:03"); ///< The MAC address representing the correct receiver,
945 ///< used for testing in MLO.
946
947 std::map<ns3::Mac48Address, uint32_t> MacToNodeId = {
948 {Mac48Address("00:00:00:00:00:04"), 0},
949 {Mac48Address("00:00:00:00:00:05"), 1},
950 {correctReceiver, 2},
951 {wrongReceiver, 3}}; ///< Maps MAC addresses to node IDs for MLO test configuration. This is
952 ///< done since there is no MAC layer configured and therefore the
953 ///< helper cannot obtain the MAC addresses automatically.
954
955 NodeContainer wifiNodes; ///< All wifi nodes
956 Ptr<SpectrumWifiPhy> m_tx0A{nullptr}; ///< The transmit function for node 0, link A.
957 Ptr<SpectrumWifiPhy> m_tx0B{nullptr}; ///< The transmit function for node 0, link B.
958 Ptr<SpectrumWifiPhy> m_tx1A{nullptr}; ///< The transmit function for node 1, link A.
959 Ptr<SpectrumWifiPhy> m_tx1B{nullptr}; ///< The transmit function for node 1, link B.
960 Ptr<SpectrumWifiPhy> m_rxA{nullptr}; ///< The receive function for node 2, link A.
961 Ptr<SpectrumWifiPhy> m_rxB{nullptr}; ///< The receive function for node 2, link B.
962
963 WifiPhyRxTraceHelper m_rxTraceHelper; ///< The helper being tested for tracking
964 ///< PHY reception events in MLO scenarios.
965};
966
968 : TestCase("Test for correct MLO operation")
969{
970}
971
972void
974{
975 double txPower = 20;
976 auto ehtConfiguration = CreateObject<EhtConfiguration>();
977
978 auto nodeA = CreateObject<Node>();
979 auto devA = CreateObject<WifiNetDevice>();
980 devA->SetStandard(WIFI_STANDARD_80211be);
981 devA->SetEhtConfiguration(ehtConfiguration);
982
983 m_tx0A = CreateObject<SpectrumWifiPhy>();
984 m_tx0A->SetDevice(devA);
985 m_tx0A->SetTxPowerStart(txPower);
986 m_tx0A->SetTxPowerEnd(txPower);
987
988 m_tx0B = CreateObject<SpectrumWifiPhy>();
989 m_tx0B->SetDevice(devA);
990 m_tx0B->SetTxPowerStart(txPower);
991 m_tx0B->SetTxPowerEnd(txPower);
992
993 auto nodeB = CreateObject<Node>();
994 auto devB = CreateObject<WifiNetDevice>();
995 devB->SetStandard(WIFI_STANDARD_80211be);
996 devB->SetEhtConfiguration(ehtConfiguration);
997
998 m_tx1A = CreateObject<SpectrumWifiPhy>();
999 m_tx1A->SetDevice(devB);
1000 m_tx1A->SetTxPowerStart(txPower);
1001 m_tx1A->SetTxPowerEnd(txPower);
1002
1003 m_tx1B = CreateObject<SpectrumWifiPhy>();
1004 m_tx1B->SetDevice(devB);
1005 m_tx1B->SetTxPowerStart(txPower);
1006 m_tx1B->SetTxPowerEnd(txPower);
1007
1008 auto nodeRx = CreateObject<Node>();
1009 auto devRx = CreateObject<WifiNetDevice>();
1010 devRx->SetStandard(WIFI_STANDARD_80211be);
1011 devRx->SetEhtConfiguration(ehtConfiguration);
1012 m_rxA = CreateObject<SpectrumWifiPhy>();
1013 m_rxA->SetDevice(devRx);
1014 m_rxB = CreateObject<SpectrumWifiPhy>();
1015 m_rxB->SetDevice(devRx);
1016
1017 auto interferenceTx0A = CreateObject<InterferenceHelper>();
1018 m_tx0A->SetInterferenceHelper(interferenceTx0A);
1019 auto errorTx0A = CreateObject<NistErrorRateModel>();
1020 m_tx0A->SetErrorRateModel(errorTx0A);
1021
1022 auto interferenceTx0B = CreateObject<InterferenceHelper>();
1023 m_tx0B->SetInterferenceHelper(interferenceTx0B);
1024 auto errorTx0B = CreateObject<NistErrorRateModel>();
1025 m_tx0B->SetErrorRateModel(errorTx0B);
1026
1027 auto interferenceTx1A = CreateObject<InterferenceHelper>();
1028 m_tx1A->SetInterferenceHelper(interferenceTx1A);
1029 auto errorTx1A = CreateObject<NistErrorRateModel>();
1030 m_tx1A->SetErrorRateModel(errorTx1A);
1031
1032 auto interferenceTx1B = CreateObject<InterferenceHelper>();
1033 m_tx1B->SetInterferenceHelper(interferenceTx1B);
1034 auto errorTx1B = CreateObject<NistErrorRateModel>();
1035 m_tx1B->SetErrorRateModel(errorTx1B);
1036
1037 auto interferenceRxA = CreateObject<InterferenceHelper>();
1038 m_rxA->SetInterferenceHelper(interferenceRxA);
1039 auto errorRxA = CreateObject<NistErrorRateModel>();
1040 m_rxA->SetErrorRateModel(errorRxA);
1041
1042 auto interferenceRxB = CreateObject<InterferenceHelper>();
1043 m_rxB->SetInterferenceHelper(interferenceRxB);
1044 auto errorRxB = CreateObject<NistErrorRateModel>();
1045 m_rxB->SetErrorRateModel(errorRxB);
1046
1047 auto spectrumChannelA = CreateObject<MultiModelSpectrumChannel>();
1048 auto spectrumChannelB = CreateObject<MultiModelSpectrumChannel>();
1049
1052
1055
1058
1059 m_tx0A->AddChannel(spectrumChannelA, WIFI_SPECTRUM_2_4_GHZ);
1060 m_tx0B->AddChannel(spectrumChannelB, WIFI_SPECTRUM_5_GHZ);
1061
1062 m_tx1A->AddChannel(spectrumChannelA, WIFI_SPECTRUM_2_4_GHZ);
1063 m_tx1B->AddChannel(spectrumChannelB, WIFI_SPECTRUM_5_GHZ);
1064
1065 m_rxA->AddChannel(spectrumChannelA, WIFI_SPECTRUM_2_4_GHZ);
1066 m_rxB->AddChannel(spectrumChannelB, WIFI_SPECTRUM_5_GHZ);
1067
1070
1073
1076
1077 std::vector<Ptr<WifiPhy>> phys0;
1078 phys0.emplace_back(m_tx0A);
1079 phys0.emplace_back(m_tx0B);
1080
1081 std::vector<Ptr<WifiPhy>> phys1;
1082 phys1.emplace_back(m_tx1A);
1083 phys1.emplace_back(m_tx1B);
1084
1085 std::vector<Ptr<WifiPhy>> physRx;
1086 physRx.emplace_back(m_rxA);
1087 physRx.emplace_back(m_rxB);
1088
1089 devA->SetPhys(phys0);
1090 nodeA->AddDevice(devA);
1091
1092 devB->SetPhys(phys1);
1093 nodeB->AddDevice(devB);
1094
1095 devRx->SetPhys(physRx);
1096 nodeRx->AddDevice(devRx);
1097
1098 wifiNodes.Add(nodeA);
1099 wifiNodes.Add(nodeB);
1100 wifiNodes.Add(nodeRx);
1101
1103
1104 auto preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel>();
1105 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
1106 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
1107 m_rxA->SetPreambleDetectionModel(preambleDetectionModel);
1108 m_rxB->SetPreambleDetectionModel(preambleDetectionModel);
1109}
1110
1111void
1113{
1114 m_tx0A->Dispose();
1115 m_tx0B->Dispose();
1116 m_tx1A->Dispose();
1117 m_tx1B->Dispose();
1118 m_rxA->Dispose();
1119 m_rxB->Dispose();
1120}
1121
1122void
1124 Mac48Address receiver1,
1125 Mac48Address receiver2,
1127{
1128 double txPower = rxPowerDbm;
1129 tx_phy->SetTxPowerStart(txPower);
1130 tx_phy->SetTxPowerEnd(txPower);
1131
1132 WifiTxVector txVector =
1133 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, true);
1134
1135 std::vector<Ptr<WifiMpdu>> mpduList;
1136
1137 WifiMacHeader hdr1;
1139 hdr1.SetQosTid(0);
1140 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1141 auto p1 = Create<Packet>(750);
1142 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1143
1144 WifiMacHeader hdr2;
1146 hdr2.SetQosTid(0);
1147 hdr2.SetAddr1(receiver2); // Changing the expected receiver
1148 auto p2 = Create<Packet>(750);
1149 mpduList.emplace_back(Create<WifiMpdu>(p2, hdr2));
1150
1151 auto psdu = Create<WifiPsdu>(mpduList);
1152
1153 tx_phy->Send(psdu, txVector);
1154}
1155
1156void
1158 Mac48Address receiver1,
1160{
1161 double txPower = rxPowerDbm;
1162 tx_phy->SetTxPowerStart(txPower);
1163 tx_phy->SetTxPowerEnd(txPower);
1164
1165 WifiTxVector txVector =
1167 0,
1169 800,
1170 1,
1171 1,
1172 0,
1173 20,
1174 true); // for some reason needs to be set to true even though only one MPDU
1175
1176 std::vector<Ptr<WifiMpdu>> mpduList;
1177
1178 WifiMacHeader hdr1;
1180 hdr1.SetQosTid(0);
1181 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1182 auto p1 = Create<Packet>(750);
1183 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1184
1185 auto psdu = Create<WifiPsdu>(mpduList);
1186 tx_phy->Send(psdu, txVector);
1187}
1188
1189void
1191{
1193 for (uint32_t i = 0; i < wifiNodes.Get(nodeId)->GetNDevices(); i++)
1194 {
1195 for (uint32_t j = 0;
1196 j < DynamicCast<WifiNetDevice>(wifiNodes.Get(nodeId)->GetDevice(i))->GetNPhys();
1197 j++)
1198 {
1199 stats = stats + m_rxTraceHelper.GetStatistics(nodeId, i, j);
1200 }
1201 }
1202
1204 expectedStats.m_receivedPpdus,
1205 "Didn't receive right number of successful PPDUs");
1207 expectedStats.m_failedPpdus,
1208 "Didn't receive right number of unsuccessful PPDUs");
1210 expectedStats.m_receivedMpdus,
1211 "Didn't receive right number of successful MPDUs");
1213 expectedStats.m_failedMpdus,
1214 "Didn't receive right number of unsuccessful MPDUs");
1216 expectedStats.m_overlappingPpdus,
1217 "Didn't receive right number of overlapping PPDUs");
1219 expectedStats.m_nonOverlappingPpdus,
1220 "Didn't receive right number of nonoverlapping PPDUs");
1221}
1222
1223void
1225 uint32_t nodeId,
1226 uint32_t deviceId)
1227{
1229
1230 for (uint32_t i = 0;
1231 i < DynamicCast<WifiNetDevice>(wifiNodes.Get(nodeId)->GetDevice(deviceId))->GetNPhys();
1232 i++)
1233 {
1234 stats = stats + m_rxTraceHelper.GetStatistics(nodeId, deviceId, i);
1235 }
1236
1238 expectedStats.m_receivedPpdus,
1239 "Didn't receive right number of successful PPDUs");
1241 expectedStats.m_failedPpdus,
1242 "Didn't receive right number of unsuccessful PPDUs");
1244 expectedStats.m_receivedMpdus,
1245 "Didn't receive right number of successful MPDUs");
1247 expectedStats.m_failedMpdus,
1248 "Didn't receive right number of unsuccessful MPDUs");
1250 expectedStats.m_overlappingPpdus,
1251 "Didn't receive right number of overlapping PPDUs");
1253 expectedStats.m_nonOverlappingPpdus,
1254 "Didn't receive right number of nonoverlapping PPDUs");
1255}
1256
1257void
1259 uint32_t nodeId,
1260 uint32_t deviceId,
1261 uint32_t linkId)
1262{
1263 WifiPhyTraceStatistics stats = m_rxTraceHelper.GetStatistics(nodeId, deviceId, linkId);
1264
1266 expectedStats.m_receivedPpdus,
1267 "Didn't receive right number of successful PPDUs");
1269 expectedStats.m_failedPpdus,
1270 "Didn't receive right number of unsuccessful PPDUs");
1272 expectedStats.m_receivedMpdus,
1273 "Didn't receive right number of successful MPDUs");
1275 expectedStats.m_failedMpdus,
1276 "Didn't receive right number of unsuccessful MPDUs");
1278 expectedStats.m_overlappingPpdus,
1279 "Didn't receive right number of overlapping PPDUs");
1281 expectedStats.m_nonOverlappingPpdus,
1282 "Didn't receive right number of nonoverlapping PPDUs");
1283}
1284
1285void
1287 uint64_t expectedPpduFailure,
1288 uint64_t expectedMpduSuccess,
1289 uint64_t expectedMpduFailure,
1290 uint64_t expectedOverlaps,
1291 uint64_t expectedNonOverlaps)
1292{
1294
1296 expectedPpduSuccess,
1297 "Didn't receive right number of successful PPDUs");
1299 expectedPpduFailure,
1300 "Didn't receive right number of unsuccessful PPDUs");
1302 expectedMpduSuccess,
1303 "Didn't receive right number of successful MPDUs");
1305 expectedMpduFailure,
1306 "Didn't receive right number of unsuccessful MPDUs");
1308 expectedOverlaps,
1309 "Didn't receive right number of overlapping PPDUs");
1311 expectedNonOverlaps,
1312 "Didn't receive right number of nonoverlapping PPDUs");
1313
1315}
1316
1317void
1319{
1320 auto records = m_rxTraceHelper.GetPpduRecords();
1321 NS_TEST_ASSERT_MSG_EQ(records.size(),
1322 expectedRecordCount,
1323 "Didn't produce the right number of Records");
1324}
1325
1326void
1328{
1331 int64_t streamNumber = 1;
1332 double rxPowerDbm = -80;
1333 streamNumber += m_tx0A->AssignStreams(streamNumber);
1334 streamNumber += m_tx0B->AssignStreams(streamNumber);
1335 streamNumber += m_tx1A->AssignStreams(streamNumber);
1336 streamNumber += m_tx1B->AssignStreams(streamNumber);
1337 streamNumber += m_rxA->AssignStreams(streamNumber);
1338 streamNumber += m_rxB->AssignStreams(streamNumber);
1339 WifiPhyTraceStatistics expectedStats;
1340
1342
1343 // CASE 1: PPDU Reception with Sufficient RSSI With SOME Frames Addressed to Receiver
1344 expectedStats.m_receivedPpdus = 2;
1345 expectedStats.m_failedPpdus = 0;
1346 expectedStats.m_receivedMpdus = 2;
1347 expectedStats.m_failedMpdus = 0;
1348 expectedStats.m_overlappingPpdus = 0;
1349 expectedStats.m_nonOverlappingPpdus = 2;
1350
1351 // A-MPDU 1
1354 this,
1355 rxPowerDbm,
1356 correctReceiver, // One MPDU addressed to
1357 wrongReceiver, // One MPDU addressed to
1358 m_tx0A);
1359
1362 this,
1363 rxPowerDbm,
1364 correctReceiver, // One MPDU addressed to
1365 wrongReceiver, // One MPDU addressed to
1366 m_tx0B);
1367
1370 this,
1371 4); // Total Records
1372
1374 Seconds(0.2),
1377 this,
1378 expectedStats,
1379 wifiNodes.Get(2)->GetId());
1380
1383 this,
1384 expectedStats.m_receivedPpdus,
1385 expectedStats.m_failedPpdus,
1386 expectedStats.m_receivedMpdus,
1387 expectedStats.m_failedMpdus,
1388 expectedStats.m_overlappingPpdus,
1389 expectedStats.m_nonOverlappingPpdus);
1390
1391 // CASE 2: PPDU Reception with Insufficient RSSI With SOME Frames Addressed to Receiver
1392 expectedStats.m_receivedPpdus = 0;
1393 expectedStats.m_failedPpdus = 2;
1394 expectedStats.m_receivedMpdus = 0;
1395 expectedStats.m_failedMpdus = 2;
1396 expectedStats.m_overlappingPpdus = 0;
1397 expectedStats.m_nonOverlappingPpdus = 2;
1398 rxPowerDbm = -83;
1399 // A-MPDU 1
1402 this,
1403 rxPowerDbm,
1404 correctReceiver, // One MPDU addressed to
1405 wrongReceiver, // One MPDU addressed to
1406 m_tx0A);
1407
1410 this,
1411 rxPowerDbm,
1412 correctReceiver, // One MPDU addressed to
1413 wrongReceiver, // One MPDU addressed to
1414 m_tx0B);
1415
1418 this,
1419 4); // TotalRecords
1420
1422 Seconds(0.4),
1425 this,
1426 expectedStats,
1427 wifiNodes.Get(2)->GetId());
1428
1431 this,
1432 expectedStats.m_receivedPpdus,
1433 expectedStats.m_failedPpdus,
1434 expectedStats.m_receivedMpdus,
1435 expectedStats.m_failedMpdus,
1436 expectedStats.m_overlappingPpdus,
1437 expectedStats.m_nonOverlappingPpdus);
1438
1439 // CASE 3: PPDU Reception with Sufficient RSSI/SNR With NO Frames Addressed to Receiver
1440 expectedStats.m_receivedPpdus = 0;
1441 expectedStats.m_failedPpdus = 0;
1442 expectedStats.m_receivedMpdus = 0;
1443 expectedStats.m_failedMpdus = 0;
1444 expectedStats.m_overlappingPpdus = 0;
1445 expectedStats.m_nonOverlappingPpdus = 0;
1446 rxPowerDbm = -80;
1447 // A-MPDU 1
1450 this,
1451 rxPowerDbm,
1452 wrongReceiver, // One MPDU addressed to
1453 wrongReceiver, // One MPDU addressed to
1454 m_tx0A);
1455
1456 // A-MPDU 1
1459 this,
1460 rxPowerDbm,
1461 wrongReceiver, // One MPDU addressed to
1462 wrongReceiver, // One MPDU addressed to
1463 m_tx0B);
1464
1467 this,
1468 4); // TotalRecords
1469
1471 Seconds(0.6),
1474 this,
1475 expectedStats,
1476 wifiNodes.Get(2)->GetId());
1477
1480 this,
1481 expectedStats.m_receivedPpdus,
1482 expectedStats.m_failedPpdus,
1483 expectedStats.m_receivedMpdus,
1484 expectedStats.m_failedMpdus,
1485 expectedStats.m_overlappingPpdus,
1486 expectedStats.m_nonOverlappingPpdus);
1487
1488 // CASE 4: PPDU Reception with Insufficient RSSI/SNR With NO Frames Addressed to Receiver
1489 expectedStats.m_receivedPpdus = 0;
1490 expectedStats.m_failedPpdus = 0;
1491 expectedStats.m_receivedMpdus = 0;
1492 expectedStats.m_failedMpdus = 0;
1493 expectedStats.m_overlappingPpdus = 0;
1494 expectedStats.m_nonOverlappingPpdus = 0;
1495 rxPowerDbm = -83;
1496 // A-MPDU 1
1499 this,
1500 rxPowerDbm,
1501 wrongReceiver, // One MPDU addressed to
1502 wrongReceiver, // One MPDU addressed to
1503 m_tx0A);
1504
1505 // A-MPDU 1
1508 this,
1509 rxPowerDbm,
1510 wrongReceiver, // One MPDU addressed to
1511 wrongReceiver, // One MPDU addressed to
1512 m_tx0B);
1513
1516 this,
1517 4); // TotalRecords
1518
1520 Seconds(0.8),
1523 this,
1524 expectedStats,
1525 wifiNodes.Get(2)->GetId());
1526
1529 this,
1530 expectedStats.m_receivedPpdus,
1531 expectedStats.m_failedPpdus,
1532 expectedStats.m_receivedMpdus,
1533 expectedStats.m_failedMpdus,
1534 expectedStats.m_overlappingPpdus,
1535 expectedStats.m_nonOverlappingPpdus);
1536
1537 // CASE 5: PPDU Overlapping Reception with sufficient RSSI/SNR With ALL Frames Addressed to
1538 // Receiver
1539 expectedStats.m_receivedPpdus = 0;
1540 expectedStats.m_failedPpdus = 4;
1541 expectedStats.m_receivedMpdus = 0;
1542 expectedStats.m_failedMpdus = 4;
1543 expectedStats.m_overlappingPpdus = 4;
1544 expectedStats.m_nonOverlappingPpdus = 0;
1545 rxPowerDbm = -80;
1546 // A-MPDU 1
1549 this,
1550 rxPowerDbm,
1551 correctReceiver, // One MPDU addressed to
1552 m_tx0A);
1553 // A-MPDU 2
1556 this,
1557 rxPowerDbm,
1558 correctReceiver, // One MPDU addressed to
1559 m_tx1A);
1560
1561 // A-MPDU 1
1564 this,
1565 rxPowerDbm,
1566 correctReceiver, // One MPDU addressed to
1567 m_tx0B);
1568 // A-MPDU 2
1571 this,
1572 rxPowerDbm,
1573 correctReceiver, // One MPDU addressed to
1574 m_tx1B);
1575
1578 this,
1579 8); // TotalRecords
1580
1582 Seconds(1),
1585 this,
1586 expectedStats,
1587 wifiNodes.Get(2)->GetId());
1588
1591 this,
1592 expectedStats.m_receivedPpdus,
1593 expectedStats.m_failedPpdus,
1594 expectedStats.m_receivedMpdus,
1595 expectedStats.m_failedMpdus,
1596 expectedStats.m_overlappingPpdus,
1597 expectedStats.m_nonOverlappingPpdus);
1598
1599 // CASE 6: PPDU Overlapping Reception with sufficient RSSI/SNR With SOME Frames Addressed to
1600 // Receiver
1601 expectedStats.m_receivedPpdus = 0;
1602 expectedStats.m_failedPpdus = 2;
1603 expectedStats.m_receivedMpdus = 0;
1604 expectedStats.m_failedMpdus = 2;
1605 expectedStats.m_overlappingPpdus = 2;
1606 expectedStats.m_nonOverlappingPpdus = 0;
1607 rxPowerDbm = -80;
1608 // A-MPDU 1
1611 this,
1612 rxPowerDbm,
1613 correctReceiver, // One MPDU addressed to
1614 m_tx0A);
1615 // A-MPDU 2
1618 this,
1619 rxPowerDbm,
1620 wrongReceiver, // One MPDU addressed to
1621 m_tx1A);
1622
1623 // A-MPDU 1
1626 this,
1627 rxPowerDbm,
1628 correctReceiver, // One MPDU addressed to
1629 m_tx0B);
1630 // A-MPDU 2
1633 this,
1634 rxPowerDbm,
1635 wrongReceiver, // One MPDU addressed to
1636 m_tx1B);
1637
1640 this,
1641 8); // TotalRecords
1642
1644 Seconds(1.2),
1647 this,
1648 expectedStats,
1649 wifiNodes.Get(2)->GetId());
1650
1653 this,
1654 expectedStats.m_receivedPpdus,
1655 expectedStats.m_failedPpdus,
1656 expectedStats.m_receivedMpdus,
1657 expectedStats.m_failedMpdus,
1658 expectedStats.m_overlappingPpdus,
1659 expectedStats.m_nonOverlappingPpdus);
1660
1662
1665}
1666
1667/**
1668 * \ingroup wifi-test
1669 * \brief Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY)
1670 * frames (PPDU) with multiple MAC Protocol Data Units (MPDUs) when using YansWifiPhy.
1671 *
1672 * This class extends the TestCase class to simulate and analyze the reception of PPDUs containing
1673 * either one or two MPDUs. It specifically tests the PHY layer's capability to handle multiple
1674 * MPDUs addressed to specific receivers, measuring success and failure rates. The simulation setup
1675 * includes configuring transmit and receive power levels, and the class provides functionality to
1676 * check statistics related to PPDU and MPDU reception success and failure, as well as overlap
1677 * handling.
1678 */
1680{
1681 public:
1682 /**
1683 * Constructs a TestWifiPhyRxTraceHelperYans instance for testing the trace helper with
1684 * Yans.
1685 */
1687
1688 private:
1689 void DoSetup() override;
1690 void DoRun() override;
1691
1692 void DoTeardown() override;
1693
1694 /**
1695 * Sends a PPDU containing two MPDUs addressed to specific receivers.
1696 * \param rxPowerDbm The transmit power in dBm.
1697 * \param add1 The MAC address of the first receiver.
1698 * \param add2 The MAC address of the second receiver.
1699 * \param tx_phy The transmitting PHY object.
1700 */
1701 void SendPpduWithTwoMpdus(double rxPowerDbm,
1702 Mac48Address add1,
1703 Mac48Address add2,
1704 Ptr<ns3::YansWifiPhy> tx_phy);
1705
1706 /**
1707 * Sends a PPDU containing one MPDU addressed to a specific receiver.
1708 * \param rxPowerDbm The transmit power in dBm.
1709 * \param add1 The MAC address of the receiver.
1710 * \param tx_phy The transmitting PHY object.
1711 */
1712 void SendPpduWithOneMpdu(double rxPowerDbm, Mac48Address add1, Ptr<ns3::YansWifiPhy> tx_phy);
1713
1714 /**
1715 * Checks the statistics of PPDU and MPDU reception success and failure.
1716 * \param expectedPpduSuccess The expected number of successful PPDU receptions.
1717 * \param expectedPpduFailure The expected number of failed PPDU receptions.
1718 * \param expectedMpduSuccess The expected number of successful MPDU receptions within PPDUs.
1719 * \param expectedMpduFailure The expected number of failed MPDU receptions within PPDUs.
1720 * \param expectedOverlaps The expected number of overlapping reception events.
1721 * \param expectedNonOverlaps The expected number of non-overlapping reception events.
1722 */
1723 void CheckAllStats(uint64_t expectedPpduSuccess,
1724 uint64_t expectedPpduFailure,
1725 uint64_t expectedMpduSuccess,
1726 uint64_t expectedMpduFailure,
1727 uint64_t expectedOverlaps,
1728 uint64_t expectedNonOverlaps);
1729
1730 /**
1731 * Checks the statistics of PPDU and MPDU reception success and failure.
1732 * \param expectedStats The expected counts for PPDU and MPDU reception.
1733 * @param nodeId The node ID for which to check the received stats.
1734 * @param deviceId The device ID for which to check the received stats.
1735 * @param linkId The link ID for which to check the received stats.
1736 */
1737 void CheckStats(WifiPhyTraceStatistics expectedStats,
1738 uint32_t nodeId,
1739 uint32_t deviceId,
1740 uint32_t linkId);
1741
1742 /**
1743 * Checks the statistics of PPDU and MPDU reception success and failure.
1744 * \param expectedRecordCount The expected number of records.
1745 */
1746 void CheckRecords(uint64_t expectedRecordCount);
1747
1749 Mac48Address("00:00:00:00:00:01"); ///< The MAC address representing an incorrect receiver,
1750 ///< used for testing.
1752 Mac48Address("00:00:00:00:00:03"); ///< The MAC address representing the correct receiver,
1753 ///< used for testing.
1754
1755 std::map<ns3::Mac48Address, uint32_t> MacToNodeId = {
1756 {Mac48Address("00:00:00:00:00:04"), 0},
1757 {Mac48Address("00:00:00:00:00:05"), 1},
1758 {correctReceiver, 2},
1759 {wrongReceiver, 3}}; ///< Maps MAC addresses to node IDs. This is done since there is no MAC
1760 ///< layer configured and therefore the helper cannot obtain the MAC
1761 ///< addresses automatically.
1762
1763 Ptr<Node> nodeRx; ///< The receiving node
1764 Ptr<YansWifiPhy> m_txA{nullptr}; ///< The transmit function for node A.
1765 Ptr<YansWifiPhy> m_txB{nullptr}; ///< The transmit function for node B.
1766 Ptr<YansWifiPhy> m_rx{nullptr}; ///< The receive function for testing.
1767
1768 Ptr<FixedRssLossModel> propLoss; ///< The propagation loss model used to configure RSSI
1769
1771 m_rxTraceHelper; ///< The helper being tested for tracking PHY reception events.
1772
1773 uint64_t m_uid{0}; //!< The unique identifier used for the PPDU in the test.
1774};
1775
1777 : TestCase("Test for correct operation when using Yans")
1778{
1779}
1780
1781void
1783{
1784 double txPower = 20;
1785
1786 auto yansChannel = CreateObject<YansWifiChannel>();
1787 auto propDelay = CreateObject<ConstantSpeedPropagationDelayModel>();
1788 propLoss = CreateObject<FixedRssLossModel>();
1789 yansChannel->SetPropagationDelayModel(propDelay);
1790 yansChannel->SetPropagationLossModel(propLoss);
1791
1792 auto nodeA = CreateObject<Node>();
1793 auto devA = CreateObject<WifiNetDevice>();
1794 m_txA = CreateObject<YansWifiPhy>();
1795 m_txA->SetDevice(devA);
1796 m_txA->SetTxPowerStart(txPower);
1797 m_txA->SetTxPowerEnd(txPower);
1798
1799 auto nodeB = CreateObject<Node>();
1800 auto devB = CreateObject<WifiNetDevice>();
1801 m_txB = CreateObject<YansWifiPhy>();
1802 m_txB->SetDevice(devB);
1803 m_txB->SetTxPowerStart(txPower);
1804 m_txB->SetTxPowerEnd(txPower);
1805
1806 nodeRx = CreateObject<Node>();
1807 auto devRx = CreateObject<WifiNetDevice>();
1808 m_rx = CreateObject<YansWifiPhy>();
1809 m_rx->SetDevice(devRx);
1810
1811 auto interferenceTxA = CreateObject<InterferenceHelper>();
1812 m_txA->SetInterferenceHelper(interferenceTxA);
1813 auto errorTxA = CreateObject<NistErrorRateModel>();
1814 m_txA->SetErrorRateModel(errorTxA);
1815
1816 auto interferenceTxB = CreateObject<InterferenceHelper>();
1817 m_txB->SetInterferenceHelper(interferenceTxB);
1818 auto errorTxB = CreateObject<NistErrorRateModel>();
1819 m_txB->SetErrorRateModel(errorTxB);
1820
1821 auto interferenceRx = CreateObject<InterferenceHelper>();
1822 m_rx->SetInterferenceHelper(interferenceRx);
1823 auto errorRx = CreateObject<NistErrorRateModel>();
1824 m_rx->SetErrorRateModel(errorRx);
1825
1826 m_txA->SetChannel(yansChannel);
1827 m_txB->SetChannel(yansChannel);
1828 m_rx->SetChannel(yansChannel);
1829
1833
1837
1838 devA->SetPhy(m_txA);
1839 nodeA->AddDevice(devA);
1840 devB->SetPhy(m_txB);
1841 nodeB->AddDevice(devB);
1842 devRx->SetPhy(m_rx);
1843 nodeRx->AddDevice(devRx);
1844
1845 auto mobilityA = CreateObject<ConstantPositionMobilityModel>();
1846 mobilityA->SetPosition(Vector(0.0, 0.0, 0.0));
1847 nodeA->AggregateObject(mobilityA);
1848
1849 auto mobilityB = CreateObject<ConstantPositionMobilityModel>();
1850 mobilityB->SetPosition(Vector(0.0, 0.0, 0.0));
1851 nodeB->AggregateObject(mobilityB);
1852
1853 auto mobilityRx = CreateObject<ConstantPositionMobilityModel>();
1854 mobilityRx->SetPosition(Vector(0.0, 0.0, 0.0));
1855 nodeRx->AggregateObject(mobilityRx);
1856
1858 nodes.Add(nodeA);
1859 nodes.Add(nodeB);
1860 nodes.Add(nodeRx);
1861
1863
1864 auto preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel>();
1865 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
1866 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
1867 m_rx->SetPreambleDetectionModel(preambleDetectionModel);
1868}
1869
1870void
1872{
1873 m_txA->Dispose();
1874 m_txB->Dispose();
1875 m_rx->Dispose();
1876}
1877
1878void
1880 Mac48Address receiver1,
1881 Mac48Address receiver2,
1882 Ptr<ns3::YansWifiPhy> tx_phy)
1883{
1884 propLoss->SetRss(rxPowerDbm);
1885
1886 WifiTxVector txVector =
1887 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, true);
1888
1889 std::vector<Ptr<WifiMpdu>> mpduList;
1890
1891 WifiMacHeader hdr1;
1893 hdr1.SetQosTid(0);
1894 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1895 auto p1 = Create<Packet>(750);
1896 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1897
1898 WifiMacHeader hdr2;
1900 hdr2.SetQosTid(0);
1901 hdr2.SetAddr1(receiver2); // Changing the expected receiver
1902 auto p2 = Create<Packet>(750);
1903 mpduList.emplace_back(Create<WifiMpdu>(p2, hdr2));
1904
1905 auto psdu = Create<WifiPsdu>(mpduList);
1906 auto ppdu =
1907 Create<HePpdu>(psdu,
1908 txVector,
1909 tx_phy->GetOperatingChannel(),
1910 tx_phy->CalculateTxDuration(psdu->GetSize(), txVector, tx_phy->GetPhyBand()),
1911 m_uid);
1912
1913 m_uid++;
1914
1915 tx_phy->StartTx(ppdu);
1916}
1917
1918void
1920 Mac48Address receiver1,
1921 Ptr<ns3::YansWifiPhy> tx_phy)
1922{
1923 propLoss->SetRss(rxPowerDbm);
1924
1925 auto txVector =
1926 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, true);
1927
1928 std::vector<Ptr<WifiMpdu>> mpduList;
1929
1930 WifiMacHeader hdr1;
1932 hdr1.SetQosTid(0);
1933 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1934 auto p1 = Create<Packet>(750);
1935 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1936
1937 auto psdu = Create<WifiPsdu>(mpduList);
1938 auto ppdu =
1939 Create<HePpdu>(psdu,
1940 txVector,
1941 tx_phy->GetOperatingChannel(),
1942 tx_phy->CalculateTxDuration(psdu->GetSize(), txVector, tx_phy->GetPhyBand()),
1943 m_uid);
1944
1945 m_uid++;
1946
1947 tx_phy->StartTx(ppdu);
1948}
1949
1950void
1952 uint64_t expectedPpduFailure,
1953 uint64_t expectedMpduSuccess,
1954 uint64_t expectedMpduFailure,
1955 uint64_t expectedOverlaps,
1956 uint64_t expectedNonOverlaps)
1957{
1958 auto stats = m_rxTraceHelper.GetStatistics();
1959
1960 NS_TEST_ASSERT_MSG_EQ(stats.m_receivedPpdus,
1961 expectedPpduSuccess,
1962 "Didn't receive right number of successful PPDUs");
1963 NS_TEST_ASSERT_MSG_EQ(stats.m_failedPpdus,
1964 expectedPpduFailure,
1965 "Didn't receive right number of unsuccessful PPDUs");
1966 NS_TEST_ASSERT_MSG_EQ(stats.m_receivedMpdus,
1967 expectedMpduSuccess,
1968 "Didn't receive right number of successful MPDUs");
1969 NS_TEST_ASSERT_MSG_EQ(stats.m_failedMpdus,
1970 expectedMpduFailure,
1971 "Didn't receive right number of unsuccessful MPDUs");
1972 NS_TEST_ASSERT_MSG_EQ(stats.m_overlappingPpdus,
1973 expectedOverlaps,
1974 "Didn't receive right number of overlapping PPDUs");
1975 NS_TEST_ASSERT_MSG_EQ(stats.m_nonOverlappingPpdus,
1976 expectedNonOverlaps,
1977 "Didn't receive right number of nonoverlapping PPDUs");
1978
1980}
1981
1982void
1984 uint32_t nodeId,
1985 uint32_t deviceId,
1986 uint32_t linkId)
1987{
1988 WifiPhyTraceStatistics stats = m_rxTraceHelper.GetStatistics(nodeId, deviceId, linkId);
1989
1991 expectedStats.m_receivedPpdus,
1992 "Didn't receive right number of successful PPDUs");
1994 expectedStats.m_failedPpdus,
1995 "Didn't receive right number of unsuccessful PPDUs");
1997 expectedStats.m_receivedMpdus,
1998 "Didn't receive right number of successful MPDUs");
2000 expectedStats.m_failedMpdus,
2001 "Didn't receive right number of unsuccessful MPDUs");
2003 expectedStats.m_overlappingPpdus,
2004 "Didn't receive right number of overlapping PPDUs");
2006 expectedStats.m_nonOverlappingPpdus,
2007 "Didn't receive right number of nonoverlapping PPDUs");
2008}
2009
2010void
2012{
2013 auto records = m_rxTraceHelper.GetPpduRecords();
2014 NS_TEST_ASSERT_MSG_EQ(records.size(),
2015 expectedRecordCount,
2016 "Didn't produce the right number of Records");
2017}
2018
2019void
2021{
2024 int64_t streamNumber = 1;
2025 double rxPowerDbm = -80;
2026 streamNumber += m_txA->AssignStreams(streamNumber);
2027 streamNumber += m_txB->AssignStreams(streamNumber);
2028 streamNumber += m_rx->AssignStreams(streamNumber);
2029 WifiPhyTraceStatistics expectedStats;
2030
2032
2033 // CASE 1: PPDU Reception with Sufficient RSSI With SOME Frames Addressed to Receiver
2034 expectedStats.m_receivedPpdus = 1;
2035 expectedStats.m_failedPpdus = 0;
2036 expectedStats.m_receivedMpdus = 1;
2037 expectedStats.m_failedMpdus = 0;
2038 expectedStats.m_overlappingPpdus = 0;
2039 expectedStats.m_nonOverlappingPpdus = 1;
2040
2041 // A-MPDU 1
2044 this,
2045 rxPowerDbm,
2046 correctReceiver, // One MPDU addressed to
2047 wrongReceiver, // One MPDU addressed to
2048 m_txA);
2049
2052 this,
2053 2); // Total Records
2054
2057 this,
2058 expectedStats,
2059 nodeRx->GetId(),
2060 0,
2061 0);
2062
2065 this,
2066 expectedStats.m_receivedPpdus,
2067 expectedStats.m_failedPpdus,
2068 expectedStats.m_receivedMpdus,
2069 expectedStats.m_failedMpdus,
2070 expectedStats.m_overlappingPpdus,
2071 expectedStats.m_nonOverlappingPpdus);
2072 // CASE 2: PPDU Reception with inSufficient RSSI With SOME Frames Addressed to Receiver
2073 expectedStats.m_receivedPpdus = 0;
2074 expectedStats.m_failedPpdus = 1;
2075 expectedStats.m_receivedMpdus = 0;
2076 expectedStats.m_failedMpdus = 1;
2077 expectedStats.m_overlappingPpdus = 0;
2078 expectedStats.m_nonOverlappingPpdus = 1;
2079 rxPowerDbm = -83;
2080 // A-MPDU 1
2083 this,
2084 rxPowerDbm,
2085 correctReceiver, // One MPDU addressed to
2086 wrongReceiver, // One MPDU addressed to
2087 m_txA);
2088
2091 this,
2092 2); // TotalRecords
2093
2096 this,
2097 expectedStats,
2098 nodeRx->GetId(),
2099 0,
2100 0);
2101
2104 this,
2105 expectedStats.m_receivedPpdus,
2106 expectedStats.m_failedPpdus,
2107 expectedStats.m_receivedMpdus,
2108 expectedStats.m_failedMpdus,
2109 expectedStats.m_overlappingPpdus,
2110 expectedStats.m_nonOverlappingPpdus);
2111
2112 // CASE 3: PPDU Reception with Sufficient RSSI/SNR With NO Frames Addressed to Receiver
2113 expectedStats.m_receivedPpdus = 0;
2114 expectedStats.m_failedPpdus = 0;
2115 expectedStats.m_receivedMpdus = 0;
2116 expectedStats.m_failedMpdus = 0;
2117 expectedStats.m_overlappingPpdus = 0;
2118 expectedStats.m_nonOverlappingPpdus = 0;
2119 rxPowerDbm = -80;
2120 // A-MPDU 1
2123 this,
2124 rxPowerDbm,
2125 wrongReceiver, // One MPDU addressed to
2126 wrongReceiver, // One MPDU addressed to
2127 m_txA);
2128
2131 this,
2132 2); // TotalRecords
2133
2136 this,
2137 expectedStats,
2138 nodeRx->GetId(),
2139 0,
2140 0);
2141
2144 this,
2145 expectedStats.m_receivedPpdus,
2146 expectedStats.m_failedPpdus,
2147 expectedStats.m_receivedMpdus,
2148 expectedStats.m_failedMpdus,
2149 expectedStats.m_overlappingPpdus,
2150 expectedStats.m_nonOverlappingPpdus);
2151
2152 // CASE 4: PPDU Reception with Insufficient RSSI/SNR With NO Frames Addressed to Receiver
2153 expectedStats.m_receivedPpdus = 0;
2154 expectedStats.m_failedPpdus = 0;
2155 expectedStats.m_receivedMpdus = 0;
2156 expectedStats.m_failedMpdus = 0;
2157 expectedStats.m_overlappingPpdus = 0;
2158 expectedStats.m_nonOverlappingPpdus = 0;
2159 rxPowerDbm = -83;
2160 // A-MPDU 1
2163 this,
2164 rxPowerDbm,
2165 wrongReceiver, // One MPDU addressed to
2166 wrongReceiver, // One MPDU addressed to
2167 m_txA);
2168
2171 this,
2172 2); // TotalRecords
2173
2176 this,
2177 expectedStats,
2178 nodeRx->GetId(),
2179 0,
2180 0);
2181
2184 this,
2185 expectedStats.m_receivedPpdus,
2186 expectedStats.m_failedPpdus,
2187 expectedStats.m_receivedMpdus,
2188 expectedStats.m_failedMpdus,
2189 expectedStats.m_overlappingPpdus,
2190 expectedStats.m_nonOverlappingPpdus);
2191
2192 // CASE 5: PPDU Overlapping Reception with sufficient RSSI/SNR With ALL Frames Addressed to
2193 // Receiver
2194 expectedStats.m_receivedPpdus = 0;
2195 expectedStats.m_failedPpdus = 2;
2196 expectedStats.m_receivedMpdus = 0;
2197 expectedStats.m_failedMpdus = 2;
2198 expectedStats.m_overlappingPpdus = 2;
2199 expectedStats.m_nonOverlappingPpdus = 0;
2200 rxPowerDbm = -80;
2201 // A-MPDU 1
2204 this,
2205 rxPowerDbm,
2206 correctReceiver, // One MPDU addressed to
2207 m_txA);
2208 // A-MPDU 2
2211 this,
2212 rxPowerDbm,
2213 correctReceiver, // One MPDU addressed to
2214 m_txB);
2215
2218 this,
2219 4); // TotalRecords
2220
2223 this,
2224 expectedStats,
2225 nodeRx->GetId(),
2226 0,
2227 0);
2228
2231 this,
2232 expectedStats.m_receivedPpdus,
2233 expectedStats.m_failedPpdus,
2234 expectedStats.m_receivedMpdus,
2235 expectedStats.m_failedMpdus,
2236 expectedStats.m_overlappingPpdus,
2237 expectedStats.m_nonOverlappingPpdus);
2238
2239 // CASE 6: PPDU Overlapping Reception with sufficient RSSI/SNR With SOME Frames Addressed to
2240 // Receiver
2241 expectedStats.m_receivedPpdus = 0;
2242 expectedStats.m_failedPpdus = 1;
2243 expectedStats.m_receivedMpdus = 0;
2244 expectedStats.m_failedMpdus = 1;
2245 expectedStats.m_overlappingPpdus = 1;
2246 expectedStats.m_nonOverlappingPpdus = 0;
2247 rxPowerDbm = -80;
2248 // A-MPDU 1
2251 this,
2252 rxPowerDbm,
2253 correctReceiver, // One MPDU addressed to
2254 m_txA);
2255 // A-MPDU 2
2258 this,
2259 rxPowerDbm,
2260 wrongReceiver, // One MPDU addressed to
2261 m_txB);
2262
2265 this,
2266 4); // TotalRecords
2267
2270 this,
2271 expectedStats,
2272 nodeRx->GetId(),
2273 0,
2274 0);
2275
2278 this,
2279 expectedStats.m_receivedPpdus,
2280 expectedStats.m_failedPpdus,
2281 expectedStats.m_receivedMpdus,
2282 expectedStats.m_failedMpdus,
2283 expectedStats.m_overlappingPpdus,
2284 expectedStats.m_nonOverlappingPpdus);
2285
2286 // Stop Statistics Collection Period Since following testcases evaluate the Start and Stop
2287 // methods
2289
2290 // CASE 7: Execution of "Start()" Before Signal Injection
2291 expectedStats.m_receivedPpdus = 1;
2292 expectedStats.m_failedPpdus = 0;
2293 expectedStats.m_receivedMpdus = 1;
2294 expectedStats.m_failedMpdus = 0;
2295 expectedStats.m_overlappingPpdus = 0;
2296 expectedStats.m_nonOverlappingPpdus = 1;
2297 rxPowerDbm = -80;
2299
2300 // A-MPDU 1
2303 this,
2304 rxPowerDbm,
2305 correctReceiver, // One MPDU addressed to
2306 m_txA);
2307
2310 this,
2311 2); // TotalRecords
2312
2315 this,
2316 expectedStats,
2317 nodeRx->GetId(),
2318 0,
2319 0);
2320
2323 this,
2324 expectedStats.m_receivedPpdus,
2325 expectedStats.m_failedPpdus,
2326 expectedStats.m_receivedMpdus,
2327 expectedStats.m_failedMpdus,
2328 expectedStats.m_overlappingPpdus,
2329 expectedStats.m_nonOverlappingPpdus);
2330
2332
2333 // CASE 8: Activation of "Start()" Followed by "Stop()" Before Signal Injection
2334 expectedStats.m_receivedPpdus = 0;
2335 expectedStats.m_failedPpdus = 0;
2336 expectedStats.m_receivedMpdus = 0;
2337 expectedStats.m_failedMpdus = 0;
2338 expectedStats.m_overlappingPpdus = 0;
2339 expectedStats.m_nonOverlappingPpdus = 0;
2340 rxPowerDbm = -80;
2341
2343
2345
2346 // A-MPDU 1
2349 this,
2350 rxPowerDbm,
2351 correctReceiver, // One MPDU addressed to
2352 m_txA);
2353
2356 this,
2357 0); // TotalRecords
2358
2361 this,
2362 expectedStats,
2363 nodeRx->GetId(),
2364 0,
2365 0);
2366
2369 this,
2370 expectedStats.m_receivedPpdus,
2371 expectedStats.m_failedPpdus,
2372 expectedStats.m_receivedMpdus,
2373 expectedStats.m_failedMpdus,
2374 expectedStats.m_overlappingPpdus,
2375 expectedStats.m_nonOverlappingPpdus);
2376
2377 // CASE 9: "Start()" Method Initiated During Ongoing PPDU Reception
2378 expectedStats.m_receivedPpdus = 1;
2379 expectedStats.m_failedPpdus = 0;
2380 expectedStats.m_receivedMpdus = 1;
2381 expectedStats.m_failedMpdus = 0;
2382 expectedStats.m_overlappingPpdus = 0;
2383 expectedStats.m_nonOverlappingPpdus = 1;
2384 rxPowerDbm = -80;
2385
2386 // A-MPDU 1
2389 this,
2390 rxPowerDbm,
2391 correctReceiver, // One MPDU addressed to
2392 m_txA);
2393
2395
2398 this,
2399 2); // TotalRecords
2400
2403 this,
2404 expectedStats,
2405 nodeRx->GetId(),
2406 0,
2407 0);
2408
2411 this,
2412 expectedStats.m_receivedPpdus,
2413 expectedStats.m_failedPpdus,
2414 expectedStats.m_receivedMpdus,
2415 expectedStats.m_failedMpdus,
2416 expectedStats.m_overlappingPpdus,
2417 expectedStats.m_nonOverlappingPpdus);
2418
2420
2421 // CASE 10: Execution of "Stop()" During Ongoing PPDU Reception
2422 expectedStats.m_receivedPpdus = 0;
2423 expectedStats.m_failedPpdus = 0;
2424 expectedStats.m_receivedMpdus = 0;
2425 expectedStats.m_failedMpdus = 0;
2426 expectedStats.m_overlappingPpdus = 0;
2427 expectedStats.m_nonOverlappingPpdus = 0;
2428 rxPowerDbm = -80;
2429
2431
2432 // A-MPDU 1
2435 this,
2436 rxPowerDbm,
2437 correctReceiver, // One MPDU addressed to
2438 m_txA);
2439
2441
2444 this,
2445 0); // TotalRecords
2446
2449 this,
2450 expectedStats,
2451 nodeRx->GetId(),
2452 0,
2453 0);
2454
2457 this,
2458 expectedStats.m_receivedPpdus,
2459 expectedStats.m_failedPpdus,
2460 expectedStats.m_receivedMpdus,
2461 expectedStats.m_failedMpdus,
2462 expectedStats.m_overlappingPpdus,
2463 expectedStats.m_nonOverlappingPpdus);
2464
2467}
2468
2469/**
2470 * \ingroup wifi-test
2471 * \ingroup tests
2472 *
2473 * \brief wifi PHY reception Test Suite
2474 */
2476{
2477 public:
2479};
2480
2482 : TestSuite("wifi-phy-rx-trace-helper", Type::UNIT)
2483{
2484 AddTestCase(new TestWifiPhyRxTraceHelper("test-statistics"), TestCase::Duration::QUICK);
2485 AddTestCase(new TestWifiPhyRxTraceHelperMloStr, TestCase::Duration::QUICK);
2486 AddTestCase(new TestWifiPhyRxTraceHelperYans, TestCase::Duration::QUICK);
2487}
2488
Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY) frames (PPDU) w...
void SendPpduWithTwoMpdus(double rxPowerDbm, Mac48Address add1, Mac48Address add2, Ptr< ns3::SpectrumWifiPhy > tx_phy)
Sends a PPDU containing two MPDUs addressed to specific receivers.
TestWifiPhyRxTraceHelper(std::string test_name)
Constructs a TestWifiPhyRxTraceHelper instance with a given test name.
void DoRun() override
Implementation to actually run this TestCase.
Mac48Address wrongReceiver
The MAC address representing an incorrect receiver, used for testing.
WifiPhyRxTraceHelper m_rxTraceHelper
The helper being tested for tracking PHY reception events.
void CheckRecords(uint64_t expectedRecordCount)
Checks the statistics of PPDU and MPDU reception success and failure.
Mac48Address correctReceiver
The MAC address representing the correct receiver, used for testing.
Ptr< SpectrumWifiPhy > m_txB
The transmit function for node B.
std::map< ns3::Mac48Address, uint32_t > MacToNodeId
Maps MAC addresses to node IDs.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< Node > nodeRx
The receiving node.
void CheckAllStats(uint64_t expectedPpduSuccess, uint64_t expectedPpduFailure, uint64_t expectedMpduSuccess, uint64_t expectedMpduFailure, uint64_t expectedOverlaps, uint64_t expectedNonOverlaps)
Checks the statistics of PPDU and MPDU reception success and failure.
~TestWifiPhyRxTraceHelper() override=default
Destructor.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SendPpduWithOneMpdu(double rxPowerDbm, Mac48Address add1, Ptr< ns3::SpectrumWifiPhy > tx_phy)
Sends a PPDU containing one MPDU addressed to a specific receiver.
Ptr< SpectrumWifiPhy > m_txA
The transmit function for node A.
void CheckStats(WifiPhyTraceStatistics expectedStats, uint32_t nodeId, uint32_t deviceId, uint32_t linkId)
Checks the statistics of PPDU and MPDU reception success and failure.
Ptr< SpectrumWifiPhy > m_rx
The receive function for testing.
Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY) frames (PPDU) c...
Ptr< SpectrumWifiPhy > m_tx1A
The transmit function for node 1, link A.
void CheckRecords(uint64_t expectedRecordCount)
Checks the statistics of PPDU and MPDU reception success and failure.
void CheckAllStats(uint64_t expectedPpduSuccess, uint64_t expectedPpduFailure, uint64_t expectedMpduSuccess, uint64_t expectedMpduFailure, uint64_t expectedOverlaps, uint64_t expectedNonOverlaps)
Checks the statistics of PPDU and MPDU reception success and failure in MLO scenarios.
WifiPhyRxTraceHelper m_rxTraceHelper
The helper being tested for tracking PHY reception events in MLO scenarios.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SendPpduWithTwoMpdus(double rxPowerDbm, Mac48Address add1, Mac48Address add2, Ptr< ns3::SpectrumWifiPhy > tx_phy)
Sends a PPDU containing two MPDUs addressed to specific receivers, simulating an MLO scenario.
TestWifiPhyRxTraceHelperMloStr()
Constructs a TestWifiPhyRxTraceHelperMloStr instance for MLO reception testing.
Ptr< SpectrumWifiPhy > m_rxA
The receive function for node 2, link A.
void DoRun() override
Implementation to actually run this TestCase.
void CheckStats(WifiPhyTraceStatistics expectedStats, uint32_t nodeId)
Checks the statistics of PPDU and MPDU reception success and failure.
Ptr< SpectrumWifiPhy > m_rxB
The receive function for node 2, link B.
Mac48Address correctReceiver
The MAC address representing the correct receiver, used for testing in MLO.
Ptr< SpectrumWifiPhy > m_tx1B
The transmit function for node 1, link B.
std::map< ns3::Mac48Address, uint32_t > MacToNodeId
Maps MAC addresses to node IDs for MLO test configuration.
Mac48Address wrongReceiver
The MAC address representing an incorrect receiver, used for testing in MLO.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_tx0A
The transmit function for node 0, link A.
void SendPpduWithOneMpdu(double rxPowerDbm, Mac48Address add1, Ptr< ns3::SpectrumWifiPhy > tx_phy)
Sends a PPDU containing one MPDU addressed to a specific receiver, within an MLO setup.
Ptr< SpectrumWifiPhy > m_tx0B
The transmit function for node 0, link B.
Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY) frames (PPDU) w...
Ptr< YansWifiPhy > m_rx
The receive function for testing.
WifiPhyRxTraceHelper m_rxTraceHelper
The helper being tested for tracking PHY reception events.
void CheckStats(WifiPhyTraceStatistics expectedStats, uint32_t nodeId, uint32_t deviceId, uint32_t linkId)
Checks the statistics of PPDU and MPDU reception success and failure.
void DoRun() override
Implementation to actually run this TestCase.
void SendPpduWithTwoMpdus(double rxPowerDbm, Mac48Address add1, Mac48Address add2, Ptr< ns3::YansWifiPhy > tx_phy)
Sends a PPDU containing two MPDUs addressed to specific receivers.
Ptr< YansWifiPhy > m_txA
The transmit function for node A.
uint64_t m_uid
The unique identifier used for the PPDU in the test.
TestWifiPhyRxTraceHelperYans()
Constructs a TestWifiPhyRxTraceHelperYans instance for testing the trace helper with Yans.
void SendPpduWithOneMpdu(double rxPowerDbm, Mac48Address add1, Ptr< ns3::YansWifiPhy > tx_phy)
Sends a PPDU containing one MPDU addressed to a specific receiver.
void CheckRecords(uint64_t expectedRecordCount)
Checks the statistics of PPDU and MPDU reception success and failure.
Mac48Address wrongReceiver
The MAC address representing an incorrect receiver, used for testing.
std::map< ns3::Mac48Address, uint32_t > MacToNodeId
Maps MAC addresses to node IDs.
Mac48Address correctReceiver
The MAC address representing the correct receiver, used for testing.
Ptr< Node > nodeRx
The receiving node.
Ptr< YansWifiPhy > m_txB
The transmit function for node B.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void CheckAllStats(uint64_t expectedPpduSuccess, uint64_t expectedPpduFailure, uint64_t expectedMpduSuccess, uint64_t expectedMpduFailure, uint64_t expectedOverlaps, uint64_t expectedNonOverlaps)
Checks the statistics of PPDU and MPDU reception success and failure.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Ptr< FixedRssLossModel > propLoss
The propagation loss model used to configure RSSI.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
static WifiMode GetHeMcs0()
Return MCS 0 from HE MCS values.
an EUI-48 address
Definition: mac48-address.h:46
keep track of a set of node pointers.
void Add(const NodeContainer &nc)
Append the contents of another NodeContainer to the end of this container.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:135
uint32_t GetId() const
Definition: node.cc:117
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:149
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:309
void Dispose()
Dispose of this Object.
Definition: object.cc:258
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static void Run()
Run the simulation.
Definition: simulator.cc:178
void SetDevice(const Ptr< WifiNetDevice > device) override
Sets the device this PHY is associated with.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:302
A suite of tests to run.
Definition: test.h:1273
Type
Type of test.
Definition: test.h:1280
Implements the IEEE 802.11 MAC header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:662
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:671
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:993
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:1130
virtual void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:625
void SetTxPowerEnd(double end)
Sets the maximum available transmission power level (dBm).
Definition: wifi-phy.cc:560
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:692
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:926
void SetTxPowerStart(double start)
Sets the minimum available transmission power level (dBm).
Definition: wifi-phy.cc:547
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: wifi-phy.cc:2298
Assists in tracing and analyzing Wi-Fi Physical Layer (PHY) receptions.
const std::vector< WifiPpduRxRecord > & GetPpduRecords() const
Accesses a vector of saved and completed PPDU reception records.
void Reset()
Resets the current statistics, clearing all counts and PPDU records.
void Stop(Time stopTime)
Stops the collection of statistics at a specified time.
WifiPhyTraceStatistics GetStatistics() const
Retrieves current statistics of successful and failed data PPDUs and MPDUs receptions,...
void Enable(NodeContainer nodes)
Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
void Start(Time startTime)
Starts the collection of statistics from a specified start time.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetChannel(const Ptr< YansWifiChannel > channel)
Set the YansWifiChannel this YansWifiPhy is to be connected to.
void SetInterferenceHelper(const Ptr< InterferenceHelper > helper) override
Sets the interference helper.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:145
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1343
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
constexpr FrequencyRange WIFI_SPECTRUM_5_GHZ
Identifier for the frequency range covering the wifi spectrum in the 5 GHz band.
@ WIFI_MAC_QOSDATA
constexpr FrequencyRange WIFI_SPECTRUM_2_4_GHZ
Identifier for the frequency range covering the wifi spectrum in the 2.4 GHz band.
Keeps track of PHY layer trace statistics.
uint64_t m_failedMpdus
Number of failed unicast data MPDU receptions.
uint64_t m_failedPpdus
Number of failed PPDU receptions (with unicast data).
uint64_t m_receivedPpdus
Number of successfully received PPDUs (with unicast data).
uint64_t m_receivedMpdus
Number of successfully received unicast data MPDUs.
uint64_t m_overlappingPpdus
Number of PPDUs that overlapped in time with at least one other PPDU.
uint64_t m_nonOverlappingPpdus
Number of PPDUs that did not overlap in time with any other PPDU.
static WifiPhyRxTraceHelperTestSuite wifiPhyRxTestSuite
the test suite