A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-phy-ofdma-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 University of Washington
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "ns3/ap-wifi-mac.h"
10#include "ns3/boolean.h"
11#include "ns3/constant-position-mobility-model.h"
12#include "ns3/ctrl-headers.h"
13#include "ns3/double.h"
14#include "ns3/he-configuration.h"
15#include "ns3/he-phy.h"
16#include "ns3/he-ppdu.h"
17#include "ns3/interference-helper.h"
18#include "ns3/log.h"
19#include "ns3/mobility-helper.h"
20#include "ns3/multi-model-spectrum-channel.h"
21#include "ns3/nist-error-rate-model.h"
22#include "ns3/node.h"
23#include "ns3/non-communicating-net-device.h"
24#include "ns3/pointer.h"
25#include "ns3/rng-seed-manager.h"
26#include "ns3/simulator.h"
27#include "ns3/spectrum-wifi-helper.h"
28#include "ns3/spectrum-wifi-phy.h"
29#include "ns3/sta-wifi-mac.h"
30#include "ns3/string.h"
31#include "ns3/test.h"
32#include "ns3/threshold-preamble-detection-model.h"
33#include "ns3/txop.h"
34#include "ns3/waveform-generator.h"
35#include "ns3/wifi-mac-header.h"
36#include "ns3/wifi-net-device.h"
37#include "ns3/wifi-phy-listener.h"
38#include "ns3/wifi-psdu.h"
39#include "ns3/wifi-spectrum-phy-interface.h"
40#include "ns3/wifi-spectrum-signal-parameters.h"
41#include "ns3/wifi-spectrum-value-helper.h"
42#include "ns3/wifi-utils.h"
43
44#include <algorithm>
45#include <iterator>
46#include <memory>
47
48using namespace ns3;
49
50NS_LOG_COMPONENT_DEFINE("WifiPhyOfdmaTest");
51
52static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
53static const MHz_u DEFAULT_FREQUENCY{5180};
57 DEFAULT_CHANNEL_WIDTH; // expanded to channel width to model spectrum mask
58
59/**
60 * HE PHY slightly modified so as to return a given
61 * STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
62 */
63class OfdmaTestHePhy : public HePhy
64{
65 public:
66 /**
67 * Constructor
68 *
69 * @param staId the ID of the STA to which this PHY belongs to
70 */
71 OfdmaTestHePhy(uint16_t staId);
72 ~OfdmaTestHePhy() override;
73
74 /**
75 * Return the STA ID that has been assigned to the station this PHY belongs to.
76 * This is typically called for MU PPDUs, in order to pick the correct PSDU.
77 *
78 * @param ppdu the PPDU for which the STA ID is requested
79 * @return the STA ID
80 */
81 uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
82
83 /**
84 * Set the global PPDU UID counter.
85 *
86 * @param uid the value to which the global PPDU UID counter should be set
87 */
88 void SetGlobalPpduUid(uint64_t uid);
89
90 private:
91 uint16_t m_staId; ///< ID of the STA to which this PHY belongs to
92}; // class OfdmaTestHePhy
93
95 : HePhy(),
96 m_staId(staId)
97{
98}
99
103
104uint16_t
106{
107 if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
108 {
109 return m_staId;
110 }
111 return HePhy::GetStaId(ppdu);
112}
113
114void
116{
117 m_globalPpduUid = uid;
118}
119
120/**
121 * SpectrumWifiPhy used for testing OFDMA.
122 */
124{
125 public:
126 /**
127 * @brief Get the type ID.
128 * @return the object TypeId
129 */
130 static TypeId GetTypeId();
131 /**
132 * Constructor
133 *
134 * @param staId the ID of the STA to which this PHY belongs to
135 */
136 OfdmaSpectrumWifiPhy(uint16_t staId);
137 ~OfdmaSpectrumWifiPhy() override;
138
139 void DoInitialize() override;
140 void DoDispose() override;
141
142 using WifiPhy::Reset;
143 void StartTx(Ptr<const WifiPpdu> ppdu) override;
144
145 /**
146 * TracedCallback signature for UID of transmitted PPDU.
147 *
148 * @param uid the UID of the transmitted PPDU
149 */
150 typedef void (*TxPpduUidCallback)(uint64_t uid);
151
152 /**
153 * Set the global PPDU UID counter.
154 *
155 * @param uid the value to which the global PPDU UID counter should be set
156 */
157 void SetPpduUid(uint64_t uid);
158
159 /**
160 * Since we assume trigger frame was previously received from AP, this is used to set its UID
161 *
162 * @param uid the PPDU UID of the trigger frame
163 */
164 void SetTriggerFrameUid(uint64_t uid);
165
166 /**
167 * @return the current preamble events map
168 */
169 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
170 /**
171 * @return the current event
172 */
174
175 /**
176 * Wrapper to InterferenceHelper method.
177 *
178 * @param energy the minimum energy requested
179 * @param band identify the requested band
180 *
181 * @returns the expected amount of time the observed
182 * energy on the medium for a given band will
183 * be higher than the requested threshold.
184 */
186
187 /**
188 * @return a const pointer to the HE PHY instance
189 */
191
192 private:
193 Ptr<OfdmaTestHePhy> m_ofdmTestHePhy; ///< Pointer to HE PHY instance used for OFDMA test
195 m_phyTxPpduUidTrace; //!< Callback providing UID of the PPDU that is about to be transmitted
196}; // class OfdmaSpectrumWifiPhy
197
198TypeId
200{
201 static TypeId tid =
202 TypeId("ns3::OfdmaSpectrumWifiPhy")
204 .SetGroupName("Wifi")
205 .AddTraceSource("TxPpduUid",
206 "UID of the PPDU to be transmitted",
208 "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
209 return tid;
210}
211
218
222
223void
225{
226 // Replace HE PHY instance with test instance
229}
230
231void
237
238void
244
245void
250
251void
257
258std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
263
269
270Time
272{
273 return m_interference->GetEnergyDuration(energy, band);
274}
275
281
282/**
283 * @ingroup wifi-test
284 * @ingroup tests
285 *
286 * @brief DL-OFDMA PHY test
287 */
289{
290 public:
293
294 private:
295 void DoSetup() override;
296 void DoTeardown() override;
297 void DoRun() override;
298
299 /**
300 * Receive success function for STA 1
301 * @param psdu the PSDU
302 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
303 * @param txVector the transmit vector
304 * @param statusPerMpdu reception status per MPDU
305 */
307 RxSignalInfo rxSignalInfo,
308 const WifiTxVector& txVector,
309 const std::vector<bool>& statusPerMpdu);
310 /**
311 * Receive success function for STA 2
312 * @param psdu the PSDU
313 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
314 * @param txVector the transmit vector
315 * @param statusPerMpdu reception status per MPDU
316 */
318 RxSignalInfo rxSignalInfo,
319 const WifiTxVector& txVector,
320 const std::vector<bool>& statusPerMpdu);
321 /**
322 * Receive success function for STA 3
323 * @param psdu the PSDU
324 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
325 * @param txVector the transmit vector
326 * @param statusPerMpdu reception status per MPDU
327 */
329 RxSignalInfo rxSignalInfo,
330 const WifiTxVector& txVector,
331 const std::vector<bool>& statusPerMpdu);
332
333 /**
334 * Receive failure function for STA 1
335 * @param psdu the PSDU
336 */
338 /**
339 * Receive failure function for STA 2
340 * @param psdu the PSDU
341 */
343 /**
344 * Receive failure function for STA 3
345 * @param psdu the PSDU
346 */
348
349 /**
350 * Check the results for STA 1
351 * @param expectedRxSuccess the expected number of RX success
352 * @param expectedRxFailure the expected number of RX failures
353 * @param expectedRxBytes the expected number of RX bytes
354 */
355 void CheckResultsSta1(uint32_t expectedRxSuccess,
356 uint32_t expectedRxFailure,
357 uint32_t expectedRxBytes);
358 /**
359 * Check the results for STA 2
360 * @param expectedRxSuccess the expected number of RX success
361 * @param expectedRxFailure the expected number of RX failures
362 * @param expectedRxBytes the expected number of RX bytes
363 */
364 void CheckResultsSta2(uint32_t expectedRxSuccess,
365 uint32_t expectedRxFailure,
366 uint32_t expectedRxBytes);
367 /**
368 * Check the results for STA 3
369 * @param expectedRxSuccess the expected number of RX success
370 * @param expectedRxFailure the expected number of RX failures
371 * @param expectedRxBytes the expected number of RX bytes
372 */
373 void CheckResultsSta3(uint32_t expectedRxSuccess,
374 uint32_t expectedRxFailure,
375 uint32_t expectedRxBytes);
376
377 /**
378 * Reset the results
379 */
380 void ResetResults();
381
382 /**
383 * Send MU-PPDU function
384 * @param rxStaId1 the ID of the recipient STA for the first PSDU
385 * @param rxStaId2 the ID of the recipient STA for the second PSDU
386 */
387 void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
388
389 /**
390 * Generate interference function
391 * @param interferencePsd the PSD of the interference to be generated
392 * @param duration the duration of the interference
393 */
394 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
395 /**
396 * Stop interference function
397 */
398 void StopInterference();
399
400 /**
401 * Run one function
402 */
403 void RunOne();
404
405 /**
406 * Schedule now to check the PHY state
407 * @param phy the PHY
408 * @param expectedState the expected state of the PHY
409 */
411 /**
412 * Check the PHY state now
413 * @param phy the PHY
414 * @param expectedState the expected state of the PHY
415 */
417
418 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
419 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
420 uint32_t m_countRxSuccessSta3; ///< count RX success for STA 3
421 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
422 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
423 uint32_t m_countRxFailureSta3; ///< count RX failure for STA 3
424 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
425 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
426 uint32_t m_countRxBytesSta3; ///< count RX bytes for STA 3
427
433
434 MHz_u m_frequency; ///< frequency
435 MHz_u m_channelWidth; ///< channel width
436 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
437};
438
440 : TestCase("DL-OFDMA PHY test"),
441 m_countRxSuccessSta1(0),
442 m_countRxSuccessSta2(0),
443 m_countRxSuccessSta3(0),
444 m_countRxFailureSta1(0),
445 m_countRxFailureSta2(0),
446 m_countRxFailureSta3(0),
447 m_countRxBytesSta1(0),
448 m_countRxBytesSta2(0),
449 m_countRxBytesSta3(0),
450 m_frequency(DEFAULT_FREQUENCY),
451 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
452 m_expectedPpduDuration(NanoSeconds(306400))
453{
454}
455
456void
469
470void
471TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
472{
473 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
474 WifiConstPsduMap psdus;
476 0,
478 NanoSeconds(800),
479 1,
480 1,
481 0,
483 false,
484 false};
486 if (m_channelWidth == MHz_u{20})
487 {
488 ruType = HeRu::RU_106_TONE;
489 txVector.SetRuAllocation({96}, 0);
490 }
491 else if (m_channelWidth == MHz_u{40})
492 {
493 ruType = HeRu::RU_242_TONE;
494 txVector.SetRuAllocation({192, 192}, 0);
495 }
496 else if (m_channelWidth == MHz_u{80})
497 {
498 ruType = HeRu::RU_484_TONE;
499 txVector.SetRuAllocation({200, 200, 200, 200}, 0);
500 }
501 else if (m_channelWidth == MHz_u{160})
502 {
503 ruType = HeRu::RU_996_TONE;
504 txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208}, 0);
505 }
506 else
507 {
508 NS_ASSERT_MSG(false, "Unsupported channel width");
509 }
510
511 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
512
513 HeRu::RuSpec ru1(ruType, 1, true);
514 txVector.SetRu(ru1, rxStaId1);
515 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
516 txVector.SetNss(1, rxStaId1);
517
518 HeRu::RuSpec ru2(ruType, (m_channelWidth == MHz_u{160} ? 1 : 2), m_channelWidth != MHz_u{160});
519 txVector.SetRu(ru2, rxStaId2);
520 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
521 txVector.SetNss(1, rxStaId2);
522
523 Ptr<Packet> pkt1 = Create<Packet>(1000);
524 WifiMacHeader hdr1;
526 hdr1.SetQosTid(0);
527 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
528 hdr1.SetSequenceNumber(1);
529 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
530 psdus.insert(std::make_pair(rxStaId1, psdu1));
531
532 Ptr<Packet> pkt2 = Create<Packet>(1500);
533 WifiMacHeader hdr2;
535 hdr2.SetQosTid(0);
536 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
537 hdr2.SetSequenceNumber(2);
538 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
539 psdus.insert(std::make_pair(rxStaId2, psdu2));
540
541 m_phyAp->Send(psdus, txVector);
542}
543
544void
546{
547 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
548 m_phyInterferer->SetPeriod(duration);
549 m_phyInterferer->Start();
551}
552
553void
558
562
563void
565 RxSignalInfo rxSignalInfo,
566 const WifiTxVector& txVector,
567 const std::vector<bool>& /*statusPerMpdu*/)
568{
569 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
571 m_countRxBytesSta1 += (psdu->GetSize() - 30);
572}
573
574void
576 RxSignalInfo rxSignalInfo,
577 const WifiTxVector& txVector,
578 const std::vector<bool>& /*statusPerMpdu*/)
579{
580 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
582 m_countRxBytesSta2 += (psdu->GetSize() - 30);
583}
584
585void
587 RxSignalInfo rxSignalInfo,
588 const WifiTxVector& txVector,
589 const std::vector<bool>& /*statusPerMpdu*/)
590{
591 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
593 m_countRxBytesSta3 += (psdu->GetSize() - 30);
594}
595
596void
602
603void
609
610void
616
617void
619 uint32_t expectedRxFailure,
620 uint32_t expectedRxBytes)
621{
623 expectedRxSuccess,
624 "The number of successfully received packets by STA 1 is not correct!");
626 expectedRxFailure,
627 "The number of unsuccessfuly received packets by STA 1 is not correct!");
629 expectedRxBytes,
630 "The number of bytes received by STA 1 is not correct!");
631}
632
633void
635 uint32_t expectedRxFailure,
636 uint32_t expectedRxBytes)
637{
639 expectedRxSuccess,
640 "The number of successfully received packets by STA 2 is not correct!");
642 expectedRxFailure,
643 "The number of unsuccessfuly received packets by STA 2 is not correct!");
645 expectedRxBytes,
646 "The number of bytes received by STA 2 is not correct!");
647}
648
649void
651 uint32_t expectedRxFailure,
652 uint32_t expectedRxBytes)
653{
655 expectedRxSuccess,
656 "The number of successfully received packets by STA 3 is not correct!");
658 expectedRxFailure,
659 "The number of unsuccessfuly received packets by STA 3 is not correct!");
661 expectedRxBytes,
662 "The number of bytes received by STA 3 is not correct!");
663}
664
665void
667{
668 // This is needed to make sure PHY state will be checked as the last event if a state change
669 // occurred at the exact same time as the check
671}
672
673void
675 WifiPhyState expectedState)
676{
677 WifiPhyState currentState;
678 PointerValue ptr;
679 phy->GetAttribute("State", ptr);
681 currentState = state->GetState();
682 NS_LOG_FUNCTION(this << currentState);
683 NS_TEST_ASSERT_MSG_EQ(currentState,
684 expectedState,
685 "PHY State " << currentState << " does not match expected state "
686 << expectedState << " at " << Simulator::Now());
687}
688
689void
691{
694 lossModel->SetFrequency(MHzToHz(m_frequency));
695 spectrumChannel->AddPropagationLossModel(lossModel);
698 spectrumChannel->SetPropagationDelayModel(delayModel);
699
700 Ptr<Node> apNode = CreateObject<Node>();
704 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
706 m_phyAp->SetErrorRateModel(apErrorModel);
707 m_phyAp->SetDevice(apDev);
708 m_phyAp->AddChannel(spectrumChannel);
709 m_phyAp->ConfigureStandard(WIFI_STANDARD_80211ax);
711 m_phyAp->SetMobility(apMobility);
712 apDev->SetPhy(m_phyAp);
713 apNode->AggregateObject(apMobility);
714 apNode->AddDevice(apDev);
715
716 Ptr<Node> sta1Node = CreateObject<Node>();
720 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
722 m_phySta1->SetErrorRateModel(sta1ErrorModel);
723 m_phySta1->SetDevice(sta1Dev);
724 m_phySta1->AddChannel(spectrumChannel);
730 m_phySta1->SetMobility(sta1Mobility);
731 sta1Dev->SetPhy(m_phySta1);
732 sta1Node->AggregateObject(sta1Mobility);
733 sta1Node->AddDevice(sta1Dev);
734
735 Ptr<Node> sta2Node = CreateObject<Node>();
739 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
741 m_phySta2->SetErrorRateModel(sta2ErrorModel);
742 m_phySta2->SetDevice(sta2Dev);
743 m_phySta2->AddChannel(spectrumChannel);
749 m_phySta2->SetMobility(sta2Mobility);
750 sta2Dev->SetPhy(m_phySta2);
751 sta2Node->AggregateObject(sta2Mobility);
752 sta2Node->AddDevice(sta2Dev);
753
754 Ptr<Node> sta3Node = CreateObject<Node>();
758 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
760 m_phySta3->SetErrorRateModel(sta3ErrorModel);
761 m_phySta3->SetDevice(sta3Dev);
762 m_phySta3->AddChannel(spectrumChannel);
768 m_phySta3->SetMobility(sta3Mobility);
769 sta3Dev->SetPhy(m_phySta3);
770 sta3Node->AggregateObject(sta3Mobility);
771 sta3Node->AddDevice(sta3Dev);
772
773 Ptr<Node> interfererNode = CreateObject<Node>();
776 m_phyInterferer->SetDevice(interfererDev);
777 m_phyInterferer->SetChannel(spectrumChannel);
778 m_phyInterferer->SetDutyCycle(1);
779 interfererNode->AddDevice(interfererDev);
780}
781
782void
784{
785 m_phyAp->Dispose();
786 m_phyAp = nullptr;
788 m_phySta1 = nullptr;
790 m_phySta2 = nullptr;
792 m_phySta3 = nullptr;
794 m_phyInterferer = nullptr;
795}
796
797void
799{
802 int64_t streamNumber = 0;
803 m_phyAp->AssignStreams(streamNumber);
804 m_phySta1->AssignStreams(streamNumber);
805 m_phySta2->AssignStreams(streamNumber);
806 m_phySta3->AssignStreams(streamNumber);
807
808 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
813 ->number;
814
815 m_phyAp->SetOperatingChannel(
823
825
826 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
827 // Each STA should receive its PSDU.
829
830 // Since it takes m_expectedPpduDuration to transmit the PPDU,
831 // all 3 PHYs should be back to IDLE at the same time,
832 // even the PHY that has no PSDU addressed to it.
835 this,
836 m_phySta1,
837 WifiPhyState::RX);
840 this,
841 m_phySta2,
842 WifiPhyState::RX);
845 this,
846 m_phySta3,
847 WifiPhyState::CCA_BUSY);
850 this,
851 m_phySta1,
852 WifiPhyState::IDLE);
855 this,
856 m_phySta2,
857 WifiPhyState::IDLE);
860 this,
861 m_phySta3,
862 WifiPhyState::IDLE);
863
864 // One PSDU of 1000 bytes should have been successfully received by STA 1
867 this,
868 1,
869 0,
870 1000);
871 // One PSDU of 1500 bytes should have been successfully received by STA 2
874 this,
875 1,
876 0,
877 1500);
878 // No PSDU should have been received by STA 3
880
882
883 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
884 // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
885 // but should keep its PHY busy during all PPDU duration.
887
888 // Since it takes m_expectedPpduDuration to transmit the PPDU,
889 // all 3 PHYs should be back to IDLE at the same time,
890 // even the PHY that has no PSDU addressed to it.
893 this,
894 m_phySta1,
895 WifiPhyState::RX);
898 this,
899 m_phySta2,
900 WifiPhyState::CCA_BUSY);
903 this,
904 m_phySta3,
905 WifiPhyState::RX);
908 this,
909 m_phySta1,
910 WifiPhyState::IDLE);
913 this,
914 m_phySta2,
915 WifiPhyState::IDLE);
918 this,
919 m_phySta3,
920 WifiPhyState::IDLE);
921
922 // One PSDU of 1000 bytes should have been successfully received by STA 1
925 this,
926 1,
927 0,
928 1000);
929 // No PSDU should have been received by STA 2
931 // One PSDU of 1500 bytes should have been successfully received by STA 3
934 this,
935 1,
936 0,
937 1500);
938
940
941 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
943
944 // A strong non-wifi interference is generated on RU 1 during PSDU reception
945 BandInfo bandInfo;
946 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 4));
947 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
948 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
949 Bands bands;
950 bands.push_back(bandInfo);
951
952 auto SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
953 auto interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
954 Watt_u interferencePower{0.1};
955 *interferencePsdRu1 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
956
959 this,
960 interferencePsdRu1,
961 MilliSeconds(100));
962
963 // Since it takes m_expectedPpduDuration to transmit the PPDU,
964 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
965 // even the PHY that has no PSDU addressed to it.
968 this,
969 m_phySta1,
970 WifiPhyState::RX);
973 this,
974 m_phySta2,
975 WifiPhyState::RX);
978 this,
979 m_phySta3,
980 WifiPhyState::CCA_BUSY);
983 this,
984 m_phySta1,
985 WifiPhyState::CCA_BUSY);
988 this,
989 m_phySta2,
990 WifiPhyState::CCA_BUSY);
993 this,
994 m_phySta3,
995 WifiPhyState::CCA_BUSY);
996
997 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
998 // occupies RU 1)
1000 // One PSDU of 1500 bytes should have been successfully received by STA 2
1003 this,
1004 1,
1005 0,
1006 1500);
1007 // No PSDU should have been received by STA3
1009
1011
1012 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1014
1015 // A strong non-wifi interference is generated on RU 2 during PSDU reception
1016 bandInfo.fc = MHzToHz(m_frequency + (m_channelWidth / 4));
1017 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
1018 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
1019 bands.clear();
1020 bands.push_back(bandInfo);
1021
1022 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1023 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1024 *interferencePsdRu2 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
1025
1028 this,
1029 interferencePsdRu2,
1030 MilliSeconds(100));
1031
1032 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1033 // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1034 // same time, even the PHY that has no PSDU addressed to it.
1037 this,
1038 m_phySta1,
1039 WifiPhyState::RX);
1042 this,
1043 m_phySta2,
1044 WifiPhyState::RX);
1047 this,
1048 m_phySta3,
1049 WifiPhyState::CCA_BUSY);
1052 this,
1053 m_phySta1,
1054 (m_channelWidth >= MHz_u{40}) ? WifiPhyState::IDLE
1055 : WifiPhyState::CCA_BUSY);
1058 this,
1059 m_phySta2,
1060 (m_channelWidth >= MHz_u{40}) ? WifiPhyState::IDLE
1061 : WifiPhyState::CCA_BUSY);
1064 this,
1065 m_phySta3,
1066 (m_channelWidth >= MHz_u{40}) ? WifiPhyState::IDLE
1067 : WifiPhyState::CCA_BUSY);
1068
1069 // One PSDU of 1000 bytes should have been successfully received by STA 1
1072 this,
1073 1,
1074 0,
1075 1000);
1076 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1077 // occupies RU 2)
1079 // No PSDU should have been received by STA3
1081
1083
1084 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1086
1087 // A strong non-wifi interference is generated on the full band during PSDU reception
1088 bandInfo.fc = MHzToHz(m_frequency);
1089 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 2);
1090 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 2);
1091 bands.clear();
1092 bands.push_back(bandInfo);
1093
1094 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1095 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1096 *interferencePsdAll = interferencePower / (MHzToHz(m_channelWidth) * 20);
1097
1100 this,
1101 interferencePsdAll,
1102 MilliSeconds(100));
1103
1104 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1105 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1106 // even the PHY that has no PSDU addressed to it.
1109 this,
1110 m_phySta1,
1111 WifiPhyState::RX);
1114 this,
1115 m_phySta2,
1116 WifiPhyState::RX);
1119 this,
1120 m_phySta3,
1121 WifiPhyState::CCA_BUSY);
1124 this,
1125 m_phySta1,
1126 WifiPhyState::CCA_BUSY);
1129 this,
1130 m_phySta2,
1131 WifiPhyState::CCA_BUSY);
1134 this,
1135 m_phySta3,
1136 WifiPhyState::CCA_BUSY);
1137
1138 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1139 // occupies RU 1)
1141 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1142 // occupies RU 2)
1144 // No PSDU should have been received by STA3
1146
1148
1150}
1151
1152void
1154{
1155 m_frequency = MHz_u{5180};
1156 m_channelWidth = MHz_u{20};
1158 RunOne();
1159
1160 m_frequency = MHz_u{5190};
1161 m_channelWidth = MHz_u{40};
1163 RunOne();
1164
1165 m_frequency = MHz_u{5210};
1166 m_channelWidth = MHz_u{80};
1168 RunOne();
1169
1170 m_frequency = MHz_u{5250};
1171 m_channelWidth = MHz_u{160};
1173 RunOne();
1174
1176}
1177
1178/**
1179 * @ingroup wifi-test
1180 * @ingroup tests
1181 *
1182 * @brief DL-OFDMA PHY puncturing test
1183 */
1185{
1186 public:
1188
1189 private:
1190 void DoSetup() override;
1191 void DoTeardown() override;
1192 void DoRun() override;
1193
1194 /**
1195 * Receive success function for STA 1
1196 * @param psdu the PSDU
1197 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1198 * @param txVector the transmit vector
1199 * @param statusPerMpdu reception status per MPDU
1200 */
1202 RxSignalInfo rxSignalInfo,
1203 const WifiTxVector& txVector,
1204 const std::vector<bool>& statusPerMpdu);
1205
1206 /**
1207 * Receive success function for STA 2
1208 * @param psdu the PSDU
1209 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1210 * @param txVector the transmit vector
1211 * @param statusPerMpdu reception status per MPDU
1212 */
1214 RxSignalInfo rxSignalInfo,
1215 const WifiTxVector& txVector,
1216 const std::vector<bool>& statusPerMpdu);
1217
1218 /**
1219 * Receive failure function for STA 1
1220 * @param psdu the PSDU
1221 */
1223
1224 /**
1225 * Receive failure function for STA 2
1226 * @param psdu the PSDU
1227 */
1229
1230 /**
1231 * Check the results for STA 1
1232 * @param expectedRxSuccess the expected number of RX success
1233 * @param expectedRxFailure the expected number of RX failures
1234 * @param expectedRxBytes the expected number of RX bytes
1235 */
1236 void CheckResultsSta1(uint32_t expectedRxSuccess,
1237 uint32_t expectedRxFailure,
1238 uint32_t expectedRxBytes);
1239
1240 /**
1241 * Check the results for STA 2
1242 * @param expectedRxSuccess the expected number of RX success
1243 * @param expectedRxFailure the expected number of RX failures
1244 * @param expectedRxBytes the expected number of RX bytes
1245 */
1246 void CheckResultsSta2(uint32_t expectedRxSuccess,
1247 uint32_t expectedRxFailure,
1248 uint32_t expectedRxBytes);
1249
1250 /**
1251 * Reset the results
1252 */
1253 void ResetResults();
1254
1255 /**
1256 * Send MU-PPDU function
1257 * @param rxStaId1 the ID of the recipient STA for the first PSDU
1258 * @param rxStaId2 the ID of the recipient STA for the second PSDU
1259 * @param puncturedSubchannels indicates for each subchannel whether it is punctured or not. if
1260 * empty, preamble puncturing is not used.
1261 */
1262 void SendMuPpdu(uint16_t rxStaId1,
1263 uint16_t rxStaId2,
1264 const std::vector<bool>& puncturedSubchannels);
1265
1266 /**
1267 * Generate interference function
1268 * @param interferencePsd the PSD of the interference to be generated
1269 * @param duration the duration of the interference
1270 */
1271 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1272
1273 /**
1274 * Stop interference function
1275 */
1276 void StopInterference();
1277
1278 /**
1279 * Run one function
1280 */
1281 void RunOne();
1282
1283 /**
1284 * Schedule now to check the PHY state
1285 * @param phy the PHY
1286 * @param expectedState the expected state of the PHY
1287 */
1288 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
1289
1290 /**
1291 * Check the PHY state now
1292 * @param phy the PHY
1293 * @param expectedState the expected state of the PHY
1294 */
1296
1297 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
1298 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
1299 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
1300 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
1301 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
1302 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
1303
1308
1309 MHz_u m_frequency; ///< frequency
1310 MHz_u m_channelWidth; ///< channel width
1311
1312 uint8_t m_indexSubchannel; ///< Index of the subchannel (starting from 0) that should contain an
1313 ///< interference and be punctured during the test run
1314
1315 Time m_expectedPpduDuration20Mhz; ///< expected duration to send MU PPDU on 20 MHz RU
1316 Time m_expectedPpduDuration40Mhz; ///< expected duration to send MU PPDU on 40 MHz RU
1317};
1318
1320 : TestCase("DL-OFDMA PHY puncturing test"),
1321 m_countRxSuccessSta1(0),
1322 m_countRxSuccessSta2(0),
1323 m_countRxFailureSta1(0),
1324 m_countRxFailureSta2(0),
1325 m_countRxBytesSta1(0),
1326 m_countRxBytesSta2(0),
1327 m_frequency(MHz_u{5210}),
1328 m_channelWidth(MHz_u{80}),
1329 m_indexSubchannel(0),
1330 m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1331 m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1332{
1333}
1334
1335void
1345
1346void
1348 uint16_t rxStaId2,
1349 const std::vector<bool>& puncturedSubchannels)
1350{
1351 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1352 WifiConstPsduMap psdus;
1353 WifiTxVector txVector{HePhy::GetHeMcs7(),
1354 0,
1356 NanoSeconds(800),
1357 1,
1358 1,
1359 0,
1361 false,
1362 false};
1363
1364 HeRu::RuType ruType =
1365 puncturedSubchannels.empty()
1367 : (puncturedSubchannels.at(1) ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1368 HeRu::RuSpec ru1(ruType, 1, true);
1369 txVector.SetRu(ru1, rxStaId1);
1370 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1371 txVector.SetNss(1, rxStaId1);
1372
1373 ruType = puncturedSubchannels.empty()
1375 : (puncturedSubchannels.at(1) ? HeRu::RU_484_TONE : HeRu::RU_242_TONE);
1376 HeRu::RuSpec ru2(ruType,
1377 ruType == HeRu::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1378 true);
1379 txVector.SetRu(ru2, rxStaId2);
1380 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1381 txVector.SetNss(1, rxStaId2);
1382
1383 RuAllocation ruAlloc;
1384 if (puncturedSubchannels.empty())
1385 {
1386 std::fill_n(std::back_inserter(ruAlloc), 4, 200);
1387 }
1388 else
1389 {
1390 ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1391 ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
1392 ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1393 : (puncturedSubchannels.at(3) ? 192 : 200));
1394 ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1395 : (puncturedSubchannels.at(3) ? 113 : 200));
1396 }
1397
1398 txVector.SetRuAllocation(ruAlloc, 0);
1399 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1400
1401 Ptr<Packet> pkt1 = Create<Packet>(1000);
1402 WifiMacHeader hdr1;
1404 hdr1.SetQosTid(0);
1405 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1406 hdr1.SetSequenceNumber(1);
1407 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1408 psdus.insert(std::make_pair(rxStaId1, psdu1));
1409
1410 Ptr<Packet> pkt2 = Create<Packet>(1500);
1411 WifiMacHeader hdr2;
1413 hdr2.SetQosTid(0);
1414 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1415 hdr2.SetSequenceNumber(2);
1416 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1417 psdus.insert(std::make_pair(rxStaId2, psdu2));
1418
1419 if (!puncturedSubchannels.empty())
1420 {
1421 txVector.SetInactiveSubchannels(puncturedSubchannels);
1422 }
1423
1424 m_phyAp->Send(psdus, txVector);
1425}
1426
1427void
1429{
1430 NS_LOG_FUNCTION(this << duration);
1431 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
1432 m_phyInterferer->SetPeriod(duration);
1433 m_phyInterferer->Start();
1435}
1436
1437void
1443
1444void
1446 RxSignalInfo rxSignalInfo,
1447 const WifiTxVector& txVector,
1448 const std::vector<bool>& /*statusPerMpdu*/)
1449{
1450 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1452 m_countRxBytesSta1 += (psdu->GetSize() - 30);
1453}
1454
1455void
1457 RxSignalInfo rxSignalInfo,
1458 const WifiTxVector& txVector,
1459 const std::vector<bool>& /*statusPerMpdu*/)
1460{
1461 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1463 m_countRxBytesSta2 += (psdu->GetSize() - 30);
1464}
1465
1466void
1472
1473void
1479
1480void
1482 uint32_t expectedRxFailure,
1483 uint32_t expectedRxBytes)
1484{
1486 expectedRxSuccess,
1487 "The number of successfully received packets by STA 1 is not correct!");
1489 expectedRxFailure,
1490 "The number of unsuccessfuly received packets by STA 1 is not correct!");
1492 expectedRxBytes,
1493 "The number of bytes received by STA 1 is not correct!");
1494}
1495
1496void
1498 uint32_t expectedRxFailure,
1499 uint32_t expectedRxBytes)
1500{
1502 expectedRxSuccess,
1503 "The number of successfully received packets by STA 2 is not correct!");
1505 expectedRxFailure,
1506 "The number of unsuccessfuly received packets by STA 2 is not correct!");
1508 expectedRxBytes,
1509 "The number of bytes received by STA 2 is not correct!");
1510}
1511
1512void
1514{
1515 // This is needed to make sure PHY state will be checked as the last event if a state change
1516 // occurred at the exact same time as the check
1518}
1519
1520void
1522{
1523 WifiPhyState currentState;
1524 PointerValue ptr;
1525 phy->GetAttribute("State", ptr);
1527 currentState = state->GetState();
1528 NS_LOG_FUNCTION(this << currentState);
1529 NS_TEST_ASSERT_MSG_EQ(currentState,
1530 expectedState,
1531 "PHY State " << currentState << " does not match expected state "
1532 << expectedState << " at " << Simulator::Now());
1533}
1534
1535void
1537{
1540 lossModel->SetFrequency(MHzToHz(m_frequency));
1541 spectrumChannel->AddPropagationLossModel(lossModel);
1544 spectrumChannel->SetPropagationDelayModel(delayModel);
1545
1546 Ptr<Node> apNode = CreateObject<Node>();
1550 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1552 m_phyAp->SetErrorRateModel(apErrorModel);
1553 m_phyAp->SetDevice(apDev);
1554 m_phyAp->AddChannel(spectrumChannel);
1555 m_phyAp->ConfigureStandard(WIFI_STANDARD_80211ax);
1557 m_phyAp->SetMobility(apMobility);
1558 apDev->SetPhy(m_phyAp);
1559 apNode->AggregateObject(apMobility);
1560 apNode->AddDevice(apDev);
1561
1562 Ptr<Node> sta1Node = CreateObject<Node>();
1566 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1568 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1569 m_phySta1->SetDevice(sta1Dev);
1570 m_phySta1->AddChannel(spectrumChannel);
1576 m_phySta1->SetMobility(sta1Mobility);
1577 sta1Dev->SetPhy(m_phySta1);
1578 sta1Node->AggregateObject(sta1Mobility);
1579 sta1Node->AddDevice(sta1Dev);
1580
1581 Ptr<Node> sta2Node = CreateObject<Node>();
1585 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1587 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1588 m_phySta2->SetDevice(sta2Dev);
1589 m_phySta2->AddChannel(spectrumChannel);
1595 m_phySta2->SetMobility(sta2Mobility);
1596 sta2Dev->SetPhy(m_phySta2);
1597 sta2Node->AggregateObject(sta2Mobility);
1598 sta2Node->AddDevice(sta2Dev);
1599
1600 Ptr<Node> interfererNode = CreateObject<Node>();
1603 m_phyInterferer->SetDevice(interfererDev);
1604 m_phyInterferer->SetChannel(spectrumChannel);
1605 m_phyInterferer->SetDutyCycle(1);
1606 interfererNode->AddDevice(interfererDev);
1607}
1608
1609void
1611{
1612 m_phyAp->Dispose();
1613 m_phyAp = nullptr;
1614 m_phySta1->Dispose();
1615 m_phySta1 = nullptr;
1616 m_phySta2->Dispose();
1617 m_phySta2 = nullptr;
1619 m_phyInterferer = nullptr;
1620}
1621
1622void
1624{
1627 int64_t streamNumber = 0;
1628 m_phyAp->AssignStreams(streamNumber);
1629 m_phySta1->AssignStreams(streamNumber);
1630 m_phySta2->AssignStreams(streamNumber);
1631
1632 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
1637 ->number;
1638
1639 m_phyAp->SetOperatingChannel(
1645
1646 // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1647 // duration of the test run
1648 BandInfo bandInfo;
1649 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20));
1650 // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1651 // the border of another RU
1652 bandInfo.fl = bandInfo.fc - MHzToHz(5);
1653 bandInfo.fh = bandInfo.fc + MHzToHz(5);
1654 Bands bands;
1655 bands.push_back(bandInfo);
1656
1657 auto spectrumInterference = Create<SpectrumModel>(bands);
1658 auto interferencePsd = Create<SpectrumValue>(spectrumInterference);
1659 Watt_u interferencePower{0.1};
1660 *interferencePsd = interferencePower / 10e6;
1661
1664 this,
1665 interferencePsd,
1666 Seconds(3));
1667
1668 //---------------------------------------------------------------------------
1669 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1672 this,
1673 1,
1674 2,
1675 std::vector<bool>{});
1676
1677 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1678 // both PHYs should be back to IDLE at the same time.
1681 this,
1682 m_phySta1,
1683 WifiPhyState::RX);
1686 this,
1687 m_phySta2,
1688 WifiPhyState::RX);
1691 this,
1692 m_phySta1,
1693 WifiPhyState::IDLE);
1696 this,
1697 m_phySta2,
1698 WifiPhyState::IDLE);
1699
1700 if (m_indexSubchannel < 2) // interference in RU 1
1701 {
1702 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1705 this,
1706 0,
1707 1,
1708 0);
1709 // One PSDU of 1500 bytes should have been successfully received by STA 2
1712 this,
1713 1,
1714 0,
1715 1500);
1716 }
1717 else // interference in RU 2
1718 {
1719 // One PSDU of 1000 bytes should have been successfully received by STA 1
1722 this,
1723 1,
1724 0,
1725 1000);
1726 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1729 this,
1730 0,
1731 1,
1732 0);
1733 }
1734
1736
1737 //---------------------------------------------------------------------------
1738 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1739 // the punctured 20 MHz subchannel is the one that has interference
1740 std::vector<bool> puncturedSubchannels;
1741 const auto num20MhzSubchannels = Count20MHzSubchannels(m_channelWidth);
1742 for (std::size_t i = 0; i < num20MhzSubchannels; ++i)
1743 {
1744 if (i == m_indexSubchannel)
1745 {
1746 puncturedSubchannels.push_back(true);
1747 }
1748 else
1749 {
1750 puncturedSubchannels.push_back(false);
1751 }
1752 }
1755 this,
1756 1,
1757 2,
1758 puncturedSubchannels);
1759
1760 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1761 // both PHYs should be back to IDLE at the same time.
1764 this,
1765 m_phySta1,
1766 WifiPhyState::RX);
1769 this,
1770 m_phySta2,
1771 WifiPhyState::RX);
1774 this,
1775 m_phySta1,
1776 WifiPhyState::IDLE);
1779 this,
1780 m_phySta2,
1781 WifiPhyState::IDLE);
1782
1783 // One PSDU of 1000 bytes should have been successfully received by STA 1
1786 this,
1787 1,
1788 0,
1789 1000);
1790 // One PSDU of 1500 bytes should have been successfully received by STA 2
1793 this,
1794 1,
1795 0,
1796 1500);
1797
1799
1801}
1802
1803void
1805{
1806 // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1807 // cannot be punctured
1808 for (auto index : {1, 2, 3})
1809 {
1810 m_indexSubchannel = index;
1811 RunOne();
1812 }
1814}
1815
1816/**
1817 * @ingroup wifi-test
1818 * @ingroup tests
1819 *
1820 * @brief UL-OFDMA PPDU UID attribution test
1821 */
1823{
1824 public:
1826 ~TestUlOfdmaPpduUid() override;
1827
1828 private:
1829 void DoSetup() override;
1830 void DoTeardown() override;
1831 void DoRun() override;
1832
1833 /**
1834 * Transmitted PPDU information function for AP
1835 * @param uid the UID of the transmitted PPDU
1836 */
1837 void TxPpduAp(uint64_t uid);
1838 /**
1839 * Transmitted PPDU information function for STA 1
1840 * @param uid the UID of the transmitted PPDU
1841 */
1842 void TxPpduSta1(uint64_t uid);
1843 /**
1844 * Transmitted PPDU information function for STA 2
1845 * @param uid the UID of the transmitted PPDU
1846 */
1847 void TxPpduSta2(uint64_t uid);
1848 /**
1849 * Reset the global PPDU UID counter in WifiPhy
1850 */
1851 void ResetPpduUid();
1852
1853 /**
1854 * Send MU-PPDU toward both STAs.
1855 */
1856 void SendMuPpdu();
1857 /**
1858 * Send TB-PPDU from both STAs.
1859 */
1860 void SendTbPpdu();
1861 /**
1862 * Send SU-PPDU function
1863 * @param txStaId the ID of the sending STA
1864 */
1865 void SendSuPpdu(uint16_t txStaId);
1866
1867 /**
1868 * Check the UID of the transmitted PPDU
1869 * @param staId the STA-ID of the PHY (0 for AP)
1870 * @param expectedUid the expected UID
1871 */
1872 void CheckUid(uint16_t staId, uint64_t expectedUid);
1873
1877
1878 uint64_t m_ppduUidAp; ///< UID of PPDU transmitted by AP
1879 uint64_t m_ppduUidSta1; ///< UID of PPDU transmitted by STA1
1880 uint64_t m_ppduUidSta2; ///< UID of PPDU transmitted by STA2
1881};
1882
1884 : TestCase("UL-OFDMA PPDU UID attribution test"),
1885 m_ppduUidAp(UINT64_MAX),
1886 m_ppduUidSta1(UINT64_MAX),
1887 m_ppduUidSta2(UINT64_MAX)
1888{
1889}
1890
1894
1895void
1897{
1900 lossModel->SetFrequency(DEFAULT_FREQUENCY);
1901 spectrumChannel->AddPropagationLossModel(lossModel);
1904 spectrumChannel->SetPropagationDelayModel(delayModel);
1905
1906 Ptr<Node> apNode = CreateObject<Node>();
1910 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1912 m_phyAp->SetErrorRateModel(apErrorModel);
1913 m_phyAp->AddChannel(spectrumChannel);
1915 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
1920 ->number;
1923 m_phyAp->SetDevice(apDev);
1927 m_phyAp->SetMobility(apMobility);
1928 apDev->SetPhy(m_phyAp);
1929 apNode->AggregateObject(apMobility);
1930 apNode->AddDevice(apDev);
1931 apDev->SetStandard(WIFI_STANDARD_80211ax);
1932 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1933
1934 Ptr<Node> sta1Node = CreateObject<Node>();
1938 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1940 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1941 m_phySta1->AddChannel(spectrumChannel);
1945 m_phySta1->SetDevice(sta1Dev);
1949 m_phySta1->SetMobility(sta1Mobility);
1950 sta1Dev->SetPhy(m_phySta1);
1951 sta1Node->AggregateObject(sta1Mobility);
1952 sta1Node->AddDevice(sta1Dev);
1953
1954 Ptr<Node> sta2Node = CreateObject<Node>();
1958 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1960 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1961 m_phySta2->AddChannel(spectrumChannel);
1965 m_phySta2->SetDevice(sta2Dev);
1969 m_phySta2->SetMobility(sta2Mobility);
1970 sta2Dev->SetPhy(m_phySta2);
1971 sta2Node->AggregateObject(sta2Mobility);
1972 sta2Node->AddDevice(sta2Dev);
1973}
1974
1975void
1977{
1978 m_phyAp->Dispose();
1979 m_phyAp = nullptr;
1980 m_phySta1->Dispose();
1981 m_phySta1 = nullptr;
1982 m_phySta2->Dispose();
1983 m_phySta2 = nullptr;
1984}
1985
1986void
1987TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
1988{
1989 uint64_t uid;
1990 std::string device;
1991 switch (staId)
1992 {
1993 case 0:
1994 uid = m_ppduUidAp;
1995 device = "AP";
1996 break;
1997 case 1:
1998 uid = m_ppduUidSta1;
1999 device = "STA1";
2000 break;
2001 case 2:
2002 uid = m_ppduUidSta2;
2003 device = "STA2";
2004 break;
2005 default:
2006 NS_ABORT_MSG("Unexpected STA-ID");
2007 }
2009 expectedUid,
2010 "UID " << uid << " does not match expected one " << expectedUid << " for "
2011 << device << " at " << Simulator::Now());
2012}
2013
2014void
2016{
2017 NS_LOG_FUNCTION(this << uid);
2018 m_ppduUidAp = uid;
2019}
2020
2021void
2023{
2024 NS_LOG_FUNCTION(this << uid);
2025 m_ppduUidSta1 = uid;
2026}
2027
2028void
2030{
2031 NS_LOG_FUNCTION(this << uid);
2032 m_ppduUidSta2 = uid;
2033}
2034
2035void
2037{
2038 NS_LOG_FUNCTION(this);
2039 m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2040}
2041
2042void
2044{
2045 WifiConstPsduMap psdus;
2046 WifiTxVector txVector{HePhy::GetHeMcs7(),
2047 0,
2049 NanoSeconds(800),
2050 1,
2051 1,
2052 0,
2054 false,
2055 false};
2056
2057 uint16_t rxStaId1 = 1;
2058 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2059 txVector.SetRu(ru1, rxStaId1);
2060 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2061 txVector.SetNss(1, rxStaId1);
2062
2063 uint16_t rxStaId2 = 2;
2064 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2065 txVector.SetRu(ru2, rxStaId2);
2066 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2067 txVector.SetNss(1, rxStaId2);
2068 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2069 txVector.SetRuAllocation({96}, 0);
2070
2071 Ptr<Packet> pkt1 = Create<Packet>(1000);
2072 WifiMacHeader hdr1;
2074 hdr1.SetQosTid(0);
2075 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2076 hdr1.SetSequenceNumber(1);
2077 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2078 psdus.insert(std::make_pair(rxStaId1, psdu1));
2079
2080 Ptr<Packet> pkt2 = Create<Packet>(1500);
2081 WifiMacHeader hdr2;
2083 hdr2.SetQosTid(0);
2084 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2085 hdr2.SetSequenceNumber(2);
2086 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2087 psdus.insert(std::make_pair(rxStaId2, psdu2));
2088
2089 m_phyAp->Send(psdus, txVector);
2090}
2091
2092void
2094{
2095 WifiConstPsduMap psdus1;
2096 WifiConstPsduMap psdus2;
2097
2098 WifiTxVector txVector1{HePhy::GetHeMcs7(),
2099 0,
2101 NanoSeconds(1600),
2102 1,
2103 1,
2104 0,
2106 false,
2107 false};
2108 WifiTxVector txVector2{txVector1};
2109 WifiTxVector trigVector{txVector2};
2110
2111 uint16_t rxStaId1 = 1;
2112 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2113 txVector1.SetRu(ru1, rxStaId1);
2114 txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2115 txVector1.SetNss(1, rxStaId1);
2116 trigVector.SetRu(ru1, rxStaId1);
2117 trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2118 trigVector.SetNss(1, rxStaId1);
2119
2120 auto pkt1 = Create<Packet>(1000);
2121 WifiMacHeader hdr1;
2123 hdr1.SetQosTid(0);
2124 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2125 hdr1.SetSequenceNumber(1);
2126 auto psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2127 psdus1.insert(std::make_pair(rxStaId1, psdu1));
2128
2129 uint16_t rxStaId2 = 2;
2130 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, false);
2131 txVector2.SetRu(ru2, rxStaId2);
2132 txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2133 txVector2.SetNss(1, rxStaId2);
2134 trigVector.SetRu(ru2, rxStaId2);
2135 trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2136 trigVector.SetNss(1, rxStaId2);
2137
2138 auto pkt2 = Create<Packet>(1500);
2139 WifiMacHeader hdr2;
2141 hdr2.SetQosTid(0);
2142 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2143 hdr2.SetSequenceNumber(2);
2144 auto psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2145 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2146
2147 const auto txDuration1 = m_phySta1->CalculateTxDuration(psdu1->GetSize(),
2148 txVector1,
2150 rxStaId1);
2151 const auto txDuration2 = m_phySta2->CalculateTxDuration(psdu2->GetSize(),
2152 txVector2,
2154 rxStaId2);
2155 const auto txDuration = std::max(txDuration1, txDuration2);
2156
2157 txVector1.SetLength(
2159 .first);
2160 txVector2.SetLength(
2162 .first);
2163
2165 hePhyAp->SetTrigVector(trigVector, txDuration);
2166
2167 m_phySta1->Send(psdus1, txVector1);
2168 m_phySta2->Send(psdus2, txVector2);
2169}
2170
2171void
2173{
2174 WifiConstPsduMap psdus;
2175 WifiTxVector txVector{HePhy::GetHeMcs7(),
2176 0,
2178 NanoSeconds(800),
2179 1,
2180 1,
2181 0,
2183 false,
2184 false};
2185
2186 auto pkt = Create<Packet>(1000);
2187 WifiMacHeader hdr;
2189 hdr.SetQosTid(0);
2191 hdr.SetSequenceNumber(1);
2192 auto psdu = Create<WifiPsdu>(pkt, hdr);
2193 psdus.insert(std::make_pair(SU_STA_ID, psdu));
2194
2195 switch (txStaId)
2196 {
2197 case 0:
2198 m_phyAp->Send(psdus, txVector);
2199 break;
2200 case 1:
2201 m_phySta1->Send(psdus, txVector);
2202 break;
2203 case 2:
2204 m_phySta2->Send(psdus, txVector);
2205 break;
2206 default:
2207 NS_ABORT_MSG("Unexpected STA-ID");
2208 }
2209}
2210
2211void
2213{
2216 int64_t streamNumber = 0;
2217 m_phyAp->AssignStreams(streamNumber);
2218 m_phySta1->AssignStreams(streamNumber);
2219 m_phySta2->AssignStreams(streamNumber);
2220
2221 // Reset PPDU UID so as not to be dependent on previously executed test cases,
2222 // since global attribute will be changed).
2223 ResetPpduUid();
2224
2225 // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2226 // PPDU UID should be equal to 0 (the first counter value).
2229
2230 // Send HE SU PPDU from AP.
2231 // PPDU UID should be incremented since this is a new PPDU.
2234
2235 // Send HE TB PPDU from STAs to AP.
2236 // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2237 // preceding correctly received PPDU (which normally contains the trigger frame).
2241
2242 // Send HE SU PPDU from STA1.
2243 // PPDU UID should be incremented since this is a new PPDU.
2246
2249}
2250
2251/**
2252 * @ingroup wifi-test
2253 * @ingroup tests
2254 *
2255 * @brief UL-OFDMA multiple RX events test
2256 */
2258{
2259 public:
2261 ~TestMultipleHeTbPreambles() override;
2262
2263 private:
2264 void DoSetup() override;
2265 void DoTeardown() override;
2266 void DoRun() override;
2267
2268 /**
2269 * Receive HE TB PPDU function.
2270 *
2271 * @param uid the UID used to identify a set of HE TB PPDUs belonging to the same UL-MU
2272 * transmission
2273 * @param staId the STA ID
2274 * @param txPower the TX power
2275 * @param payloadSize the size of the payload in bytes
2276 */
2277 void RxHeTbPpdu(uint64_t uid, uint16_t staId, Watt_u txPower, size_t payloadSize);
2278
2279 /**
2280 * Receive OFDMA part of HE TB PPDU function.
2281 * Immediately schedules DoRxHeTbPpduOfdmaPart.
2282 *
2283 * @param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2284 */
2286 /**
2287 * Receive OFDMA part of HE TB PPDU function.
2288 * Actual reception call.
2289 *
2290 * @param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2291 */
2293
2294 /**
2295 * RX dropped function
2296 * @param p the packet
2297 * @param reason the reason
2298 */
2300
2301 /**
2302 * Reset function
2303 */
2304 void Reset();
2305
2306 /**
2307 * Check the received HE TB preambles
2308 * @param nEvents the number of events created by the PHY
2309 * @param uids the vector of expected UIDs
2310 */
2311 void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2312
2313 /**
2314 * Check the number of bytes dropped
2315 * @param expectedBytesDropped the expected number of bytes dropped
2316 */
2317 void CheckBytesDropped(size_t expectedBytesDropped);
2318
2320
2321 uint64_t m_totalBytesDropped; ///< total number of dropped bytes
2323};
2324
2326 : TestCase("UL-OFDMA multiple RX events test"),
2327 m_totalBytesDropped(0),
2328 m_trigVector(HePhy::GetHeMcs7(),
2329 0,
2331 NanoSeconds(1600),
2332 1,
2333 1,
2334 0,
2336 false,
2337 false)
2338{
2339}
2340
2344
2345void
2347{
2348 NS_LOG_FUNCTION(this);
2350 // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2351 m_phy->Reset();
2353}
2354
2355void
2357{
2358 NS_LOG_FUNCTION(this << p << reason);
2359 m_totalBytesDropped += (p->GetSize() - 30);
2360}
2361
2362void
2363TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2364{
2365 auto events = m_phy->GetCurrentPreambleEvents();
2366 NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2367 for (const auto& uid : uids)
2368 {
2369 auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2370 auto it = events.find(pair);
2371 bool found = (it != events.end());
2373 true,
2374 "HE TB PPDU with UID " << uid << " has not been received!");
2375 }
2376}
2377
2378void
2380{
2382 expectedBytesDropped,
2383 "The number of dropped bytes is not correct!");
2384}
2385
2386void
2388 uint16_t staId,
2389 Watt_u txPower,
2390 size_t payloadSize)
2391{
2392 WifiConstPsduMap psdus;
2393 WifiTxVector txVector{HePhy::GetHeMcs7(),
2394 0,
2396 NanoSeconds(1600),
2397 1,
2398 1,
2399 0,
2401 false,
2402 false};
2403
2404 HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2405 txVector.SetRu(ru, staId);
2406 txVector.SetMode(HePhy::GetHeMcs7(), staId);
2407 txVector.SetNss(1, staId);
2408
2409 m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2410
2411 auto pkt = Create<Packet>(payloadSize);
2412 WifiMacHeader hdr;
2414 hdr.SetQosTid(0);
2415 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2416 hdr.SetSequenceNumber(1);
2417 auto psdu = Create<WifiPsdu>(pkt, hdr);
2418 psdus.insert(std::make_pair(staId, psdu));
2419
2420 auto ppduDuration =
2421 m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand(), staId);
2422 auto ppdu = Create<HePpdu>(psdus,
2423 txVector,
2425 ppduDuration,
2426 uid,
2428
2429 // Send non-OFDMA part
2430 const auto nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonHeDurationForHeTb(txVector);
2431 const auto centerFrequency =
2432 m_phy->GetHePhy()->GetCenterFrequenciesForNonHePart(ppdu, staId).front();
2433 MHz_u ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2434 MHz_u channelWidth = ruWidth < MHz_u{20} ? MHz_u{20} : ruWidth;
2436 centerFrequency,
2437 channelWidth,
2438 txPower,
2439 m_phy->GetGuardBandwidth(channelWidth));
2440 auto rxParams = Create<WifiSpectrumSignalParameters>();
2441 rxParams->psd = rxPsd;
2442 rxParams->txPhy = nullptr;
2443 rxParams->duration = nonOfdmaDuration;
2444 rxParams->ppdu = ppdu;
2445
2446 uint16_t length;
2447 std::tie(length, ppduDuration) =
2449 txVector.SetLength(length);
2450 m_trigVector.SetLength(length);
2452 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2453 ppdu->ResetTxVector();
2454 m_phy->StartRx(rxParams, nullptr);
2455
2456 // Schedule OFDMA part
2457 auto ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2458 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2459 const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2460 auto rxPsdOfdma =
2463 txPower,
2465 band.indices);
2466 auto rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2467 rxParamsOfdma->psd = rxPsd;
2468 rxParamsOfdma->txPhy = nullptr;
2469 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2470 rxParamsOfdma->ppdu = ppduOfdma;
2471 Simulator::Schedule(nonOfdmaDuration,
2473 this,
2474 rxParamsOfdma);
2475}
2476
2477void
2482
2483void
2485{
2486 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2487 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2488 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2489 m_phy->StartRx(rxParamsOfdma, nullptr);
2490}
2491
2492void
2494{
2498 dev->SetStandard(WIFI_STANDARD_80211ax);
2503 "Txop",
2504 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
2505 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2506 dev->SetMac(mac);
2507 m_phy->SetInterferenceHelper(interferenceHelper);
2508 m_phy->SetErrorRateModel(error);
2509 m_phy->AddChannel(spectrumChannel);
2514 0});
2515 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2517 m_phy->SetDevice(dev);
2518 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2520 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2521 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2522 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2524 heConfiguration->m_maxTbPpduDelay = NanoSeconds(400);
2525 dev->SetHeConfiguration(heConfiguration);
2526 dev->SetPhy(m_phy);
2527 node->AddDevice(dev);
2528}
2529
2530void
2532{
2533 m_phy->Dispose();
2534 m_phy = nullptr;
2535}
2536
2537void
2539{
2542 int64_t streamNumber = 0;
2543 m_phy->AssignStreams(streamNumber);
2544
2545 Watt_u txPower{0.01};
2546
2547 {
2548 // Verify a single UL MU transmission with two stations belonging to the same BSS
2549 std::vector<uint64_t> uids{0};
2552 this,
2553 uids[0],
2554 1,
2555 txPower,
2556 1001);
2559 this,
2560 uids[0],
2561 2,
2562 txPower,
2563 1002);
2564 // Check that we received a single UL MU transmission with the corresponding UID
2567 this,
2568 1,
2569 uids);
2571 }
2572
2573 {
2574 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2575 // the second transmission arrives during the preamble detection window and with half the
2576 // power of the first transmission.
2577 std::vector<uint64_t> uids{1, 2};
2580 this,
2581 uids[0],
2582 1,
2583 txPower,
2584 1001);
2587 this,
2588 uids[0],
2589 2,
2590 txPower,
2591 1002);
2594 this,
2595 uids[1],
2596 1,
2597 txPower / 2,
2598 1003);
2601 this,
2602 uids[1],
2603 2,
2604 txPower / 2,
2605 1004);
2606 // Check that we received the correct reception of 2 UL MU transmissions with the
2607 // corresponding UIDs
2610 this,
2611 2,
2612 uids);
2614 // TODO: verify PPDUs from second UL MU transmission are dropped
2615 }
2616
2617 {
2618 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2619 // the second transmission arrives during the preamble detection window and with twice the
2620 // power of the first transmission.
2621 std::vector<uint64_t> uids{3, 4};
2624 this,
2625 uids[0],
2626 1,
2627 txPower / 2,
2628 1001);
2631 this,
2632 uids[0],
2633 2,
2634 txPower / 2,
2635 1002);
2638 this,
2639 uids[1],
2640 1,
2641 txPower,
2642 1003);
2645 this,
2646 uids[1],
2647 2,
2648 txPower,
2649 1004);
2650 // Check that we received the correct reception of 2 UL MU transmissions with the
2651 // corresponding UIDs
2654 this,
2655 2,
2656 uids);
2658 // TODO: verify PPDUs from first UL MU transmission are dropped
2659 }
2660
2661 {
2662 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2663 // the second transmission arrives during PHY header reception and with the same power as
2664 // the first transmission.
2665 std::vector<uint64_t> uids{5, 6};
2668 this,
2669 uids[0],
2670 1,
2671 txPower,
2672 1001);
2675 this,
2676 uids[0],
2677 2,
2678 txPower,
2679 1002);
2682 this,
2683 uids[1],
2684 1,
2685 txPower,
2686 1003);
2689 this,
2690 uids[1],
2691 2,
2692 txPower,
2693 1004);
2694 // Check that we received the correct reception of the first UL MU transmission with the
2695 // corresponding UID (second one dropped)
2698 this,
2699 1,
2700 std::vector<uint64_t>{uids[0]});
2701 // The packets of the second UL MU transmission should have been dropped
2704 this,
2705 1003 + 1004);
2707 }
2708
2709 {
2710 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2711 // BSS, where the second transmission arrives during payload reception and with the same
2712 // power as the first transmission.
2713 std::vector<uint64_t> uids{7, 8};
2716 this,
2717 uids[0],
2718 1,
2719 txPower,
2720 1001);
2723 this,
2724 uids[0],
2725 2,
2726 txPower,
2727 1002);
2730 this,
2731 uids[1],
2732 1,
2733 txPower,
2734 1003);
2737 this,
2738 uids[1],
2739 2,
2740 txPower,
2741 1004);
2742 // Check that we received the correct reception of the first UL MU transmission with the
2743 // corresponding UID (second one dropped)
2746 this,
2747 1,
2748 std::vector<uint64_t>{uids[0]});
2749 // The packets of the second UL MU transmission should have been dropped
2752 this,
2753 1003 + 1004);
2755 }
2756
2757 {
2758 // Verify the correct reception of a single UL MU transmission with two stations belonging
2759 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2760 // the configured delay spread of 400ns
2761 std::vector<uint64_t> uids{9};
2764 this,
2765 uids[0],
2766 1,
2767 txPower,
2768 1001);
2771 this,
2772 uids[0],
2773 2,
2774 txPower,
2775 1002);
2776 // Check that we received a single UL MU transmission with the corresponding UID
2779 this,
2780 1,
2781 uids);
2782 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2783 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2784 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2785 // second packet of 1002 bytes is dropped as well.
2788 this,
2789 1001 + 1002);
2791 }
2792
2795}
2796
2797/**
2798 * @ingroup wifi-test
2799 * @ingroup tests
2800 *
2801 * @brief PHY listener for OFDMA tests
2802 */
2804{
2805 public:
2807
2808 void NotifyRxStart(Time duration) override
2809 {
2810 NS_LOG_FUNCTION(this << duration);
2813 m_lastRxSuccess = false;
2814 }
2815
2816 void NotifyRxEndOk() override
2817 {
2818 NS_LOG_FUNCTION(this);
2820 ++m_notifyRxEnd;
2821 m_lastRxSuccess = true;
2822 }
2823
2824 void NotifyRxEndError() override
2825 {
2826 NS_LOG_FUNCTION(this);
2828 ++m_notifyRxEnd;
2829 m_lastRxSuccess = false;
2830 }
2831
2832 void NotifyTxStart(Time duration, dBm_u txPower) override
2833 {
2834 NS_LOG_FUNCTION(this << duration << txPower);
2835 }
2836
2838 WifiChannelListType channelType,
2839 const std::vector<Time>& /*per20MhzDurations*/) override
2840 {
2841 NS_LOG_FUNCTION(this << duration << channelType);
2842 }
2843
2844 void NotifySwitchingStart(Time duration) override
2845 {
2846 }
2847
2848 void NotifySleep() override
2849 {
2850 }
2851
2852 void NotifyOff() override
2853 {
2854 }
2855
2856 void NotifyWakeup() override
2857 {
2858 }
2859
2860 void NotifyOn() override
2861 {
2862 }
2863
2864 /**
2865 * Reset function.
2866 */
2867 void Reset()
2868 {
2869 m_notifyRxStart = 0;
2870 m_notifyRxEnd = 0;
2872 m_lastRxEnd = Seconds(0);
2873 m_lastRxSuccess = false;
2874 }
2875
2876 /**
2877 * Return the number of RX start notifications that has been received since the last reset.
2878 * @return the number of RX start notifications that has been received
2879 */
2881 {
2882 return m_notifyRxStart;
2883 }
2884
2885 /**
2886 * Return the number of RX end notifications that has been received since the last reset.
2887 * @return the number of RX end notifications that has been received
2888 */
2890 {
2891 return m_notifyRxEnd;
2892 }
2893
2894 /**
2895 * Return the time at which the last RX start notification has been received.
2896 * @return the time at which the last RX start notification has been received
2897 */
2899 {
2900 return m_lastRxStart;
2901 }
2902
2903 /**
2904 * Return the time at which the last RX end notification has been received.
2905 * @return the time at which the last RX end notification has been received
2906 */
2908 {
2909 return m_lastRxEnd;
2910 }
2911
2912 /**
2913 * Return whether last RX has been successful.
2914 * @return true if last RX has been successful, false otherwise
2915 */
2916 bool IsLastRxSuccess() const
2917 {
2918 return m_lastRxSuccess;
2919 }
2920
2921 private:
2922 uint32_t m_notifyRxStart{0}; ///< count number of RX start notifications
2923 uint32_t m_notifyRxEnd{0}; ///< count number of RX end notifications
2924 Time m_lastRxStart{Seconds(0)}; ///< last time a RX start notification has been received
2925 Time m_lastRxEnd{Seconds(0)}; ///< last time a RX end notification has been received
2926 bool m_lastRxSuccess{false}; ///< flag whether last RX has been successful
2927};
2928
2929/**
2930 * @ingroup wifi-test
2931 * @ingroup tests
2932 *
2933 * @brief UL-OFDMA PHY test
2934 */
2936{
2937 public:
2938 /**
2939 * Erroneous info included in a TRIGVECTOR
2940 */
2948
2950 ~TestUlOfdmaPhyTransmission() override;
2951
2952 private:
2953 void DoSetup() override;
2954 void DoTeardown() override;
2955 void DoRun() override;
2956
2957 /**
2958 * Get TXVECTOR for HE TB PPDU.
2959 * @param txStaId the ID of the TX STA
2960 * @param index the RU index used for the transmission
2961 * @param bssColor the BSS color of the TX STA
2962 * @return the TXVECTOR for HE TB PPDU
2963 */
2964 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2965 std::size_t index,
2966 uint8_t bssColor) const;
2967 /**
2968 * Set TRIGVECTOR for HE TB PPDU
2969 *
2970 * @param bssColor the BSS color of the TX STA
2971 * @param error the erroneous info (if any) in the TRIGVECTOR to set
2972 */
2973 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2974 /**
2975 * Send HE TB PPDU function
2976 * @param txStaId the ID of the TX STA
2977 * @param index the RU index used for the transmission
2978 * @param payloadSize the size of the payload in bytes
2979 * @param uid the UID of the trigger frame that is initiating this transmission
2980 * @param bssColor the BSS color of the TX STA
2981 * @param incrementUid whether UID shall be incremented
2982 */
2983 void SendHeTbPpdu(uint16_t txStaId,
2984 std::size_t index,
2985 std::size_t payloadSize,
2986 uint64_t uid,
2987 uint8_t bssColor,
2988 bool incrementUid);
2989
2990 /**
2991 * Send HE SU PPDU function
2992 * @param txStaId the ID of the TX STA
2993 * @param payloadSize the size of the payload in bytes
2994 * @param uid the UID of the trigger frame that is initiating this transmission
2995 * @param bssColor the BSS color of the TX STA
2996 */
2997 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
2998
2999 /**
3000 * Set the BSS color
3001 * @param phy the PHY
3002 * @param bssColor the BSS color
3003 */
3004 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3005
3006 /**
3007 * Set the PSD limit
3008 * @param phy the PHY
3009 * @param psdLimit the PSD limit
3010 */
3011 void SetPsdLimit(Ptr<WifiPhy> phy, dBm_per_MHz_u psdLimit);
3012
3013 /**
3014 * Generate interference function
3015 * @param interferencePsd the PSD of the interference to be generated
3016 * @param duration the duration of the interference
3017 */
3018 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3019 /**
3020 * Stop interference function
3021 */
3022 void StopInterference();
3023
3024 /**
3025 * Run one function
3026 */
3027 void RunOne();
3028
3029 /**
3030 * Check the received PSDUs from STA1
3031 * @param expectedSuccess the expected number of success
3032 * @param expectedFailures the expected number of failures
3033 * @param expectedBytes the expected number of bytes
3034 */
3035 void CheckRxFromSta1(uint32_t expectedSuccess,
3036 uint32_t expectedFailures,
3037 uint32_t expectedBytes);
3038
3039 /**
3040 * Check the received PSDUs from STA2
3041 * @param expectedSuccess the expected number of success
3042 * @param expectedFailures the expected number of failures
3043 * @param expectedBytes the expected number of bytes
3044 */
3045 void CheckRxFromSta2(uint32_t expectedSuccess,
3046 uint32_t expectedFailures,
3047 uint32_t expectedBytes);
3048
3049 /**
3050 * Check the received power for the non-OFDMA of the HE TB PPDUs over the given band
3051 * @param phy the PHY
3052 * @param band the indices of the band over which the power is measured
3053 * @param expectedRxPower the expected received power
3054 */
3057 Watt_u expectedRxPower);
3058 /**
3059 * Check the received power for the OFDMA part of the HE TB PPDUs over the given band
3060 * @param phy the PHY
3061 * @param band the indices of the band over which the power is measured
3062 * @param expectedRxPower the expected received power
3063 */
3066 Watt_u expectedRxPower);
3067
3068 /**
3069 * Verify all events are cleared at end of TX or RX
3070 */
3071 void VerifyEventsCleared();
3072
3073 /**
3074 * Check the PHY state
3075 * @param phy the PHY
3076 * @param expectedState the expected state of the PHY
3077 */
3078 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
3079 /// @copydoc CheckPhyState
3081
3082 /**
3083 * Check the the number of RX start notifications at the AP as well as the last time a RX start
3084 * has been notified
3085 * @param expectedNotifications the expected number of RX start notifications at the AP
3086 * @param expectedLastNotification the expected time of the last RX start notification at the AP
3087 */
3088 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3089 /**
3090 * Check the the number of RX end notifications at the AP as well as the last time a RX end has
3091 * been notified
3092 * @param expectedNotifications the expected number of RX end notifications at the AP
3093 * @param expectedLastNotification the expected time of the last RX end notification at the AP
3094 * @param expectedSuccess true if the last RX notification indicates a success, false otherwise
3095 */
3096 void CheckApRxEnd(uint32_t expectedNotifications,
3097 Time expectedLastNotification,
3098 bool expectedSuccess);
3099
3100 /**
3101 * Reset function
3102 */
3103 void Reset();
3104
3105 /**
3106 * Receive success function
3107 * @param psdu the PSDU
3108 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
3109 * @param txVector the transmit vector
3110 * @param statusPerMpdu reception status per MPDU
3111 */
3113 RxSignalInfo rxSignalInfo,
3114 const WifiTxVector& txVector,
3115 const std::vector<bool>& statusPerMpdu);
3116
3117 /**
3118 * Receive failure function
3119 * @param psdu the PSDU
3120 */
3121 void RxFailure(Ptr<const WifiPsdu> psdu);
3122
3123 /**
3124 * Schedule test to perform.
3125 * The interference generation should be scheduled apart.
3126 *
3127 * @param delay the reference delay to schedule the events
3128 * @param solicited flag indicating if HE TB PPDUs were solicited by the AP
3129 * @param expectedStateAtEnd the expected state of the PHY at the end of the reception
3130 * @param expectedSuccessFromSta1 the expected number of success from STA 1
3131 * @param expectedFailuresFromSta1 the expected number of failures from STA 1
3132 * @param expectedBytesFromSta1 the expected number of bytes from STA 1
3133 * @param expectedSuccessFromSta2 the expected number of success from STA 2
3134 * @param expectedFailuresFromSta2 the expected number of failures from STA 2
3135 * @param expectedBytesFromSta2 the expected number of bytes from STA 2
3136 * @param scheduleTxSta1 flag indicating to schedule a HE TB PPDU from STA 1
3137 * @param ulTimeDifference delay between HE TB PPDU from STA 1 and HE TB PPDU from STA 2
3138 * are received
3139 * @param expectedStateBeforeEnd the expected state of the PHY before the end of the
3140 * transmission
3141 * @param error the erroneous info (if any) in the TRIGVECTOR to set
3142 */
3143 void ScheduleTest(Time delay,
3144 bool solicited,
3145 WifiPhyState expectedStateAtEnd,
3146 uint32_t expectedSuccessFromSta1,
3147 uint32_t expectedFailuresFromSta1,
3148 uint32_t expectedBytesFromSta1,
3149 uint32_t expectedSuccessFromSta2,
3150 uint32_t expectedFailuresFromSta2,
3151 uint32_t expectedBytesFromSta2,
3152 bool scheduleTxSta1 = true,
3153 Time ulTimeDifference = Seconds(0),
3154 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3155 TrigVectorInfo error = NONE);
3156
3157 /**
3158 * Schedule power measurement related checks.
3159 *
3160 * @param delay the reference delay used to schedule the events
3161 * @param rxPowerNonOfdmaRu1 the received power on the non-OFDMA part of RU1
3162 * @param rxPowerNonOfdmaRu2 the received power on the non-OFDMA part of RU2
3163 * @param rxPowerOfdmaRu1 the received power on RU1
3164 * @param rxPowerOfdmaRu2 the received power on RU2
3165 */
3167 Watt_u rxPowerNonOfdmaRu1,
3168 Watt_u rxPowerNonOfdmaRu2,
3169 Watt_u rxPowerOfdmaRu1,
3170 Watt_u rxPowerOfdmaRu2);
3171 /**
3172 * Log scenario description
3173 *
3174 * @param log the scenario description to add to log
3175 */
3176 void LogScenario(std::string log) const;
3177
3182
3183 std::shared_ptr<OfdmaTestPhyListener>
3184 m_apPhyStateListener; ///< listener for AP PHY state transitions
3185
3187
3188 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
3189 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
3190 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
3191 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
3192 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
3193 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
3194
3195 MHz_u m_frequency; ///< frequency
3196 MHz_u m_channelWidth; ///< channel width
3197 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
3198};
3199
3201 : TestCase("UL-OFDMA PHY test"),
3202 m_countRxSuccessFromSta1(0),
3203 m_countRxSuccessFromSta2(0),
3204 m_countRxFailureFromSta1(0),
3205 m_countRxFailureFromSta2(0),
3206 m_countRxBytesFromSta1(0),
3207 m_countRxBytesFromSta2(0),
3208 m_frequency(DEFAULT_FREQUENCY),
3209 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3210 m_expectedPpduDuration(NanoSeconds(271200))
3211{
3212}
3213
3214void
3216 std::size_t payloadSize,
3217 uint64_t uid,
3218 uint8_t bssColor)
3219{
3220 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3221 WifiConstPsduMap psdus;
3222
3223 WifiTxVector txVector{HePhy::GetHeMcs7(),
3224 0,
3226 NanoSeconds(800),
3227 1,
3228 1,
3229 0,
3231 false,
3232 false,
3233 false,
3234 bssColor};
3235
3236 auto pkt = Create<Packet>(payloadSize);
3237 WifiMacHeader hdr;
3239 hdr.SetQosTid(0);
3240 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3241 std::ostringstream addr;
3242 addr << "00:00:00:00:00:0" << txStaId;
3243 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3244 hdr.SetSequenceNumber(1);
3245 auto psdu = Create<WifiPsdu>(pkt, hdr);
3246 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3247
3249 if (txStaId == 1)
3250 {
3251 phy = m_phySta1;
3252 }
3253 else if (txStaId == 2)
3254 {
3255 phy = m_phySta2;
3256 }
3257 else if (txStaId == 3)
3258 {
3259 phy = m_phySta3;
3260 }
3261 else if (txStaId == 0)
3262 {
3263 phy = m_phyAp;
3264 }
3265 phy->SetPpduUid(uid);
3266 phy->Send(psdus, txVector);
3267}
3268
3271 std::size_t index,
3272 uint8_t bssColor) const
3273{
3274 WifiTxVector txVector{HePhy::GetHeMcs7(),
3275 0,
3277 NanoSeconds(1600),
3278 1,
3279 1,
3280 0,
3282 false,
3283 false,
3284 false,
3285 bssColor};
3286
3287 auto ruType = HeRu::RU_106_TONE;
3288 if (m_channelWidth == MHz_u{20})
3289 {
3290 ruType = HeRu::RU_106_TONE;
3291 }
3292 else if (m_channelWidth == MHz_u{40})
3293 {
3294 ruType = HeRu::RU_242_TONE;
3295 }
3296 else if (m_channelWidth == MHz_u{80})
3297 {
3298 ruType = HeRu::RU_484_TONE;
3299 }
3300 else if (m_channelWidth == MHz_u{160})
3301 {
3302 ruType = HeRu::RU_996_TONE;
3303 }
3304 else
3305 {
3306 NS_ASSERT_MSG(false, "Unsupported channel width");
3307 }
3308
3309 auto primary80MHz = true;
3310 if (m_channelWidth == MHz_u{160} && index == 2)
3311 {
3312 primary80MHz = false;
3313 index = 1;
3314 }
3315 HeRu::RuSpec ru(ruType, index, primary80MHz);
3316 txVector.SetRu(ru, txStaId);
3317 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3318 txVector.SetNss(1, txStaId);
3319 return txVector;
3320}
3321
3322void
3324{
3325 auto channelWidth = m_channelWidth;
3326 if (error == CHANNEL_WIDTH)
3327 {
3328 channelWidth = (channelWidth == MHz_u{160} ? MHz_u{20} : channelWidth * 2);
3329 }
3330
3331 WifiTxVector txVector(HePhy::GetHeMcs7(),
3332 0,
3334 NanoSeconds(1600),
3335 1,
3336 1,
3337 0,
3338 channelWidth,
3339 false,
3340 false,
3341 false,
3342 bssColor);
3343
3345 if (channelWidth == MHz_u{20})
3346 {
3347 ruType = HeRu::RU_106_TONE;
3348 }
3349 else if (channelWidth == MHz_u{40})
3350 {
3351 ruType = HeRu::RU_242_TONE;
3352 }
3353 else if (channelWidth == MHz_u{80})
3354 {
3355 ruType = HeRu::RU_484_TONE;
3356 }
3357 else if (channelWidth == MHz_u{160})
3358 {
3359 ruType = HeRu::RU_996_TONE;
3360 }
3361 else
3362 {
3363 NS_ASSERT_MSG(false, "Unsupported channel width");
3364 }
3365
3366 uint16_t aid1 = (error == AID ? 3 : 1);
3367 uint16_t aid2 = (error == AID ? 4 : 2);
3368
3369 HeRu::RuSpec ru1(ruType, 1, true);
3370 txVector.SetRu(ru1, aid1);
3371 txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3372 txVector.SetNss(1, aid1);
3373
3374 HeRu::RuSpec ru2(ruType, (channelWidth == MHz_u{160} ? 1 : 2), (channelWidth != MHz_u{160}));
3375 txVector.SetRu(ru2, aid2);
3376 txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3377 txVector.SetNss(1, aid2);
3378
3379 uint16_t length;
3380 std::tie(length, m_expectedPpduDuration) =
3382 txVector,
3383 m_phyAp->GetPhyBand());
3384 if (error == UL_LENGTH)
3385 {
3386 ++length;
3387 }
3388 txVector.SetLength(length);
3390 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3391}
3392
3393void
3395 std::size_t index,
3396 std::size_t payloadSize,
3397 uint64_t uid,
3398 uint8_t bssColor,
3399 bool incrementUid)
3400{
3401 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3402 WifiConstPsduMap psdus;
3403
3404 if (incrementUid)
3405 {
3406 ++uid;
3407 }
3408
3409 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3410 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3411 WifiMacHeader hdr;
3413 hdr.SetQosTid(0);
3414 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3415 std::ostringstream addr;
3416 addr << "00:00:00:00:00:0" << txStaId;
3417 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3418 hdr.SetSequenceNumber(1);
3419 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3420 psdus.insert(std::make_pair(txStaId, psdu));
3421
3423 if (txStaId == 1)
3424 {
3425 phy = m_phySta1;
3426 }
3427 else if (txStaId == 2)
3428 {
3429 phy = m_phySta2;
3430 }
3431 else if (txStaId == 3)
3432 {
3433 phy = m_phySta3;
3434 }
3435
3436 Time txDuration =
3437 phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
3438 txVector.SetLength(
3439 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3440
3441 phy->SetPpduUid(uid);
3442 phy->Send(psdus, txVector);
3443}
3444
3445void
3447{
3448 NS_LOG_FUNCTION(this << duration);
3449 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
3450 m_phyInterferer->SetPeriod(duration);
3451 m_phyInterferer->Start();
3453}
3454
3455void
3460
3464
3465void
3467 RxSignalInfo rxSignalInfo,
3468 const WifiTxVector& txVector,
3469 const std::vector<bool>& /*statusPerMpdu*/)
3470{
3471 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3472 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3473 {
3475 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3476 }
3477 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3478 {
3480 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3481 }
3482}
3483
3484void
3486{
3487 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3488 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3489 {
3491 }
3492 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3493 {
3495 }
3496}
3497
3498void
3500 uint32_t expectedFailures,
3501 uint32_t expectedBytes)
3502{
3504 expectedSuccess,
3505 "The number of successfully received packets from STA 1 is not correct!");
3508 expectedFailures,
3509 "The number of unsuccessfuly received packets from STA 1 is not correct!");
3511 expectedBytes,
3512 "The number of bytes received from STA 1 is not correct!");
3513}
3514
3515void
3517 uint32_t expectedFailures,
3518 uint32_t expectedBytes)
3519{
3521 expectedSuccess,
3522 "The number of successfully received packets from STA 2 is not correct!");
3525 expectedFailures,
3526 "The number of unsuccessfuly received packets from STA 2 is not correct!");
3528 expectedBytes,
3529 "The number of bytes received from STA 2 is not correct!");
3530}
3531
3532void
3535 Watt_u expectedRxPower)
3536{
3537 auto event = phy->GetCurrentEvent();
3538 NS_ASSERT(event);
3539 auto rxPower = event->GetRxPower(band);
3540 NS_LOG_FUNCTION(this << band << expectedRxPower << rxPower);
3541 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3543 expectedRxPower,
3544 Watt_u{5e-3},
3545 "RX power " << rxPower << " over (" << band
3546 << ") does not match expected power " << expectedRxPower
3547 << " at " << Simulator::Now());
3548}
3549
3550void
3553 Watt_u expectedRxPower)
3554{
3555 /**
3556 * The current event cannot be used since it points to the preamble part of the HE TB PPDU.
3557 * We will have to check if the expected power is indeed the max power returning a positive
3558 * duration when calling GetEnergyDuration.
3559 */
3560 NS_LOG_FUNCTION(this << band << expectedRxPower);
3561 Watt_u step{5e-3};
3562 if (expectedRxPower > Watt_u{0.0})
3563 {
3565 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3566 true,
3567 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3568 << Simulator::Now());
3570 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3571 false,
3572 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3573 << Simulator::Now());
3574 }
3575 else
3576 {
3578 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3579 false,
3580 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3581 << Simulator::Now());
3582 }
3583}
3584
3585void
3587{
3589 nullptr,
3590 "m_currentEvent for AP was not cleared");
3592 nullptr,
3593 "m_currentEvent for STA 1 was not cleared");
3595 nullptr,
3596 "m_currentEvent for STA 2 was not cleared");
3597}
3598
3599void
3601{
3602 // This is needed to make sure PHY state will be checked as the last event if a state change
3603 // occurred at the exact same time as the check
3605}
3606
3607void
3609 WifiPhyState expectedState)
3610{
3611 WifiPhyState currentState;
3612 PointerValue ptr;
3613 phy->GetAttribute("State", ptr);
3615 currentState = state->GetState();
3616 NS_LOG_FUNCTION(this << currentState);
3617 NS_TEST_ASSERT_MSG_EQ(currentState,
3618 expectedState,
3619 "PHY State " << currentState << " does not match expected state "
3620 << expectedState << " at " << Simulator::Now());
3621}
3622
3623void
3625 Time expectedLastNotification)
3626{
3628 expectedNotifications,
3629 "Number of RX start notifications "
3631 << " does not match expected count " << expectedNotifications
3632 << " for AP at " << Simulator::Now());
3634 expectedLastNotification,
3635 "Last time RX start notification has been received "
3637 << " does not match expected time " << expectedLastNotification
3638 << " for AP at " << Simulator::Now());
3639}
3640
3641void
3643 Time expectedLastNotification,
3644 bool expectedSuccess)
3645{
3647 expectedNotifications,
3648 "Number of RX end notifications "
3650 << " does not match expected count " << expectedNotifications
3651 << " for AP at " << Simulator::Now());
3653 expectedLastNotification,
3654 "Last time RX end notification has been received "
3656 << " does not match expected time " << expectedLastNotification
3657 << " for AP at " << Simulator::Now());
3659 expectedSuccess,
3660 "Last time RX end notification indicated a "
3661 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3662 << " but expected a " << (expectedSuccess ? "success" : "failure")
3663 << " for AP at " << Simulator::Now());
3664}
3665
3666void
3681
3682void
3684{
3685 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3686 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3687 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3688}
3689
3690void
3692{
3693 NS_LOG_FUNCTION(this << phy << psdLimit);
3694 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3695}
3696
3697void
3699{
3702 lossModel->SetFrequency(m_frequency);
3703 spectrumChannel->AddPropagationLossModel(lossModel);
3706 spectrumChannel->SetPropagationDelayModel(delayModel);
3707
3708 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3710 preambleDetectionModel->SetAttribute(
3711 "MinimumRssi",
3713 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3714 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3715
3716 Ptr<Node> apNode = CreateObject<Node>();
3718 apDev->SetStandard(WIFI_STANDARD_80211ax);
3720 "Txop",
3721 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
3722 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3723 apDev->SetMac(apMac);
3726 apDev->SetHeConfiguration(heConfiguration);
3728 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3730 m_phyAp->SetErrorRateModel(apErrorModel);
3731 m_phyAp->SetDevice(apDev);
3732 m_phyAp->AddChannel(spectrumChannel);
3736 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3738 m_phyAp->SetMobility(apMobility);
3739 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3741 apDev->SetPhy(m_phyAp);
3742 apMac->SetWifiPhys({m_phyAp});
3743 apNode->AggregateObject(apMobility);
3744 apNode->AddDevice(apDev);
3745
3746 Ptr<Node> sta1Node = CreateObject<Node>();
3748 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
3749 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3752 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3754 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3755 m_phySta1->SetDevice(sta1Dev);
3756 m_phySta1->AddChannel(spectrumChannel);
3758 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3760 m_phySta1->SetMobility(sta1Mobility);
3761 sta1Dev->SetPhy(m_phySta1);
3762 sta1Node->AggregateObject(sta1Mobility);
3763 sta1Node->AddDevice(sta1Dev);
3764
3765 Ptr<Node> sta2Node = CreateObject<Node>();
3767 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
3768 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3771 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3773 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3774 m_phySta2->SetDevice(sta2Dev);
3775 m_phySta2->AddChannel(spectrumChannel);
3777 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3779 m_phySta2->SetMobility(sta2Mobility);
3780 sta2Dev->SetPhy(m_phySta2);
3781 sta2Node->AggregateObject(sta2Mobility);
3782 sta2Node->AddDevice(sta2Dev);
3783
3784 Ptr<Node> sta3Node = CreateObject<Node>();
3786 sta3Dev->SetStandard(WIFI_STANDARD_80211ax);
3787 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3790 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3792 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3793 m_phySta3->SetDevice(sta3Dev);
3794 m_phySta3->AddChannel(spectrumChannel);
3796 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3798 m_phySta3->SetMobility(sta3Mobility);
3799 sta3Dev->SetPhy(m_phySta3);
3800 sta3Node->AggregateObject(sta3Mobility);
3801 sta3Node->AddDevice(sta3Dev);
3802
3803 Ptr<Node> interfererNode = CreateObject<Node>();
3806 m_phyInterferer->SetDevice(interfererDev);
3807 m_phyInterferer->SetChannel(spectrumChannel);
3808 m_phyInterferer->SetDutyCycle(1);
3809 interfererNode->AddDevice(interfererDev);
3810
3811 // Configure power attributes of all wifi devices
3812 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3813 for (auto& phy : phys)
3814 {
3815 phy->SetAttribute("TxGain", DoubleValue(1.0));
3816 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3817 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3818 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3819 phy->SetAttribute("RxGain", DoubleValue(2.0));
3820 // test assumes no rejection power for simplicity
3821 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3822 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3823 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3824 }
3825}
3826
3827void
3829{
3830 m_phyAp->Dispose();
3831 m_phyAp = nullptr;
3832 m_phySta1->Dispose();
3833 m_phySta1 = nullptr;
3834 m_phySta2->Dispose();
3835 m_phySta2 = nullptr;
3836 m_phySta3->Dispose();
3837 m_phySta3 = nullptr;
3839 m_phyInterferer = nullptr;
3840}
3841
3842void
3844{
3845 NS_LOG_INFO(log);
3846}
3847
3848void
3850 bool solicited,
3851 WifiPhyState expectedStateAtEnd,
3852 uint32_t expectedSuccessFromSta1,
3853 uint32_t expectedFailuresFromSta1,
3854 uint32_t expectedBytesFromSta1,
3855 uint32_t expectedSuccessFromSta2,
3856 uint32_t expectedFailuresFromSta2,
3857 uint32_t expectedBytesFromSta2,
3858 bool scheduleTxSta1,
3859 Time ulTimeDifference,
3860 WifiPhyState expectedStateBeforeEnd,
3861 TrigVectorInfo error)
3862{
3863 static uint64_t uid = 0;
3864
3865 // AP sends an SU packet preceding HE TB PPDUs
3868 this,
3869 0,
3870 50,
3871 ++uid,
3872 0);
3873 if (!solicited)
3874 {
3875 // UID of TB PPDUs will be different than the one of the preceding frame
3876 ++uid;
3877 }
3878 else
3879 {
3881 }
3882 // STA1 and STA2 send MU UL PPDUs addressed to AP
3885 m_apPhyStateListener.get());
3886 if (scheduleTxSta1)
3887 {
3888 Simulator::Schedule(delay,
3890 this,
3891 1,
3892 1,
3893 1000,
3894 uid,
3895 0,
3896 false);
3897 }
3898 Simulator::Schedule(delay + ulTimeDifference,
3900 this,
3901 2,
3902 2,
3903 1001,
3904 uid,
3905 0,
3906 false);
3907
3908 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3911 this,
3912 m_phyAp,
3913 expectedStateBeforeEnd);
3914 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3916 this,
3917 m_phyAp,
3918 expectedStateAtEnd);
3919 // TODO: add checks on TX stop for STAs
3920
3921 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3922 expectedFailuresFromSta2 >
3923 0)
3924 {
3925 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3926 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3927 // The expected time at which the reception is started corresponds to the time at which the
3928 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3929 const Time expectedPayloadStart = delay + MicroSeconds(48);
3930 // The expected time at which the reception is terminated corresponds to the time at which
3931 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3932 // received HE TB PPDU and the last received HE TB PPDU.
3933 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3934 // At the end of the transmission, verify that a single RX start notification shall have
3935 // been notified when the reception of the first HE RB PPDU starts.
3936 Simulator::Schedule(expectedPayloadEnd,
3938 this,
3939 1,
3940 Simulator::Now() + expectedPayloadStart);
3941 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3942 // notification shall have been notified when the reception of the last HE RB PPDU ends
3943 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3945 this,
3946 1,
3947 Simulator::Now() + expectedPayloadEnd,
3948 isSuccess);
3949 }
3950
3951 delay += MilliSeconds(100);
3952 // Check reception state from STA 1
3953 Simulator::Schedule(delay,
3955 this,
3956 expectedSuccessFromSta1,
3957 expectedFailuresFromSta1,
3958 expectedBytesFromSta1);
3959 // Check reception state from STA 2
3960 Simulator::Schedule(delay,
3962 this,
3963 expectedSuccessFromSta2,
3964 expectedFailuresFromSta2,
3965 expectedBytesFromSta2);
3966 // Verify events data have been cleared
3968
3969 delay += MilliSeconds(100);
3971}
3972
3973void
3975 Watt_u rxPowerNonOfdmaRu1,
3976 Watt_u rxPowerNonOfdmaRu2,
3977 Watt_u rxPowerOfdmaRu1,
3978 Watt_u rxPowerOfdmaRu2)
3979{
3980 const auto detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3981 const auto txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3982 const auto txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3983 const auto hePhy = m_phyAp->GetHePhy();
3984 const auto nonOfdmaDuration = hePhy->CalculateNonHeDurationForHeTb(txVectorSta2);
3985 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonHeDurationForHeTb(txVectorSta1));
3986
3987 std::vector<Watt_u> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3988 std::vector<WifiSpectrumBandInfo> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3989 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
3990 std::vector<Watt_u> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
3991 std::vector<WifiSpectrumBandInfo> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
3992 hePhy->GetRuBandForRx(txVectorSta2, 2)};
3993
3994 for (uint8_t i = 0; i < 2; ++i)
3995 {
3996 /**
3997 * Perform checks at AP
3998 */
3999 // Check received power on non-OFDMA portion
4001 delay + detectionDuration +
4002 NanoSeconds(1), // just after beginning of portion (once event is stored)
4004 this,
4005 m_phyAp,
4006 nonOfdmaBand[i],
4007 rxPowerNonOfdma[i]);
4008 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4010 this,
4011 m_phyAp,
4012 nonOfdmaBand[i],
4013 rxPowerNonOfdma[i]);
4014 // Check received power on OFDMA portion
4015 Simulator::Schedule(delay + nonOfdmaDuration +
4016 NanoSeconds(1), // just after beginning of portion
4018 this,
4019 m_phyAp,
4020 ofdmaBand[i],
4021 rxPowerOfdma[i]);
4023 NanoSeconds(1), // just before end of portion
4025 this,
4026 m_phyAp,
4027 ofdmaBand[i],
4028 rxPowerOfdma[i]);
4029
4030 /**
4031 * Perform checks for non-transmitting STA (STA 3).
4032 * Cannot use CheckNonOfdmaRxPower method since current event may be reset if
4033 * preamble not detected (e.g. not on primary).
4034 */
4035 // Check received power on non-OFDMA portion
4037 delay + detectionDuration +
4038 NanoSeconds(1), // just after beginning of portion (once event is stored)
4040 this,
4041 m_phySta3,
4042 nonOfdmaBand[i],
4043 rxPowerNonOfdma[i]);
4044 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4046 this,
4047 m_phySta3,
4048 nonOfdmaBand[i],
4049 rxPowerNonOfdma[i]);
4050 // Check received power on OFDMA portion
4051 Simulator::Schedule(delay + nonOfdmaDuration +
4052 NanoSeconds(1), // just after beginning of portion
4054 this,
4055 m_phySta3,
4056 ofdmaBand[i],
4057 rxPowerOfdma[i]);
4059 NanoSeconds(1), // just before end of portion
4061 this,
4062 m_phySta3,
4063 ofdmaBand[i],
4064 rxPowerOfdma[i]);
4065 }
4066
4067 if (rxPowerOfdmaRu1 != Watt_u{0.0})
4068 {
4069 /**
4070 * Perform checks for transmitting STA (STA 2) to ensure it has correctly logged
4071 * power received from other transmitting STA (STA 1).
4072 * Cannot use CheckNonOfdmaRxPower method since current event not set.
4073 */
4074 const auto rxPowerNonOfdmaSta1Only =
4075 (m_channelWidth >= MHz_u{40})
4076 ? rxPowerNonOfdma[0]
4077 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4078 // Check received power on non-OFDMA portion
4080 delay + detectionDuration +
4081 NanoSeconds(1), // just after beginning of portion (once event is stored)
4083 this,
4084 m_phySta2,
4085 nonOfdmaBand[0],
4086 rxPowerNonOfdmaSta1Only);
4087 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4089 this,
4090 m_phySta2,
4091 nonOfdmaBand[0],
4092 rxPowerNonOfdmaSta1Only);
4093 // Check received power on OFDMA portion
4094 Simulator::Schedule(delay + nonOfdmaDuration +
4095 NanoSeconds(1), // just after beginning of portion
4097 this,
4098 m_phySta2,
4099 ofdmaBand[0],
4100 rxPowerOfdma[0]);
4102 NanoSeconds(1), // just before end of portion
4104 this,
4105 m_phySta2,
4106 ofdmaBand[0],
4107 rxPowerOfdma[0]);
4108 }
4109}
4110
4111void
4113{
4116 int64_t streamNumber = 0;
4117 m_phyAp->AssignStreams(streamNumber);
4118 m_phySta1->AssignStreams(streamNumber);
4119 m_phySta2->AssignStreams(streamNumber);
4120 m_phySta3->AssignStreams(streamNumber);
4121
4122 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
4127 ->number;
4128
4137
4138 Time delay;
4140 delay += Seconds(1);
4141
4142 /**
4143 * In all the following tests, 2 HE TB PPDUs of the same UL MU transmission
4144 * are sent on RU 1 for STA 1 and RU 2 for STA 2.
4145 * The difference between solicited and unsolicited lies in that their PPDU
4146 * ID correspond to the one of the immediately preceding HE SU PPDU (thus
4147 * mimicking trigger frame reception).
4148 */
4149
4150 //---------------------------------------------------------------------------
4151 // Verify that both solicited HE TB PPDUs have been corrected received
4152 Simulator::Schedule(delay,
4154 this,
4155 "Reception of solicited HE TB PPDUs");
4156 ScheduleTest(delay,
4157 true,
4158 WifiPhyState::IDLE,
4159 1,
4160 0,
4161 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4162 1,
4163 0,
4164 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4165 delay += Seconds(1);
4166
4167 //---------------------------------------------------------------------------
4168 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4169 // corrected received
4171 delay,
4173 this,
4174 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4175 ScheduleTest(delay,
4176 true,
4177 WifiPhyState::IDLE,
4178 1,
4179 0,
4180 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4181 1,
4182 0,
4183 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4184 true,
4185 NanoSeconds(100));
4186 delay += Seconds(1);
4187
4188 //---------------------------------------------------------------------------
4189 // Verify that no unsolicited HE TB PPDU is received
4190 Simulator::Schedule(delay,
4192 this,
4193 "Dropping of unsolicited HE TB PPDUs");
4194 ScheduleTest(delay,
4195 false,
4196 WifiPhyState::IDLE,
4197 0,
4198 0,
4199 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4200 0,
4201 0,
4202 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4203 true,
4204 Seconds(0),
4205 WifiPhyState::CCA_BUSY);
4206 delay += Seconds(1);
4207
4208 //---------------------------------------------------------------------------
4209 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4210 Simulator::Schedule(delay,
4212 this,
4213 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4214 ScheduleTest(delay,
4215 true,
4216 WifiPhyState::IDLE,
4217 0,
4218 0,
4219 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4220 0,
4221 0,
4222 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4223 true,
4224 Seconds(0),
4225 WifiPhyState::CCA_BUSY,
4227 delay += Seconds(1);
4228
4229 //---------------------------------------------------------------------------
4230 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4231 Simulator::Schedule(delay,
4233 this,
4234 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4235 ScheduleTest(delay,
4236 true,
4237 WifiPhyState::IDLE,
4238 0,
4239 0,
4240 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4241 0,
4242 0,
4243 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4244 true,
4245 Seconds(0),
4246 WifiPhyState::CCA_BUSY,
4247 UL_LENGTH);
4248 delay += Seconds(1);
4249
4250 //---------------------------------------------------------------------------
4251 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4252 Simulator::Schedule(delay,
4254 this,
4255 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4256 ScheduleTest(delay,
4257 true,
4258 WifiPhyState::IDLE,
4259 0,
4260 0,
4261 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4262 0,
4263 0,
4264 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4265 true,
4266 Seconds(0),
4267 WifiPhyState::CCA_BUSY,
4268 AID);
4269 delay += Seconds(1);
4270
4271 //---------------------------------------------------------------------------
4272 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4273 // impacted
4275 delay,
4277 this,
4278 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4279 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4280 BandInfo bandInfo;
4281 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 4));
4282 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
4283 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
4284 Bands bands;
4285 bands.push_back(bandInfo);
4286
4287 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4288 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4289 Watt_u interferencePower{0.1};
4290 *interferencePsdRu1 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
4291
4294 this,
4295 interferencePsdRu1,
4296 MilliSeconds(100));
4298 delay,
4299 true,
4300 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4301 // interference
4302 0,
4303 1,
4304 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4305 1,
4306 0,
4307 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4308 delay += Seconds(1);
4309
4310 //---------------------------------------------------------------------------
4311 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4312 // impacted
4314 delay,
4316 this,
4317 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4318 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4319 bandInfo.fc = MHzToHz(m_frequency + (m_channelWidth / 4));
4320 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
4321 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
4322 bands.clear();
4323 bands.push_back(bandInfo);
4324
4325 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4326 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4327 *interferencePsdRu2 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
4328
4331 this,
4332 interferencePsdRu2,
4333 MilliSeconds(100));
4334 ScheduleTest(delay,
4335 true,
4336 (m_channelWidth >= MHz_u{40})
4337 ? WifiPhyState::IDLE
4338 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4339 // generated in its primary channel
4340 1,
4341 0,
4342 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4343 0,
4344 1,
4345 0); // Reception of the PSDU from STA 2 should have failed (since interference
4346 // occupies RU 2)
4347 delay += Seconds(1);
4348
4349 //---------------------------------------------------------------------------
4350 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4351 // been impacted
4352 Simulator::Schedule(delay,
4354 this,
4355 "Reception of solicited HE TB PPDUs with interference on the full band "
4356 "during PSDU reception");
4357 // A strong non-wifi interference is generated on the full band during PSDU reception
4358 bandInfo.fc = MHzToHz(m_frequency);
4359 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 2);
4360 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 2);
4361 bands.clear();
4362 bands.push_back(bandInfo);
4363
4364 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4365 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4366 *interferencePsdAll = interferencePower / (MHzToHz(m_channelWidth) * 20);
4367
4370 this,
4371 interferencePsdAll,
4372 MilliSeconds(100));
4374 delay,
4375 true,
4376 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4377 // interference
4378 0,
4379 1,
4380 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4381 0,
4382 1,
4383 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4384 // 2)
4385 delay += Seconds(1);
4386
4387 //---------------------------------------------------------------------------
4388 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4389 // solicited HE TB PPDUs have been impacted if they are on the same
4390 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4391 Simulator::Schedule(delay,
4393 this,
4394 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4395 "1 during PSDU reception");
4396 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4399 this,
4400 3,
4401 1,
4402 1002,
4403 1,
4404 0,
4405 false);
4406 // Expected figures from STA 2
4407 uint32_t succ;
4408 uint32_t fail;
4409 uint32_t bytes;
4410 if (m_channelWidth > MHz_u{20})
4411 {
4412 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4413 // interference from STA 3 on distinct 20 MHz channel)
4414 succ = 1;
4415 fail = 0;
4416 bytes = 1001;
4417 }
4418 else
4419 {
4420 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4421 // same 20 MHz channel)
4422 succ = 0;
4423 fail = 1;
4424 bytes = 0;
4425 }
4426 ScheduleTest(delay,
4427 true,
4428 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4429 // interference on measurement channel width
4430 0,
4431 1,
4432 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4433 // STA 3 on same 20 MHz channel)
4434 succ,
4435 fail,
4436 bytes);
4437 delay += Seconds(1);
4438
4439 //---------------------------------------------------------------------------
4440 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4441 // solicited HE TB PPDUs have been impacted if they are on the same
4442 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4443 Simulator::Schedule(delay,
4445 this,
4446 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4447 "2 during PSDU reception");
4448 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4451 this,
4452 3,
4453 2,
4454 1002,
4455 1,
4456 0,
4457 false);
4458 // Expected figures from STA 1
4459 if (m_channelWidth > MHz_u{20})
4460 {
4461 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4462 // interference from STA 3 on distinct 20 MHz channel)
4463 succ = 1;
4464 fail = 0;
4465 bytes = 1000;
4466 }
4467 else
4468 {
4469 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4470 // same 20 MHz channel)
4471 succ = 0;
4472 fail = 1;
4473 bytes = 0;
4474 }
4475 ScheduleTest(delay,
4476 true,
4477 (m_channelWidth >= MHz_u{40})
4478 ? WifiPhyState::IDLE
4479 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4480 // TB PPDU on primary channel
4481 succ,
4482 fail,
4483 bytes,
4484 0,
4485 1,
4486 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4487 // STA 3 on same 20 MHz channel)
4488 delay += Seconds(1);
4489
4490 //---------------------------------------------------------------------------
4491 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4492 // impacted
4494 delay,
4496 this,
4497 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4498 // One HE SU arrives at AP during the 400ns window
4499 Simulator::Schedule(delay + NanoSeconds(300),
4501 this,
4502 3,
4503 1002,
4504 1,
4505 0);
4507 delay,
4508 true,
4509 WifiPhyState::IDLE,
4510 0,
4511 1,
4512 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4513 0,
4514 1,
4515 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4516 delay += Seconds(1);
4517
4518 //---------------------------------------------------------------------------
4519 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4520 // received
4521 Simulator::Schedule(delay,
4523 this,
4524 "Reception of solicited HE TB PPDU only on RU 2");
4525 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4526 // otherwise
4529 this,
4530 m_phySta3,
4531 (m_channelWidth >= MHz_u{40})
4532 ? WifiPhyState::IDLE
4533 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4534 // IDLE if HE TB PPDU on primary channel
4535 ScheduleTest(delay,
4536 true,
4537 WifiPhyState::IDLE,
4538 0,
4539 0,
4540 0, // No transmission scheduled for STA 1
4541 1,
4542 0,
4543 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4544 false,
4545 Seconds(0),
4546 WifiPhyState::RX); // Measurement channel is total channel width
4547 delay += Seconds(1);
4548
4549 //---------------------------------------------------------------------------
4550 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4551 Simulator::Schedule(delay,
4553 this,
4554 "Measure power for reception of HE TB PPDU only on RU 2");
4555 auto rxPower = DbmToW(
4556 dBm_u{19}); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4558 (m_channelWidth >= MHz_u{40}) ? Watt_u{0.0} : rxPower,
4559 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4560 Watt_u{0.0},
4561 rxPower);
4562 ScheduleTest(delay,
4563 true,
4564 WifiPhyState::IDLE,
4565 0,
4566 0,
4567 0, // No transmission scheduled for STA 1
4568 1,
4569 0,
4570 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4571 false,
4572 Seconds(0),
4573 WifiPhyState::RX); // Measurement channel is total channel width
4574 delay += Seconds(1);
4575
4576 //---------------------------------------------------------------------------
4577 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4578 // limitation enforced
4580 delay,
4582 this,
4583 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4584 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4585 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4586 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4588 this,
4589 m_phySta2,
4590 dBm_per_MHz_u{3});
4591
4592 rxPower = (m_channelWidth > MHz_u{40})
4593 ? DbmToW(dBm_u{19})
4594 : DbmToW(dBm_u{18.0103}); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4595 // transmitted only on one 20 MHz channel
4596 auto rxPowerOfdma = rxPower;
4597 if (m_channelWidth <= MHz_u{40})
4598 {
4599 rxPowerOfdma =
4600 (m_channelWidth == MHz_u{20})
4601 ? DbmToW(dBm_u{14.0309}) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4602 : DbmToW(dBm_u{18.0103}); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4603 }
4605 (m_channelWidth >= MHz_u{40}) ? Watt_u{0.0} : rxPower,
4606 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4607 Watt_u{0.0},
4608 rxPowerOfdma);
4609
4610 // Reset PSD limitation once HE TB has been sent
4613 this,
4614 m_phySta2,
4615 dBm_per_MHz_u{100});
4616 ScheduleTest(delay,
4617 true,
4618 WifiPhyState::IDLE,
4619 0,
4620 0,
4621 0, // No transmission scheduled for STA 1
4622 1,
4623 0,
4624 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4625 false,
4626 Seconds(0),
4627 WifiPhyState::RX); // Measurement channel is total channel width
4628 delay += Seconds(1);
4629
4630 //---------------------------------------------------------------------------
4631 // Measure the power of 2 solicited HE TB PPDU from both STAs
4632 Simulator::Schedule(delay,
4634 this,
4635 "Measure power for reception of HE TB PPDU on both RUs");
4636 rxPower = DbmToW(
4637 dBm_u{19}); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4638 const auto rxPowerNonOfdma =
4639 (m_channelWidth >= MHz_u{40})
4640 ? rxPower
4641 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4642 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4643 ScheduleTest(delay,
4644 true,
4645 WifiPhyState::IDLE,
4646 1,
4647 0,
4648 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4649 1,
4650 0,
4651 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4652 delay += Seconds(1);
4653
4654 //---------------------------------------------------------------------------
4655 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4656 // ongoing)
4657 Simulator::Schedule(delay,
4659 this,
4660 "Reception of an HE TB PPDU from another BSS");
4661 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4663 Simulator::Schedule(delay + MilliSeconds(100),