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/rng-seed-manager.h"
28#include "ns3/simple-frame-capture-model.h"
29#include "ns3/single-model-spectrum-channel.h"
30#include "ns3/spectrum-wifi-helper.h"
31#include "ns3/spectrum-wifi-phy.h"
32#include "ns3/test.h"
33#include "ns3/threshold-preamble-detection-model.h"
34#include "ns3/wifi-bandwidth-filter.h"
35#include "ns3/wifi-mac-header.h"
36#include "ns3/wifi-mpdu.h"
37#include "ns3/wifi-net-device.h"
38#include "ns3/wifi-phy-rx-trace-helper.h"
39#include "ns3/wifi-psdu.h"
40#include "ns3/wifi-spectrum-phy-interface.h"
41#include "ns3/wifi-spectrum-signal-parameters.h"
42#include "ns3/wifi-spectrum-value-helper.h"
43#include "ns3/wifi-utils.h"
44#include "ns3/yans-wifi-channel.h"
45#include "ns3/yans-wifi-phy.h"
46#include <ns3/propagation-loss-model.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 rxPowerDbm The transmit power in dBm.
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(double rxPowerDbm,
93 Mac48Address add1,
94 Mac48Address add2,
96
97 /**
98 * Sends a PPDU containing one MPDU addressed to a specific receiver.
99 * @param rxPowerDbm The transmit power in dBm.
100 * @param add1 The MAC address of the receiver.
101 * @param tx_phy The transmitting PHY object.
102 */
103 void SendPpduWithOneMpdu(double rxPowerDbm,
104 Mac48Address add1,
106
107 /**
108 * Checks the statistics of PPDU and MPDU reception success and failure.
109 * @param expectedPpduSuccess The expected number of successful PPDU receptions.
110 * @param expectedPpduFailure The expected number of failed PPDU receptions.
111 * @param expectedMpduSuccess The expected number of successful MPDU receptions within PPDUs.
112 * @param expectedMpduFailure The expected number of failed MPDU receptions within PPDUs.
113 * @param expectedOverlaps The expected number of overlapping reception events.
114 * @param expectedNonOverlaps The expected number of non-overlapping reception events.
115 */
116 void CheckAllStats(uint64_t expectedPpduSuccess,
117 uint64_t expectedPpduFailure,
118 uint64_t expectedMpduSuccess,
119 uint64_t expectedMpduFailure,
120 uint64_t expectedOverlaps,
121 uint64_t expectedNonOverlaps);
122
123 /**
124 * Checks the statistics of PPDU and MPDU reception success and failure.
125 * @param expectedStats The expected counts for PPDU and MPDU reception.
126 * @param nodeId The node ID for which to check the received stats.
127 * @param deviceId The device ID for which to check the received stats.
128 * @param linkId The link ID for which to check the received stats.
129 */
130 void CheckStats(WifiPhyTraceStatistics expectedStats,
131 uint32_t nodeId,
132 uint32_t deviceId,
133 uint32_t linkId);
134
135 /**
136 * Checks the statistics of PPDU and MPDU reception success and failure.
137 * @param expectedRecordCount The expected number of records.
138 */
139 void CheckRecords(uint64_t expectedRecordCount);
140
142 Mac48Address("00:00:00:00:00:01"); ///< The MAC address representing an incorrect receiver,
143 ///< used for testing.
145 Mac48Address("00:00:00:00:00:03"); ///< The MAC address representing the correct receiver,
146 ///< used for testing.
147
148 std::map<ns3::Mac48Address, uint32_t> MacToNodeId = {
149 {Mac48Address("00:00:00:00:00:04"), 0},
150 {Mac48Address("00:00:00:00:00:05"), 1},
151 {correctReceiver, 2},
152 {wrongReceiver, 3}}; ///< Maps MAC addresses to node IDs. This is done since there is no MAC
153 ///< layer configured and therefore the helper cannot obtain the MAC
154 ///< addresses automatically.
155
156 Ptr<Node> nodeRx; ///< The receiving node
157 Ptr<SpectrumWifiPhy> m_txA{nullptr}; ///< The transmit function for node A.
158 Ptr<SpectrumWifiPhy> m_txB{nullptr}; ///< The transmit function for node B.
159 Ptr<SpectrumWifiPhy> m_rx{nullptr}; ///< The receive function for testing.
160
162 m_rxTraceHelper; ///< The helper being tested for tracking PHY reception events.
163};
164
166 : TestCase{test_name}
167{
168}
169
170void
172{
173 double txPower = 20;
174
175 auto spectrumChannel = CreateObject<SingleModelSpectrumChannel>();
176
177 auto nodeA = CreateObject<Node>();
178 auto devA = CreateObject<WifiNetDevice>();
180 m_txA->SetDevice(devA);
181 m_txA->SetTxPowerStart(txPower);
182 m_txA->SetTxPowerEnd(txPower);
183
184 auto nodeB = CreateObject<Node>();
185 auto devB = CreateObject<WifiNetDevice>();
187 m_txB->SetDevice(devB);
188 m_txB->SetTxPowerStart(txPower);
189 m_txB->SetTxPowerEnd(txPower);
190
192 auto devRx = CreateObject<WifiNetDevice>();
194 m_rx->SetDevice(devRx);
195
197 m_txA->SetInterferenceHelper(interferenceTxA);
198 auto errorTxA = CreateObject<NistErrorRateModel>();
199 m_txA->SetErrorRateModel(errorTxA);
200
201 auto interferenceTxB = CreateObject<InterferenceHelper>();
202 m_txB->SetInterferenceHelper(interferenceTxB);
203 auto errorTxB = CreateObject<NistErrorRateModel>();
204 m_txB->SetErrorRateModel(errorTxB);
205
206 auto interferenceRx = CreateObject<InterferenceHelper>();
207 m_rx->SetInterferenceHelper(interferenceRx);
208 auto errorRx = CreateObject<NistErrorRateModel>();
209 m_rx->SetErrorRateModel(errorRx);
210
211 m_txA->AddChannel(spectrumChannel);
212 m_txB->AddChannel(spectrumChannel);
213 m_rx->AddChannel(spectrumChannel);
214
215 m_txA->ConfigureStandard(WIFI_STANDARD_80211ax);
216 m_txB->ConfigureStandard(WIFI_STANDARD_80211ax);
217 m_rx->ConfigureStandard(WIFI_STANDARD_80211ax);
218
219 m_txA->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
220 m_txB->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
221 m_rx->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
222
223 devA->SetPhy(m_txA);
224 nodeA->AddDevice(devA);
225 devB->SetPhy(m_txB);
226 nodeB->AddDevice(devB);
227 devRx->SetPhy(m_rx);
228 nodeRx->AddDevice(devRx);
229
231 nodes.Add(nodeA);
232 nodes.Add(nodeB);
234
236
237 auto preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel>();
238 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
239 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
240 m_rx->SetPreambleDetectionModel(preambleDetectionModel);
241}
242
243void
245{
246 m_txA->Dispose();
247 m_txB->Dispose();
248 m_rx->Dispose();
249}
250
251void
253 Mac48Address receiver1,
254 Mac48Address receiver2,
256{
257 double txPower = rxPowerDbm;
258 tx_phy->SetTxPowerStart(txPower);
259 tx_phy->SetTxPowerEnd(txPower);
260
262 0,
264 NanoSeconds(800),
265 1,
266 1,
267 0,
268 20,
269 true);
270
271 std::vector<Ptr<WifiMpdu>> mpduList;
272
273 WifiMacHeader hdr1;
275 hdr1.SetQosTid(0);
276 hdr1.SetAddr1(receiver1); // Changing the expected receiver
277 auto p1 = Create<Packet>(750);
278 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
279
280 WifiMacHeader hdr2;
282 hdr2.SetQosTid(0);
283 hdr2.SetAddr1(receiver2); // Changing the expected receiver
284 auto p2 = Create<Packet>(750);
285 mpduList.emplace_back(Create<WifiMpdu>(p2, hdr2));
286
287 auto psdu = Create<WifiPsdu>(mpduList);
288
289 tx_phy->Send(psdu, txVector);
290}
291
292void
294 Mac48Address receiver1,
296{
297 double txPower = rxPowerDbm;
298 tx_phy->SetTxPowerStart(txPower);
299 tx_phy->SetTxPowerEnd(txPower);
300
302 0,
304 NanoSeconds(800),
305 1,
306 1,
307 0,
308 20,
309 true);
310
311 std::vector<Ptr<WifiMpdu>> mpduList;
312
313 WifiMacHeader hdr1;
315 hdr1.SetQosTid(0);
316 hdr1.SetAddr1(receiver1); // Changing the expected receiver
317 auto p1 = Create<Packet>(750);
318 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
319
320 auto psdu = Create<WifiPsdu>(mpduList);
321 tx_phy->Send(psdu, txVector);
322}
323
324void
325TestWifiPhyRxTraceHelper::CheckAllStats(uint64_t expectedPpduSuccess,
326 uint64_t expectedPpduFailure,
327 uint64_t expectedMpduSuccess,
328 uint64_t expectedMpduFailure,
329 uint64_t expectedOverlaps,
330 uint64_t expectedNonOverlaps)
331{
333
335 expectedPpduSuccess,
336 "Didn't receive right number of successful PPDUs");
338 expectedPpduFailure,
339 "Didn't receive right number of unsuccessful PPDUs");
341 expectedMpduSuccess,
342 "Didn't receive right number of successful MPDUs");
344 expectedMpduFailure,
345 "Didn't receive right number of unsuccessful MPDUs");
347 expectedOverlaps,
348 "Didn't receive right number of overlapping PPDUs");
350 expectedNonOverlaps,
351 "Didn't receive right number of nonoverlapping PPDUs");
353}
354
355void
357 uint32_t nodeId,
358 uint32_t deviceId,
359 uint32_t linkId)
360{
361 WifiPhyTraceStatistics stats = m_rxTraceHelper.GetStatistics(nodeId, deviceId, linkId);
362
364 expectedStats.m_receivedPpdus,
365 "Didn't receive right number of successful PPDUs");
367 expectedStats.m_failedPpdus,
368 "Didn't receive right number of unsuccessful PPDUs");
370 expectedStats.m_receivedMpdus,
371 "Didn't receive right number of successful MPDUs");
373 expectedStats.m_failedMpdus,
374 "Didn't receive right number of unsuccessful MPDUs");
376 expectedStats.m_overlappingPpdus,
377 "Didn't receive right number of overlapping PPDUs");
379 expectedStats.m_nonOverlappingPpdus,
380 "Didn't receive right number of nonoverlapping PPDUs");
381}
382
383void
384TestWifiPhyRxTraceHelper::CheckRecords(uint64_t expectedRecordCount)
385{
386 auto records = m_rxTraceHelper.GetPpduRecords();
387 NS_TEST_ASSERT_MSG_EQ(records.size(),
388 expectedRecordCount,
389 "Didn't produce the right number of Records");
390}
391
392void
394{
397 int64_t streamNumber = 1;
398 double rxPowerDbm = -80;
399 streamNumber += m_txA->AssignStreams(streamNumber);
400 streamNumber += m_txB->AssignStreams(streamNumber);
401 streamNumber += m_rx->AssignStreams(streamNumber);
402 WifiPhyTraceStatistics expectedStats;
403
405
406 // CASE 1: PPDU Reception with Sufficient RSSI With SOME Frames Addressed to Receiver
407 expectedStats.m_receivedPpdus = 1;
408 expectedStats.m_failedPpdus = 0;
409 expectedStats.m_receivedMpdus = 1;
410 expectedStats.m_failedMpdus = 0;
411 expectedStats.m_overlappingPpdus = 0;
412 expectedStats.m_nonOverlappingPpdus = 1;
413
414 // A-MPDU 1
417 this,
418 rxPowerDbm,
419 correctReceiver, // One MPDU addressed to
420 wrongReceiver, // One MPDU addressed to
421 m_txA);
422
425 this,
426 2); // Total Records
427
430 this,
431 expectedStats,
432 nodeRx->GetId(),
433 0,
434 0);
435
438 this,
439 expectedStats.m_receivedPpdus,
440 expectedStats.m_failedPpdus,
441 expectedStats.m_receivedMpdus,
442 expectedStats.m_failedMpdus,
443 expectedStats.m_overlappingPpdus,
444 expectedStats.m_nonOverlappingPpdus);
445
446 // CASE 2: PPDU Reception with inSufficient RSSI With SOME Frames Addressed to Receiver
447 expectedStats.m_receivedPpdus = 0;
448 expectedStats.m_failedPpdus = 1;
449 expectedStats.m_receivedMpdus = 0;
450 expectedStats.m_failedMpdus = 1;
451 expectedStats.m_overlappingPpdus = 0;
452 expectedStats.m_nonOverlappingPpdus = 1;
453 rxPowerDbm = -83;
454 // A-MPDU 1
457 this,
458 rxPowerDbm,
459 correctReceiver, // One MPDU addressed to
460 wrongReceiver, // One MPDU addressed to
461 m_txA);
462
465 this,
466 2); // TotalRecords
467
470 this,
471 expectedStats,
472 nodeRx->GetId(),
473 0,
474 0);
475
478 this,
479 expectedStats.m_receivedPpdus,
480 expectedStats.m_failedPpdus,
481 expectedStats.m_receivedMpdus,
482 expectedStats.m_failedMpdus,
483 expectedStats.m_overlappingPpdus,
484 expectedStats.m_nonOverlappingPpdus);
485
486 // CASE 3: PPDU Reception with Sufficient RSSI/SNR With NO Frames Addressed to Receiver
487 expectedStats.m_receivedPpdus = 0;
488 expectedStats.m_failedPpdus = 0;
489 expectedStats.m_receivedMpdus = 0;
490 expectedStats.m_failedMpdus = 0;
491 expectedStats.m_overlappingPpdus = 0;
492 expectedStats.m_nonOverlappingPpdus = 0;
493 rxPowerDbm = -80;
494 // A-MPDU 1
497 this,
498 rxPowerDbm,
499 wrongReceiver, // One MPDU addressed to
500 wrongReceiver, // One MPDU addressed to
501 m_txA);
502
505 this,
506 2); // TotalRecords
507
510 this,
511 expectedStats,
512 nodeRx->GetId(),
513 0,
514 0);
515
518 this,
519 expectedStats.m_receivedPpdus,
520 expectedStats.m_failedPpdus,
521 expectedStats.m_receivedMpdus,
522 expectedStats.m_failedMpdus,
523 expectedStats.m_overlappingPpdus,
524 expectedStats.m_nonOverlappingPpdus);
525
526 // CASE 4: PPDU Reception with Insufficient RSSI/SNR With NO Frames Addressed to Receiver
527 expectedStats.m_receivedPpdus = 0;
528 expectedStats.m_failedPpdus = 0;
529 expectedStats.m_receivedMpdus = 0;
530 expectedStats.m_failedMpdus = 0;
531 expectedStats.m_overlappingPpdus = 0;
532 expectedStats.m_nonOverlappingPpdus = 0;
533 rxPowerDbm = -83;
534 // A-MPDU 1
537 this,
538 rxPowerDbm,
539 wrongReceiver, // One MPDU addressed to
540 wrongReceiver, // One MPDU addressed to
541 m_txA);
542
545 this,
546 2); // TotalRecords
547
550 this,
551 expectedStats,
552 nodeRx->GetId(),
553 0,
554 0);
555
558 this,
559 expectedStats.m_receivedPpdus,
560 expectedStats.m_failedPpdus,
561 expectedStats.m_receivedMpdus,
562 expectedStats.m_failedMpdus,
563 expectedStats.m_overlappingPpdus,
564 expectedStats.m_nonOverlappingPpdus);
565
566 // CASE 5: PPDU Overlapping Reception with sufficient RSSI/SNR With ALL Frames Addressed to
567 // Receiver
568 expectedStats.m_receivedPpdus = 0;
569 expectedStats.m_failedPpdus = 2;
570 expectedStats.m_receivedMpdus = 0;
571 expectedStats.m_failedMpdus = 2;
572 expectedStats.m_overlappingPpdus = 2;
573 expectedStats.m_nonOverlappingPpdus = 0;
574 rxPowerDbm = -80;
575 // A-MPDU 1
578 this,
579 rxPowerDbm,
580 correctReceiver, // One MPDU addressed to
581 m_txA);
582 // A-MPDU 2
585 this,
586 rxPowerDbm,
587 correctReceiver, // One MPDU addressed to
588 m_txB);
589
592 this,
593 4); // TotalRecords
594
597 this,
598 expectedStats,
599 nodeRx->GetId(),
600 0,
601 0);
602
605 this,
606 expectedStats.m_receivedPpdus,
607 expectedStats.m_failedPpdus,
608 expectedStats.m_receivedMpdus,
609 expectedStats.m_failedMpdus,
610 expectedStats.m_overlappingPpdus,
611 expectedStats.m_nonOverlappingPpdus);
612
613 // CASE 6: PPDU Overlapping Reception with sufficient RSSI/SNR With SOME Frames Addressed to
614 // Receiver
615 expectedStats.m_receivedPpdus = 0;
616 expectedStats.m_failedPpdus = 1;
617 expectedStats.m_receivedMpdus = 0;
618 expectedStats.m_failedMpdus = 1;
619 expectedStats.m_overlappingPpdus = 1;
620 expectedStats.m_nonOverlappingPpdus = 0;
621 rxPowerDbm = -80;
622 // A-MPDU 1
625 this,
626 rxPowerDbm,
627 correctReceiver, // One MPDU addressed to
628 m_txA);
629 // A-MPDU 2
632 this,
633 rxPowerDbm,
634 wrongReceiver, // One MPDU addressed to
635 m_txB);
636
639 this,
640 4); // TotalRecords
641
644 this,
645 expectedStats,
646 nodeRx->GetId(),
647 0,
648 0);
649
652 this,
653 expectedStats.m_receivedPpdus,
654 expectedStats.m_failedPpdus,
655 expectedStats.m_receivedMpdus,
656 expectedStats.m_failedMpdus,
657 expectedStats.m_overlappingPpdus,
658 expectedStats.m_nonOverlappingPpdus);
659
660 // Stop Statistics Collection Period Since following testcases evaluate the Start and Stop
661 // methods
663
664 // CASE 7: Execution of "Start()" Before Signal Injection
665 expectedStats.m_receivedPpdus = 1;
666 expectedStats.m_failedPpdus = 0;
667 expectedStats.m_receivedMpdus = 1;
668 expectedStats.m_failedMpdus = 0;
669 expectedStats.m_overlappingPpdus = 0;
670 expectedStats.m_nonOverlappingPpdus = 1;
671 rxPowerDbm = -80;
673
674 // A-MPDU 1
677 this,
678 rxPowerDbm,
679 correctReceiver, // One MPDU addressed to
680 m_txA);
681
684 this,
685 2); // TotalRecords
686
689 this,
690 expectedStats,
691 nodeRx->GetId(),
692 0,
693 0);
694
697 this,
698 expectedStats.m_receivedPpdus,
699 expectedStats.m_failedPpdus,
700 expectedStats.m_receivedMpdus,
701 expectedStats.m_failedMpdus,
702 expectedStats.m_overlappingPpdus,
703 expectedStats.m_nonOverlappingPpdus);
704
706
707 // CASE 8: Activation of "Start()" Followed by "Stop()" Before Signal Injection
708 expectedStats.m_receivedPpdus = 0;
709 expectedStats.m_failedPpdus = 0;
710 expectedStats.m_receivedMpdus = 0;
711 expectedStats.m_failedMpdus = 0;
712 expectedStats.m_overlappingPpdus = 0;
713 expectedStats.m_nonOverlappingPpdus = 0;
714 rxPowerDbm = -80;
715
717
719
720 // A-MPDU 1
723 this,
724 rxPowerDbm,
725 correctReceiver, // One MPDU addressed to
726 m_txA);
727
730 this,
731 0); // TotalRecords
732
735 this,
736 expectedStats,
737 nodeRx->GetId(),
738 0,
739 0);
740
743 this,
744 expectedStats.m_receivedPpdus,
745 expectedStats.m_failedPpdus,
746 expectedStats.m_receivedMpdus,
747 expectedStats.m_failedMpdus,
748 expectedStats.m_overlappingPpdus,
749 expectedStats.m_nonOverlappingPpdus);
750
751 // CASE 9: "Start()" Method Initiated During Ongoing PPDU Reception
752 expectedStats.m_receivedPpdus = 1;
753 expectedStats.m_failedPpdus = 0;
754 expectedStats.m_receivedMpdus = 1;
755 expectedStats.m_failedMpdus = 0;
756 expectedStats.m_overlappingPpdus = 0;
757 expectedStats.m_nonOverlappingPpdus = 1;
758 rxPowerDbm = -80;
759
760 // A-MPDU 1
763 this,
764 rxPowerDbm,
765 correctReceiver, // One MPDU addressed to
766 m_txA);
767
769
772 this,
773 2); // TotalRecords
774
777 this,
778 expectedStats,
779 nodeRx->GetId(),
780 0,
781 0);
782
785 this,
786 expectedStats.m_receivedPpdus,
787 expectedStats.m_failedPpdus,
788 expectedStats.m_receivedMpdus,
789 expectedStats.m_failedMpdus,
790 expectedStats.m_overlappingPpdus,
791 expectedStats.m_nonOverlappingPpdus);
792
794
795 // CASE 10: Execution of "Stop()" During Ongoing PPDU Reception
796 expectedStats.m_receivedPpdus = 0;
797 expectedStats.m_failedPpdus = 0;
798 expectedStats.m_receivedMpdus = 0;
799 expectedStats.m_failedMpdus = 0;
800 expectedStats.m_overlappingPpdus = 0;
801 expectedStats.m_nonOverlappingPpdus = 0;
802 rxPowerDbm = -80;
803
805
806 // A-MPDU 1
809 this,
810 rxPowerDbm,
811 correctReceiver, // One MPDU addressed to
812 m_txA);
813
815
818 this,
819 0); // TotalRecords
820
823 this,
824 expectedStats,
825 nodeRx->GetId(),
826 0,
827 0);
828
831 this,
832 expectedStats.m_receivedPpdus,
833 expectedStats.m_failedPpdus,
834 expectedStats.m_receivedMpdus,
835 expectedStats.m_failedMpdus,
836 expectedStats.m_overlappingPpdus,
837 expectedStats.m_nonOverlappingPpdus);
838
841}
842
843/**
844 * @ingroup wifi-test
845 * @brief Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY)
846 * frames (PPDU) containing multiple MAC Protocol Data Units (MPDUs) in Multi-Link Operation (MLO)
847 * contexts.
848 *
849 * This class extends the TestCase class to simulate and analyze the reception of PPDUs containing
850 * either one or two MPDUs in MLO setups. It specifically assesses the WifiPhyRxTraceHelper
851 * ability to manage MLO by handling multiple MPDUs addressed to specific receivers across different
852 * links, measuring success and failure rates. The simulation setup includes configuring transmit
853 * and receive power levels and provides functionality to check statistics related to PPDU and MPDU
854 * reception success and failure, as well overlaps and non-overlaps in reception
855 * events.
856 */
858{
859 public:
860 /**
861 * Constructs a TestWifiPhyRxTraceHelperMloStr instance for MLO reception testing.
862 */
864
865 private:
866 void DoSetup() override;
867 void DoRun() override;
868
869 void DoTeardown() override;
870
871 /**
872 * Sends a PPDU containing two MPDUs addressed to specific receivers, simulating an MLO
873 * scenario.
874 * @param rxPowerDbm The transmit power in dBm.
875 * @param add1 The MAC address of the first receiver.
876 * @param add2 The MAC address of the second receiver.
877 * @param tx_phy The transmitting PHY object for MLO.
878 */
879 void SendPpduWithTwoMpdus(double rxPowerDbm,
880 Mac48Address add1,
881 Mac48Address add2,
883
884 /**
885 * Sends a PPDU containing one MPDU addressed to a specific receiver, within an MLO setup.
886 * @param rxPowerDbm The transmit power in dBm.
887 * @param add1 The MAC address of the receiver.
888 * @param tx_phy The transmitting PHY object for MLO.
889 */
890 void SendPpduWithOneMpdu(double rxPowerDbm,
891 Mac48Address add1,
893
894 /**
895 * Checks the statistics of PPDU and MPDU reception success and failure.
896 * @param expectedStats The expected counts for PPDU and MPDU reception.
897 * @param nodeId The node ID for which to check the received stats.
898 */
899 void CheckStats(WifiPhyTraceStatistics expectedStats, uint32_t nodeId);
900
901 /**
902 * Checks the statistics of PPDU and MPDU reception success and failure.
903 * @param expectedStats The expected counts for PPDU and MPDU reception.
904 * @param nodeId The node ID for which to check the received stats.
905 * @param deviceId The device ID for which to check the received stats.
906 */
907 void CheckStats(WifiPhyTraceStatistics expectedStats, uint32_t nodeId, uint32_t deviceId);
908
909 /**
910 * Checks the statistics of PPDU and MPDU reception success and failure.
911 * @param expectedStats The expected counts for PPDU and MPDU reception.
912 * @param nodeId The node ID for which to check the received stats.
913 * @param deviceId The device ID for which to check the received stats.
914 * @param linkId The link ID for which to check the received stats.
915 */
916 void CheckStats(WifiPhyTraceStatistics expectedStats,
917 uint32_t nodeId,
918 uint32_t deviceId,
919 uint32_t linkId);
920
921 /**
922 * Checks the statistics of PPDU and MPDU reception success and failure in MLO scenarios.
923 * @param expectedPpduSuccess The expected number of successful PPDU receptions.
924 * @param expectedPpduFailure The expected number of failed PPDU receptions.
925 * @param expectedMpduSuccess The expected number of successful MPDU receptions within PPDUs.
926 * @param expectedMpduFailure The expected number of failed MPDU receptions within PPDUs.
927 * @param expectedOverlaps The expected number of overlapping reception events.
928 * @param expectedNonOverlaps The expected number of non-overlapping reception events.
929 */
930 void CheckAllStats(uint64_t expectedPpduSuccess,
931 uint64_t expectedPpduFailure,
932 uint64_t expectedMpduSuccess,
933 uint64_t expectedMpduFailure,
934 uint64_t expectedOverlaps,
935 uint64_t expectedNonOverlaps);
936
937 /**
938 * Checks the statistics of PPDU and MPDU reception success and failure.
939 * @param expectedRecordCount The expected number of records.
940 */
941 void CheckRecords(uint64_t expectedRecordCount);
942
944 Mac48Address("00:00:00:00:00:01"); ///< The MAC address representing an incorrect receiver,
945 ///< used for testing in MLO.
947 Mac48Address("00:00:00:00:00:03"); ///< The MAC address representing the correct receiver,
948 ///< used for testing in MLO.
949
950 std::map<ns3::Mac48Address, uint32_t> MacToNodeId = {
951 {Mac48Address("00:00:00:00:00:04"), 0},
952 {Mac48Address("00:00:00:00:00:05"), 1},
953 {correctReceiver, 2},
954 {wrongReceiver, 3}}; ///< Maps MAC addresses to node IDs for MLO test configuration. This is
955 ///< done since there is no MAC layer configured and therefore the
956 ///< helper cannot obtain the MAC addresses automatically.
957
958 NodeContainer wifiNodes; ///< All wifi nodes
959 Ptr<SpectrumWifiPhy> m_tx0A{nullptr}; ///< The transmit function for node 0, link A.
960 Ptr<SpectrumWifiPhy> m_tx0B{nullptr}; ///< The transmit function for node 0, link B.
961 Ptr<SpectrumWifiPhy> m_tx1A{nullptr}; ///< The transmit function for node 1, link A.
962 Ptr<SpectrumWifiPhy> m_tx1B{nullptr}; ///< The transmit function for node 1, link B.
963 Ptr<SpectrumWifiPhy> m_rxA{nullptr}; ///< The receive function for node 2, link A.
964 Ptr<SpectrumWifiPhy> m_rxB{nullptr}; ///< The receive function for node 2, link B.
965
966 WifiPhyRxTraceHelper m_rxTraceHelper; ///< The helper being tested for tracking
967 ///< PHY reception events in MLO scenarios.
968};
969
971 : TestCase("Test for correct MLO operation")
972{
973}
974
975void
977{
978 double txPower = 20;
979 auto ehtConfiguration = CreateObject<EhtConfiguration>();
980
981 auto nodeA = CreateObject<Node>();
982 auto devA = CreateObject<WifiNetDevice>();
983 devA->SetStandard(WIFI_STANDARD_80211be);
984 devA->SetEhtConfiguration(ehtConfiguration);
985
987 m_tx0A->SetDevice(devA);
988 m_tx0A->SetTxPowerStart(txPower);
989 m_tx0A->SetTxPowerEnd(txPower);
990
992 m_tx0B->SetDevice(devA);
993 m_tx0B->SetTxPowerStart(txPower);
994 m_tx0B->SetTxPowerEnd(txPower);
995
996 auto nodeB = CreateObject<Node>();
997 auto devB = CreateObject<WifiNetDevice>();
998 devB->SetStandard(WIFI_STANDARD_80211be);
999 devB->SetEhtConfiguration(ehtConfiguration);
1000
1002 m_tx1A->SetDevice(devB);
1003 m_tx1A->SetTxPowerStart(txPower);
1004 m_tx1A->SetTxPowerEnd(txPower);
1005
1007 m_tx1B->SetDevice(devB);
1008 m_tx1B->SetTxPowerStart(txPower);
1009 m_tx1B->SetTxPowerEnd(txPower);
1010
1011 auto nodeRx = CreateObject<Node>();
1012 auto devRx = CreateObject<WifiNetDevice>();
1013 devRx->SetStandard(WIFI_STANDARD_80211be);
1014 devRx->SetEhtConfiguration(ehtConfiguration);
1016 m_rxA->SetDevice(devRx);
1018 m_rxB->SetDevice(devRx);
1019
1020 auto interferenceTx0A = CreateObject<InterferenceHelper>();
1021 m_tx0A->SetInterferenceHelper(interferenceTx0A);
1022 auto errorTx0A = CreateObject<NistErrorRateModel>();
1023 m_tx0A->SetErrorRateModel(errorTx0A);
1024
1025 auto interferenceTx0B = CreateObject<InterferenceHelper>();
1026 m_tx0B->SetInterferenceHelper(interferenceTx0B);
1027 auto errorTx0B = CreateObject<NistErrorRateModel>();
1028 m_tx0B->SetErrorRateModel(errorTx0B);
1029
1030 auto interferenceTx1A = CreateObject<InterferenceHelper>();
1031 m_tx1A->SetInterferenceHelper(interferenceTx1A);
1032 auto errorTx1A = CreateObject<NistErrorRateModel>();
1033 m_tx1A->SetErrorRateModel(errorTx1A);
1034
1035 auto interferenceTx1B = CreateObject<InterferenceHelper>();
1036 m_tx1B->SetInterferenceHelper(interferenceTx1B);
1037 auto errorTx1B = CreateObject<NistErrorRateModel>();
1038 m_tx1B->SetErrorRateModel(errorTx1B);
1039
1040 auto interferenceRxA = CreateObject<InterferenceHelper>();
1041 m_rxA->SetInterferenceHelper(interferenceRxA);
1042 auto errorRxA = CreateObject<NistErrorRateModel>();
1043 m_rxA->SetErrorRateModel(errorRxA);
1044
1045 auto interferenceRxB = CreateObject<InterferenceHelper>();
1046 m_rxB->SetInterferenceHelper(interferenceRxB);
1047 auto errorRxB = CreateObject<NistErrorRateModel>();
1048 m_rxB->SetErrorRateModel(errorRxB);
1049
1050 auto spectrumChannelA = CreateObject<MultiModelSpectrumChannel>();
1051 auto spectrumChannelB = CreateObject<MultiModelSpectrumChannel>();
1052
1053 m_tx0A->SetOperatingChannel(WifiPhy::ChannelTuple{2, 0, WIFI_PHY_BAND_2_4GHZ, 0});
1054 m_tx0B->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
1055
1056 m_tx1A->SetOperatingChannel(WifiPhy::ChannelTuple{2, 0, WIFI_PHY_BAND_2_4GHZ, 0});
1057 m_tx1B->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
1058
1059 m_rxA->SetOperatingChannel(WifiPhy::ChannelTuple{2, 0, WIFI_PHY_BAND_2_4GHZ, 0});
1060 m_rxB->SetOperatingChannel(WifiPhy::ChannelTuple{36, 20, WIFI_PHY_BAND_5GHZ, 0});
1061
1062 m_tx0A->AddChannel(spectrumChannelA, WIFI_SPECTRUM_2_4_GHZ);
1063 m_tx0B->AddChannel(spectrumChannelB, WIFI_SPECTRUM_5_GHZ);
1064
1065 m_tx1A->AddChannel(spectrumChannelA, WIFI_SPECTRUM_2_4_GHZ);
1066 m_tx1B->AddChannel(spectrumChannelB, WIFI_SPECTRUM_5_GHZ);
1067
1068 m_rxA->AddChannel(spectrumChannelA, WIFI_SPECTRUM_2_4_GHZ);
1069 m_rxB->AddChannel(spectrumChannelB, WIFI_SPECTRUM_5_GHZ);
1070
1071 m_tx0A->ConfigureStandard(WIFI_STANDARD_80211be);
1072 m_tx0B->ConfigureStandard(WIFI_STANDARD_80211be);
1073
1074 m_tx1A->ConfigureStandard(WIFI_STANDARD_80211be);
1075 m_tx1B->ConfigureStandard(WIFI_STANDARD_80211be);
1076
1077 m_rxA->ConfigureStandard(WIFI_STANDARD_80211be);
1078 m_rxB->ConfigureStandard(WIFI_STANDARD_80211be);
1079
1080 std::vector<Ptr<WifiPhy>> phys0;
1081 phys0.emplace_back(m_tx0A);
1082 phys0.emplace_back(m_tx0B);
1083
1084 std::vector<Ptr<WifiPhy>> phys1;
1085 phys1.emplace_back(m_tx1A);
1086 phys1.emplace_back(m_tx1B);
1087
1088 std::vector<Ptr<WifiPhy>> physRx;
1089 physRx.emplace_back(m_rxA);
1090 physRx.emplace_back(m_rxB);
1091
1092 devA->SetPhys(phys0);
1093 nodeA->AddDevice(devA);
1094
1095 devB->SetPhys(phys1);
1096 nodeB->AddDevice(devB);
1097
1098 devRx->SetPhys(physRx);
1099 nodeRx->AddDevice(devRx);
1100
1101 wifiNodes.Add(nodeA);
1102 wifiNodes.Add(nodeB);
1103 wifiNodes.Add(nodeRx);
1104
1106
1107 auto preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel>();
1108 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
1109 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
1110 m_rxA->SetPreambleDetectionModel(preambleDetectionModel);
1111 m_rxB->SetPreambleDetectionModel(preambleDetectionModel);
1112}
1113
1114void
1116{
1117 m_tx0A->Dispose();
1118 m_tx0B->Dispose();
1119 m_tx1A->Dispose();
1120 m_tx1B->Dispose();
1121 m_rxA->Dispose();
1122 m_rxB->Dispose();
1123}
1124
1125void
1127 Mac48Address receiver1,
1128 Mac48Address receiver2,
1130{
1131 double txPower = rxPowerDbm;
1132 tx_phy->SetTxPowerStart(txPower);
1133 tx_phy->SetTxPowerEnd(txPower);
1134
1136 0,
1138 NanoSeconds(800),
1139 1,
1140 1,
1141 0,
1142 20,
1143 true);
1144
1145 std::vector<Ptr<WifiMpdu>> mpduList;
1146
1147 WifiMacHeader hdr1;
1149 hdr1.SetQosTid(0);
1150 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1151 auto p1 = Create<Packet>(750);
1152 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1153
1154 WifiMacHeader hdr2;
1156 hdr2.SetQosTid(0);
1157 hdr2.SetAddr1(receiver2); // Changing the expected receiver
1158 auto p2 = Create<Packet>(750);
1159 mpduList.emplace_back(Create<WifiMpdu>(p2, hdr2));
1160
1161 auto psdu = Create<WifiPsdu>(mpduList);
1162
1163 tx_phy->Send(psdu, txVector);
1164}
1165
1166void
1168 Mac48Address receiver1,
1170{
1171 double txPower = rxPowerDbm;
1172 tx_phy->SetTxPowerStart(txPower);
1173 tx_phy->SetTxPowerEnd(txPower);
1174
1175 WifiTxVector txVector =
1177 0,
1179 NanoSeconds(800),
1180 1,
1181 1,
1182 0,
1183 20,
1184 true); // for some reason needs to be set to true even though only one MPDU
1185
1186 std::vector<Ptr<WifiMpdu>> mpduList;
1187
1188 WifiMacHeader hdr1;
1190 hdr1.SetQosTid(0);
1191 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1192 auto p1 = Create<Packet>(750);
1193 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1194
1195 auto psdu = Create<WifiPsdu>(mpduList);
1196 tx_phy->Send(psdu, txVector);
1197}
1198
1199void
1201{
1203 for (uint32_t i = 0; i < wifiNodes.Get(nodeId)->GetNDevices(); i++)
1204 {
1205 for (uint32_t j = 0;
1206 j < DynamicCast<WifiNetDevice>(wifiNodes.Get(nodeId)->GetDevice(i))->GetNPhys();
1207 j++)
1208 {
1209 stats = stats + m_rxTraceHelper.GetStatistics(nodeId, i, j);
1210 }
1211 }
1212
1214 expectedStats.m_receivedPpdus,
1215 "Didn't receive right number of successful PPDUs");
1217 expectedStats.m_failedPpdus,
1218 "Didn't receive right number of unsuccessful PPDUs");
1220 expectedStats.m_receivedMpdus,
1221 "Didn't receive right number of successful MPDUs");
1223 expectedStats.m_failedMpdus,
1224 "Didn't receive right number of unsuccessful MPDUs");
1226 expectedStats.m_overlappingPpdus,
1227 "Didn't receive right number of overlapping PPDUs");
1229 expectedStats.m_nonOverlappingPpdus,
1230 "Didn't receive right number of nonoverlapping PPDUs");
1231}
1232
1233void
1235 uint32_t nodeId,
1236 uint32_t deviceId)
1237{
1239
1240 for (uint32_t i = 0;
1241 i < DynamicCast<WifiNetDevice>(wifiNodes.Get(nodeId)->GetDevice(deviceId))->GetNPhys();
1242 i++)
1243 {
1244 stats = stats + m_rxTraceHelper.GetStatistics(nodeId, deviceId, i);
1245 }
1246
1248 expectedStats.m_receivedPpdus,
1249 "Didn't receive right number of successful PPDUs");
1251 expectedStats.m_failedPpdus,
1252 "Didn't receive right number of unsuccessful PPDUs");
1254 expectedStats.m_receivedMpdus,
1255 "Didn't receive right number of successful MPDUs");
1257 expectedStats.m_failedMpdus,
1258 "Didn't receive right number of unsuccessful MPDUs");
1260 expectedStats.m_overlappingPpdus,
1261 "Didn't receive right number of overlapping PPDUs");
1263 expectedStats.m_nonOverlappingPpdus,
1264 "Didn't receive right number of nonoverlapping PPDUs");
1265}
1266
1267void
1269 uint32_t nodeId,
1270 uint32_t deviceId,
1271 uint32_t linkId)
1272{
1273 WifiPhyTraceStatistics stats = m_rxTraceHelper.GetStatistics(nodeId, deviceId, linkId);
1274
1276 expectedStats.m_receivedPpdus,
1277 "Didn't receive right number of successful PPDUs");
1279 expectedStats.m_failedPpdus,
1280 "Didn't receive right number of unsuccessful PPDUs");
1282 expectedStats.m_receivedMpdus,
1283 "Didn't receive right number of successful MPDUs");
1285 expectedStats.m_failedMpdus,
1286 "Didn't receive right number of unsuccessful MPDUs");
1288 expectedStats.m_overlappingPpdus,
1289 "Didn't receive right number of overlapping PPDUs");
1291 expectedStats.m_nonOverlappingPpdus,
1292 "Didn't receive right number of nonoverlapping PPDUs");
1293}
1294
1295void
1297 uint64_t expectedPpduFailure,
1298 uint64_t expectedMpduSuccess,
1299 uint64_t expectedMpduFailure,
1300 uint64_t expectedOverlaps,
1301 uint64_t expectedNonOverlaps)
1302{
1304
1306 expectedPpduSuccess,
1307 "Didn't receive right number of successful PPDUs");
1309 expectedPpduFailure,
1310 "Didn't receive right number of unsuccessful PPDUs");
1312 expectedMpduSuccess,
1313 "Didn't receive right number of successful MPDUs");
1315 expectedMpduFailure,
1316 "Didn't receive right number of unsuccessful MPDUs");
1318 expectedOverlaps,
1319 "Didn't receive right number of overlapping PPDUs");
1321 expectedNonOverlaps,
1322 "Didn't receive right number of nonoverlapping PPDUs");
1323
1325}
1326
1327void
1329{
1330 auto records = m_rxTraceHelper.GetPpduRecords();
1331 NS_TEST_ASSERT_MSG_EQ(records.size(),
1332 expectedRecordCount,
1333 "Didn't produce the right number of Records");
1334}
1335
1336void
1338{
1341 int64_t streamNumber = 1;
1342 double rxPowerDbm = -80;
1343 streamNumber += m_tx0A->AssignStreams(streamNumber);
1344 streamNumber += m_tx0B->AssignStreams(streamNumber);
1345 streamNumber += m_tx1A->AssignStreams(streamNumber);
1346 streamNumber += m_tx1B->AssignStreams(streamNumber);
1347 streamNumber += m_rxA->AssignStreams(streamNumber);
1348 streamNumber += m_rxB->AssignStreams(streamNumber);
1349 WifiPhyTraceStatistics expectedStats;
1350
1352
1353 // CASE 1: PPDU Reception with Sufficient RSSI With SOME Frames Addressed to Receiver
1354 expectedStats.m_receivedPpdus = 2;
1355 expectedStats.m_failedPpdus = 0;
1356 expectedStats.m_receivedMpdus = 2;
1357 expectedStats.m_failedMpdus = 0;
1358 expectedStats.m_overlappingPpdus = 0;
1359 expectedStats.m_nonOverlappingPpdus = 2;
1360
1361 // A-MPDU 1
1364 this,
1365 rxPowerDbm,
1366 correctReceiver, // One MPDU addressed to
1367 wrongReceiver, // One MPDU addressed to
1368 m_tx0A);
1369
1372 this,
1373 rxPowerDbm,
1374 correctReceiver, // One MPDU addressed to
1375 wrongReceiver, // One MPDU addressed to
1376 m_tx0B);
1377
1380 this,
1381 4); // Total Records
1382
1384 Seconds(0.2),
1387 this,
1388 expectedStats,
1389 wifiNodes.Get(2)->GetId());
1390
1393 this,
1394 expectedStats.m_receivedPpdus,
1395 expectedStats.m_failedPpdus,
1396 expectedStats.m_receivedMpdus,
1397 expectedStats.m_failedMpdus,
1398 expectedStats.m_overlappingPpdus,
1399 expectedStats.m_nonOverlappingPpdus);
1400
1401 // CASE 2: PPDU Reception with Insufficient RSSI With SOME Frames Addressed to Receiver
1402 expectedStats.m_receivedPpdus = 0;
1403 expectedStats.m_failedPpdus = 2;
1404 expectedStats.m_receivedMpdus = 0;
1405 expectedStats.m_failedMpdus = 2;
1406 expectedStats.m_overlappingPpdus = 0;
1407 expectedStats.m_nonOverlappingPpdus = 2;
1408 rxPowerDbm = -83;
1409 // A-MPDU 1
1412 this,
1413 rxPowerDbm,
1414 correctReceiver, // One MPDU addressed to
1415 wrongReceiver, // One MPDU addressed to
1416 m_tx0A);
1417
1420 this,
1421 rxPowerDbm,
1422 correctReceiver, // One MPDU addressed to
1423 wrongReceiver, // One MPDU addressed to
1424 m_tx0B);
1425
1428 this,
1429 4); // TotalRecords
1430
1432 Seconds(0.4),
1435 this,
1436 expectedStats,
1437 wifiNodes.Get(2)->GetId());
1438
1441 this,
1442 expectedStats.m_receivedPpdus,
1443 expectedStats.m_failedPpdus,
1444 expectedStats.m_receivedMpdus,
1445 expectedStats.m_failedMpdus,
1446 expectedStats.m_overlappingPpdus,
1447 expectedStats.m_nonOverlappingPpdus);
1448
1449 // CASE 3: PPDU Reception with Sufficient RSSI/SNR With NO Frames Addressed to Receiver
1450 expectedStats.m_receivedPpdus = 0;
1451 expectedStats.m_failedPpdus = 0;
1452 expectedStats.m_receivedMpdus = 0;
1453 expectedStats.m_failedMpdus = 0;
1454 expectedStats.m_overlappingPpdus = 0;
1455 expectedStats.m_nonOverlappingPpdus = 0;
1456 rxPowerDbm = -80;
1457 // A-MPDU 1
1460 this,
1461 rxPowerDbm,
1462 wrongReceiver, // One MPDU addressed to
1463 wrongReceiver, // One MPDU addressed to
1464 m_tx0A);
1465
1466 // A-MPDU 1
1469 this,
1470 rxPowerDbm,
1471 wrongReceiver, // One MPDU addressed to
1472 wrongReceiver, // One MPDU addressed to
1473 m_tx0B);
1474
1477 this,
1478 4); // TotalRecords
1479
1481 Seconds(0.6),
1484 this,
1485 expectedStats,
1486 wifiNodes.Get(2)->GetId());
1487
1490 this,
1491 expectedStats.m_receivedPpdus,
1492 expectedStats.m_failedPpdus,
1493 expectedStats.m_receivedMpdus,
1494 expectedStats.m_failedMpdus,
1495 expectedStats.m_overlappingPpdus,
1496 expectedStats.m_nonOverlappingPpdus);
1497
1498 // CASE 4: PPDU Reception with Insufficient RSSI/SNR With NO Frames Addressed to Receiver
1499 expectedStats.m_receivedPpdus = 0;
1500 expectedStats.m_failedPpdus = 0;
1501 expectedStats.m_receivedMpdus = 0;
1502 expectedStats.m_failedMpdus = 0;
1503 expectedStats.m_overlappingPpdus = 0;
1504 expectedStats.m_nonOverlappingPpdus = 0;
1505 rxPowerDbm = -83;
1506 // A-MPDU 1
1509 this,
1510 rxPowerDbm,
1511 wrongReceiver, // One MPDU addressed to
1512 wrongReceiver, // One MPDU addressed to
1513 m_tx0A);
1514
1515 // A-MPDU 1
1518 this,
1519 rxPowerDbm,
1520 wrongReceiver, // One MPDU addressed to
1521 wrongReceiver, // One MPDU addressed to
1522 m_tx0B);
1523
1526 this,
1527 4); // TotalRecords
1528
1530 Seconds(0.8),
1533 this,
1534 expectedStats,
1535 wifiNodes.Get(2)->GetId());
1536
1539 this,
1540 expectedStats.m_receivedPpdus,
1541 expectedStats.m_failedPpdus,
1542 expectedStats.m_receivedMpdus,
1543 expectedStats.m_failedMpdus,
1544 expectedStats.m_overlappingPpdus,
1545 expectedStats.m_nonOverlappingPpdus);
1546
1547 // CASE 5: PPDU Overlapping Reception with sufficient RSSI/SNR With ALL Frames Addressed to
1548 // Receiver
1549 expectedStats.m_receivedPpdus = 0;
1550 expectedStats.m_failedPpdus = 4;
1551 expectedStats.m_receivedMpdus = 0;
1552 expectedStats.m_failedMpdus = 4;
1553 expectedStats.m_overlappingPpdus = 4;
1554 expectedStats.m_nonOverlappingPpdus = 0;
1555 rxPowerDbm = -80;
1556 // A-MPDU 1
1559 this,
1560 rxPowerDbm,
1561 correctReceiver, // One MPDU addressed to
1562 m_tx0A);
1563 // A-MPDU 2
1566 this,
1567 rxPowerDbm,
1568 correctReceiver, // One MPDU addressed to
1569 m_tx1A);
1570
1571 // A-MPDU 1
1574 this,
1575 rxPowerDbm,
1576 correctReceiver, // One MPDU addressed to
1577 m_tx0B);
1578 // A-MPDU 2
1581 this,
1582 rxPowerDbm,
1583 correctReceiver, // One MPDU addressed to
1584 m_tx1B);
1585
1588 this,
1589 8); // TotalRecords
1590
1592 Seconds(1),
1595 this,
1596 expectedStats,
1597 wifiNodes.Get(2)->GetId());
1598
1601 this,
1602 expectedStats.m_receivedPpdus,
1603 expectedStats.m_failedPpdus,
1604 expectedStats.m_receivedMpdus,
1605 expectedStats.m_failedMpdus,
1606 expectedStats.m_overlappingPpdus,
1607 expectedStats.m_nonOverlappingPpdus);
1608
1609 // CASE 6: PPDU Overlapping Reception with sufficient RSSI/SNR With SOME Frames Addressed to
1610 // Receiver
1611 expectedStats.m_receivedPpdus = 0;
1612 expectedStats.m_failedPpdus = 2;
1613 expectedStats.m_receivedMpdus = 0;
1614 expectedStats.m_failedMpdus = 2;
1615 expectedStats.m_overlappingPpdus = 2;
1616 expectedStats.m_nonOverlappingPpdus = 0;
1617 rxPowerDbm = -80;
1618 // A-MPDU 1
1621 this,
1622 rxPowerDbm,
1623 correctReceiver, // One MPDU addressed to
1624 m_tx0A);
1625 // A-MPDU 2
1628 this,
1629 rxPowerDbm,
1630 wrongReceiver, // One MPDU addressed to
1631 m_tx1A);
1632
1633 // A-MPDU 1
1636 this,
1637 rxPowerDbm,
1638 correctReceiver, // One MPDU addressed to
1639 m_tx0B);
1640 // A-MPDU 2
1643 this,
1644 rxPowerDbm,
1645 wrongReceiver, // One MPDU addressed to
1646 m_tx1B);
1647
1650 this,
1651 8); // TotalRecords
1652
1654 Seconds(1.2),
1657 this,
1658 expectedStats,
1659 wifiNodes.Get(2)->GetId());
1660
1663 this,
1664 expectedStats.m_receivedPpdus,
1665 expectedStats.m_failedPpdus,
1666 expectedStats.m_receivedMpdus,
1667 expectedStats.m_failedMpdus,
1668 expectedStats.m_overlappingPpdus,
1669 expectedStats.m_nonOverlappingPpdus);
1670
1672
1675}
1676
1677/**
1678 * @ingroup wifi-test
1679 * @brief Implements a test case to evaluate the reception process of WiFi Physical Layer (PHY)
1680 * frames (PPDU) with multiple MAC Protocol Data Units (MPDUs) when using YansWifiPhy.
1681 *
1682 * This class extends the TestCase class to simulate and analyze the reception of PPDUs containing
1683 * either one or two MPDUs. It specifically tests the PHY layer's capability to handle multiple
1684 * MPDUs addressed to specific receivers, measuring success and failure rates. The simulation setup
1685 * includes configuring transmit and receive power levels, and the class provides functionality to
1686 * check statistics related to PPDU and MPDU reception success and failure, as well as overlap
1687 * handling.
1688 */
1690{
1691 public:
1692 /**
1693 * Constructs a TestWifiPhyRxTraceHelperYans instance for testing the trace helper with
1694 * Yans.
1695 */
1697
1698 private:
1699 void DoSetup() override;
1700 void DoRun() override;
1701
1702 void DoTeardown() override;
1703
1704 /**
1705 * Sends a PPDU containing two MPDUs addressed to specific receivers.
1706 * @param rxPowerDbm The transmit power in dBm.
1707 * @param add1 The MAC address of the first receiver.
1708 * @param add2 The MAC address of the second receiver.
1709 * @param tx_phy The transmitting PHY object.
1710 */
1711 void SendPpduWithTwoMpdus(double rxPowerDbm,
1712 Mac48Address add1,
1713 Mac48Address add2,
1714 Ptr<ns3::YansWifiPhy> tx_phy);
1715
1716 /**
1717 * Sends a PPDU containing one MPDU addressed to a specific receiver.
1718 * @param rxPowerDbm The transmit power in dBm.
1719 * @param add1 The MAC address of the receiver.
1720 * @param tx_phy The transmitting PHY object.
1721 */
1722 void SendPpduWithOneMpdu(double rxPowerDbm, Mac48Address add1, Ptr<ns3::YansWifiPhy> tx_phy);
1723
1724 /**
1725 * Checks the statistics of PPDU and MPDU reception success and failure.
1726 * @param expectedPpduSuccess The expected number of successful PPDU receptions.
1727 * @param expectedPpduFailure The expected number of failed PPDU receptions.
1728 * @param expectedMpduSuccess The expected number of successful MPDU receptions within PPDUs.
1729 * @param expectedMpduFailure The expected number of failed MPDU receptions within PPDUs.
1730 * @param expectedOverlaps The expected number of overlapping reception events.
1731 * @param expectedNonOverlaps The expected number of non-overlapping reception events.
1732 */
1733 void CheckAllStats(uint64_t expectedPpduSuccess,
1734 uint64_t expectedPpduFailure,
1735 uint64_t expectedMpduSuccess,
1736 uint64_t expectedMpduFailure,
1737 uint64_t expectedOverlaps,
1738 uint64_t expectedNonOverlaps);
1739
1740 /**
1741 * Checks the statistics of PPDU and MPDU reception success and failure.
1742 * @param expectedStats The expected counts for PPDU and MPDU reception.
1743 * @param nodeId The node ID for which to check the received stats.
1744 * @param deviceId The device ID for which to check the received stats.
1745 * @param linkId The link ID for which to check the received stats.
1746 */
1747 void CheckStats(WifiPhyTraceStatistics expectedStats,
1748 uint32_t nodeId,
1749 uint32_t deviceId,
1750 uint32_t linkId);
1751
1752 /**
1753 * Checks the statistics of PPDU and MPDU reception success and failure.
1754 * @param expectedRecordCount The expected number of records.
1755 */
1756 void CheckRecords(uint64_t expectedRecordCount);
1757
1759 Mac48Address("00:00:00:00:00:01"); ///< The MAC address representing an incorrect receiver,
1760 ///< used for testing.
1762 Mac48Address("00:00:00:00:00:03"); ///< The MAC address representing the correct receiver,
1763 ///< used for testing.
1764
1765 std::map<ns3::Mac48Address, uint32_t> MacToNodeId = {
1766 {Mac48Address("00:00:00:00:00:04"), 0},
1767 {Mac48Address("00:00:00:00:00:05"), 1},
1768 {correctReceiver, 2},
1769 {wrongReceiver, 3}}; ///< Maps MAC addresses to node IDs. This is done since there is no MAC
1770 ///< layer configured and therefore the helper cannot obtain the MAC
1771 ///< addresses automatically.
1772
1773 Ptr<Node> nodeRx; ///< The receiving node
1774 Ptr<YansWifiPhy> m_txA{nullptr}; ///< The transmit function for node A.
1775 Ptr<YansWifiPhy> m_txB{nullptr}; ///< The transmit function for node B.
1776 Ptr<YansWifiPhy> m_rx{nullptr}; ///< The receive function for testing.
1777
1778 Ptr<FixedRssLossModel> propLoss; ///< The propagation loss model used to configure RSSI
1779
1781 m_rxTraceHelper; ///< The helper being tested for tracking PHY reception events.
1782
1783 uint64_t m_uid{0}; //!< The unique identifier used for the PPDU in the test.
1784};
1785
1787 : TestCase("Test for correct operation when using Yans")
1788{
1789}
1790
1791void
1793{
1794 double txPower = 20;
1795
1796 auto yansChannel = CreateObject<YansWifiChannel>();
1799 yansChannel->SetPropagationDelayModel(propDelay);
1800 yansChannel->SetPropagationLossModel(propLoss);
1801
1802 auto nodeA = CreateObject<Node>();
1803 auto devA = CreateObject<WifiNetDevice>();
1805 m_txA->SetDevice(devA);
1806 m_txA->SetTxPowerStart(txPower);
1807 m_txA->SetTxPowerEnd(txPower);
1808
1809 auto nodeB = CreateObject<Node>();
1810 auto devB = CreateObject<WifiNetDevice>();
1812 m_txB->SetDevice(devB);
1813 m_txB->SetTxPowerStart(txPower);
1814 m_txB->SetTxPowerEnd(txPower);
1815
1817 auto devRx = CreateObject<WifiNetDevice>();
1819 m_rx->SetDevice(devRx);
1820
1821 auto interferenceTxA = CreateObject<InterferenceHelper>();
1822 m_txA->SetInterferenceHelper(interferenceTxA);
1823 auto errorTxA = CreateObject<NistErrorRateModel>();
1824 m_txA->SetErrorRateModel(errorTxA);
1825
1826 auto interferenceTxB = CreateObject<InterferenceHelper>();
1827 m_txB->SetInterferenceHelper(interferenceTxB);
1828 auto errorTxB = CreateObject<NistErrorRateModel>();
1829 m_txB->SetErrorRateModel(errorTxB);
1830
1831 auto interferenceRx = CreateObject<InterferenceHelper>();
1832 m_rx->SetInterferenceHelper(interferenceRx);
1833 auto errorRx = CreateObject<NistErrorRateModel>();
1834 m_rx->SetErrorRateModel(errorRx);
1835
1836 m_txA->SetChannel(yansChannel);
1837 m_txB->SetChannel(yansChannel);
1838 m_rx->SetChannel(yansChannel);
1839
1843
1847
1848 devA->SetPhy(m_txA);
1849 nodeA->AddDevice(devA);
1850 devB->SetPhy(m_txB);
1851 nodeB->AddDevice(devB);
1852 devRx->SetPhy(m_rx);
1853 nodeRx->AddDevice(devRx);
1854
1856 mobilityA->SetPosition(Vector(0.0, 0.0, 0.0));
1857 nodeA->AggregateObject(mobilityA);
1858
1860 mobilityB->SetPosition(Vector(0.0, 0.0, 0.0));
1861 nodeB->AggregateObject(mobilityB);
1862
1864 mobilityRx->SetPosition(Vector(0.0, 0.0, 0.0));
1865 nodeRx->AggregateObject(mobilityRx);
1866
1868 nodes.Add(nodeA);
1869 nodes.Add(nodeB);
1870 nodes.Add(nodeRx);
1871
1873
1874 auto preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel>();
1875 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
1876 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
1877 m_rx->SetPreambleDetectionModel(preambleDetectionModel);
1878}
1879
1880void
1887
1888void
1890 Mac48Address receiver1,
1891 Mac48Address receiver2,
1892 Ptr<ns3::YansWifiPhy> tx_phy)
1893{
1894 propLoss->SetRss(rxPowerDbm);
1895
1897 0,
1899 NanoSeconds(800),
1900 1,
1901 1,
1902 0,
1903 20,
1904 true);
1905
1906 std::vector<Ptr<WifiMpdu>> mpduList;
1907
1908 WifiMacHeader hdr1;
1910 hdr1.SetQosTid(0);
1911 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1912 auto p1 = Create<Packet>(750);
1913 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1914
1915 WifiMacHeader hdr2;
1917 hdr2.SetQosTid(0);
1918 hdr2.SetAddr1(receiver2); // Changing the expected receiver
1919 auto p2 = Create<Packet>(750);
1920 mpduList.emplace_back(Create<WifiMpdu>(p2, hdr2));
1921
1922 auto psdu = Create<WifiPsdu>(mpduList);
1923 auto ppdu =
1924 Create<HePpdu>(psdu,
1925 txVector,
1926 tx_phy->GetOperatingChannel(),
1927 tx_phy->CalculateTxDuration(psdu->GetSize(), txVector, tx_phy->GetPhyBand()),
1928 m_uid);
1929
1930 m_uid++;
1931
1932 tx_phy->StartTx(ppdu);
1933}
1934
1935void
1937 Mac48Address receiver1,
1938 Ptr<ns3::YansWifiPhy> tx_phy)
1939{
1940 propLoss->SetRss(rxPowerDbm);
1941
1942 auto txVector = WifiTxVector(HePhy::GetHeMcs0(),
1943 0,
1945 NanoSeconds(800),
1946 1,
1947 1,
1948 0,
1949 20,
1950 true);
1951
1952 std::vector<Ptr<WifiMpdu>> mpduList;
1953
1954 WifiMacHeader hdr1;
1956 hdr1.SetQosTid(0);
1957 hdr1.SetAddr1(receiver1); // Changing the expected receiver
1958 auto p1 = Create<Packet>(750);
1959 mpduList.emplace_back(Create<WifiMpdu>(p1, hdr1));
1960
1961 auto psdu = Create<WifiPsdu>(mpduList);
1962 auto ppdu =
1963 Create<HePpdu>(psdu,
1964 txVector,
1965 tx_phy->GetOperatingChannel(),
1966 tx_phy->CalculateTxDuration(psdu->GetSize(), txVector, tx_phy->GetPhyBand()),
1967 m_uid);
1968
1969 m_uid++;
1970
1971 tx_phy->StartTx(ppdu);
1972}
1973
1974void
1976 uint64_t expectedPpduFailure,
1977 uint64_t expectedMpduSuccess,
1978 uint64_t expectedMpduFailure,
1979 uint64_t expectedOverlaps,
1980 uint64_t expectedNonOverlaps)
1981{
1982 auto stats = m_rxTraceHelper.GetStatistics();
1983
1984 NS_TEST_ASSERT_MSG_EQ(stats.m_receivedPpdus,
1985 expectedPpduSuccess,
1986 "Didn't receive right number of successful PPDUs");
1987 NS_TEST_ASSERT_MSG_EQ(stats.m_failedPpdus,
1988 expectedPpduFailure,
1989 "Didn't receive right number of unsuccessful PPDUs");
1990 NS_TEST_ASSERT_MSG_EQ(stats.m_receivedMpdus,
1991 expectedMpduSuccess,
1992 "Didn't receive right number of successful MPDUs");
1993 NS_TEST_ASSERT_MSG_EQ(stats.m_failedMpdus,
1994 expectedMpduFailure,
1995 "Didn't receive right number of unsuccessful MPDUs");
1996 NS_TEST_ASSERT_MSG_EQ(stats.m_overlappingPpdus,
1997 expectedOverlaps,
1998 "Didn't receive right number of overlapping PPDUs");
1999 NS_TEST_ASSERT_MSG_EQ(stats.m_nonOverlappingPpdus,
2000 expectedNonOverlaps,
2001 "Didn't receive right number of nonoverlapping PPDUs");
2002
2004}
2005
2006void
2008 uint32_t nodeId,
2009 uint32_t deviceId,
2010 uint32_t linkId)
2011{
2012 WifiPhyTraceStatistics stats = m_rxTraceHelper.GetStatistics(nodeId, deviceId, linkId);
2013
2015 expectedStats.m_receivedPpdus,
2016 "Didn't receive right number of successful PPDUs");
2018 expectedStats.m_failedPpdus,
2019 "Didn't receive right number of unsuccessful PPDUs");
2021 expectedStats.m_receivedMpdus,
2022 "Didn't receive right number of successful MPDUs");
2024 expectedStats.m_failedMpdus,
2025 "Didn't receive right number of unsuccessful MPDUs");
2027 expectedStats.m_overlappingPpdus,
2028 "Didn't receive right number of overlapping PPDUs");
2030 expectedStats.m_nonOverlappingPpdus,
2031 "Didn't receive right number of nonoverlapping PPDUs");
2032}
2033
2034void
2036{
2037 auto records = m_rxTraceHelper.GetPpduRecords();
2038 NS_TEST_ASSERT_MSG_EQ(records.size(),
2039 expectedRecordCount,
2040 "Didn't produce the right number of Records");
2041}
2042
2043void
2045{
2048 int64_t streamNumber = 1;
2049 double rxPowerDbm = -80;
2050 streamNumber += m_txA->AssignStreams(streamNumber);
2051 streamNumber += m_txB->AssignStreams(streamNumber);
2052 streamNumber += m_rx->AssignStreams(streamNumber);
2053 WifiPhyTraceStatistics expectedStats;
2054
2056
2057 // CASE 1: PPDU Reception with Sufficient RSSI With SOME Frames Addressed to Receiver
2058 expectedStats.m_receivedPpdus = 1;
2059 expectedStats.m_failedPpdus = 0;
2060 expectedStats.m_receivedMpdus = 1;
2061 expectedStats.m_failedMpdus = 0;
2062 expectedStats.m_overlappingPpdus = 0;
2063 expectedStats.m_nonOverlappingPpdus = 1;
2064
2065 // A-MPDU 1
2068 this,
2069 rxPowerDbm,
2070 correctReceiver, // One MPDU addressed to
2071 wrongReceiver, // One MPDU addressed to
2072 m_txA);
2073
2076 this,
2077 2); // Total Records
2078
2081 this,
2082 expectedStats,
2083 nodeRx->GetId(),
2084 0,
2085 0);
2086
2089 this,
2090 expectedStats.m_receivedPpdus,
2091 expectedStats.m_failedPpdus,
2092 expectedStats.m_receivedMpdus,
2093 expectedStats.m_failedMpdus,
2094 expectedStats.m_overlappingPpdus,
2095 expectedStats.m_nonOverlappingPpdus);
2096 // CASE 2: PPDU Reception with inSufficient RSSI With SOME Frames Addressed to Receiver
2097 expectedStats.m_receivedPpdus = 0;
2098 expectedStats.m_failedPpdus = 1;
2099 expectedStats.m_receivedMpdus = 0;
2100 expectedStats.m_failedMpdus = 1;
2101 expectedStats.m_overlappingPpdus = 0;
2102 expectedStats.m_nonOverlappingPpdus = 1;
2103 rxPowerDbm = -83;
2104 // A-MPDU 1
2107 this,
2108 rxPowerDbm,
2109 correctReceiver, // One MPDU addressed to
2110 wrongReceiver, // One MPDU addressed to
2111 m_txA);
2112
2115 this,
2116 2); // TotalRecords
2117
2120 this,
2121 expectedStats,
2122 nodeRx->GetId(),
2123 0,
2124 0);
2125
2128 this,
2129 expectedStats.m_receivedPpdus,
2130 expectedStats.m_failedPpdus,
2131 expectedStats.m_receivedMpdus,
2132 expectedStats.m_failedMpdus,
2133 expectedStats.m_overlappingPpdus,
2134 expectedStats.m_nonOverlappingPpdus);
2135
2136 // CASE 3: PPDU Reception with Sufficient RSSI/SNR With NO Frames Addressed to Receiver
2137 expectedStats.m_receivedPpdus = 0;
2138 expectedStats.m_failedPpdus = 0;
2139 expectedStats.m_receivedMpdus = 0;
2140 expectedStats.m_failedMpdus = 0;
2141 expectedStats.m_overlappingPpdus = 0;
2142 expectedStats.m_nonOverlappingPpdus = 0;
2143 rxPowerDbm = -80;
2144 // A-MPDU 1
2147 this,
2148 rxPowerDbm,
2149 wrongReceiver, // One MPDU addressed to
2150 wrongReceiver, // One MPDU addressed to
2151 m_txA);
2152
2155 this,
2156 2); // TotalRecords
2157
2160 this,
2161 expectedStats,
2162 nodeRx->GetId(),
2163 0,
2164 0);
2165
2168 this,
2169 expectedStats.m_receivedPpdus,
2170 expectedStats.m_failedPpdus,
2171 expectedStats.m_receivedMpdus,
2172 expectedStats.m_failedMpdus,
2173 expectedStats.m_overlappingPpdus,
2174 expectedStats.m_nonOverlappingPpdus);
2175
2176 // CASE 4: PPDU Reception with Insufficient RSSI/SNR With NO Frames Addressed to Receiver
2177 expectedStats.m_receivedPpdus = 0;
2178 expectedStats.m_failedPpdus = 0;
2179 expectedStats.m_receivedMpdus = 0;
2180 expectedStats.m_failedMpdus = 0;
2181 expectedStats.m_overlappingPpdus = 0;
2182 expectedStats.m_nonOverlappingPpdus = 0;
2183 rxPowerDbm = -83;
2184 // A-MPDU 1
2187 this,
2188 rxPowerDbm,
2189 wrongReceiver, // One MPDU addressed to
2190 wrongReceiver, // One MPDU addressed to
2191 m_txA);
2192
2195 this,
2196 2); // TotalRecords
2197
2200 this,
2201 expectedStats,
2202 nodeRx->GetId(),
2203 0,
2204 0);
2205
2208 this,
2209 expectedStats.m_receivedPpdus,
2210 expectedStats.m_failedPpdus,
2211 expectedStats.m_receivedMpdus,
2212 expectedStats.m_failedMpdus,
2213 expectedStats.m_overlappingPpdus,
2214 expectedStats.m_nonOverlappingPpdus);
2215
2216 // CASE 5: PPDU Overlapping Reception with sufficient RSSI/SNR With ALL Frames Addressed to
2217 // Receiver
2218 expectedStats.m_receivedPpdus = 0;
2219 expectedStats.m_failedPpdus = 2;
2220 expectedStats.m_receivedMpdus = 0;
2221 expectedStats.m_failedMpdus = 2;
2222 expectedStats.m_overlappingPpdus = 2;
2223 expectedStats.m_nonOverlappingPpdus = 0;
2224 rxPowerDbm = -80;
2225 // A-MPDU 1
2228 this,
2229 rxPowerDbm,
2230 correctReceiver, // One MPDU addressed to
2231 m_txA);
2232 // A-MPDU 2
2235 this,
2236 rxPowerDbm,
2237 correctReceiver, // One MPDU addressed to
2238 m_txB);
2239
2242 this,
2243 4); // TotalRecords
2244
2247 this,
2248 expectedStats,
2249 nodeRx->GetId(),
2250 0,
2251 0);
2252
2255 this,
2256 expectedStats.m_receivedPpdus,
2257 expectedStats.m_failedPpdus,
2258 expectedStats.m_receivedMpdus,
2259 expectedStats.m_failedMpdus,
2260 expectedStats.m_overlappingPpdus,
2261 expectedStats.m_nonOverlappingPpdus);
2262
2263 // CASE 6: PPDU Overlapping Reception with sufficient RSSI/SNR With SOME Frames Addressed to
2264 // Receiver
2265 expectedStats.m_receivedPpdus = 0;
2266 expectedStats.m_failedPpdus = 1;
2267 expectedStats.m_receivedMpdus = 0;
2268 expectedStats.m_failedMpdus = 1;
2269 expectedStats.m_overlappingPpdus = 1;
2270 expectedStats.m_nonOverlappingPpdus = 0;
2271 rxPowerDbm = -80;
2272 // A-MPDU 1
2275 this,
2276 rxPowerDbm,
2277 correctReceiver, // One MPDU addressed to
2278 m_txA);
2279 // A-MPDU 2
2282 this,
2283 rxPowerDbm,
2284 wrongReceiver, // One MPDU addressed to
2285 m_txB);
2286
2289 this,
2290 4); // TotalRecords
2291
2294 this,
2295 expectedStats,
2296 nodeRx->GetId(),
2297 0,
2298 0);
2299
2302 this,
2303 expectedStats.m_receivedPpdus,
2304 expectedStats.m_failedPpdus,
2305 expectedStats.m_receivedMpdus,
2306 expectedStats.m_failedMpdus,
2307 expectedStats.m_overlappingPpdus,
2308 expectedStats.m_nonOverlappingPpdus);
2309
2310 // Stop Statistics Collection Period Since following testcases evaluate the Start and Stop
2311 // methods
2313
2314 // CASE 7: Execution of "Start()" Before Signal Injection
2315 expectedStats.m_receivedPpdus = 1;
2316 expectedStats.m_failedPpdus = 0;
2317 expectedStats.m_receivedMpdus = 1;
2318 expectedStats.m_failedMpdus = 0;
2319 expectedStats.m_overlappingPpdus = 0;
2320 expectedStats.m_nonOverlappingPpdus = 1;
2321 rxPowerDbm = -80;
2323
2324 // A-MPDU 1
2327 this,
2328 rxPowerDbm,
2329 correctReceiver, // One MPDU addressed to
2330 m_txA);
2331
2334 this,
2335 2); // TotalRecords
2336
2339 this,
2340 expectedStats,
2341 nodeRx->GetId(),
2342 0,
2343 0);
2344
2347 this,
2348 expectedStats.m_receivedPpdus,
2349 expectedStats.m_failedPpdus,
2350 expectedStats.m_receivedMpdus,
2351 expectedStats.m_failedMpdus,
2352 expectedStats.m_overlappingPpdus,
2353 expectedStats.m_nonOverlappingPpdus);
2354
2356
2357 // CASE 8: Activation of "Start()" Followed by "Stop()" Before Signal Injection
2358 expectedStats.m_receivedPpdus = 0;
2359 expectedStats.m_failedPpdus = 0;
2360 expectedStats.m_receivedMpdus = 0;
2361 expectedStats.m_failedMpdus = 0;
2362 expectedStats.m_overlappingPpdus = 0;
2363 expectedStats.m_nonOverlappingPpdus = 0;
2364 rxPowerDbm = -80;
2365
2367
2369
2370 // A-MPDU 1
2373 this,
2374 rxPowerDbm,
2375 correctReceiver, // One MPDU addressed to
2376 m_txA);
2377
2380 this,
2381 0); // TotalRecords
2382
2385 this,
2386 expectedStats,
2387 nodeRx->GetId(),
2388 0,
2389 0);
2390
2393 this,
2394 expectedStats.m_receivedPpdus,
2395 expectedStats.m_failedPpdus,
2396 expectedStats.m_receivedMpdus,
2397 expectedStats.m_failedMpdus,
2398 expectedStats.m_overlappingPpdus,
2399 expectedStats.m_nonOverlappingPpdus);
2400
2401 // CASE 9: "Start()" Method Initiated During Ongoing PPDU Reception
2402 expectedStats.m_receivedPpdus = 1;
2403 expectedStats.m_failedPpdus = 0;
2404 expectedStats.m_receivedMpdus = 1;
2405 expectedStats.m_failedMpdus = 0;
2406 expectedStats.m_overlappingPpdus = 0;
2407 expectedStats.m_nonOverlappingPpdus = 1;
2408 rxPowerDbm = -80;
2409
2410 // A-MPDU 1
2413 this,
2414 rxPowerDbm,
2415 correctReceiver, // One MPDU addressed to
2416 m_txA);
2417
2419
2422 this,
2423 2); // TotalRecords
2424
2427 this,
2428 expectedStats,
2429 nodeRx->GetId(),
2430 0,
2431 0);
2432
2435 this,
2436 expectedStats.m_receivedPpdus,
2437 expectedStats.m_failedPpdus,
2438 expectedStats.m_receivedMpdus,
2439 expectedStats.m_failedMpdus,
2440 expectedStats.m_overlappingPpdus,
2441 expectedStats.m_nonOverlappingPpdus);
2442
2444
2445 // CASE 10: Execution of "Stop()" During Ongoing PPDU Reception
2446 expectedStats.m_receivedPpdus = 0;
2447 expectedStats.m_failedPpdus = 0;
2448 expectedStats.m_receivedMpdus = 0;
2449 expectedStats.m_failedMpdus = 0;
2450 expectedStats.m_overlappingPpdus = 0;
2451 expectedStats.m_nonOverlappingPpdus = 0;
2452 rxPowerDbm = -80;
2453
2455
2456 // A-MPDU 1
2459 this,
2460 rxPowerDbm,
2461 correctReceiver, // One MPDU addressed to
2462 m_txA);
2463
2465
2468 this,
2469 0); // TotalRecords
2470
2473 this,
2474 expectedStats,
2475 nodeRx->GetId(),
2476 0,
2477 0);
2478
2481 this,
2482 expectedStats.m_receivedPpdus,
2483 expectedStats.m_failedPpdus,
2484 expectedStats.m_receivedMpdus,
2485 expectedStats.m_failedMpdus,
2486 expectedStats.m_overlappingPpdus,
2487 expectedStats.m_nonOverlappingPpdus);
2488
2491}
2492
2493/**
2494 * @ingroup wifi-test
2495 * @ingroup tests
2496 *
2497 * @brief wifi PHY reception Test Suite
2498 */
2500{
2501 public:
2503};
2504
2506 : TestSuite("wifi-phy-rx-trace-helper", Type::UNIT)
2507{
2508 AddTestCase(new TestWifiPhyRxTraceHelper("test-statistics"), TestCase::Duration::QUICK);
2509 AddTestCase(new TestWifiPhyRxTraceHelperMloStr, TestCase::Duration::QUICK);
2510 AddTestCase(new TestWifiPhyRxTraceHelperYans, TestCase::Duration::QUICK);
2511}
2512
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< 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:921
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:2345
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