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 * SPDX-License-Identifier: GPL-2.0-only
5 */
6#include "ns3/ampdu-tag.h"
7#include "ns3/ap-wifi-mac.h"
8#include "ns3/boolean.h"
9#include "ns3/config.h"
10#include "ns3/constant-position-mobility-model.h"
11#include "ns3/double.h"
12#include "ns3/eht-configuration.h"
13#include "ns3/he-phy.h"
14#include "ns3/he-ppdu.h"
15#include "ns3/interference-helper.h"
16#include "ns3/log.h"
17#include "ns3/mobility-helper.h"
18#include "ns3/mpdu-aggregator.h"
19#include "ns3/multi-model-spectrum-channel.h"
20#include "ns3/nist-error-rate-model.h"
21#include "ns3/ofdm-ppdu.h"
22#include "ns3/packet-socket-address.h"
23#include "ns3/packet-socket-client.h"
24#include "ns3/packet-socket-helper.h"
25#include "ns3/packet-socket-server.h"
26#include "ns3/pointer.h"
27#include "ns3/propagation-loss-model.h"
28#include "ns3/rng-seed-manager.h"
29#include "ns3/simple-frame-capture-model.h"
30#include "ns3/single-model-spectrum-channel.h"
31#include "ns3/spectrum-wifi-helper.h"
32#include "ns3/spectrum-wifi-phy.h"
33#include "ns3/test.h"
34#include "ns3/threshold-preamble-detection-model.h"
35#include "ns3/wifi-bandwidth-filter.h"
36#include "ns3/wifi-mac-header.h"
37#include "ns3/wifi-mpdu.h"
38#include "ns3/wifi-net-device.h"
39#include "ns3/wifi-phy-rx-trace-helper.h"
40#include "ns3/wifi-psdu.h"
41#include "ns3/wifi-spectrum-phy-interface.h"
42#include "ns3/wifi-spectrum-signal-parameters.h"
43#include "ns3/wifi-spectrum-value-helper.h"
44#include "ns3/wifi-utils.h"
45#include "ns3/yans-wifi-channel.h"
46#include "ns3/yans-wifi-phy.h"
47
48#include <optional>
49
50using namespace ns3;
51
52NS_LOG_COMPONENT_DEFINE("WifiPhyRxTraceHelperTest");
53
54/**
55 * @ingroup wifi-test
56 * @brief Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY)
57 * frames (PPDU) with multiple MAC Protocol Data Units (MPDUs).
58 *
59 * This class extends the TestCase class to simulate and analyze the reception of PPDUs containing
60 * either one or two MPDUs. It specifically tests the PHY layer's capability to handle multiple
61 * MPDUs addressed to specific receivers, measuring success and failure rates. The simulation setup
62 * includes configuring transmit and receive power levels, and the class provides functionality to
63 * check statistics related to PPDU and MPDU reception success and failure, as well as overlap
64 * handling.
65 */
67{
68 public:
69 /**
70 * Constructs a TestWifiPhyRxTraceHelper instance with a given test name.
71 * @param test_name The name of the test case.
72 */
73 TestWifiPhyRxTraceHelper(std::string test_name);
74
75 /**
76 * Destructor.
77 */
78 ~TestWifiPhyRxTraceHelper() override = default;
79
80 private:
81 void DoSetup() override;
82 void DoRun() override;
83 void DoTeardown() override;
84
85 /**
86 * Sends a PPDU containing two MPDUs addressed to specific receivers.
87 * @param rxPower The transmit power.
88 * @param add1 The MAC address of the first receiver.
89 * @param add2 The MAC address of the second receiver.
90 * @param tx_phy The transmitting PHY object.
91 */
92 void SendPpduWithTwoMpdus(dBm_u rxPower,
93 Mac48Address add1,
94 Mac48Address add2,
96
97 /**
98 * Sends a PPDU containing one MPDU addressed to a specific receiver.
99 * @param rxPower The transmit power.
100 * @param add1 The MAC address of the receiver.
101 * @param tx_phy The transmitting PHY object.
102 */
104
105 /**
106 * Checks the statistics of PPDU and MPDU reception success and failure.
107 * @param expectedPpduSuccess The expected number of successful PPDU receptions.
108 * @param expectedPpduFailure The expected number of failed PPDU receptions.
109 * @param expectedMpduSuccess The expected number of successful MPDU receptions within PPDUs.
110 * @param expectedMpduFailure The expected number of failed MPDU receptions within PPDUs.
111 * @param expectedOverlaps The expected number of overlapping reception events.
112 * @param expectedNonOverlaps The expected number of non-overlapping reception events.
113 */
114 void CheckAllStats(uint64_t expectedPpduSuccess,
115 uint64_t expectedPpduFailure,
116 uint64_t expectedMpduSuccess,
117 uint64_t expectedMpduFailure,
118 uint64_t expectedOverlaps,
119 uint64_t expectedNonOverlaps);
120
121 /**
122 * Checks the statistics of PPDU and MPDU reception success and failure.
123 * @param expectedStats The expected counts for PPDU and MPDU reception.
124 * @param nodeId The node ID for which to check the received stats.
125 * @param deviceId The device ID for which to check the received stats.
126 * @param linkId The link ID for which to check the received stats.
127 */
128 void CheckStats(WifiPhyTraceStatistics expectedStats,
129 uint32_t nodeId,
130 uint32_t deviceId,
131 uint32_t linkId);
132
133 /**
134 * Checks the statistics of PPDU and MPDU reception success and failure.
135 * @param expectedRecordCount The expected number of records.
136 */
137 void CheckRecords(uint64_t expectedRecordCount);
138
140 Mac48Address("00:00:00:00:00:01"); ///< The MAC address representing an incorrect receiver,
141 ///< used for testing.
143 Mac48Address("00:00:00:00:00:03"); ///< The MAC address representing the correct receiver,
144 ///< used for testing.
145
146 std::map<ns3::Mac48Address, uint32_t> MacToNodeId = {
147 {Mac48Address("00:00:00:00:00:04"), 0},
148 {Mac48Address("00:00:00:00:00:05"), 1},
149 {correctReceiver, 2},
150 {wrongReceiver, 3}}; ///< Maps MAC addresses to node IDs. This is done since there is no MAC
151 ///< layer configured and therefore the helper cannot obtain the MAC
152 ///< addresses automatically.
153
154 Ptr<Node> nodeRx; ///< The receiving node
155 Ptr<SpectrumWifiPhy> m_txA{nullptr}; ///< The transmit function for node A.
156 Ptr<SpectrumWifiPhy> m_txB{nullptr}; ///< The transmit function for node B.
157 Ptr<SpectrumWifiPhy> m_rx{nullptr}; ///< The receive function for testing.
158
160 m_rxTraceHelper; ///< The helper being tested for tracking PHY reception events.
161};
162
164 : TestCase{test_name}
165{
166}
167
168void
170{
171 dBm_u txPower{20};
172
173 auto spectrumChannel = CreateObject<SingleModelSpectrumChannel>();
174
175 auto nodeA = CreateObject<Node>();
176 auto devA = CreateObject<WifiNetDevice>();
178 m_txA->SetDevice(devA);
179 m_txA->SetTxPowerStart(txPower);
180 m_txA->SetTxPowerEnd(txPower);
181
182 auto nodeB = CreateObject<Node>();
183 auto devB = CreateObject<WifiNetDevice>();
185 m_txB->SetDevice(devB);
186 m_txB->SetTxPowerStart(txPower);
187 m_txB->SetTxPowerEnd(txPower);
188
190 auto devRx = CreateObject<WifiNetDevice>();
192 m_rx->SetDevice(devRx);
193
195 m_txA->SetInterferenceHelper(interferenceTxA);
196 auto errorTxA = CreateObject<NistErrorRateModel>();
197 m_txA->SetErrorRateModel(errorTxA);
198
199 auto interferenceTxB = CreateObject<InterferenceHelper>();
200 m_txB->SetInterferenceHelper(interferenceTxB);
201 auto errorTxB = CreateObject<NistErrorRateModel>();
202 m_txB->SetErrorRateModel(errorTxB);
203
204 auto interferenceRx = CreateObject<InterferenceHelper>();
205 m_rx->SetInterferenceHelper(interferenceRx);
206 auto errorRx = CreateObject<NistErrorRateModel>();
207 m_rx->SetErrorRateModel(errorRx);
208
209 m_txA->AddChannel(spectrumChannel);
210 m_txB->AddChannel(spectrumChannel);
211 m_rx->AddChannel(spectrumChannel);
212
213 m_txA->ConfigureStandard(WIFI_STANDARD_80211ax);
214 m_txB->ConfigureStandard(WIFI_STANDARD_80211ax);
215 m_rx->ConfigureStandard(WIFI_STANDARD_80211ax);
216
217 m_txA->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
218 m_txB->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
219 m_rx->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
220
221 devA->SetPhy(m_txA);
222 nodeA->AddDevice(devA);
223 devB->SetPhy(m_txB);
224 nodeB->AddDevice(devB);
225 devRx->SetPhy(m_rx);
226 nodeRx->AddDevice(devRx);
227
229 nodes.Add(nodeA);
230 nodes.Add(nodeB);
232
234
235 auto preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel>();
236 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
237 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
238 m_rx->SetPreambleDetectionModel(preambleDetectionModel);
239}
240
241void
243{
244 m_txA->Dispose();
245 m_txB->Dispose();
246 m_rx->Dispose();
247}
248
249void
251 Mac48Address receiver1,
252 Mac48Address receiver2,
254{
255 auto txPower = rxPower;
256 tx_phy->SetTxPowerStart(txPower);
257 tx_phy->SetTxPowerEnd(txPower);
258
260 0,
262 NanoSeconds(800),
263 1,
264 1,
265 0,
266 MHz_u{20},
267 true);
268
269 std::vector<Ptr<WifiMpdu>> mpduList;
270
271 WifiMacHeader hdr1;
273 hdr1.SetQosTid(0);
274 hdr1.SetAddr1(receiver1); // Changing the expected receiver
275 auto p1 = Create<Packet>(750);
276 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
277
278 WifiMacHeader hdr2;
280 hdr2.SetQosTid(0);
281 hdr2.SetAddr1(receiver2); // Changing the expected receiver
282 auto p2 = Create<Packet>(750);
283 mpduList.emplace_back(Create<WifiMpdu>(p2, hdr2));
284
285 auto psdu = Create<WifiPsdu>(mpduList);
286
287 tx_phy->Send(psdu, txVector);
288}
289
290void
292 Mac48Address receiver1,
294{
295 auto txPower = rxPower;
296 tx_phy->SetTxPowerStart(txPower);
297 tx_phy->SetTxPowerEnd(txPower);
298
300 0,
302 NanoSeconds(800),
303 1,
304 1,
305 0,
306 MHz_u{20},
307 true);
308
309 std::vector<Ptr<WifiMpdu>> mpduList;
310
311 WifiMacHeader hdr1;
313 hdr1.SetQosTid(0);
314 hdr1.SetAddr1(receiver1); // Changing the expected receiver
315 auto p1 = Create<Packet>(750);
316 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
317
318 auto psdu = Create<WifiPsdu>(mpduList);
319 tx_phy->Send(psdu, txVector);
320}
321
322void
323TestWifiPhyRxTraceHelper::CheckAllStats(uint64_t expectedPpduSuccess,
324 uint64_t expectedPpduFailure,
325 uint64_t expectedMpduSuccess,
326 uint64_t expectedMpduFailure,
327 uint64_t expectedOverlaps,
328 uint64_t expectedNonOverlaps)
329{
331
333 expectedPpduSuccess,
334 "Didn't receive right number of successful PPDUs");
336 expectedPpduFailure,
337 "Didn't receive right number of unsuccessful PPDUs");
339 expectedMpduSuccess,
340 "Didn't receive right number of successful MPDUs");
342 expectedMpduFailure,
343 "Didn't receive right number of unsuccessful MPDUs");
345 expectedOverlaps,
346 "Didn't receive right number of overlapping PPDUs");
348 expectedNonOverlaps,
349 "Didn't receive right number of nonoverlapping PPDUs");
351}
352
353void
355 uint32_t nodeId,
356 uint32_t deviceId,
357 uint32_t linkId)
358{
359 WifiPhyTraceStatistics stats = m_rxTraceHelper.GetStatistics(nodeId, deviceId, linkId);
360
362 expectedStats.m_receivedPpdus,
363 "Didn't receive right number of successful PPDUs");
365 expectedStats.m_failedPpdus,
366 "Didn't receive right number of unsuccessful PPDUs");
368 expectedStats.m_receivedMpdus,
369 "Didn't receive right number of successful MPDUs");
371 expectedStats.m_failedMpdus,
372 "Didn't receive right number of unsuccessful MPDUs");
374 expectedStats.m_overlappingPpdus,
375 "Didn't receive right number of overlapping PPDUs");
377 expectedStats.m_nonOverlappingPpdus,
378 "Didn't receive right number of nonoverlapping PPDUs");
379}
380
381void
382TestWifiPhyRxTraceHelper::CheckRecords(uint64_t expectedRecordCount)
383{
384 auto records = m_rxTraceHelper.GetPpduRecords();
385 NS_TEST_ASSERT_MSG_EQ(records.size(),
386 expectedRecordCount,
387 "Didn't produce the right number of Records");
388}
389
390void
392{
395 int64_t streamNumber = 1;
396 dBm_u rxPower{-80};
397 streamNumber += m_txA->AssignStreams(streamNumber);
398 streamNumber += m_txB->AssignStreams(streamNumber);
399 streamNumber += m_rx->AssignStreams(streamNumber);
400 WifiPhyTraceStatistics expectedStats;
401
403
404 // CASE 1: PPDU Reception with Sufficient RSSI With SOME Frames Addressed to Receiver
405 expectedStats.m_receivedPpdus = 1;
406 expectedStats.m_failedPpdus = 0;
407 expectedStats.m_receivedMpdus = 1;
408 expectedStats.m_failedMpdus = 0;
409 expectedStats.m_overlappingPpdus = 0;
410 expectedStats.m_nonOverlappingPpdus = 1;
411
412 // A-MPDU 1
415 this,
416 rxPower,
417 correctReceiver, // One MPDU addressed to
418 wrongReceiver, // One MPDU addressed to
419 m_txA);
420
423 this,
424 2); // Total Records
425
428 this,
429 expectedStats,
430 nodeRx->GetId(),
431 0,
432 0);
433
436 this,
437 expectedStats.m_receivedPpdus,
438 expectedStats.m_failedPpdus,
439 expectedStats.m_receivedMpdus,
440 expectedStats.m_failedMpdus,
441 expectedStats.m_overlappingPpdus,
442 expectedStats.m_nonOverlappingPpdus);
443
444 // CASE 2: PPDU Reception with inSufficient RSSI With SOME Frames Addressed to Receiver
445 expectedStats.m_receivedPpdus = 0;
446 expectedStats.m_failedPpdus = 1;
447 expectedStats.m_receivedMpdus = 0;
448 expectedStats.m_failedMpdus = 1;
449 expectedStats.m_overlappingPpdus = 0;
450 expectedStats.m_nonOverlappingPpdus = 1;
451 rxPower = dBm_u{-83};
452 // A-MPDU 1
455 this,
456 rxPower,
457 correctReceiver, // One MPDU addressed to
458 wrongReceiver, // One MPDU addressed to
459 m_txA);
460
463 this,
464 2); // TotalRecords
465
468 this,
469 expectedStats,
470 nodeRx->GetId(),
471 0,
472 0);
473
476 this,
477 expectedStats.m_receivedPpdus,
478 expectedStats.m_failedPpdus,
479 expectedStats.m_receivedMpdus,
480 expectedStats.m_failedMpdus,
481 expectedStats.m_overlappingPpdus,
482 expectedStats.m_nonOverlappingPpdus);
483
484 // CASE 3: PPDU Reception with Sufficient RSSI/SNR With NO Frames Addressed to Receiver
485 expectedStats.m_receivedPpdus = 0;
486 expectedStats.m_failedPpdus = 0;
487 expectedStats.m_receivedMpdus = 0;
488 expectedStats.m_failedMpdus = 0;
489 expectedStats.m_overlappingPpdus = 0;
490 expectedStats.m_nonOverlappingPpdus = 0;
491 rxPower = dBm_u{-80};
492 // A-MPDU 1
495 this,
496 rxPower,
497 wrongReceiver, // One MPDU addressed to
498 wrongReceiver, // One MPDU addressed to
499 m_txA);
500
503 this,
504 2); // TotalRecords
505
508 this,
509 expectedStats,
510 nodeRx->GetId(),
511 0,
512 0);
513
516 this,
517 expectedStats.m_receivedPpdus,
518 expectedStats.m_failedPpdus,
519 expectedStats.m_receivedMpdus,
520 expectedStats.m_failedMpdus,
521 expectedStats.m_overlappingPpdus,
522 expectedStats.m_nonOverlappingPpdus);
523
524 // CASE 4: PPDU Reception with Insufficient RSSI/SNR With NO Frames Addressed to Receiver
525 expectedStats.m_receivedPpdus = 0;
526 expectedStats.m_failedPpdus = 0;
527 expectedStats.m_receivedMpdus = 0;
528 expectedStats.m_failedMpdus = 0;
529 expectedStats.m_overlappingPpdus = 0;
530 expectedStats.m_nonOverlappingPpdus = 0;
531 rxPower = dBm_u{-83};
532 // A-MPDU 1
535 this,
536 rxPower,
537 wrongReceiver, // One MPDU addressed to
538 wrongReceiver, // One MPDU addressed to
539 m_txA);
540
543 this,
544 2); // TotalRecords
545
548 this,
549 expectedStats,
550 nodeRx->GetId(),
551 0,
552 0);
553
556 this,
557 expectedStats.m_receivedPpdus,
558 expectedStats.m_failedPpdus,
559 expectedStats.m_receivedMpdus,
560 expectedStats.m_failedMpdus,
561 expectedStats.m_overlappingPpdus,
562 expectedStats.m_nonOverlappingPpdus);
563
564 // CASE 5: PPDU Overlapping Reception with sufficient RSSI/SNR With ALL Frames Addressed to
565 // Receiver
566 expectedStats.m_receivedPpdus = 0;
567 expectedStats.m_failedPpdus = 2;
568 expectedStats.m_receivedMpdus = 0;
569 expectedStats.m_failedMpdus = 2;
570 expectedStats.m_overlappingPpdus = 2;
571 expectedStats.m_nonOverlappingPpdus = 0;
572 rxPower = dBm_u{-80};
573 // A-MPDU 1
576 this,
577 rxPower,
578 correctReceiver, // One MPDU addressed to
579 m_txA);
580 // A-MPDU 2
583 this,
584 rxPower,
585 correctReceiver, // One MPDU addressed to
586 m_txB);
587
590 this,
591 4); // TotalRecords
592
595 this,
596 expectedStats,
597 nodeRx->GetId(),
598 0,
599 0);
600
603 this,
604 expectedStats.m_receivedPpdus,
605 expectedStats.m_failedPpdus,
606 expectedStats.m_receivedMpdus,
607 expectedStats.m_failedMpdus,
608 expectedStats.m_overlappingPpdus,
609 expectedStats.m_nonOverlappingPpdus);
610
611 // CASE 6: PPDU Overlapping Reception with sufficient RSSI/SNR With SOME Frames Addressed to
612 // Receiver
613 expectedStats.m_receivedPpdus = 0;
614 expectedStats.m_failedPpdus = 1;
615 expectedStats.m_receivedMpdus = 0;
616 expectedStats.m_failedMpdus = 1;
617 expectedStats.m_overlappingPpdus = 1;
618 expectedStats.m_nonOverlappingPpdus = 0;
619 rxPower = dBm_u{-80};
620 // A-MPDU 1
623 this,
624 rxPower,
625 correctReceiver, // One MPDU addressed to
626 m_txA);
627 // A-MPDU 2
630 this,
631 rxPower,
632 wrongReceiver, // One MPDU addressed to
633 m_txB);
634
637 this,
638 4); // TotalRecords
639
642 this,
643 expectedStats,
644 nodeRx->GetId(),
645 0,
646 0);
647
650 this,
651 expectedStats.m_receivedPpdus,
652 expectedStats.m_failedPpdus,
653 expectedStats.m_receivedMpdus,
654 expectedStats.m_failedMpdus,
655 expectedStats.m_overlappingPpdus,
656 expectedStats.m_nonOverlappingPpdus);
657
658 // Stop Statistics Collection Period Since following testcases evaluate the Start and Stop
659 // methods
661
662 // CASE 7: Execution of "Start()" Before Signal Injection
663 expectedStats.m_receivedPpdus = 1;
664 expectedStats.m_failedPpdus = 0;
665 expectedStats.m_receivedMpdus = 1;
666 expectedStats.m_failedMpdus = 0;
667 expectedStats.m_overlappingPpdus = 0;
668 expectedStats.m_nonOverlappingPpdus = 1;
669 rxPower = dBm_u{-80};
671
672 // A-MPDU 1
675 this,
676 rxPower,
677 correctReceiver, // One MPDU addressed to
678 m_txA);
679
682 this,
683 2); // TotalRecords
684
687 this,
688 expectedStats,
689 nodeRx->GetId(),
690 0,
691 0);
692
695 this,
696 expectedStats.m_receivedPpdus,
697 expectedStats.m_failedPpdus,
698 expectedStats.m_receivedMpdus,
699 expectedStats.m_failedMpdus,
700 expectedStats.m_overlappingPpdus,
701 expectedStats.m_nonOverlappingPpdus);
702
704
705 // CASE 8: Activation of "Start()" Followed by "Stop()" Before Signal Injection
706 expectedStats.m_receivedPpdus = 0;
707 expectedStats.m_failedPpdus = 0;
708 expectedStats.m_receivedMpdus = 0;
709 expectedStats.m_failedMpdus = 0;
710 expectedStats.m_overlappingPpdus = 0;
711 expectedStats.m_nonOverlappingPpdus = 0;
712 rxPower = dBm_u{-80};
713
715
717
718 // A-MPDU 1
721 this,
722 rxPower,
723 correctReceiver, // One MPDU addressed to
724 m_txA);
725
728 this,
729 0); // TotalRecords
730
733 this,
734 expectedStats,
735 nodeRx->GetId(),
736 0,
737 0);
738
741 this,
742 expectedStats.m_receivedPpdus,
743 expectedStats.m_failedPpdus,
744 expectedStats.m_receivedMpdus,
745 expectedStats.m_failedMpdus,
746 expectedStats.m_overlappingPpdus,
747 expectedStats.m_nonOverlappingPpdus);
748
749 // CASE 9: "Start()" Method Initiated During Ongoing PPDU Reception
750 expectedStats.m_receivedPpdus = 1;
751 expectedStats.m_failedPpdus = 0;
752 expectedStats.m_receivedMpdus = 1;
753 expectedStats.m_failedMpdus = 0;
754 expectedStats.m_overlappingPpdus = 0;
755 expectedStats.m_nonOverlappingPpdus = 1;
756 rxPower = dBm_u{-80};
757
758 // A-MPDU 1
761 this,
762 rxPower,
763 correctReceiver, // One MPDU addressed to
764 m_txA);
765
767
770 this,
771 2); // TotalRecords
772
775 this,
776 expectedStats,
777 nodeRx->GetId(),
778 0,
779 0);
780
783 this,
784 expectedStats.m_receivedPpdus,
785 expectedStats.m_failedPpdus,
786 expectedStats.m_receivedMpdus,
787 expectedStats.m_failedMpdus,
788 expectedStats.m_overlappingPpdus,
789 expectedStats.m_nonOverlappingPpdus);
790
792
793 // CASE 10: Execution of "Stop()" During Ongoing PPDU Reception
794 expectedStats.m_receivedPpdus = 0;
795 expectedStats.m_failedPpdus = 0;
796 expectedStats.m_receivedMpdus = 0;
797 expectedStats.m_failedMpdus = 0;
798 expectedStats.m_overlappingPpdus = 0;
799 expectedStats.m_nonOverlappingPpdus = 0;
800 rxPower = dBm_u{-80};
801
803
804 // A-MPDU 1
807 this,
808 rxPower,
809 correctReceiver, // One MPDU addressed to
810 m_txA);
811
813
816 this,
817 0); // TotalRecords
818
821 this,
822 expectedStats,
823 nodeRx->GetId(),
824 0,
825 0);
826
829 this,
830 expectedStats.m_receivedPpdus,
831 expectedStats.m_failedPpdus,
832 expectedStats.m_receivedMpdus,
833 expectedStats.m_failedMpdus,
834 expectedStats.m_overlappingPpdus,
835 expectedStats.m_nonOverlappingPpdus);
836
839}
840
841/**
842 * @ingroup wifi-test
843 * @brief Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY)
844 * frames (PPDU) containing multiple MAC Protocol Data Units (MPDUs) in Multi-Link Operation (MLO)
845 * contexts.
846 *
847 * This class extends the TestCase class to simulate and analyze the reception of PPDUs containing
848 * either one or two MPDUs in MLO setups. It specifically assesses the WifiPhyRxTraceHelper
849 * ability to manage MLO by handling multiple MPDUs addressed to specific receivers across different
850 * links, measuring success and failure rates. The simulation setup includes configuring transmit
851 * and receive power levels and provides functionality to check statistics related to PPDU and MPDU
852 * reception success and failure, as well overlaps and non-overlaps in reception
853 * events.
854 */
856{
857 public:
858 /**
859 * Constructs a TestWifiPhyRxTraceHelperMloStr instance for MLO reception testing.
860 */
862
863 private:
864 void DoSetup() override;
865 void DoRun() override;
866
867 void DoTeardown() override;
868
869 /**
870 * Sends a PPDU containing two MPDUs addressed to specific receivers, simulating an MLO
871 * scenario.
872 * @param rxPower The transmit power.
873 * @param add1 The MAC address of the first receiver.
874 * @param add2 The MAC address of the second receiver.
875 * @param tx_phy The transmitting PHY object for MLO.
876 */
877 void SendPpduWithTwoMpdus(dBm_u rxPower,
878 Mac48Address add1,
879 Mac48Address add2,
881
882 /**
883 * Sends a PPDU containing one MPDU addressed to a specific receiver, within an MLO setup.
884 * @param rxPower The transmit power.
885 * @param add1 The MAC address of the receiver.
886 * @param tx_phy The transmitting PHY object for MLO.
887 */
889
890 /**
891 * Checks the statistics of PPDU and MPDU reception success and failure.
892 * @param expectedStats The expected counts for PPDU and MPDU reception.
893 * @param nodeId The node ID for which to check the received stats.
894 */
895 void CheckStats(WifiPhyTraceStatistics expectedStats, uint32_t nodeId);
896
897 /**
898 * Checks the statistics of PPDU and MPDU reception success and failure.
899 * @param expectedStats The expected counts for PPDU and MPDU reception.
900 * @param nodeId The node ID for which to check the received stats.
901 * @param deviceId The device ID for which to check the received stats.
902 */
903 void CheckStats(WifiPhyTraceStatistics expectedStats, uint32_t nodeId, uint32_t deviceId);
904
905 /**
906 * Checks the statistics of PPDU and MPDU reception success and failure.
907 * @param expectedStats The expected counts for PPDU and MPDU reception.
908 * @param nodeId The node ID for which to check the received stats.
909 * @param deviceId The device ID for which to check the received stats.
910 * @param linkId The link ID for which to check the received stats.
911 */
912 void CheckStats(WifiPhyTraceStatistics expectedStats,
913 uint32_t nodeId,
914 uint32_t deviceId,
915 uint32_t linkId);
916
917 /**
918 * Checks the statistics of PPDU and MPDU reception success and failure in MLO scenarios.
919 * @param expectedPpduSuccess The expected number of successful PPDU receptions.
920 * @param expectedPpduFailure The expected number of failed PPDU receptions.
921 * @param expectedMpduSuccess The expected number of successful MPDU receptions within PPDUs.
922 * @param expectedMpduFailure The expected number of failed MPDU receptions within PPDUs.
923 * @param expectedOverlaps The expected number of overlapping reception events.
924 * @param expectedNonOverlaps The expected number of non-overlapping reception events.
925 */
926 void CheckAllStats(uint64_t expectedPpduSuccess,
927 uint64_t expectedPpduFailure,
928 uint64_t expectedMpduSuccess,
929 uint64_t expectedMpduFailure,
930 uint64_t expectedOverlaps,
931 uint64_t expectedNonOverlaps);
932
933 /**
934 * Checks the statistics of PPDU and MPDU reception success and failure.
935 * @param expectedRecordCount The expected number of records.
936 */
937 void CheckRecords(uint64_t expectedRecordCount);
938
940 Mac48Address("00:00:00:00:00:01"); ///< The MAC address representing an incorrect receiver,
941 ///< used for testing in MLO.
943 Mac48Address("00:00:00:00:00:03"); ///< The MAC address representing the correct receiver,
944 ///< used for testing in MLO.
945
946 std::map<ns3::Mac48Address, uint32_t> MacToNodeId = {
947 {Mac48Address("00:00:00:00:00:04"), 0},
948 {Mac48Address("00:00:00:00:00:05"), 1},
949 {correctReceiver, 2},
950 {wrongReceiver, 3}}; ///< Maps MAC addresses to node IDs for MLO test configuration. This is
951 ///< done since there is no MAC layer configured and therefore the
952 ///< helper cannot obtain the MAC addresses automatically.
953
954 NodeContainer wifiNodes; ///< All wifi nodes
955 Ptr<SpectrumWifiPhy> m_tx0A{nullptr}; ///< The transmit function for node 0, link A.
956 Ptr<SpectrumWifiPhy> m_tx0B{nullptr}; ///< The transmit function for node 0, link B.
957 Ptr<SpectrumWifiPhy> m_tx1A{nullptr}; ///< The transmit function for node 1, link A.
958 Ptr<SpectrumWifiPhy> m_tx1B{nullptr}; ///< The transmit function for node 1, link B.
959 Ptr<SpectrumWifiPhy> m_rxA{nullptr}; ///< The receive function for node 2, link A.
960 Ptr<SpectrumWifiPhy> m_rxB{nullptr}; ///< The receive function for node 2, link B.
961
962 WifiPhyRxTraceHelper m_rxTraceHelper; ///< The helper being tested for tracking
963 ///< PHY reception events in MLO scenarios.
964};
965
967 : TestCase("Test for correct MLO operation")
968{
969}
970
971void
973{
974 dBm_u txPower{20};
975 auto ehtConfiguration = CreateObject<EhtConfiguration>();
976
977 auto nodeA = CreateObject<Node>();
978 auto devA = CreateObject<WifiNetDevice>();
979 devA->SetStandard(WIFI_STANDARD_80211be);
980 devA->SetEhtConfiguration(ehtConfiguration);
981
983 m_tx0A->SetDevice(devA);
984 m_tx0A->SetTxPowerStart(txPower);
985 m_tx0A->SetTxPowerEnd(txPower);
986
988 m_tx0B->SetDevice(devA);
989 m_tx0B->SetTxPowerStart(txPower);
990 m_tx0B->SetTxPowerEnd(txPower);
991
992 auto nodeB = CreateObject<Node>();
993 auto devB = CreateObject<WifiNetDevice>();
994 devB->SetStandard(WIFI_STANDARD_80211be);
995 devB->SetEhtConfiguration(ehtConfiguration);
996
998 m_tx1A->SetDevice(devB);
999 m_tx1A->SetTxPowerStart(txPower);
1000 m_tx1A->SetTxPowerEnd(txPower);
1001
1003 m_tx1B->SetDevice(devB);
1004 m_tx1B->SetTxPowerStart(txPower);
1005 m_tx1B->SetTxPowerEnd(txPower);
1006
1007 auto nodeRx = CreateObject<Node>();
1008 auto devRx = CreateObject<WifiNetDevice>();
1009 devRx->SetStandard(WIFI_STANDARD_80211be);
1010 devRx->SetEhtConfiguration(ehtConfiguration);
1012 m_rxA->SetDevice(devRx);
1014 m_rxB->SetDevice(devRx);
1015
1016 auto interferenceTx0A = CreateObject<InterferenceHelper>();
1017 m_tx0A->SetInterferenceHelper(interferenceTx0A);
1018 auto errorTx0A = CreateObject<NistErrorRateModel>();
1019 m_tx0A->SetErrorRateModel(errorTx0A);
1020
1021 auto interferenceTx0B = CreateObject<InterferenceHelper>();
1022 m_tx0B->SetInterferenceHelper(interferenceTx0B);
1023 auto errorTx0B = CreateObject<NistErrorRateModel>();
1024 m_tx0B->SetErrorRateModel(errorTx0B);
1025
1026 auto interferenceTx1A = CreateObject<InterferenceHelper>();
1027 m_tx1A->SetInterferenceHelper(interferenceTx1A);
1028 auto errorTx1A = CreateObject<NistErrorRateModel>();
1029 m_tx1A->SetErrorRateModel(errorTx1A);
1030
1031 auto interferenceTx1B = CreateObject<InterferenceHelper>();
1032 m_tx1B->SetInterferenceHelper(interferenceTx1B);
1033 auto errorTx1B = CreateObject<NistErrorRateModel>();
1034 m_tx1B->SetErrorRateModel(errorTx1B);
1035
1036 auto interferenceRxA = CreateObject<InterferenceHelper>();
1037 m_rxA->SetInterferenceHelper(interferenceRxA);
1038 auto errorRxA = CreateObject<NistErrorRateModel>();
1039 m_rxA->SetErrorRateModel(errorRxA);
1040
1041 auto interferenceRxB = CreateObject<InterferenceHelper>();
1042 m_rxB->SetInterferenceHelper(interferenceRxB);
1043 auto errorRxB = CreateObject<NistErrorRateModel>();
1044 m_rxB->SetErrorRateModel(errorRxB);
1045
1046 auto spectrumChannelA = CreateObject<MultiModelSpectrumChannel>();
1047 auto spectrumChannelB = CreateObject<MultiModelSpectrumChannel>();
1048
1049 m_tx0A->SetOperatingChannel(WifiPhy::ChannelTuple{2, 0, WIFI_PHY_BAND_2_4GHZ, 0});
1050 m_tx0B->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
1051
1052 m_tx1A->SetOperatingChannel(WifiPhy::ChannelTuple{2, 0, WIFI_PHY_BAND_2_4GHZ, 0});
1053 m_tx1B->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
1054
1055 m_rxA->SetOperatingChannel(WifiPhy::ChannelTuple{2, 0, WIFI_PHY_BAND_2_4GHZ, 0});
1056 m_rxB->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
1057
1058 m_tx0A->AddChannel(spectrumChannelA, WIFI_SPECTRUM_2_4_GHZ);
1059 m_tx0B->AddChannel(spectrumChannelB, WIFI_SPECTRUM_5_GHZ);
1060
1061 m_tx1A->AddChannel(spectrumChannelA, WIFI_SPECTRUM_2_4_GHZ);
1062 m_tx1B->AddChannel(spectrumChannelB, WIFI_SPECTRUM_5_GHZ);
1063
1064 m_rxA->AddChannel(spectrumChannelA, WIFI_SPECTRUM_2_4_GHZ);
1065 m_rxB->AddChannel(spectrumChannelB, WIFI_SPECTRUM_5_GHZ);
1066
1067 m_tx0A->ConfigureStandard(WIFI_STANDARD_80211be);
1068 m_tx0B->ConfigureStandard(WIFI_STANDARD_80211be);
1069
1070 m_tx1A->ConfigureStandard(WIFI_STANDARD_80211be);
1071 m_tx1B->ConfigureStandard(WIFI_STANDARD_80211be);
1072
1073 m_rxA->ConfigureStandard(WIFI_STANDARD_80211be);
1074 m_rxB->ConfigureStandard(WIFI_STANDARD_80211be);
1075
1076 std::vector<Ptr<WifiPhy>> phys0;
1077 phys0.emplace_back(m_tx0A);
1078 phys0.emplace_back(m_tx0B);
1079
1080 std::vector<Ptr<WifiPhy>> phys1;
1081 phys1.emplace_back(m_tx1A);
1082 phys1.emplace_back(m_tx1B);
1083
1084 std::vector<Ptr<WifiPhy>> physRx;
1085 physRx.emplace_back(m_rxA);
1086 physRx.emplace_back(m_rxB);
1087
1088 devA->SetPhys(phys0);
1089 nodeA->AddDevice(devA);
1090
1091 devB->SetPhys(phys1);
1092 nodeB->AddDevice(devB);
1093
1094 devRx->SetPhys(physRx);
1095 nodeRx->AddDevice(devRx);
1096
1097 wifiNodes.Add(nodeA);
1098 wifiNodes.Add(nodeB);
1099 wifiNodes.Add(nodeRx);
1100
1102
1103 auto preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel>();
1104 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
1105 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
1106 m_rxA->SetPreambleDetectionModel(preambleDetectionModel);
1107 m_rxB->SetPreambleDetectionModel(preambleDetectionModel);
1108}
1109
1110void
1112{
1113 m_tx0A->Dispose();
1114 m_tx0B->Dispose();
1115 m_tx1A->Dispose();
1116 m_tx1B->Dispose();
1117 m_rxA->Dispose();
1118 m_rxB->Dispose();
1119}
1120
1121void
1123 Mac48Address receiver1,
1124 Mac48Address receiver2,
1126{
1127 auto txPower = rxPower;
1128 tx_phy->SetTxPowerStart(txPower);
1129 tx_phy->SetTxPowerEnd(txPower);
1130
1132 0,
1134 NanoSeconds(800),
1135 1,
1136 1,
1137 0,
1138 MHz_u{20},
1139 true);
1140
1141 std::vector<Ptr<WifiMpdu>> mpduList;
1142
1143 WifiMacHeader hdr1;
1145 hdr1.SetQosTid(0);
1146 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1147 auto p1 = Create<Packet>(750);
1148 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1149
1150 WifiMacHeader hdr2;
1152 hdr2.SetQosTid(0);
1153 hdr2.SetAddr1(receiver2); // Changing the expected receiver
1154 auto p2 = Create<Packet>(750);
1155 mpduList.emplace_back(Create<WifiMpdu>(p2, hdr2));
1156
1157 auto psdu = Create<WifiPsdu>(mpduList);
1158
1159 tx_phy->Send(psdu, txVector);
1160}
1161
1162void
1164 Mac48Address receiver1,
1166{
1167 auto txPower = rxPower;
1168 tx_phy->SetTxPowerStart(txPower);
1169 tx_phy->SetTxPowerEnd(txPower);
1170
1171 WifiTxVector txVector =
1173 0,
1175 NanoSeconds(800),
1176 1,
1177 1,
1178 0,
1179 MHz_u{20},
1180 true); // for some reason needs to be set to true even though only one MPDU
1181
1182 std::vector<Ptr<WifiMpdu>> mpduList;
1183
1184 WifiMacHeader hdr1;
1186 hdr1.SetQosTid(0);
1187 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1188 auto p1 = Create<Packet>(750);
1189 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1190
1191 auto psdu = Create<WifiPsdu>(mpduList);
1192 tx_phy->Send(psdu, txVector);
1193}
1194
1195void
1197{
1199 for (uint32_t i = 0; i < wifiNodes.Get(nodeId)->GetNDevices(); i++)
1200 {
1201 for (uint32_t j = 0;
1202 j < DynamicCast<WifiNetDevice>(wifiNodes.Get(nodeId)->GetDevice(i))->GetNPhys();
1203 j++)
1204 {
1205 stats = stats + m_rxTraceHelper.GetStatistics(nodeId, i, j);
1206 }
1207 }
1208
1210 expectedStats.m_receivedPpdus,
1211 "Didn't receive right number of successful PPDUs");
1213 expectedStats.m_failedPpdus,
1214 "Didn't receive right number of unsuccessful PPDUs");
1216 expectedStats.m_receivedMpdus,
1217 "Didn't receive right number of successful MPDUs");
1219 expectedStats.m_failedMpdus,
1220 "Didn't receive right number of unsuccessful MPDUs");
1222 expectedStats.m_overlappingPpdus,
1223 "Didn't receive right number of overlapping PPDUs");
1225 expectedStats.m_nonOverlappingPpdus,
1226 "Didn't receive right number of nonoverlapping PPDUs");
1227}
1228
1229void
1231 uint32_t nodeId,
1232 uint32_t deviceId)
1233{
1235
1236 for (uint32_t i = 0;
1237 i < DynamicCast<WifiNetDevice>(wifiNodes.Get(nodeId)->GetDevice(deviceId))->GetNPhys();
1238 i++)
1239 {
1240 stats = stats + m_rxTraceHelper.GetStatistics(nodeId, deviceId, i);
1241 }
1242
1244 expectedStats.m_receivedPpdus,
1245 "Didn't receive right number of successful PPDUs");
1247 expectedStats.m_failedPpdus,
1248 "Didn't receive right number of unsuccessful PPDUs");
1250 expectedStats.m_receivedMpdus,
1251 "Didn't receive right number of successful MPDUs");
1253 expectedStats.m_failedMpdus,
1254 "Didn't receive right number of unsuccessful MPDUs");
1256 expectedStats.m_overlappingPpdus,
1257 "Didn't receive right number of overlapping PPDUs");
1259 expectedStats.m_nonOverlappingPpdus,
1260 "Didn't receive right number of nonoverlapping PPDUs");
1261}
1262
1263void
1265 uint32_t nodeId,
1266 uint32_t deviceId,
1267 uint32_t linkId)
1268{
1269 WifiPhyTraceStatistics stats = m_rxTraceHelper.GetStatistics(nodeId, deviceId, linkId);
1270
1272 expectedStats.m_receivedPpdus,
1273 "Didn't receive right number of successful PPDUs");
1275 expectedStats.m_failedPpdus,
1276 "Didn't receive right number of unsuccessful PPDUs");
1278 expectedStats.m_receivedMpdus,
1279 "Didn't receive right number of successful MPDUs");
1281 expectedStats.m_failedMpdus,
1282 "Didn't receive right number of unsuccessful MPDUs");
1284 expectedStats.m_overlappingPpdus,
1285 "Didn't receive right number of overlapping PPDUs");
1287 expectedStats.m_nonOverlappingPpdus,
1288 "Didn't receive right number of nonoverlapping PPDUs");
1289}
1290
1291void
1293 uint64_t expectedPpduFailure,
1294 uint64_t expectedMpduSuccess,
1295 uint64_t expectedMpduFailure,
1296 uint64_t expectedOverlaps,
1297 uint64_t expectedNonOverlaps)
1298{
1300
1302 expectedPpduSuccess,
1303 "Didn't receive right number of successful PPDUs");
1305 expectedPpduFailure,
1306 "Didn't receive right number of unsuccessful PPDUs");
1308 expectedMpduSuccess,
1309 "Didn't receive right number of successful MPDUs");
1311 expectedMpduFailure,
1312 "Didn't receive right number of unsuccessful MPDUs");
1314 expectedOverlaps,
1315 "Didn't receive right number of overlapping PPDUs");
1317 expectedNonOverlaps,
1318 "Didn't receive right number of nonoverlapping PPDUs");
1319
1321}
1322
1323void
1325{
1326 auto records = m_rxTraceHelper.GetPpduRecords();
1327 NS_TEST_ASSERT_MSG_EQ(records.size(),
1328 expectedRecordCount,
1329 "Didn't produce the right number of Records");
1330}
1331
1332void
1334{
1337 int64_t streamNumber = 1;
1338 dBm_u rxPower{-80};
1339 streamNumber += m_tx0A->AssignStreams(streamNumber);
1340 streamNumber += m_tx0B->AssignStreams(streamNumber);
1341 streamNumber += m_tx1A->AssignStreams(streamNumber);
1342 streamNumber += m_tx1B->AssignStreams(streamNumber);
1343 streamNumber += m_rxA->AssignStreams(streamNumber);
1344 streamNumber += m_rxB->AssignStreams(streamNumber);
1345 WifiPhyTraceStatistics expectedStats;
1346
1348
1349 // CASE 1: PPDU Reception with Sufficient RSSI With SOME Frames Addressed to Receiver
1350 expectedStats.m_receivedPpdus = 2;
1351 expectedStats.m_failedPpdus = 0;
1352 expectedStats.m_receivedMpdus = 2;
1353 expectedStats.m_failedMpdus = 0;
1354 expectedStats.m_overlappingPpdus = 0;
1355 expectedStats.m_nonOverlappingPpdus = 2;
1356
1357 // A-MPDU 1
1360 this,
1361 rxPower,
1362 correctReceiver, // One MPDU addressed to
1363 wrongReceiver, // One MPDU addressed to
1364 m_tx0A);
1365
1368 this,
1369 rxPower,
1370 correctReceiver, // One MPDU addressed to
1371 wrongReceiver, // One MPDU addressed to
1372 m_tx0B);
1373
1376 this,
1377 4); // Total Records
1378
1380 Seconds(0.2),
1383 this,
1384 expectedStats,
1385 wifiNodes.Get(2)->GetId());
1386
1389 this,
1390 expectedStats.m_receivedPpdus,
1391 expectedStats.m_failedPpdus,
1392 expectedStats.m_receivedMpdus,
1393 expectedStats.m_failedMpdus,
1394 expectedStats.m_overlappingPpdus,
1395 expectedStats.m_nonOverlappingPpdus);
1396
1397 // CASE 2: PPDU Reception with Insufficient RSSI With SOME Frames Addressed to Receiver
1398 expectedStats.m_receivedPpdus = 0;
1399 expectedStats.m_failedPpdus = 2;
1400 expectedStats.m_receivedMpdus = 0;
1401 expectedStats.m_failedMpdus = 2;
1402 expectedStats.m_overlappingPpdus = 0;
1403 expectedStats.m_nonOverlappingPpdus = 2;
1404 rxPower = dBm_u{-83};
1405 // A-MPDU 1
1408 this,
1409 rxPower,
1410 correctReceiver, // One MPDU addressed to
1411 wrongReceiver, // One MPDU addressed to
1412 m_tx0A);
1413
1416 this,
1417 rxPower,
1418 correctReceiver, // One MPDU addressed to
1419 wrongReceiver, // One MPDU addressed to
1420 m_tx0B);
1421
1424 this,
1425 4); // TotalRecords
1426
1428 Seconds(0.4),
1431 this,
1432 expectedStats,
1433 wifiNodes.Get(2)->GetId());
1434
1437 this,
1438 expectedStats.m_receivedPpdus,
1439 expectedStats.m_failedPpdus,
1440 expectedStats.m_receivedMpdus,
1441 expectedStats.m_failedMpdus,
1442 expectedStats.m_overlappingPpdus,
1443 expectedStats.m_nonOverlappingPpdus);
1444
1445 // CASE 3: PPDU Reception with Sufficient RSSI/SNR With NO Frames Addressed to Receiver
1446 expectedStats.m_receivedPpdus = 0;
1447 expectedStats.m_failedPpdus = 0;
1448 expectedStats.m_receivedMpdus = 0;
1449 expectedStats.m_failedMpdus = 0;
1450 expectedStats.m_overlappingPpdus = 0;
1451 expectedStats.m_nonOverlappingPpdus = 0;
1452 rxPower = dBm_u{-80};
1453 // A-MPDU 1
1456 this,
1457 rxPower,
1458 wrongReceiver, // One MPDU addressed to
1459 wrongReceiver, // One MPDU addressed to
1460 m_tx0A);
1461
1462 // A-MPDU 1
1465 this,
1466 rxPower,
1467 wrongReceiver, // One MPDU addressed to
1468 wrongReceiver, // One MPDU addressed to
1469 m_tx0B);
1470
1473 this,
1474 4); // TotalRecords
1475
1477 Seconds(0.6),
1480 this,
1481 expectedStats,
1482 wifiNodes.Get(2)->GetId());
1483
1486 this,
1487 expectedStats.m_receivedPpdus,
1488 expectedStats.m_failedPpdus,
1489 expectedStats.m_receivedMpdus,
1490 expectedStats.m_failedMpdus,
1491 expectedStats.m_overlappingPpdus,
1492 expectedStats.m_nonOverlappingPpdus);
1493
1494 // CASE 4: PPDU Reception with Insufficient RSSI/SNR With NO Frames Addressed to Receiver
1495 expectedStats.m_receivedPpdus = 0;
1496 expectedStats.m_failedPpdus = 0;
1497 expectedStats.m_receivedMpdus = 0;
1498 expectedStats.m_failedMpdus = 0;
1499 expectedStats.m_overlappingPpdus = 0;
1500 expectedStats.m_nonOverlappingPpdus = 0;
1501 rxPower = dBm_u{-83};
1502 // A-MPDU 1
1505 this,
1506 rxPower,
1507 wrongReceiver, // One MPDU addressed to
1508 wrongReceiver, // One MPDU addressed to
1509 m_tx0A);
1510
1511 // A-MPDU 1
1514 this,
1515 rxPower,
1516 wrongReceiver, // One MPDU addressed to
1517 wrongReceiver, // One MPDU addressed to
1518 m_tx0B);
1519
1522 this,
1523 4); // TotalRecords
1524
1526 Seconds(0.8),
1529 this,
1530 expectedStats,
1531 wifiNodes.Get(2)->GetId());
1532
1535 this,
1536 expectedStats.m_receivedPpdus,
1537 expectedStats.m_failedPpdus,
1538 expectedStats.m_receivedMpdus,
1539 expectedStats.m_failedMpdus,
1540 expectedStats.m_overlappingPpdus,
1541 expectedStats.m_nonOverlappingPpdus);
1542
1543 // CASE 5: PPDU Overlapping Reception with sufficient RSSI/SNR With ALL Frames Addressed to
1544 // Receiver
1545 expectedStats.m_receivedPpdus = 0;
1546 expectedStats.m_failedPpdus = 4;
1547 expectedStats.m_receivedMpdus = 0;
1548 expectedStats.m_failedMpdus = 4;
1549 expectedStats.m_overlappingPpdus = 4;
1550 expectedStats.m_nonOverlappingPpdus = 0;
1551 rxPower = dBm_u{-80};
1552 // A-MPDU 1
1555 this,
1556 rxPower,
1557 correctReceiver, // One MPDU addressed to
1558 m_tx0A);
1559 // A-MPDU 2
1562 this,
1563 rxPower,
1564 correctReceiver, // One MPDU addressed to
1565 m_tx1A);
1566
1567 // A-MPDU 1
1570 this,
1571 rxPower,
1572 correctReceiver, // One MPDU addressed to
1573 m_tx0B);
1574 // A-MPDU 2
1577 this,
1578 rxPower,
1579 correctReceiver, // One MPDU addressed to
1580 m_tx1B);
1581
1584 this,
1585 8); // TotalRecords
1586
1588 Seconds(1),
1591 this,
1592 expectedStats,
1593 wifiNodes.Get(2)->GetId());
1594
1597 this,
1598 expectedStats.m_receivedPpdus,
1599 expectedStats.m_failedPpdus,
1600 expectedStats.m_receivedMpdus,
1601 expectedStats.m_failedMpdus,
1602 expectedStats.m_overlappingPpdus,
1603 expectedStats.m_nonOverlappingPpdus);
1604
1605 // CASE 6: PPDU Overlapping Reception with sufficient RSSI/SNR With SOME Frames Addressed to
1606 // Receiver
1607 expectedStats.m_receivedPpdus = 0;
1608 expectedStats.m_failedPpdus = 2;
1609 expectedStats.m_receivedMpdus = 0;
1610 expectedStats.m_failedMpdus = 2;
1611 expectedStats.m_overlappingPpdus = 2;
1612 expectedStats.m_nonOverlappingPpdus = 0;
1613 rxPower = dBm_u{-80};
1614 // A-MPDU 1
1617 this,
1618 rxPower,
1619 correctReceiver, // One MPDU addressed to
1620 m_tx0A);
1621 // A-MPDU 2
1624 this,
1625 rxPower,
1626 wrongReceiver, // One MPDU addressed to
1627 m_tx1A);
1628
1629 // A-MPDU 1
1632 this,
1633 rxPower,
1634 correctReceiver, // One MPDU addressed to
1635 m_tx0B);
1636 // A-MPDU 2
1639 this,
1640 rxPower,
1641 wrongReceiver, // One MPDU addressed to
1642 m_tx1B);
1643
1646 this,
1647 8); // TotalRecords
1648
1650 Seconds(1.2),
1653 this,
1654 expectedStats,
1655 wifiNodes.Get(2)->GetId());
1656
1659 this,
1660 expectedStats.m_receivedPpdus,
1661 expectedStats.m_failedPpdus,
1662 expectedStats.m_receivedMpdus,
1663 expectedStats.m_failedMpdus,
1664 expectedStats.m_overlappingPpdus,
1665 expectedStats.m_nonOverlappingPpdus);
1666
1668
1671}
1672
1673/**
1674 * @ingroup wifi-test
1675 * @brief Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY)
1676 * frames (PPDU) with multiple MAC Protocol Data Units (MPDUs) when using YansWifiPhy.
1677 *
1678 * This class extends the TestCase class to simulate and analyze the reception of PPDUs containing
1679 * either one or two MPDUs. It specifically tests the PHY layer's capability to handle multiple
1680 * MPDUs addressed to specific receivers, measuring success and failure rates. The simulation setup
1681 * includes configuring transmit and receive power levels, and the class provides functionality to
1682 * check statistics related to PPDU and MPDU reception success and failure, as well as overlap
1683 * handling.
1684 */
1686{
1687 public:
1688 /**
1689 * Constructs a TestWifiPhyRxTraceHelperYans instance for testing the trace helper with
1690 * Yans.
1691 */
1693
1694 private:
1695 void DoSetup() override;
1696 void DoRun() override;
1697
1698 void DoTeardown() override;
1699
1700 /**
1701 * Sends a PPDU containing two MPDUs addressed to specific receivers.
1702 * @param rxPower The transmit power.
1703 * @param add1 The MAC address of the first receiver.
1704 * @param add2 The MAC address of the second receiver.
1705 * @param tx_phy The transmitting PHY object.
1706 */
1707 void SendPpduWithTwoMpdus(dBm_u rxPower,
1708 Mac48Address add1,
1709 Mac48Address add2,
1710 Ptr<ns3::YansWifiPhy> tx_phy);
1711
1712 /**
1713 * Sends a PPDU containing one MPDU addressed to a specific receiver.
1714 * @param rxPower The transmit power.
1715 * @param add1 The MAC address of the receiver.
1716 * @param tx_phy The transmitting PHY object.
1717 */
1718 void SendPpduWithOneMpdu(dBm_u rxPower, Mac48Address add1, Ptr<ns3::YansWifiPhy> tx_phy);
1719
1720 /**
1721 * Checks the statistics of PPDU and MPDU reception success and failure.
1722 * @param expectedPpduSuccess The expected number of successful PPDU receptions.
1723 * @param expectedPpduFailure The expected number of failed PPDU receptions.
1724 * @param expectedMpduSuccess The expected number of successful MPDU receptions within PPDUs.
1725 * @param expectedMpduFailure The expected number of failed MPDU receptions within PPDUs.
1726 * @param expectedOverlaps The expected number of overlapping reception events.
1727 * @param expectedNonOverlaps The expected number of non-overlapping reception events.
1728 */
1729 void CheckAllStats(uint64_t expectedPpduSuccess,
1730 uint64_t expectedPpduFailure,
1731 uint64_t expectedMpduSuccess,
1732 uint64_t expectedMpduFailure,
1733 uint64_t expectedOverlaps,
1734 uint64_t expectedNonOverlaps);
1735
1736 /**
1737 * Checks the statistics of PPDU and MPDU reception success and failure.
1738 * @param expectedStats The expected counts for PPDU and MPDU reception.
1739 * @param nodeId The node ID for which to check the received stats.
1740 * @param deviceId The device ID for which to check the received stats.
1741 * @param linkId The link ID for which to check the received stats.
1742 */
1743 void CheckStats(WifiPhyTraceStatistics expectedStats,
1744 uint32_t nodeId,
1745 uint32_t deviceId,
1746 uint32_t linkId);
1747
1748 /**
1749 * Checks the statistics of PPDU and MPDU reception success and failure.
1750 * @param expectedRecordCount The expected number of records.
1751 */
1752 void CheckRecords(uint64_t expectedRecordCount);
1753
1755 Mac48Address("00:00:00:00:00:01"); ///< The MAC address representing an incorrect receiver,
1756 ///< used for testing.
1758 Mac48Address("00:00:00:00:00:03"); ///< The MAC address representing the correct receiver,
1759 ///< used for testing.
1760
1761 std::map<ns3::Mac48Address, uint32_t> MacToNodeId = {
1762 {Mac48Address("00:00:00:00:00:04"), 0},
1763 {Mac48Address("00:00:00:00:00:05"), 1},
1764 {correctReceiver, 2},
1765 {wrongReceiver, 3}}; ///< Maps MAC addresses to node IDs. This is done since there is no MAC
1766 ///< layer configured and therefore the helper cannot obtain the MAC
1767 ///< addresses automatically.
1768
1769 Ptr<Node> nodeRx; ///< The receiving node
1770 Ptr<YansWifiPhy> m_txA{nullptr}; ///< The transmit function for node A.
1771 Ptr<YansWifiPhy> m_txB{nullptr}; ///< The transmit function for node B.
1772 Ptr<YansWifiPhy> m_rx{nullptr}; ///< The receive function for testing.
1773
1774 Ptr<FixedRssLossModel> propLoss; ///< The propagation loss model used to configure RSSI
1775
1777 m_rxTraceHelper; ///< The helper being tested for tracking PHY reception events.
1778
1779 uint64_t m_uid{0}; //!< The unique identifier used for the PPDU in the test.
1780};
1781
1783 : TestCase("Test for correct operation when using Yans")
1784{
1785}
1786
1787void
1789{
1790 dBm_u txPower{20};
1791
1792 auto yansChannel = CreateObject<YansWifiChannel>();
1795 yansChannel->SetPropagationDelayModel(propDelay);
1796 yansChannel->SetPropagationLossModel(propLoss);
1797
1798 auto nodeA = CreateObject<Node>();
1799 auto devA = CreateObject<WifiNetDevice>();
1801 m_txA->SetDevice(devA);
1802 m_txA->SetTxPowerStart(txPower);
1803 m_txA->SetTxPowerEnd(txPower);
1804
1805 auto nodeB = CreateObject<Node>();
1806 auto devB = CreateObject<WifiNetDevice>();
1808 m_txB->SetDevice(devB);
1809 m_txB->SetTxPowerStart(txPower);
1810 m_txB->SetTxPowerEnd(txPower);
1811
1813 auto devRx = CreateObject<WifiNetDevice>();
1815 m_rx->SetDevice(devRx);
1816
1817 auto interferenceTxA = CreateObject<InterferenceHelper>();
1818 m_txA->SetInterferenceHelper(interferenceTxA);
1819 auto errorTxA = CreateObject<NistErrorRateModel>();
1820 m_txA->SetErrorRateModel(errorTxA);
1821
1822 auto interferenceTxB = CreateObject<InterferenceHelper>();
1823 m_txB->SetInterferenceHelper(interferenceTxB);
1824 auto errorTxB = CreateObject<NistErrorRateModel>();
1825 m_txB->SetErrorRateModel(errorTxB);
1826
1827 auto interferenceRx = CreateObject<InterferenceHelper>();
1828 m_rx->SetInterferenceHelper(interferenceRx);
1829 auto errorRx = CreateObject<NistErrorRateModel>();
1830 m_rx->SetErrorRateModel(errorRx);
1831
1832 m_txA->SetChannel(yansChannel);
1833 m_txB->SetChannel(yansChannel);
1834 m_rx->SetChannel(yansChannel);
1835
1839
1843
1844 devA->SetPhy(m_txA);
1845 nodeA->AddDevice(devA);
1846 devB->SetPhy(m_txB);
1847 nodeB->AddDevice(devB);
1848 devRx->SetPhy(m_rx);
1849 nodeRx->AddDevice(devRx);
1850
1852 mobilityA->SetPosition(Vector(0.0, 0.0, 0.0));
1853 nodeA->AggregateObject(mobilityA);
1854
1856 mobilityB->SetPosition(Vector(0.0, 0.0, 0.0));
1857 nodeB->AggregateObject(mobilityB);
1858
1860 mobilityRx->SetPosition(Vector(0.0, 0.0, 0.0));
1861 nodeRx->AggregateObject(mobilityRx);
1862
1864 nodes.Add(nodeA);
1865 nodes.Add(nodeB);
1866 nodes.Add(nodeRx);
1867
1869
1870 auto preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel>();
1871 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
1872 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
1873 m_rx->SetPreambleDetectionModel(preambleDetectionModel);
1874}
1875
1876void
1883
1884void
1886 Mac48Address receiver1,
1887 Mac48Address receiver2,
1888 Ptr<ns3::YansWifiPhy> tx_phy)
1889{
1890 propLoss->SetRss(rxPower);
1891
1893 0,
1895 NanoSeconds(800),
1896 1,
1897 1,
1898 0,
1899 MHz_u{20},
1900 true);
1901
1902 std::vector<Ptr<WifiMpdu>> mpduList;
1903
1904 WifiMacHeader hdr1;
1906 hdr1.SetQosTid(0);
1907 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1908 auto p1 = Create<Packet>(750);
1909 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1910
1911 WifiMacHeader hdr2;
1913 hdr2.SetQosTid(0);
1914 hdr2.SetAddr1(receiver2); // Changing the expected receiver
1915 auto p2 = Create<Packet>(750);
1916 mpduList.emplace_back(Create<WifiMpdu>(p2, hdr2));
1917
1918 auto psdu = Create<WifiPsdu>(mpduList);
1919 auto ppdu = Create<HePpdu>(
1920 psdu,
1921 txVector,
1922 tx_phy->GetOperatingChannel(),
1923 YansWifiPhy::CalculateTxDuration(psdu->GetSize(), txVector, tx_phy->GetPhyBand()),
1924 m_uid);
1925
1926 m_uid++;
1927
1928 tx_phy->StartTx(ppdu);
1929}
1930
1931void
1933 Mac48Address receiver1,
1934 Ptr<ns3::YansWifiPhy> tx_phy)
1935{
1936 propLoss->SetRss(rxPower);
1937
1938 auto txVector = WifiTxVector(HePhy::GetHeMcs0(),
1939 0,
1941 NanoSeconds(800),
1942 1,
1943 1,
1944 0,
1945 MHz_u{20},
1946 true);
1947
1948 std::vector<Ptr<WifiMpdu>> mpduList;
1949
1950 WifiMacHeader hdr1;
1952 hdr1.SetQosTid(0);
1953 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1954 auto p1 = Create<Packet>(750);
1955 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1956
1957 auto psdu = Create<WifiPsdu>(mpduList);
1958 auto ppdu = Create<HePpdu>(
1959 psdu,
1960 txVector,
1961 tx_phy->GetOperatingChannel(),
1962 YansWifiPhy::CalculateTxDuration(psdu->GetSize(), txVector, tx_phy->GetPhyBand()),
1963 m_uid);
1964
1965 m_uid++;
1966
1967 tx_phy->StartTx(ppdu);
1968}
1969
1970void
1972 uint64_t expectedPpduFailure,
1973 uint64_t expectedMpduSuccess,
1974 uint64_t expectedMpduFailure,
1975 uint64_t expectedOverlaps,
1976 uint64_t expectedNonOverlaps)
1977{
1978 auto stats = m_rxTraceHelper.GetStatistics();
1979
1980 NS_TEST_ASSERT_MSG_EQ(stats.m_receivedPpdus,
1981 expectedPpduSuccess,
1982 "Didn't receive right number of successful PPDUs");
1983 NS_TEST_ASSERT_MSG_EQ(stats.m_failedPpdus,
1984 expectedPpduFailure,
1985 "Didn't receive right number of unsuccessful PPDUs");
1986 NS_TEST_ASSERT_MSG_EQ(stats.m_receivedMpdus,
1987 expectedMpduSuccess,
1988 "Didn't receive right number of successful MPDUs");
1989 NS_TEST_ASSERT_MSG_EQ(stats.m_failedMpdus,
1990 expectedMpduFailure,
1991 "Didn't receive right number of unsuccessful MPDUs");
1992 NS_TEST_ASSERT_MSG_EQ(stats.m_overlappingPpdus,
1993 expectedOverlaps,
1994 "Didn't receive right number of overlapping PPDUs");
1995 NS_TEST_ASSERT_MSG_EQ(stats.m_nonOverlappingPpdus,
1996 expectedNonOverlaps,
1997 "Didn't receive right number of nonoverlapping PPDUs");
1998
2000}
2001
2002void
2004 uint32_t nodeId,
2005 uint32_t deviceId,
2006 uint32_t linkId)
2007{
2008 WifiPhyTraceStatistics stats = m_rxTraceHelper.GetStatistics(nodeId, deviceId, linkId);
2009
2011 expectedStats.m_receivedPpdus,
2012 "Didn't receive right number of successful PPDUs");
2014 expectedStats.m_failedPpdus,
2015 "Didn't receive right number of unsuccessful PPDUs");
2017 expectedStats.m_receivedMpdus,
2018 "Didn't receive right number of successful MPDUs");
2020 expectedStats.m_failedMpdus,
2021 "Didn't receive right number of unsuccessful MPDUs");
2023 expectedStats.m_overlappingPpdus,
2024 "Didn't receive right number of overlapping PPDUs");
2026 expectedStats.m_nonOverlappingPpdus,
2027 "Didn't receive right number of nonoverlapping PPDUs");
2028}
2029
2030void
2032{
2033 auto records = m_rxTraceHelper.GetPpduRecords();
2034 NS_TEST_ASSERT_MSG_EQ(records.size(),
2035 expectedRecordCount,
2036 "Didn't produce the right number of Records");
2037}
2038
2039void
2041{
2044 int64_t streamNumber = 1;
2045 dBm_u rxPower{-80};
2046 streamNumber += m_txA->AssignStreams(streamNumber);
2047 streamNumber += m_txB->AssignStreams(streamNumber);
2048 streamNumber += m_rx->AssignStreams(streamNumber);
2049 WifiPhyTraceStatistics expectedStats;
2050
2052
2053 // CASE 1: PPDU Reception with Sufficient RSSI With SOME Frames Addressed to Receiver
2054 expectedStats.m_receivedPpdus = 1;
2055 expectedStats.m_failedPpdus = 0;
2056 expectedStats.m_receivedMpdus = 1;
2057 expectedStats.m_failedMpdus = 0;
2058 expectedStats.m_overlappingPpdus = 0;
2059 expectedStats.m_nonOverlappingPpdus = 1;
2060
2061 // A-MPDU 1
2064 this,
2065 rxPower,
2066 correctReceiver, // One MPDU addressed to
2067 wrongReceiver, // One MPDU addressed to
2068 m_txA);
2069
2072 this,
2073 2); // Total Records
2074
2077 this,
2078 expectedStats,
2079 nodeRx->GetId(),
2080 0,
2081 0);
2082
2085 this,
2086 expectedStats.m_receivedPpdus,
2087 expectedStats.m_failedPpdus,
2088 expectedStats.m_receivedMpdus,
2089 expectedStats.m_failedMpdus,
2090 expectedStats.m_overlappingPpdus,
2091 expectedStats.m_nonOverlappingPpdus);
2092 // CASE 2: PPDU Reception with inSufficient RSSI With SOME Frames Addressed to Receiver
2093 expectedStats.m_receivedPpdus = 0;
2094 expectedStats.m_failedPpdus = 1;
2095 expectedStats.m_receivedMpdus = 0;
2096 expectedStats.m_failedMpdus = 1;
2097 expectedStats.m_overlappingPpdus = 0;
2098 expectedStats.m_nonOverlappingPpdus = 1;
2099 rxPower = dBm_u{-83};
2100 // A-MPDU 1
2103 this,
2104 rxPower,
2105 correctReceiver, // One MPDU addressed to
2106 wrongReceiver, // One MPDU addressed to
2107 m_txA);
2108
2111 this,
2112 2); // TotalRecords
2113
2116 this,
2117 expectedStats,
2118 nodeRx->GetId(),
2119 0,
2120 0);
2121
2124 this,
2125 expectedStats.m_receivedPpdus,
2126 expectedStats.m_failedPpdus,
2127 expectedStats.m_receivedMpdus,
2128 expectedStats.m_failedMpdus,
2129 expectedStats.m_overlappingPpdus,
2130 expectedStats.m_nonOverlappingPpdus);
2131
2132 // CASE 3: PPDU Reception with Sufficient RSSI/SNR With NO Frames Addressed to Receiver
2133 expectedStats.m_receivedPpdus = 0;
2134 expectedStats.m_failedPpdus = 0;
2135 expectedStats.m_receivedMpdus = 0;
2136 expectedStats.m_failedMpdus = 0;
2137 expectedStats.m_overlappingPpdus = 0;
2138 expectedStats.m_nonOverlappingPpdus = 0;
2139 rxPower = dBm_u{-80};
2140 // A-MPDU 1
2143 this,
2144 rxPower,
2145 wrongReceiver, // One MPDU addressed to
2146 wrongReceiver, // One MPDU addressed to
2147 m_txA);
2148
2151 this,
2152 2); // TotalRecords
2153
2156 this,
2157 expectedStats,
2158 nodeRx->GetId(),
2159 0,
2160 0);
2161
2164 this,
2165 expectedStats.m_receivedPpdus,
2166 expectedStats.m_failedPpdus,
2167 expectedStats.m_receivedMpdus,
2168 expectedStats.m_failedMpdus,
2169 expectedStats.m_overlappingPpdus,
2170 expectedStats.m_nonOverlappingPpdus);
2171
2172 // CASE 4: PPDU Reception with Insufficient RSSI/SNR With NO Frames Addressed to Receiver
2173 expectedStats.m_receivedPpdus = 0;
2174 expectedStats.m_failedPpdus = 0;
2175 expectedStats.m_receivedMpdus = 0;
2176 expectedStats.m_failedMpdus = 0;
2177 expectedStats.m_overlappingPpdus = 0;
2178 expectedStats.m_nonOverlappingPpdus = 0;
2179 rxPower = dBm_u{-83};
2180 // A-MPDU 1
2183 this,
2184 rxPower,
2185 wrongReceiver, // One MPDU addressed to
2186 wrongReceiver, // One MPDU addressed to
2187 m_txA);
2188
2191 this,
2192 2); // TotalRecords
2193
2196 this,
2197 expectedStats,
2198 nodeRx->GetId(),
2199 0,
2200 0);
2201
2204 this,
2205 expectedStats.m_receivedPpdus,
2206 expectedStats.m_failedPpdus,
2207 expectedStats.m_receivedMpdus,
2208 expectedStats.m_failedMpdus,
2209 expectedStats.m_overlappingPpdus,
2210 expectedStats.m_nonOverlappingPpdus);
2211
2212 // CASE 5: PPDU Overlapping Reception with sufficient RSSI/SNR With ALL Frames Addressed to
2213 // Receiver
2214 expectedStats.m_receivedPpdus = 0;
2215 expectedStats.m_failedPpdus = 2;
2216 expectedStats.m_receivedMpdus = 0;
2217 expectedStats.m_failedMpdus = 2;
2218 expectedStats.m_overlappingPpdus = 2;
2219 expectedStats.m_nonOverlappingPpdus = 0;
2220 rxPower = dBm_u{-80};
2221 // A-MPDU 1
2224 this,
2225 rxPower,
2226 correctReceiver, // One MPDU addressed to
2227 m_txA);
2228 // A-MPDU 2
2231 this,
2232 rxPower,
2233 correctReceiver, // One MPDU addressed to
2234 m_txB);
2235
2238 this,
2239 4); // TotalRecords
2240
2243 this,
2244 expectedStats,
2245 nodeRx->GetId(),
2246 0,
2247 0);
2248
2251 this,
2252 expectedStats.m_receivedPpdus,
2253 expectedStats.m_failedPpdus,
2254 expectedStats.m_receivedMpdus,
2255 expectedStats.m_failedMpdus,
2256 expectedStats.m_overlappingPpdus,
2257 expectedStats.m_nonOverlappingPpdus);
2258
2259 // CASE 6: PPDU Overlapping Reception with sufficient RSSI/SNR With SOME Frames Addressed to
2260 // Receiver
2261 expectedStats.m_receivedPpdus = 0;
2262 expectedStats.m_failedPpdus = 1;
2263 expectedStats.m_receivedMpdus = 0;
2264 expectedStats.m_failedMpdus = 1;
2265 expectedStats.m_overlappingPpdus = 1;
2266 expectedStats.m_nonOverlappingPpdus = 0;
2267 rxPower = dBm_u{-80};
2268 // A-MPDU 1
2271 this,
2272 rxPower,
2273 correctReceiver, // One MPDU addressed to
2274 m_txA);
2275 // A-MPDU 2
2278 this,
2279 rxPower,
2280 wrongReceiver, // One MPDU addressed to
2281 m_txB);
2282
2285 this,
2286 4); // TotalRecords
2287
2290 this,
2291 expectedStats,
2292 nodeRx->GetId(),
2293 0,
2294 0);
2295
2298 this,
2299 expectedStats.m_receivedPpdus,
2300 expectedStats.m_failedPpdus,
2301 expectedStats.m_receivedMpdus,
2302 expectedStats.m_failedMpdus,
2303 expectedStats.m_overlappingPpdus,
2304 expectedStats.m_nonOverlappingPpdus);
2305
2306 // Stop Statistics Collection Period Since following testcases evaluate the Start and Stop
2307 // methods
2309
2310 // CASE 7: Execution of "Start()" Before Signal Injection
2311 expectedStats.m_receivedPpdus = 1;
2312 expectedStats.m_failedPpdus = 0;
2313 expectedStats.m_receivedMpdus = 1;
2314 expectedStats.m_failedMpdus = 0;
2315 expectedStats.m_overlappingPpdus = 0;
2316 expectedStats.m_nonOverlappingPpdus = 1;
2317 rxPower = dBm_u{-80};
2319
2320 // A-MPDU 1
2323 this,
2324 rxPower,
2325 correctReceiver, // One MPDU addressed to
2326 m_txA);
2327
2330 this,
2331 2); // TotalRecords
2332
2335 this,
2336 expectedStats,
2337 nodeRx->GetId(),
2338 0,
2339 0);
2340
2343 this,
2344 expectedStats.m_receivedPpdus,
2345 expectedStats.m_failedPpdus,
2346 expectedStats.m_receivedMpdus,
2347 expectedStats.m_failedMpdus,
2348 expectedStats.m_overlappingPpdus,
2349 expectedStats.m_nonOverlappingPpdus);
2350
2352
2353 // CASE 8: Activation of "Start()" Followed by "Stop()" Before Signal Injection
2354 expectedStats.m_receivedPpdus = 0;
2355 expectedStats.m_failedPpdus = 0;
2356 expectedStats.m_receivedMpdus = 0;
2357 expectedStats.m_failedMpdus = 0;
2358 expectedStats.m_overlappingPpdus = 0;
2359 expectedStats.m_nonOverlappingPpdus = 0;
2360 rxPower = dBm_u{-80};
2361
2363
2365
2366 // A-MPDU 1
2369 this,
2370 rxPower,
2371 correctReceiver, // One MPDU addressed to
2372 m_txA);
2373
2376 this,
2377 0); // TotalRecords
2378
2381 this,
2382 expectedStats,
2383 nodeRx->GetId(),
2384 0,
2385 0);
2386
2389 this,
2390 expectedStats.m_receivedPpdus,
2391 expectedStats.m_failedPpdus,
2392 expectedStats.m_receivedMpdus,
2393 expectedStats.m_failedMpdus,
2394 expectedStats.m_overlappingPpdus,
2395 expectedStats.m_nonOverlappingPpdus);
2396
2397 // CASE 9: "Start()" Method Initiated During Ongoing PPDU Reception
2398 expectedStats.m_receivedPpdus = 1;
2399 expectedStats.m_failedPpdus = 0;
2400 expectedStats.m_receivedMpdus = 1;
2401 expectedStats.m_failedMpdus = 0;
2402 expectedStats.m_overlappingPpdus = 0;
2403 expectedStats.m_nonOverlappingPpdus = 1;
2404 rxPower = dBm_u{-80};
2405
2406 // A-MPDU 1
2409 this,
2410 rxPower,
2411 correctReceiver, // One MPDU addressed to
2412 m_txA);
2413
2415
2418 this,
2419 2); // TotalRecords
2420
2423 this,
2424 expectedStats,
2425 nodeRx->GetId(),
2426 0,
2427 0);
2428
2431 this,
2432 expectedStats.m_receivedPpdus,
2433 expectedStats.m_failedPpdus,
2434 expectedStats.m_receivedMpdus,
2435 expectedStats.m_failedMpdus,
2436 expectedStats.m_overlappingPpdus,
2437 expectedStats.m_nonOverlappingPpdus);
2438
2440
2441 // CASE 10: Execution of "Stop()" During Ongoing PPDU Reception
2442 expectedStats.m_receivedPpdus = 0;
2443 expectedStats.m_failedPpdus = 0;
2444 expectedStats.m_receivedMpdus = 0;
2445 expectedStats.m_failedMpdus = 0;
2446 expectedStats.m_overlappingPpdus = 0;
2447 expectedStats.m_nonOverlappingPpdus = 0;
2448 rxPower = dBm_u{-80};
2449
2451
2452 // A-MPDU 1
2455 this,
2456 rxPower,
2457 correctReceiver, // One MPDU addressed to
2458 m_txA);
2459
2461
2464 this,
2465 0); // TotalRecords
2466
2469 this,
2470 expectedStats,
2471 nodeRx->GetId(),
2472 0,
2473 0);
2474
2477 this,
2478 expectedStats.m_receivedPpdus,
2479 expectedStats.m_failedPpdus,
2480 expectedStats.m_receivedMpdus,
2481 expectedStats.m_failedMpdus,
2482 expectedStats.m_overlappingPpdus,
2483 expectedStats.m_nonOverlappingPpdus);
2484
2487}
2488
2489/**
2490 * @ingroup wifi-test
2491 * @ingroup tests
2492 *
2493 * @brief wifi PHY reception Test Suite
2494 */
2496{
2497 public:
2499};
2500
2502 : TestSuite("wifi-phy-rx-trace-helper", Type::UNIT)
2503{
2504 AddTestCase(new TestWifiPhyRxTraceHelper("test-statistics"), TestCase::Duration::QUICK);
2505 AddTestCase(new TestWifiPhyRxTraceHelperMloStr, TestCase::Duration::QUICK);
2506 AddTestCase(new TestWifiPhyRxTraceHelperYans, TestCase::Duration::QUICK);
2507}
2508
Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY) frames (PPDU) w...
TestWifiPhyRxTraceHelper(std::string test_name)
Constructs a TestWifiPhyRxTraceHelper instance with a given test name.
void DoRun() override
Implementation to actually run this TestCase.
void SendPpduWithTwoMpdus(dBm_u rxPower, Mac48Address add1, Mac48Address add2, Ptr< ns3::SpectrumWifiPhy > tx_phy)
Sends a PPDU containing two MPDUs addressed to specific receivers.
Mac48Address wrongReceiver
The MAC address representing an incorrect receiver, used for testing.
void SendPpduWithOneMpdu(dBm_u rxPower, Mac48Address add1, Ptr< ns3::SpectrumWifiPhy > tx_phy)
Sends a PPDU containing one MPDU addressed to a specific receiver.
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.
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.
TestWifiPhyRxTraceHelperMloStr()
Constructs a TestWifiPhyRxTraceHelperMloStr instance for MLO reception testing.
void SendPpduWithTwoMpdus(dBm_u rxPower, Mac48Address add1, Mac48Address add2, Ptr< ns3::SpectrumWifiPhy > tx_phy)
Sends a PPDU containing two MPDUs addressed to specific receivers, simulating an MLO scenario.
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.
void SendPpduWithOneMpdu(dBm_u rxPower, Mac48Address add1, Ptr< ns3::SpectrumWifiPhy > tx_phy)
Sends a PPDU containing one MPDU addressed to a specific receiver, within an MLO setup.
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.
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.
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 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.
void SendPpduWithOneMpdu(dBm_u rxPower, Mac48Address add1, Ptr< ns3::YansWifiPhy > tx_phy)
Sends a PPDU containing one MPDU addressed to a specific receiver.
void SendPpduWithTwoMpdus(dBm_u rxPower, Mac48Address add1, Mac48Address add2, Ptr< ns3::YansWifiPhy > tx_phy)
Sends a PPDU containing two MPDUs addressed to specific receivers.
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:31
static WifiMode GetHeMcs0()
Return MCS 0 from HE MCS values.
an EUI-48 address
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:124
uint32_t GetId() const
Definition node.cc:106
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition node.cc:138
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition object.cc:298
void Dispose()
Dispose of this Object.
Definition object.cc:247
Smart pointer class similar to boost::intrusive_ptr.
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:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
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.
void SetTxPowerEnd(dBm_u end)
Sets the maximum available transmission power level.
Definition wifi-phy.cc:576
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition wifi-phy.cc:687
std::tuple< uint8_t, MHz_u, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying a segment of an operating channel.
Definition wifi-phy.h:940
void SetTxPowerStart(dBm_u start)
Sets the minimum available transmission power level.
Definition wifi-phy.cc:563
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition wifi-phy.cc:1009
virtual void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition wifi-phy.cc:641
void SetOperatingChannel(const WifiPhyOperatingChannel &channel)
If the standard for this object has not been set yet, store the channel settings corresponding to the...
Definition wifi-phy.cc:1135
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition wifi-phy.cc:708
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:2363
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:191
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#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:134
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1368
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1380
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
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