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 = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu1->GetSize(),
2148 txVector1,
2150 rxStaId1);
2151 const auto txDuration2 = OfdmaSpectrumWifiPhy::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 = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu->GetSize(),
2421 txVector,
2422 m_phy->GetPhyBand(),
2423 staId);
2424 auto ppdu = Create<HePpdu>(psdus,
2425 txVector,
2427 ppduDuration,
2428 uid,
2430
2431 // Send non-OFDMA part
2432 const auto nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonHeDurationForHeTb(txVector);
2433 const auto centerFrequency =
2434 m_phy->GetHePhy()->GetCenterFrequenciesForNonHePart(ppdu, staId).front();
2435 MHz_u ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2436 MHz_u channelWidth = ruWidth < MHz_u{20} ? MHz_u{20} : ruWidth;
2438 centerFrequency,
2439 channelWidth,
2440 txPower,
2441 m_phy->GetGuardBandwidth(channelWidth));
2442 auto rxParams = Create<WifiSpectrumSignalParameters>();
2443 rxParams->psd = rxPsd;
2444 rxParams->txPhy = nullptr;
2445 rxParams->duration = nonOfdmaDuration;
2446 rxParams->ppdu = ppdu;
2447
2448 uint16_t length;
2449 std::tie(length, ppduDuration) =
2451 txVector.SetLength(length);
2452 m_trigVector.SetLength(length);
2454 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2455 ppdu->ResetTxVector();
2456 m_phy->StartRx(rxParams, nullptr);
2457
2458 // Schedule OFDMA part
2459 auto ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2460 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2461 const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2462 auto rxPsdOfdma =
2465 txPower,
2467 band.indices);
2468 auto rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2469 rxParamsOfdma->psd = rxPsd;
2470 rxParamsOfdma->txPhy = nullptr;
2471 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2472 rxParamsOfdma->ppdu = ppduOfdma;
2473 Simulator::Schedule(nonOfdmaDuration,
2475 this,
2476 rxParamsOfdma);
2477}
2478
2479void
2484
2485void
2487{
2488 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2489 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2490 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2491 m_phy->StartRx(rxParamsOfdma, nullptr);
2492}
2493
2494void
2496{
2500 dev->SetStandard(WIFI_STANDARD_80211ax);
2505 "Txop",
2506 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
2507 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2508 dev->SetMac(mac);
2509 m_phy->SetInterferenceHelper(interferenceHelper);
2510 m_phy->SetErrorRateModel(error);
2511 m_phy->AddChannel(spectrumChannel);
2516 0});
2517 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2519 m_phy->SetDevice(dev);
2520 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2522 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2523 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2524 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2526 heConfiguration->m_maxTbPpduDelay = NanoSeconds(400);
2527 dev->SetHeConfiguration(heConfiguration);
2528 dev->SetPhy(m_phy);
2529 node->AddDevice(dev);
2530}
2531
2532void
2534{
2535 m_phy->Dispose();
2536 m_phy = nullptr;
2537}
2538
2539void
2541{
2544 int64_t streamNumber = 0;
2545 m_phy->AssignStreams(streamNumber);
2546
2547 Watt_u txPower{0.01};
2548
2549 {
2550 // Verify a single UL MU transmission with two stations belonging to the same BSS
2551 std::vector<uint64_t> uids{0};
2554 this,
2555 uids[0],
2556 1,
2557 txPower,
2558 1001);
2561 this,
2562 uids[0],
2563 2,
2564 txPower,
2565 1002);
2566 // Check that we received a single UL MU transmission with the corresponding UID
2569 this,
2570 1,
2571 uids);
2573 }
2574
2575 {
2576 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2577 // the second transmission arrives during the preamble detection window and with half the
2578 // power of the first transmission.
2579 std::vector<uint64_t> uids{1, 2};
2582 this,
2583 uids[0],
2584 1,
2585 txPower,
2586 1001);
2589 this,
2590 uids[0],
2591 2,
2592 txPower,
2593 1002);
2596 this,
2597 uids[1],
2598 1,
2599 txPower / 2,
2600 1003);
2603 this,
2604 uids[1],
2605 2,
2606 txPower / 2,
2607 1004);
2608 // Check that we received the correct reception of 2 UL MU transmissions with the
2609 // corresponding UIDs
2612 this,
2613 2,
2614 uids);
2616 // TODO: verify PPDUs from second UL MU transmission are dropped
2617 }
2618
2619 {
2620 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2621 // the second transmission arrives during the preamble detection window and with twice the
2622 // power of the first transmission.
2623 std::vector<uint64_t> uids{3, 4};
2626 this,
2627 uids[0],
2628 1,
2629 txPower / 2,
2630 1001);
2633 this,
2634 uids[0],
2635 2,
2636 txPower / 2,
2637 1002);
2640 this,
2641 uids[1],
2642 1,
2643 txPower,
2644 1003);
2647 this,
2648 uids[1],
2649 2,
2650 txPower,
2651 1004);
2652 // Check that we received the correct reception of 2 UL MU transmissions with the
2653 // corresponding UIDs
2656 this,
2657 2,
2658 uids);
2660 // TODO: verify PPDUs from first UL MU transmission are dropped
2661 }
2662
2663 {
2664 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2665 // the second transmission arrives during PHY header reception and with the same power as
2666 // the first transmission.
2667 std::vector<uint64_t> uids{5, 6};
2670 this,
2671 uids[0],
2672 1,
2673 txPower,
2674 1001);
2677 this,
2678 uids[0],
2679 2,
2680 txPower,
2681 1002);
2684 this,
2685 uids[1],
2686 1,
2687 txPower,
2688 1003);
2691 this,
2692 uids[1],
2693 2,
2694 txPower,
2695 1004);
2696 // Check that we received the correct reception of the first UL MU transmission with the
2697 // corresponding UID (second one dropped)
2700 this,
2701 1,
2702 std::vector<uint64_t>{uids[0]});
2703 // The packets of the second UL MU transmission should have been dropped
2706 this,
2707 1003 + 1004);
2709 }
2710
2711 {
2712 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2713 // BSS, where the second transmission arrives during payload reception and with the same
2714 // power as the first transmission.
2715 std::vector<uint64_t> uids{7, 8};
2718 this,
2719 uids[0],
2720 1,
2721 txPower,
2722 1001);
2725 this,
2726 uids[0],
2727 2,
2728 txPower,
2729 1002);
2732 this,
2733 uids[1],
2734 1,
2735 txPower,
2736 1003);
2739 this,
2740 uids[1],
2741 2,
2742 txPower,
2743 1004);
2744 // Check that we received the correct reception of the first UL MU transmission with the
2745 // corresponding UID (second one dropped)
2748 this,
2749 1,
2750 std::vector<uint64_t>{uids[0]});
2751 // The packets of the second UL MU transmission should have been dropped
2754 this,
2755 1003 + 1004);
2757 }
2758
2759 {
2760 // Verify the correct reception of a single UL MU transmission with two stations belonging
2761 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2762 // the configured delay spread of 400ns
2763 std::vector<uint64_t> uids{9};
2766 this,
2767 uids[0],
2768 1,
2769 txPower,
2770 1001);
2773 this,
2774 uids[0],
2775 2,
2776 txPower,
2777 1002);
2778 // Check that we received a single UL MU transmission with the corresponding UID
2781 this,
2782 1,
2783 uids);
2784 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2785 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2786 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2787 // second packet of 1002 bytes is dropped as well.
2790 this,
2791 1001 + 1002);
2793 }
2794
2797}
2798
2799/**
2800 * @ingroup wifi-test
2801 * @ingroup tests
2802 *
2803 * @brief PHY listener for OFDMA tests
2804 */
2806{
2807 public:
2809
2810 void NotifyRxStart(Time duration) override
2811 {
2812 NS_LOG_FUNCTION(this << duration);
2815 m_lastRxSuccess = false;
2816 }
2817
2818 void NotifyRxEndOk() override
2819 {
2820 NS_LOG_FUNCTION(this);
2822 ++m_notifyRxEnd;
2823 m_lastRxSuccess = true;
2824 }
2825
2826 void NotifyRxEndError() override
2827 {
2828 NS_LOG_FUNCTION(this);
2830 ++m_notifyRxEnd;
2831 m_lastRxSuccess = false;
2832 }
2833
2834 void NotifyTxStart(Time duration, dBm_u txPower) override
2835 {
2836 NS_LOG_FUNCTION(this << duration << txPower);
2837 }
2838
2840 WifiChannelListType channelType,
2841 const std::vector<Time>& /*per20MhzDurations*/) override
2842 {
2843 NS_LOG_FUNCTION(this << duration << channelType);
2844 }
2845
2846 void NotifySwitchingStart(Time duration) override
2847 {
2848 }
2849
2850 void NotifySleep() override
2851 {
2852 }
2853
2854 void NotifyOff() override
2855 {
2856 }
2857
2858 void NotifyWakeup() override
2859 {
2860 }
2861
2862 void NotifyOn() override
2863 {
2864 }
2865
2866 /**
2867 * Reset function.
2868 */
2869 void Reset()
2870 {
2871 m_notifyRxStart = 0;
2872 m_notifyRxEnd = 0;
2874 m_lastRxEnd = Seconds(0);
2875 m_lastRxSuccess = false;
2876 }
2877
2878 /**
2879 * Return the number of RX start notifications that has been received since the last reset.
2880 * @return the number of RX start notifications that has been received
2881 */
2883 {
2884 return m_notifyRxStart;
2885 }
2886
2887 /**
2888 * Return the number of RX end notifications that has been received since the last reset.
2889 * @return the number of RX end notifications that has been received
2890 */
2892 {
2893 return m_notifyRxEnd;
2894 }
2895
2896 /**
2897 * Return the time at which the last RX start notification has been received.
2898 * @return the time at which the last RX start notification has been received
2899 */
2901 {
2902 return m_lastRxStart;
2903 }
2904
2905 /**
2906 * Return the time at which the last RX end notification has been received.
2907 * @return the time at which the last RX end notification has been received
2908 */
2910 {
2911 return m_lastRxEnd;
2912 }
2913
2914 /**
2915 * Return whether last RX has been successful.
2916 * @return true if last RX has been successful, false otherwise
2917 */
2918 bool IsLastRxSuccess() const
2919 {
2920 return m_lastRxSuccess;
2921 }
2922
2923 private:
2924 uint32_t m_notifyRxStart{0}; ///< count number of RX start notifications
2925 uint32_t m_notifyRxEnd{0}; ///< count number of RX end notifications
2926 Time m_lastRxStart{Seconds(0)}; ///< last time a RX start notification has been received
2927 Time m_lastRxEnd{Seconds(0)}; ///< last time a RX end notification has been received
2928 bool m_lastRxSuccess{false}; ///< flag whether last RX has been successful
2929};
2930
2931/**
2932 * @ingroup wifi-test
2933 * @ingroup tests
2934 *
2935 * @brief UL-OFDMA PHY test
2936 */
2938{
2939 public:
2940 /**
2941 * Erroneous info included in a TRIGVECTOR
2942 */
2950
2952 ~TestUlOfdmaPhyTransmission() override;
2953
2954 private:
2955 void DoSetup() override;
2956 void DoTeardown() override;
2957 void DoRun() override;
2958
2959 /**
2960 * Get TXVECTOR for HE TB PPDU.
2961 * @param txStaId the ID of the TX STA
2962 * @param index the RU index used for the transmission
2963 * @param bssColor the BSS color of the TX STA
2964 * @return the TXVECTOR for HE TB PPDU
2965 */
2966 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2967 std::size_t index,
2968 uint8_t bssColor) const;
2969 /**
2970 * Set TRIGVECTOR for HE TB PPDU
2971 *
2972 * @param bssColor the BSS color of the TX STA
2973 * @param error the erroneous info (if any) in the TRIGVECTOR to set
2974 */
2975 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2976 /**
2977 * Send HE TB PPDU function
2978 * @param txStaId the ID of the TX STA
2979 * @param index the RU index used for the transmission
2980 * @param payloadSize the size of the payload in bytes
2981 * @param uid the UID of the trigger frame that is initiating this transmission
2982 * @param bssColor the BSS color of the TX STA
2983 * @param incrementUid whether UID shall be incremented
2984 */
2985 void SendHeTbPpdu(uint16_t txStaId,
2986 std::size_t index,
2987 std::size_t payloadSize,
2988 uint64_t uid,
2989 uint8_t bssColor,
2990 bool incrementUid);
2991
2992 /**
2993 * Send HE SU PPDU function
2994 * @param txStaId the ID of the TX STA
2995 * @param payloadSize the size of the payload in bytes
2996 * @param uid the UID of the trigger frame that is initiating this transmission
2997 * @param bssColor the BSS color of the TX STA
2998 */
2999 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
3000
3001 /**
3002 * Set the BSS color
3003 * @param phy the PHY
3004 * @param bssColor the BSS color
3005 */
3006 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3007
3008 /**
3009 * Set the PSD limit
3010 * @param phy the PHY
3011 * @param psdLimit the PSD limit
3012 */
3013 void SetPsdLimit(Ptr<WifiPhy> phy, dBm_per_MHz_u psdLimit);
3014
3015 /**
3016 * Generate interference function
3017 * @param interferencePsd the PSD of the interference to be generated
3018 * @param duration the duration of the interference
3019 */
3020 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3021 /**
3022 * Stop interference function
3023 */
3024 void StopInterference();
3025
3026 /**
3027 * Run one function
3028 */
3029 void RunOne();
3030
3031 /**
3032 * Check the received PSDUs from STA1
3033 * @param expectedSuccess the expected number of success
3034 * @param expectedFailures the expected number of failures
3035 * @param expectedBytes the expected number of bytes
3036 */
3037 void CheckRxFromSta1(uint32_t expectedSuccess,
3038 uint32_t expectedFailures,
3039 uint32_t expectedBytes);
3040
3041 /**
3042 * Check the received PSDUs from STA2
3043 * @param expectedSuccess the expected number of success
3044 * @param expectedFailures the expected number of failures
3045 * @param expectedBytes the expected number of bytes
3046 */
3047 void CheckRxFromSta2(uint32_t expectedSuccess,
3048 uint32_t expectedFailures,
3049 uint32_t expectedBytes);
3050
3051 /**
3052 * Check the received power for the non-OFDMA of the HE TB PPDUs over the given band
3053 * @param phy the PHY
3054 * @param band the indices of the band over which the power is measured
3055 * @param expectedRxPower the expected received power
3056 */
3059 Watt_u expectedRxPower);
3060 /**
3061 * Check the received power for the OFDMA part of the HE TB PPDUs over the given band
3062 * @param phy the PHY
3063 * @param band the indices of the band over which the power is measured
3064 * @param expectedRxPower the expected received power
3065 */
3068 Watt_u expectedRxPower);
3069
3070 /**
3071 * Verify all events are cleared at end of TX or RX
3072 */
3073 void VerifyEventsCleared();
3074
3075 /**
3076 * Check the PHY state
3077 * @param phy the PHY
3078 * @param expectedState the expected state of the PHY
3079 */
3080 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
3081 /// @copydoc CheckPhyState
3083
3084 /**
3085 * Check the the number of RX start notifications at the AP as well as the last time a RX start
3086 * has been notified
3087 * @param expectedNotifications the expected number of RX start notifications at the AP
3088 * @param expectedLastNotification the expected time of the last RX start notification at the AP
3089 */
3090 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3091 /**
3092 * Check the the number of RX end notifications at the AP as well as the last time a RX end has
3093 * been notified
3094 * @param expectedNotifications the expected number of RX end notifications at the AP
3095 * @param expectedLastNotification the expected time of the last RX end notification at the AP
3096 * @param expectedSuccess true if the last RX notification indicates a success, false otherwise
3097 */
3098 void CheckApRxEnd(uint32_t expectedNotifications,
3099 Time expectedLastNotification,
3100 bool expectedSuccess);
3101
3102 /**
3103 * Reset function
3104 */
3105 void Reset();
3106
3107 /**
3108 * Receive success function
3109 * @param psdu the PSDU
3110 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
3111 * @param txVector the transmit vector
3112 * @param statusPerMpdu reception status per MPDU
3113 */
3115 RxSignalInfo rxSignalInfo,
3116 const WifiTxVector& txVector,
3117 const std::vector<bool>& statusPerMpdu);
3118
3119 /**
3120 * Receive failure function
3121 * @param psdu the PSDU
3122 */
3123 void RxFailure(Ptr<const WifiPsdu> psdu);
3124
3125 /**
3126 * Schedule test to perform.
3127 * The interference generation should be scheduled apart.
3128 *
3129 * @param delay the reference delay to schedule the events
3130 * @param solicited flag indicating if HE TB PPDUs were solicited by the AP
3131 * @param expectedStateAtEnd the expected state of the PHY at the end of the reception
3132 * @param expectedSuccessFromSta1 the expected number of success from STA 1
3133 * @param expectedFailuresFromSta1 the expected number of failures from STA 1
3134 * @param expectedBytesFromSta1 the expected number of bytes from STA 1
3135 * @param expectedSuccessFromSta2 the expected number of success from STA 2
3136 * @param expectedFailuresFromSta2 the expected number of failures from STA 2
3137 * @param expectedBytesFromSta2 the expected number of bytes from STA 2
3138 * @param scheduleTxSta1 flag indicating to schedule a HE TB PPDU from STA 1
3139 * @param ulTimeDifference delay between HE TB PPDU from STA 1 and HE TB PPDU from STA 2
3140 * are received
3141 * @param expectedStateBeforeEnd the expected state of the PHY before the end of the
3142 * transmission
3143 * @param error the erroneous info (if any) in the TRIGVECTOR to set
3144 */
3145 void ScheduleTest(Time delay,
3146 bool solicited,
3147 WifiPhyState expectedStateAtEnd,
3148 uint32_t expectedSuccessFromSta1,
3149 uint32_t expectedFailuresFromSta1,
3150 uint32_t expectedBytesFromSta1,
3151 uint32_t expectedSuccessFromSta2,
3152 uint32_t expectedFailuresFromSta2,
3153 uint32_t expectedBytesFromSta2,
3154 bool scheduleTxSta1 = true,
3155 Time ulTimeDifference = Seconds(0),
3156 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3157 TrigVectorInfo error = NONE);
3158
3159 /**
3160 * Schedule power measurement related checks.
3161 *
3162 * @param delay the reference delay used to schedule the events
3163 * @param rxPowerNonOfdmaRu1 the received power on the non-OFDMA part of RU1
3164 * @param rxPowerNonOfdmaRu2 the received power on the non-OFDMA part of RU2
3165 * @param rxPowerOfdmaRu1 the received power on RU1
3166 * @param rxPowerOfdmaRu2 the received power on RU2
3167 */
3169 Watt_u rxPowerNonOfdmaRu1,
3170 Watt_u rxPowerNonOfdmaRu2,
3171 Watt_u rxPowerOfdmaRu1,
3172 Watt_u rxPowerOfdmaRu2);
3173 /**
3174 * Log scenario description
3175 *
3176 * @param log the scenario description to add to log
3177 */
3178 void LogScenario(std::string log) const;
3179
3184
3185 std::shared_ptr<OfdmaTestPhyListener>
3186 m_apPhyStateListener; ///< listener for AP PHY state transitions
3187
3189
3190 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
3191 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
3192 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
3193 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
3194 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
3195 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
3196
3197 MHz_u m_frequency; ///< frequency
3198 MHz_u m_channelWidth; ///< channel width
3199 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
3200};
3201
3203 : TestCase("UL-OFDMA PHY test"),
3204 m_countRxSuccessFromSta1(0),
3205 m_countRxSuccessFromSta2(0),
3206 m_countRxFailureFromSta1(0),
3207 m_countRxFailureFromSta2(0),
3208 m_countRxBytesFromSta1(0),
3209 m_countRxBytesFromSta2(0),
3210 m_frequency(DEFAULT_FREQUENCY),
3211 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3212 m_expectedPpduDuration(NanoSeconds(271200))
3213{
3214}
3215
3216void
3218 std::size_t payloadSize,
3219 uint64_t uid,
3220 uint8_t bssColor)
3221{
3222 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3223 WifiConstPsduMap psdus;
3224
3225 WifiTxVector txVector{HePhy::GetHeMcs7(),
3226 0,
3228 NanoSeconds(800),
3229 1,
3230 1,
3231 0,
3233 false,
3234 false,
3235 false,
3236 bssColor};
3237
3238 auto pkt = Create<Packet>(payloadSize);
3239 WifiMacHeader hdr;
3241 hdr.SetQosTid(0);
3242 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3243 std::ostringstream addr;
3244 addr << "00:00:00:00:00:0" << txStaId;
3245 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3246 hdr.SetSequenceNumber(1);
3247 auto psdu = Create<WifiPsdu>(pkt, hdr);
3248 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3249
3251 if (txStaId == 1)
3252 {
3253 phy = m_phySta1;
3254 }
3255 else if (txStaId == 2)
3256 {
3257 phy = m_phySta2;
3258 }
3259 else if (txStaId == 3)
3260 {
3261 phy = m_phySta3;
3262 }
3263 else if (txStaId == 0)
3264 {
3265 phy = m_phyAp;
3266 }
3267 phy->SetPpduUid(uid);
3268 phy->Send(psdus, txVector);
3269}
3270
3273 std::size_t index,
3274 uint8_t bssColor) const
3275{
3276 WifiTxVector txVector{HePhy::GetHeMcs7(),
3277 0,
3279 NanoSeconds(1600),
3280 1,
3281 1,
3282 0,
3284 false,
3285 false,
3286 false,
3287 bssColor};
3288
3289 auto ruType = HeRu::RU_106_TONE;
3290 if (m_channelWidth == MHz_u{20})
3291 {
3292 ruType = HeRu::RU_106_TONE;
3293 }
3294 else if (m_channelWidth == MHz_u{40})
3295 {
3296 ruType = HeRu::RU_242_TONE;
3297 }
3298 else if (m_channelWidth == MHz_u{80})
3299 {
3300 ruType = HeRu::RU_484_TONE;
3301 }
3302 else if (m_channelWidth == MHz_u{160})
3303 {
3304 ruType = HeRu::RU_996_TONE;
3305 }
3306 else
3307 {
3308 NS_ASSERT_MSG(false, "Unsupported channel width");
3309 }
3310
3311 auto primary80MHz = true;
3312 if (m_channelWidth == MHz_u{160} && index == 2)
3313 {
3314 primary80MHz = false;
3315 index = 1;
3316 }
3317 HeRu::RuSpec ru(ruType, index, primary80MHz);
3318 txVector.SetRu(ru, txStaId);
3319 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3320 txVector.SetNss(1, txStaId);
3321 return txVector;
3322}
3323
3324void
3326{
3327 auto channelWidth = m_channelWidth;
3328 if (error == CHANNEL_WIDTH)
3329 {
3330 channelWidth = (channelWidth == MHz_u{160} ? MHz_u{20} : channelWidth * 2);
3331 }
3332
3333 WifiTxVector txVector(HePhy::GetHeMcs7(),
3334 0,
3336 NanoSeconds(1600),
3337 1,
3338 1,
3339 0,
3340 channelWidth,
3341 false,
3342 false,
3343 false,
3344 bssColor);
3345
3347 if (channelWidth == MHz_u{20})
3348 {
3349 ruType = HeRu::RU_106_TONE;
3350 }
3351 else if (channelWidth == MHz_u{40})
3352 {
3353 ruType = HeRu::RU_242_TONE;
3354 }
3355 else if (channelWidth == MHz_u{80})
3356 {
3357 ruType = HeRu::RU_484_TONE;
3358 }
3359 else if (channelWidth == MHz_u{160})
3360 {
3361 ruType = HeRu::RU_996_TONE;
3362 }
3363 else
3364 {
3365 NS_ASSERT_MSG(false, "Unsupported channel width");
3366 }
3367
3368 uint16_t aid1 = (error == AID ? 3 : 1);
3369 uint16_t aid2 = (error == AID ? 4 : 2);
3370
3371 HeRu::RuSpec ru1(ruType, 1, true);
3372 txVector.SetRu(ru1, aid1);
3373 txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3374 txVector.SetNss(1, aid1);
3375
3376 HeRu::RuSpec ru2(ruType, (channelWidth == MHz_u{160} ? 1 : 2), (channelWidth != MHz_u{160}));
3377 txVector.SetRu(ru2, aid2);
3378 txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3379 txVector.SetNss(1, aid2);
3380
3381 uint16_t length;
3382 std::tie(length, m_expectedPpduDuration) =
3384 txVector,
3385 m_phyAp->GetPhyBand());
3386 if (error == UL_LENGTH)
3387 {
3388 ++length;
3389 }
3390 txVector.SetLength(length);
3392 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3393}
3394
3395void
3397 std::size_t index,
3398 std::size_t payloadSize,
3399 uint64_t uid,
3400 uint8_t bssColor,
3401 bool incrementUid)
3402{
3403 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3404 WifiConstPsduMap psdus;
3405
3406 if (incrementUid)
3407 {
3408 ++uid;
3409 }
3410
3411 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3412 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3413 WifiMacHeader hdr;
3415 hdr.SetQosTid(0);
3416 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3417 std::ostringstream addr;
3418 addr << "00:00:00:00:00:0" << txStaId;
3419 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3420 hdr.SetSequenceNumber(1);
3421 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3422 psdus.insert(std::make_pair(txStaId, psdu));
3423
3425 if (txStaId == 1)
3426 {
3427 phy = m_phySta1;
3428 }
3429 else if (txStaId == 2)
3430 {
3431 phy = m_phySta2;
3432 }
3433 else if (txStaId == 3)
3434 {
3435 phy = m_phySta3;
3436 }
3437
3438 Time txDuration = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu->GetSize(),
3439 txVector,
3440 phy->GetPhyBand(),
3441 txStaId);
3442 txVector.SetLength(
3443 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3444
3445 phy->SetPpduUid(uid);
3446 phy->Send(psdus, txVector);
3447}
3448
3449void
3451{
3452 NS_LOG_FUNCTION(this << duration);
3453 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
3454 m_phyInterferer->SetPeriod(duration);
3455 m_phyInterferer->Start();
3457}
3458
3459void
3464
3468
3469void
3471 RxSignalInfo rxSignalInfo,
3472 const WifiTxVector& txVector,
3473 const std::vector<bool>& /*statusPerMpdu*/)
3474{
3475 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3476 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3477 {
3479 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3480 }
3481 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3482 {
3484 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3485 }
3486}
3487
3488void
3490{
3491 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3492 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3493 {
3495 }
3496 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3497 {
3499 }
3500}
3501
3502void
3504 uint32_t expectedFailures,
3505 uint32_t expectedBytes)
3506{
3508 expectedSuccess,
3509 "The number of successfully received packets from STA 1 is not correct!");
3512 expectedFailures,
3513 "The number of unsuccessfuly received packets from STA 1 is not correct!");
3515 expectedBytes,
3516 "The number of bytes received from STA 1 is not correct!");
3517}
3518
3519void
3521 uint32_t expectedFailures,
3522 uint32_t expectedBytes)
3523{
3525 expectedSuccess,
3526 "The number of successfully received packets from STA 2 is not correct!");
3529 expectedFailures,
3530 "The number of unsuccessfuly received packets from STA 2 is not correct!");
3532 expectedBytes,
3533 "The number of bytes received from STA 2 is not correct!");
3534}
3535
3536void
3539 Watt_u expectedRxPower)
3540{
3541 auto event = phy->GetCurrentEvent();
3542 NS_ASSERT(event);
3543 auto rxPower = event->GetRxPower(band);
3544 NS_LOG_FUNCTION(this << band << expectedRxPower << rxPower);
3545 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3547 expectedRxPower,
3548 Watt_u{5e-3},
3549 "RX power " << rxPower << " over (" << band
3550 << ") does not match expected power " << expectedRxPower
3551 << " at " << Simulator::Now());
3552}
3553
3554void
3557 Watt_u expectedRxPower)
3558{
3559 /**
3560 * The current event cannot be used since it points to the preamble part of the HE TB PPDU.
3561 * We will have to check if the expected power is indeed the max power returning a positive
3562 * duration when calling GetEnergyDuration.
3563 */
3564 NS_LOG_FUNCTION(this << band << expectedRxPower);
3565 Watt_u step{5e-3};
3566 if (expectedRxPower > Watt_u{0.0})
3567 {
3569 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3570 true,
3571 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3572 << Simulator::Now());
3574 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3575 false,
3576 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3577 << Simulator::Now());
3578 }
3579 else
3580 {
3582 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3583 false,
3584 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3585 << Simulator::Now());
3586 }
3587}
3588
3589void
3591{
3593 nullptr,
3594 "m_currentEvent for AP was not cleared");
3596 nullptr,
3597 "m_currentEvent for STA 1 was not cleared");
3599 nullptr,
3600 "m_currentEvent for STA 2 was not cleared");
3601}
3602
3603void
3605{
3606 // This is needed to make sure PHY state will be checked as the last event if a state change
3607 // occurred at the exact same time as the check
3609}
3610
3611void
3613 WifiPhyState expectedState)
3614{
3615 WifiPhyState currentState;
3616 PointerValue ptr;
3617 phy->GetAttribute("State", ptr);
3619 currentState = state->GetState();
3620 NS_LOG_FUNCTION(this << currentState);
3621 NS_TEST_ASSERT_MSG_EQ(currentState,
3622 expectedState,
3623 "PHY State " << currentState << " does not match expected state "
3624 << expectedState << " at " << Simulator::Now());
3625}
3626
3627void
3629 Time expectedLastNotification)
3630{
3632 expectedNotifications,
3633 "Number of RX start notifications "
3635 << " does not match expected count " << expectedNotifications
3636 << " for AP at " << Simulator::Now());
3638 expectedLastNotification,
3639 "Last time RX start notification has been received "
3641 << " does not match expected time " << expectedLastNotification
3642 << " for AP at " << Simulator::Now());
3643}
3644
3645void
3647 Time expectedLastNotification,
3648 bool expectedSuccess)
3649{
3651 expectedNotifications,
3652 "Number of RX end notifications "
3654 << " does not match expected count " << expectedNotifications
3655 << " for AP at " << Simulator::Now());
3657 expectedLastNotification,
3658 "Last time RX end notification has been received "
3660 << " does not match expected time " << expectedLastNotification
3661 << " for AP at " << Simulator::Now());
3663 expectedSuccess,
3664 "Last time RX end notification indicated a "
3665 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3666 << " but expected a " << (expectedSuccess ? "success" : "failure")
3667 << " for AP at " << Simulator::Now());
3668}
3669
3670void
3685
3686void
3688{
3689 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3690 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3691 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3692}
3693
3694void
3696{
3697 NS_LOG_FUNCTION(this << phy << psdLimit);
3698 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3699}
3700
3701void
3703{
3706 lossModel->SetFrequency(m_frequency);
3707 spectrumChannel->AddPropagationLossModel(lossModel);
3710 spectrumChannel->SetPropagationDelayModel(delayModel);
3711
3712 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3714 preambleDetectionModel->SetAttribute(
3715 "MinimumRssi",
3717 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3718 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3719
3720 Ptr<Node> apNode = CreateObject<Node>();
3722 apDev->SetStandard(WIFI_STANDARD_80211ax);
3724 "Txop",
3725 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
3726 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3727 apDev->SetMac(apMac);
3730 apDev->SetHeConfiguration(heConfiguration);
3732 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3734 m_phyAp->SetErrorRateModel(apErrorModel);
3735 m_phyAp->SetDevice(apDev);
3736 m_phyAp->AddChannel(spectrumChannel);
3740 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3742 m_phyAp->SetMobility(apMobility);
3743 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3745 apDev->SetPhy(m_phyAp);
3746 apMac->SetWifiPhys({m_phyAp});
3747 apNode->AggregateObject(apMobility);
3748 apNode->AddDevice(apDev);
3749
3750 Ptr<Node> sta1Node = CreateObject<Node>();
3752 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
3753 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3756 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3758 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3759 m_phySta1->SetDevice(sta1Dev);
3760 m_phySta1->AddChannel(spectrumChannel);
3762 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3764 m_phySta1->SetMobility(sta1Mobility);
3765 sta1Dev->SetPhy(m_phySta1);
3766 sta1Node->AggregateObject(sta1Mobility);
3767 sta1Node->AddDevice(sta1Dev);
3768
3769 Ptr<Node> sta2Node = CreateObject<Node>();
3771 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
3772 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3775 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3777 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3778 m_phySta2->SetDevice(sta2Dev);
3779 m_phySta2->AddChannel(spectrumChannel);
3781 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3783 m_phySta2->SetMobility(sta2Mobility);
3784 sta2Dev->SetPhy(m_phySta2);
3785 sta2Node->AggregateObject(sta2Mobility);
3786 sta2Node->AddDevice(sta2Dev);
3787
3788 Ptr<Node> sta3Node = CreateObject<Node>();
3790 sta3Dev->SetStandard(WIFI_STANDARD_80211ax);
3791 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3794 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3796 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3797 m_phySta3->SetDevice(sta3Dev);
3798 m_phySta3->AddChannel(spectrumChannel);
3800 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3802 m_phySta3->SetMobility(sta3Mobility);
3803 sta3Dev->SetPhy(m_phySta3);
3804 sta3Node->AggregateObject(sta3Mobility);
3805 sta3Node->AddDevice(sta3Dev);
3806
3807 Ptr<Node> interfererNode = CreateObject<Node>();
3810 m_phyInterferer->SetDevice(interfererDev);
3811 m_phyInterferer->SetChannel(spectrumChannel);
3812 m_phyInterferer->SetDutyCycle(1);
3813 interfererNode->AddDevice(interfererDev);
3814
3815 // Configure power attributes of all wifi devices
3816 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3817 for (auto& phy : phys)
3818 {
3819 phy->SetAttribute("TxGain", DoubleValue(1.0));
3820 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3821 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3822 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3823 phy->SetAttribute("RxGain", DoubleValue(2.0));
3824 // test assumes no rejection power for simplicity
3825 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3826 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3827 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3828 }
3829}
3830
3831void
3833{
3834 m_phyAp->Dispose();
3835 m_phyAp = nullptr;
3836 m_phySta1->Dispose();
3837 m_phySta1 = nullptr;
3838 m_phySta2->Dispose();
3839 m_phySta2 = nullptr;
3840 m_phySta3->Dispose();
3841 m_phySta3 = nullptr;
3843 m_phyInterferer = nullptr;
3844}
3845
3846void
3848{
3849 NS_LOG_INFO(log);
3850}
3851
3852void
3854 bool solicited,
3855 WifiPhyState expectedStateAtEnd,
3856 uint32_t expectedSuccessFromSta1,
3857 uint32_t expectedFailuresFromSta1,
3858 uint32_t expectedBytesFromSta1,
3859 uint32_t expectedSuccessFromSta2,
3860 uint32_t expectedFailuresFromSta2,
3861 uint32_t expectedBytesFromSta2,
3862 bool scheduleTxSta1,
3863 Time ulTimeDifference,
3864 WifiPhyState expectedStateBeforeEnd,
3865 TrigVectorInfo error)
3866{
3867 static uint64_t uid = 0;
3868
3869 // AP sends an SU packet preceding HE TB PPDUs
3872 this,
3873 0,
3874 50,
3875 ++uid,
3876 0);
3877 if (!solicited)
3878 {
3879 // UID of TB PPDUs will be different than the one of the preceding frame
3880 ++uid;
3881 }
3882 else
3883 {
3885 }
3886 // STA1 and STA2 send MU UL PPDUs addressed to AP
3889 m_apPhyStateListener.get());
3890 if (scheduleTxSta1)
3891 {
3892 Simulator::Schedule(delay,
3894 this,
3895 1,
3896 1,
3897 1000,
3898 uid,
3899 0,
3900 false);
3901 }
3902 Simulator::Schedule(delay + ulTimeDifference,
3904 this,
3905 2,
3906 2,
3907 1001,
3908 uid,
3909 0,
3910 false);
3911
3912 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3915 this,
3916 m_phyAp,
3917 expectedStateBeforeEnd);
3918 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3920 this,
3921 m_phyAp,
3922 expectedStateAtEnd);
3923 // TODO: add checks on TX stop for STAs
3924
3925 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3926 expectedFailuresFromSta2 >
3927 0)
3928 {
3929 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3930 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3931 // The expected time at which the reception is started corresponds to the time at which the
3932 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3933 const Time expectedPayloadStart = delay + MicroSeconds(48);
3934 // The expected time at which the reception is terminated corresponds to the time at which
3935 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3936 // received HE TB PPDU and the last received HE TB PPDU.
3937 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3938 // At the end of the transmission, verify that a single RX start notification shall have
3939 // been notified when the reception of the first HE RB PPDU starts.
3940 Simulator::Schedule(expectedPayloadEnd,
3942 this,
3943 1,
3944 Simulator::Now() + expectedPayloadStart);
3945 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3946 // notification shall have been notified when the reception of the last HE RB PPDU ends
3947 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3949 this,
3950 1,
3951 Simulator::Now() + expectedPayloadEnd,
3952 isSuccess);
3953 }
3954
3955 delay += MilliSeconds(100);
3956 // Check reception state from STA 1
3957 Simulator::Schedule(delay,
3959 this,
3960 expectedSuccessFromSta1,
3961 expectedFailuresFromSta1,
3962 expectedBytesFromSta1);
3963 // Check reception state from STA 2
3964 Simulator::Schedule(delay,
3966 this,
3967 expectedSuccessFromSta2,
3968 expectedFailuresFromSta2,
3969 expectedBytesFromSta2);
3970 // Verify events data have been cleared
3972
3973 delay += MilliSeconds(100);
3975}
3976
3977void
3979 Watt_u rxPowerNonOfdmaRu1,
3980 Watt_u rxPowerNonOfdmaRu2,
3981 Watt_u rxPowerOfdmaRu1,
3982 Watt_u rxPowerOfdmaRu2)
3983{
3984 const auto detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3985 const auto txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3986 const auto txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3987 const auto hePhy = m_phyAp->GetHePhy();
3988 const auto nonOfdmaDuration = hePhy->CalculateNonHeDurationForHeTb(txVectorSta2);
3989 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonHeDurationForHeTb(txVectorSta1));
3990
3991 std::vector<Watt_u> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3992 std::vector<WifiSpectrumBandInfo> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3993 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
3994 std::vector<Watt_u> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
3995 std::vector<WifiSpectrumBandInfo> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
3996 hePhy->GetRuBandForRx(txVectorSta2, 2)};
3997
3998 for (uint8_t i = 0; i < 2; ++i)
3999 {
4000 /**
4001 * Perform checks at AP
4002 */
4003 // Check received power on non-OFDMA portion
4005 delay + detectionDuration +
4006 NanoSeconds(1), // just after beginning of portion (once event is stored)
4008 this,
4009 m_phyAp,
4010 nonOfdmaBand[i],
4011 rxPowerNonOfdma[i]);
4012 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4014 this,
4015 m_phyAp,
4016 nonOfdmaBand[i],
4017 rxPowerNonOfdma[i]);
4018 // Check received power on OFDMA portion
4019 Simulator::Schedule(delay + nonOfdmaDuration +
4020 NanoSeconds(1), // just after beginning of portion
4022 this,
4023 m_phyAp,
4024 ofdmaBand[i],
4025 rxPowerOfdma[i]);
4027 NanoSeconds(1), // just before end of portion
4029 this,
4030 m_phyAp,
4031 ofdmaBand[i],
4032 rxPowerOfdma[i]);
4033
4034 /**
4035 * Perform checks for non-transmitting STA (STA 3).
4036 * Cannot use CheckNonOfdmaRxPower method since current event may be reset if
4037 * preamble not detected (e.g. not on primary).
4038 */
4039 // Check received power on non-OFDMA portion
4041 delay + detectionDuration +
4042 NanoSeconds(1), // just after beginning of portion (once event is stored)
4044 this,
4045 m_phySta3,
4046 nonOfdmaBand[i],
4047 rxPowerNonOfdma[i]);
4048 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4050 this,
4051 m_phySta3,
4052 nonOfdmaBand[i],
4053 rxPowerNonOfdma[i]);
4054 // Check received power on OFDMA portion
4055 Simulator::Schedule(delay + nonOfdmaDuration +
4056 NanoSeconds(1), // just after beginning of portion
4058 this,
4059 m_phySta3,
4060 ofdmaBand[i],
4061 rxPowerOfdma[i]);
4063 NanoSeconds(1), // just before end of portion
4065 this,
4066 m_phySta3,
4067 ofdmaBand[i],
4068 rxPowerOfdma[i]);
4069 }
4070
4071 if (rxPowerOfdmaRu1 != Watt_u{0.0})
4072 {
4073 /**
4074 * Perform checks for transmitting STA (STA 2) to ensure it has correctly logged
4075 * power received from other transmitting STA (STA 1).
4076 * Cannot use CheckNonOfdmaRxPower method since current event not set.
4077 */
4078 const auto rxPowerNonOfdmaSta1Only =
4079 (m_channelWidth >= MHz_u{40})
4080 ? rxPowerNonOfdma[0]
4081 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4082 // Check received power on non-OFDMA portion
4084 delay + detectionDuration +
4085 NanoSeconds(1), // just after beginning of portion (once event is stored)
4087 this,
4088 m_phySta2,
4089 nonOfdmaBand[0],
4090 rxPowerNonOfdmaSta1Only);
4091 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4093 this,
4094 m_phySta2,
4095 nonOfdmaBand[0],
4096 rxPowerNonOfdmaSta1Only);
4097 // Check received power on OFDMA portion
4098 Simulator::Schedule(delay + nonOfdmaDuration +
4099 NanoSeconds(1), // just after beginning of portion
4101 this,
4102 m_phySta2,
4103 ofdmaBand[0],
4104 rxPowerOfdma[0]);
4106 NanoSeconds(1), // just before end of portion
4108 this,
4109 m_phySta2,
4110 ofdmaBand[0],
4111 rxPowerOfdma[0]);
4112 }
4113}
4114
4115void
4117{
4120 int64_t streamNumber = 0;
4121 m_phyAp->AssignStreams(streamNumber);
4122 m_phySta1->AssignStreams(streamNumber);
4123 m_phySta2->AssignStreams(streamNumber);
4124 m_phySta3->AssignStreams(streamNumber);
4125
4126 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
4131 ->number;
4132
4141
4142 Time delay;
4144 delay += Seconds(1);
4145
4146 /**
4147 * In all the following tests, 2 HE TB PPDUs of the same UL MU transmission
4148 * are sent on RU 1 for STA 1 and RU 2 for STA 2.
4149 * The difference between solicited and unsolicited lies in that their PPDU
4150 * ID correspond to the one of the immediately preceding HE SU PPDU (thus
4151 * mimicking trigger frame reception).
4152 */
4153
4154 //---------------------------------------------------------------------------
4155 // Verify that both solicited HE TB PPDUs have been corrected received
4156 Simulator::Schedule(delay,
4158 this,
4159 "Reception of solicited HE TB PPDUs");
4160 ScheduleTest(delay,
4161 true,
4162 WifiPhyState::IDLE,
4163 1,
4164 0,
4165 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4166 1,
4167 0,
4168 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4169 delay += Seconds(1);
4170
4171 //---------------------------------------------------------------------------
4172 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4173 // corrected received
4175 delay,
4177 this,
4178 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4179 ScheduleTest(delay,
4180 true,
4181 WifiPhyState::IDLE,
4182 1,
4183 0,
4184 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4185 1,
4186 0,
4187 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4188 true,
4189 NanoSeconds(100));
4190 delay += Seconds(1);
4191
4192 //---------------------------------------------------------------------------
4193 // Verify that no unsolicited HE TB PPDU is received
4194 Simulator::Schedule(delay,
4196 this,
4197 "Dropping of unsolicited HE TB PPDUs");
4198 ScheduleTest(delay,
4199 false,
4200 WifiPhyState::IDLE,
4201 0,
4202 0,
4203 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4204 0,
4205 0,
4206 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4207 true,
4208 Seconds(0),
4209 WifiPhyState::CCA_BUSY);
4210 delay += Seconds(1);
4211
4212 //---------------------------------------------------------------------------
4213 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4214 Simulator::Schedule(delay,
4216 this,
4217 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4218 ScheduleTest(delay,
4219 true,
4220 WifiPhyState::IDLE,
4221 0,
4222 0,
4223 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4224 0,
4225 0,
4226 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4227 true,
4228 Seconds(0),
4229 WifiPhyState::CCA_BUSY,
4231 delay += Seconds(1);
4232
4233 //---------------------------------------------------------------------------
4234 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4235 Simulator::Schedule(delay,
4237 this,
4238 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4239 ScheduleTest(delay,
4240 true,
4241 WifiPhyState::IDLE,
4242 0,
4243 0,
4244 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4245 0,
4246 0,
4247 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4248 true,
4249 Seconds(0),
4250 WifiPhyState::CCA_BUSY,
4251 UL_LENGTH);
4252 delay += Seconds(1);
4253
4254 //---------------------------------------------------------------------------
4255 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4256 Simulator::Schedule(delay,
4258 this,
4259 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4260 ScheduleTest(delay,
4261 true,
4262 WifiPhyState::IDLE,
4263 0,
4264 0,
4265 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4266 0,
4267 0,
4268 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4269 true,
4270 Seconds(0),
4271 WifiPhyState::CCA_BUSY,
4272 AID);
4273 delay += Seconds(1);
4274
4275 //---------------------------------------------------------------------------
4276 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4277 // impacted
4279 delay,
4281 this,
4282 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4283 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4284 BandInfo bandInfo;
4285 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 4));
4286 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
4287 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
4288 Bands bands;
4289 bands.push_back(bandInfo);
4290
4291 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4292 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4293 Watt_u interferencePower{0.1};
4294 *interferencePsdRu1 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
4295
4298 this,
4299 interferencePsdRu1,
4300 MilliSeconds(100));
4302 delay,
4303 true,
4304 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4305 // interference
4306 0,
4307 1,
4308 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4309 1,
4310 0,
4311 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4312 delay += Seconds(1);
4313
4314 //---------------------------------------------------------------------------
4315 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4316 // impacted
4318 delay,
4320 this,
4321 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4322 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4323 bandInfo.fc = MHzToHz(m_frequency + (m_channelWidth / 4));
4324 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
4325 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
4326 bands.clear();
4327 bands.push_back(bandInfo);
4328
4329 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4330 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4331 *interferencePsdRu2 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
4332
4335 this,
4336 interferencePsdRu2,
4337 MilliSeconds(100));
4338 ScheduleTest(delay,
4339 true,
4340 (m_channelWidth >= MHz_u{40})
4341 ? WifiPhyState::IDLE
4342 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4343 // generated in its primary channel
4344 1,
4345 0,
4346 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4347 0,
4348 1,
4349 0); // Reception of the PSDU from STA 2 should have failed (since interference
4350 // occupies RU 2)
4351 delay += Seconds(1);
4352
4353 //---------------------------------------------------------------------------
4354 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4355 // been impacted
4356 Simulator::Schedule(delay,
4358 this,
4359 "Reception of solicited HE TB PPDUs with interference on the full band "
4360 "during PSDU reception");
4361 // A strong non-wifi interference is generated on the full band during PSDU reception
4362 bandInfo.fc = MHzToHz(m_frequency);
4363 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 2);
4364 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 2);
4365 bands.clear();
4366 bands.push_back(bandInfo);
4367
4368 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4369 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4370 *interferencePsdAll = interferencePower / (MHzToHz(m_channelWidth) * 20);
4371
4374 this,
4375 interferencePsdAll,
4376 MilliSeconds(100));
4378 delay,
4379 true,
4380 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4381 // interference
4382 0,
4383 1,
4384 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4385 0,
4386 1,
4387 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4388 // 2)
4389 delay += Seconds(1);
4390
4391 //---------------------------------------------------------------------------
4392 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4393 // solicited HE TB PPDUs have been impacted if they are on the same
4394 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4395 Simulator::Schedule(delay,
4397 this,
4398 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4399 "1 during PSDU reception");
4400 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4403 this,
4404 3,
4405 1,
4406 1002,
4407 1,
4408 0,
4409 false);
4410 // Expected figures from STA 2
4411 uint32_t succ;
4412 uint32_t fail;
4413 uint32_t bytes;
4414 if (m_channelWidth > MHz_u{20})
4415 {
4416 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4417 // interference from STA 3 on distinct 20 MHz channel)
4418 succ = 1;
4419 fail = 0;
4420 bytes = 1001;
4421 }
4422 else
4423 {
4424 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4425 // same 20 MHz channel)
4426 succ = 0;
4427 fail = 1;
4428 bytes = 0;
4429 }
4430 ScheduleTest(delay,
4431 true,
4432 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4433 // interference on measurement channel width
4434 0,
4435 1,
4436 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4437 // STA 3 on same 20 MHz channel)
4438 succ,
4439 fail,
4440 bytes);
4441 delay += Seconds(1);
4442
4443 //---------------------------------------------------------------------------
4444 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4445 // solicited HE TB PPDUs have been impacted if they are on the same
4446 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4447 Simulator::Schedule(delay,
4449 this,
4450 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4451 "2 during PSDU reception");
4452 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4455 this,
4456 3,
4457 2,
4458 1002,
4459 1,
4460 0,
4461 false);
4462 // Expected figures from STA 1
4463 if (m_channelWidth > MHz_u{20})
4464 {
4465 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4466 // interference from STA 3 on distinct 20 MHz channel)
4467 succ = 1;
4468 fail = 0;
4469 bytes = 1000;
4470 }
4471 else
4472 {
4473 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4474 // same 20 MHz channel)
4475 succ = 0;
4476 fail = 1;
4477 bytes = 0;
4478 }
4479 ScheduleTest(delay,
4480 true,
4481 (m_channelWidth >= MHz_u{40})
4482 ? WifiPhyState::IDLE
4483 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4484 // TB PPDU on primary channel
4485 succ,
4486 fail,
4487 bytes,
4488 0,
4489 1,
4490 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4491 // STA 3 on same 20 MHz channel)
4492 delay += Seconds(1);
4493
4494 //---------------------------------------------------------------------------
4495 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4496 // impacted
4498 delay,
4500 this,
4501 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4502 // One HE SU arrives at AP during the 400ns window
4503 Simulator::Schedule(delay + NanoSeconds(300),
4505 this,
4506 3,
4507 1002,
4508 1,
4509 0);
4511 delay,
4512 true,
4513 WifiPhyState::IDLE,
4514 0,
4515 1,
4516 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4517 0,
4518 1,
4519 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4520 delay += Seconds(1);
4521
4522 //---------------------------------------------------------------------------
4523 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4524 // received
4525 Simulator::Schedule(delay,
4527 this,
4528 "Reception of solicited HE TB PPDU only on RU 2");
4529 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4530 // otherwise
4533 this,
4534 m_phySta3,
4535 (m_channelWidth >= MHz_u{40})
4536 ? WifiPhyState::IDLE
4537 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4538 // IDLE if HE TB PPDU on primary channel
4539 ScheduleTest(delay,
4540 true,
4541 WifiPhyState::IDLE,
4542 0,
4543 0,
4544 0, // No transmission scheduled for STA 1
4545 1,
4546 0,
4547 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4548 false,
4549 Seconds(0),
4550 WifiPhyState::RX); // Measurement channel is total channel width
4551 delay += Seconds(1);
4552
4553 //---------------------------------------------------------------------------
4554 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4555 Simulator::Schedule(delay,
4557 this,
4558 "Measure power for reception of HE TB PPDU only on RU 2");
4559 auto rxPower = DbmToW(
4560 dBm_u{19}); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4562 (m_channelWidth >= MHz_u{40}) ? Watt_u{0.0} : rxPower,
4563 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4564 Watt_u{0.0},
4565 rxPower);
4566 ScheduleTest(delay,
4567 true,
4568 WifiPhyState::IDLE,
4569 0,
4570 0,
4571 0, // No transmission scheduled for STA 1
4572 1,
4573 0,
4574 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4575 false,
4576 Seconds(0),
4577 WifiPhyState::RX); // Measurement channel is total channel width
4578 delay += Seconds(1);
4579
4580 //---------------------------------------------------------------------------
4581 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4582 // limitation enforced
4584 delay,
4586 this,
4587 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4588 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4589 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4590 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4592 this,
4593 m_phySta2,
4594 dBm_per_MHz_u{3});
4595
4596 rxPower = (m_channelWidth > MHz_u{40})
4597 ? DbmToW(dBm_u{19})
4598 : DbmToW(dBm_u{18.0103}); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4599 // transmitted only on one 20 MHz channel
4600 auto rxPowerOfdma = rxPower;
4601 if (m_channelWidth <= MHz_u{40})
4602 {
4603 rxPowerOfdma =
4604 (m_channelWidth == MHz_u{20})
4605 ? DbmToW(dBm_u{14.0309}) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4606 : DbmToW(dBm_u{18.0103}); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4607 }
4609 (m_channelWidth >= MHz_u{40}) ? Watt_u{0.0} : rxPower,
4610 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4611 Watt_u{0.0},
4612 rxPowerOfdma);
4613
4614 // Reset PSD limitation once HE TB has been sent
4617 this,
4618 m_phySta2,
4619 dBm_per_MHz_u{100});
4620 ScheduleTest(delay,
4621 true,
4622 WifiPhyState::IDLE,
4623 0,
4624 0,
4625 0, // No transmission scheduled for STA 1
4626 1,
4627 0,
4628 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4629 false,
4630 Seconds(0),
4631 WifiPhyState::RX); // Measurement channel is total channel width
4632 delay += Seconds(1);
4633
4634 //---------------------------------------------------------------------------
4635 // Measure the power of 2 solicited HE TB PPDU from both STAs
4636 Simulator::Schedule(delay,
4638 this,
4639 "Measure power for reception of HE TB PPDU on both RUs");
4640 rxPower = DbmToW(
4641 dBm_u{19}); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4642 const auto rxPowerNonOfdma =
4643 (m_channelWidth >= MHz_u{40})
4644 ? rxPower
4645 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4646 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4647 ScheduleTest(delay,
4648 true,
4649 WifiPhyState::IDLE,
4650 1,
4651 0,
4652 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4653 1,
4654 0,
4655 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4656 delay += Seconds(1);
4657
4658 //---------------------------------------------------------------------------
4659 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4660 // ongoing)
4661 Simulator::Schedule(delay,
4663 this,
4664 "Reception of an HE TB PPDU from another BSS");
4665 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4667 Simulator::Schedule(delay + MilliSeconds(100),
4669 this,
4670 3,
4671 1,
4672 1002,
4673 1,
4674 2,
4675 false);
4676
4677 // Verify events data have been cleared
4678 Simulator::Schedule(delay + MilliSeconds(200),
4680 this);
4681
4683 delay += Seconds(1);
4684
4685 //---------------------------------------------------------------------------
4686 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4687 // corrected received
4689 delay,
4691 this,
4692 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4693 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4697 this,
4698 3,
4699 1,
4700 1002,
4701 1,
4702 2,
4703 true);
4704 ScheduleTest(delay,
4705 true,
4706 WifiPhyState::CCA_BUSY,
4707 1,
4708 0,
4709 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4710 1,
4711 0,
4712 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4713 true,
4714 NanoSeconds(200));
4715 delay += Seconds(1);
4716
4718}
4719
4720void
4722{
4723 m_frequency = MHz_u{5180};
4724 m_channelWidth = MHz_u{20};
4726 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4727 RunOne();
4728
4729 m_frequency = MHz_u{5190};
4730 m_channelWidth = MHz_u{40};
4732 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4733 RunOne();
4734
4735 m_frequency = MHz_u{5210};
4736 m_channelWidth = MHz_u{80};
4738 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4739 RunOne();
4740
4741 m_frequency = MHz_u{5250};
4742 m_channelWidth = MHz_u{160};
4744 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4745 RunOne();
4746
4748}
4749
4750/**
4751 * @ingroup wifi-test
4752 * @ingroup tests
4753 *
4754 * @brief PHY padding exclusion test
4755 */
4757{
4758 public:
4760 ~TestPhyPaddingExclusion() override;
4761
4762 private:
4763 void DoSetup() override;
4764 void DoTeardown() override;
4765 void DoRun() override;
4766
4767 /**
4768 * Send HE TB PPDU function
4769 * @param txStaId the ID of the TX STA
4770 * @param index the RU index used for the transmission
4771 * @param payloadSize the size of the payload in bytes
4772 * @param txDuration the duration of the PPDU
4773 */
4774 void SendHeTbPpdu(uint16_t txStaId,
4775 std::size_t index,
4776 std::size_t payloadSize,
4777 Time txDuration);
4778 /**
4779 * Set TRIGVECTOR for HE TB PPDU
4780 *
4781 * @param ppduDuration the duration of the HE TB PPDU
4782 */
4783 void SetTrigVector(Time ppduDuration);
4784
4785 /**
4786 * Generate interference function
4787 * @param interferencePsd the PSD of the interference to be generated
4788 * @param duration the duration of the interference
4789 */
4790 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4791 /**
4792 * Stop interference function
4793 */
4794 void StopInterference();
4795
4796 /**
4797 * Run one function
4798 */
4799 void RunOne();
4800
4801 /**
4802 * Check the received PSDUs from STA1
4803 * @param expectedSuccess the expected number of success
4804 * @param expectedFailures the expected number of failures
4805 * @param expectedBytes the expected number of bytes
4806 */
4807 void CheckRxFromSta1(uint32_t expectedSuccess,
4808 uint32_t expectedFailures,
4809 uint32_t expectedBytes);
4810
4811 /**
4812 * Check the received PSDUs from STA2
4813 * @param expectedSuccess the expected number of success
4814 * @param expectedFailures the expected number of failures
4815 * @param expectedBytes the expected number of bytes
4816 */
4817 void CheckRxFromSta2(uint32_t expectedSuccess,
4818 uint32_t expectedFailures,
4819 uint32_t expectedBytes);
4820
4821 /**
4822 * Verify all events are cleared at end of TX or RX
4823 */
4824 void VerifyEventsCleared();
4825
4826 /**
4827 * Check the PHY state
4828 * @param phy the PHY
4829 * @param expectedState the expected state of the PHY
4830 */
4831 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
4832 /// @copydoc CheckPhyState
4834
4835 /**
4836 * Reset function
4837 */
4838 void Reset();
4839
4840 /**
4841 * Receive success function
4842 * @param psdu the PSDU
4843 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
4844 * @param txVector the transmit vector
4845 * @param statusPerMpdu reception status per MPDU
4846 */
4848 RxSignalInfo rxSignalInfo,
4849 const WifiTxVector& txVector,
4850 const std::vector<bool>& statusPerMpdu);
4851
4852 /**
4853 * Receive failure function
4854 * @param psdu the PSDU
4855 */
4856 void RxFailure(Ptr<const WifiPsdu> psdu);
4857
4861
4863
4864 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
4865 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
4866 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
4867 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
4868 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
4869 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
4870};
4871
4873 : TestCase("PHY padding exclusion test"),
4874 m_countRxSuccessFromSta1(0),
4875 m_countRxSuccessFromSta2(0),
4876 m_countRxFailureFromSta1(0),
4877 m_countRxFailureFromSta2(0),
4878 m_countRxBytesFromSta1(0),
4879 m_countRxBytesFromSta2(0)
4880{
4881}
4882
4883void
4885 std::size_t index,
4886 std::size_t payloadSize,
4887 Time txDuration)
4888{
4889 WifiConstPsduMap psdus;
4890
4891 WifiTxVector txVector{HePhy::GetHeMcs7(),
4892 0,
4894 NanoSeconds(1600),
4895 1,
4896 1,
4897 0,
4899 false,
4900 false,
4901 true};
4902
4903 HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4904 txVector.SetRu(ru, txStaId);
4905 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4906 txVector.SetNss(1, txStaId);
4907
4908 auto pkt = Create<Packet>(payloadSize);
4909 WifiMacHeader hdr;
4911 hdr.SetQosTid(0);
4912 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4913 std::ostringstream addr;
4914 addr << "00:00:00:00:00:0" << txStaId;
4915 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4916 hdr.SetSequenceNumber(1);
4917 auto psdu = Create<WifiPsdu>(pkt, hdr);
4918 psdus.insert(std::make_pair(txStaId, psdu));
4919
4921 if (txStaId == 1)
4922 {
4923 phy = m_phySta1;
4924 }
4925 else if (txStaId == 2)
4926 {
4927 phy = m_phySta2;
4928 }
4929
4930 txVector.SetLength(
4931 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4932
4933 phy->SetPpduUid(0);
4934 phy->Send(psdus, txVector);
4935}
4936
4937void
4939{
4940 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
4941 m_phyInterferer->SetPeriod(duration);
4942 m_phyInterferer->Start();
4944}
4945
4946void
4951
4955
4956void
4958 RxSignalInfo rxSignalInfo,
4959 const WifiTxVector& txVector,
4960 const std::vector<bool>& /*statusPerMpdu*/)
4961{
4962 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
4963 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4964 {
4966 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
4967 }
4968 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4969 {
4971 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
4972 }
4973}
4974
4975void
4977{
4978 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
4979 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4980 {
4982 }
4983 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4984 {
4986 }
4987}
4988
4989void
4991 uint32_t expectedFailures,
4992 uint32_t expectedBytes)
4993{
4995 expectedSuccess,
4996 "The number of successfully received packets from STA 1 is not correct!");
4999 expectedFailures,
5000 "The number of unsuccessfuly received packets from STA 1 is not correct!");
5002 expectedBytes,
5003 "The number of bytes received from STA 1 is not correct!");
5004}
5005
5006void
5008 uint32_t expectedFailures,
5009 uint32_t expectedBytes)
5010{
5012 expectedSuccess,
5013 "The number of successfully received packets from STA 2 is not correct!");
5016 expectedFailures,
5017 "The number of unsuccessfuly received packets from STA 2 is not correct!");
5019 expectedBytes,
5020 "The number of bytes received from STA 2 is not correct!");
5021}
5022
5023void
5025{
5027 nullptr,
5028 "m_currentEvent for AP was not cleared");
5030 nullptr,
5031 "m_currentEvent for STA 1 was not cleared");
5033 nullptr,
5034 "m_currentEvent for STA 2 was not cleared");
5035}
5036
5037void
5039{
5040 // This is needed to make sure PHY state will be checked as the last event if a state change
5041 // occurred at the exact same time as the check
5043}
5044
5045void
5047{
5048 WifiPhyState currentState = phy->GetState()->GetState();
5049 NS_LOG_FUNCTION(this << currentState);
5050 NS_TEST_ASSERT_MSG_EQ(currentState,
5051 expectedState,
5052 "PHY State " << currentState << " does not match expected state "
5053 << expectedState << " at " << Simulator::Now());
5054}
5055
5056void
5069
5070void
5072{
5075 int64_t streamNumber = 0;
5076
5079 lossModel->SetFrequency(MHzToHz(DEFAULT_FREQUENCY));
5080 spectrumChannel->AddPropagationLossModel(lossModel);
5083 spectrumChannel->SetPropagationDelayModel(delayModel);
5084
5085 Ptr<Node> apNode = CreateObject<Node>();
5088 "Txop",
5089 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
5090 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5091 apDev->SetMac(apMac);
5094 apDev->SetHeConfiguration(heConfiguration);
5096 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5098 m_phyAp->SetErrorRateModel(apErrorModel);
5099 m_phyAp->SetDevice(apDev);
5100 m_phyAp->AddChannel(spectrumChannel);
5102 m_phyAp->AssignStreams(streamNumber);
5103 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
5108 ->number;
5109
5115 m_phyAp->SetMobility(apMobility);
5116 apDev->SetPhy(m_phyAp);
5117 apDev->SetStandard(WIFI_STANDARD_80211ax);
5118 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5119 apMac->SetWifiPhys({m_phyAp});
5120 apNode->AggregateObject(apMobility);
5121 apNode->AddDevice(apDev);
5122
5123 Ptr<Node> sta1Node = CreateObject<Node>();
5127 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5129 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5130 m_phySta1->SetDevice(sta1Dev);
5131 m_phySta1->AddChannel(spectrumChannel);
5133 m_phySta1->AssignStreams(streamNumber);
5137 m_phySta1->SetMobility(sta1Mobility);
5138 sta1Dev->SetPhy(m_phySta1);
5139 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
5140 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5141 sta1Node->AggregateObject(sta1Mobility);
5142 sta1Node->AddDevice(sta1Dev);
5143
5144 Ptr<Node> sta2Node = CreateObject<Node>();
5148 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5150 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5151 m_phySta2->SetDevice(sta2Dev);
5152 m_phySta2->AddChannel(spectrumChannel);
5154 m_phySta2->AssignStreams(streamNumber);
5158 m_phySta2->SetMobility(sta2Mobility);
5159 sta2Dev->SetPhy(m_phySta2);
5160 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
5161 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5162 sta2Node->AggregateObject(sta2Mobility);
5163 sta2Node->AddDevice(sta2Dev);
5164
5165 Ptr<Node> interfererNode = CreateObject<Node>();
5168 m_phyInterferer->SetDevice(interfererDev);
5169 m_phyInterferer->SetChannel(spectrumChannel);
5170 m_phyInterferer->SetDutyCycle(1);
5171 interfererNode->AddDevice(interfererDev);
5172}
5173
5174void
5176{
5177 m_phyAp->Dispose();
5178 m_phyAp = nullptr;
5179 m_phySta1->Dispose();
5180 m_phySta1 = nullptr;
5181 m_phySta2->Dispose();
5182 m_phySta2 = nullptr;
5184 m_phyInterferer = nullptr;
5185}
5186
5187void
5189{
5190 WifiTxVector trigVector{HePhy::GetHeMcs7(),
5191 0,
5193 NanoSeconds(1600),
5194 1,
5195 1,
5196 0,
5198 false,
5199 false,
5200 true};
5201 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5202 trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5203 trigVector.SetNss(1, 1);
5204 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5205 trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5206 trigVector.SetNss(1, 2);
5207 uint16_t length;
5208 std::tie(length, ppduDuration) =
5210 trigVector.SetLength(length);
5212 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5213}
5214
5215void
5217{
5218 Time expectedPpduDuration = NanoSeconds(292800);
5219 Time ppduWithPaddingDuration =
5220 expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5221
5223
5224 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5227 this,
5228 1,
5229 1,
5230 1000,
5231 ppduWithPaddingDuration);
5234 this,
5235 2,
5236 2,
5237 1001,
5238 ppduWithPaddingDuration);
5239
5240 // Set TRIGVECTOR on AP
5243 this,
5244 ppduWithPaddingDuration);
5245
5246 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5247 Simulator::Schedule(Seconds(1) + ppduWithPaddingDuration - NanoSeconds(1),
5249 this,
5250 m_phyAp,
5251 WifiPhyState::RX);
5252 Simulator::Schedule(Seconds(1) + ppduWithPaddingDuration,
5254 this,
5255 m_phyAp,
5256 WifiPhyState::IDLE);
5257
5258 // One PSDU of 1000 bytes should have been successfully received from STA 1
5260 // One PSDU of 1001 bytes should have been successfully received from STA 2
5262 // Verify events data have been cleared
5264
5266
5267 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5270 this,
5271 1,
5272 1,
5273 1000,
5274 ppduWithPaddingDuration);
5277 this,
5278 2,
5279 2,
5280 1001,
5281 ppduWithPaddingDuration);
5282
5283 // Set TRIGVECTOR on AP
5286 this,
5287 ppduWithPaddingDuration);
5288
5289 // A strong non-wifi interference is generated on RU 1 during padding reception
5290 BandInfo bandInfo;
5292 bandInfo.fl = bandInfo.fc - MHzToHz(DEFAULT_CHANNEL_WIDTH / 4);
5293 bandInfo.fh = bandInfo.fc + MHzToHz(DEFAULT_CHANNEL_WIDTH / 4);
5294 Bands bands;
5295 bands.push_back(bandInfo);
5296
5297 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5298 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5299 Watt_u interferencePower{0.1};
5300 *interferencePsdRu1 = interferencePower / (MHzToHz(DEFAULT_CHANNEL_WIDTH / 2) * 20);
5301
5302 Simulator::Schedule(Seconds(2) + MicroSeconds(50) + expectedPpduDuration,
5304 this,
5305 interferencePsdRu1,
5306 MilliSeconds(100));
5307
5308 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5309 // CCA_BUSY instead of IDLE due to the interference)
5310 Simulator::Schedule(Seconds(2) + ppduWithPaddingDuration - NanoSeconds(1),
5312 this,
5313 m_phyAp,
5314 WifiPhyState::RX);
5315 Simulator::Schedule(Seconds(2) + ppduWithPaddingDuration,
5317 this,
5318 m_phyAp,
5319 WifiPhyState::CCA_BUSY);
5320
5321 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5322 // occupies RU 1 after payload, during PHY padding)
5324 // One PSDU of 1001 bytes should have been successfully received from STA 2
5326 // Verify events data have been cleared
5328
5330
5332
5334}
5335
5336/**
5337 * @ingroup wifi-test
5338 * @ingroup tests
5339 *
5340 * @brief UL-OFDMA power control test
5341 */
5343{
5344 public:
5346 ~TestUlOfdmaPowerControl() override;
5347
5348 private:
5349 void DoSetup() override;
5350 void DoTeardown() override;
5351 void DoRun() override;
5352
5353 /**
5354 * Send a MU BAR through the AP to the STAs listed in the provided vector.
5355 *
5356 * @param staIds the vector of STA-IDs of STAs to address the MU-BAR to
5357 */
5358 void SendMuBar(std::vector<uint16_t> staIds);
5359
5360 /**
5361 * Send a QoS Data packet to the destination station in order
5362 * to set up a block Ack session (so that the MU-BAR may have a reply).
5363 *
5364 * @param destination the address of the destination station
5365 */
5366 void SetupBa(Address destination);
5367
5368 /**
5369 * Run one simulation with an optional BA session set up phase.
5370 *
5371 * @param setupBa true if BA session should be set up (i.e. upon first run),
5372 * false otherwise
5373 */
5374 void RunOne(bool setupBa);
5375
5376 /**
5377 * Replace the AP's callback on its PHY's ReceiveOkCallback
5378 * by the ReceiveOkCallbackAtAp method.
5379 */
5381
5382 /**
5383 * Receive OK callback function at AP.
5384 * This method will be plugged into the AP PHY's ReceiveOkCallback once the
5385 * block Ack session has been set up. This is done in the Reset function.
5386 * @param psdu the PSDU
5387 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
5388 * @param txVector the TXVECTOR used for the packet
5389 * @param statusPerMpdu reception status per MPDU
5390 */
5392 RxSignalInfo rxSignalInfo,
5393 const WifiTxVector& txVector,
5394 const std::vector<bool>& statusPerMpdu);
5395
5396 uint8_t m_bssColor; ///< BSS color
5397
5398 Ptr<WifiNetDevice> m_apDev; ///< network device of AP
5399 Ptr<WifiNetDevice> m_sta1Dev; ///< network device of STA 1
5400 Ptr<WifiNetDevice> m_sta2Dev; ///< network device of STA 2
5401
5403
5404 dBm_u m_txPowerAp; ///< transmit power of AP
5405 dBm_u m_txPowerStart; ///< minimum transmission power for STAs
5406 dBm_u m_txPowerEnd; ///< maximum transmission power for STAs
5407 uint8_t m_txPowerLevels; ///< number of transmission power levels for STAs
5408
5409 dBm_u m_requestedRssiSta1; ///< requested RSSI from STA 1 at AP for HE TB PPDUs
5410 dBm_u m_requestedRssiSta2; ///< requested RSSI from STA 2 at AP for HE TB PPDUs
5411
5412 dBm_u m_rssiSta1; ///< expected RSSI from STA 1 at AP for HE TB PPDUs
5413 dBm_u m_rssiSta2; ///< expected RSSI from STA 2 at AP for HE TB PPDUs
5414
5415 dB_u m_tol; ///< tolerance between received and expected RSSIs
5416};
5417
5419 : TestCase("UL-OFDMA power control test"),
5420 m_bssColor(1),
5421 m_txPowerAp(dBm_u{0}),
5422 m_txPowerStart(dBm_u{0}),
5423 m_txPowerEnd(dBm_u{0}),
5424 m_txPowerLevels(0),
5425 m_requestedRssiSta1(dBm_u{0}),
5426 m_requestedRssiSta2(dBm_u{0}),
5427 m_rssiSta1(dBm_u{0}),
5428 m_rssiSta2(dBm_u{0}),
5429 m_tol(dB_u{0.1})
5430{
5431}
5432
5434{
5435 m_phyAp = nullptr;
5436 m_apDev = nullptr;
5437 m_sta1Dev = nullptr;
5438 m_sta2Dev = nullptr;
5439}
5440
5441void
5443{
5444 // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5445 Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5446 m_apDev->Send(pkt, destination, 0);
5447}
5448
5449void
5450TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5451{
5452 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5453
5454 // Build MU-BAR trigger frame
5455 CtrlTriggerHeader muBar;
5456 muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5457 muBar.SetMoreTF(true);
5458 muBar.SetCsRequired(true);
5460 muBar.SetGiAndLtfType(NanoSeconds(1600), 2);
5461 muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5462 muBar.SetUlSpatialReuse(60500);
5463
5464 HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5465 std::size_t index = 1;
5466 int8_t ulTargetRssi = -40; // will be overwritten
5467 for (const auto& staId : staIds)
5468 {
5470 ui.SetAid12(staId);
5471 ui.SetRuAllocation({ru, index, true});
5472 ui.SetUlFecCodingType(true);
5473 ui.SetUlMcs(7);
5474 ui.SetUlDcm(false);
5475 ui.SetSsAllocation(1, 1);
5476 if (staId == 1)
5477 {
5478 ulTargetRssi = m_requestedRssiSta1;
5479 }
5480 else if (staId == 2)
5481 {
5482 ulTargetRssi = m_requestedRssiSta2;
5483 }
5484 else
5485 {
5486 NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5487 }
5488 ui.SetUlTargetRssi(ulTargetRssi);
5489
5492 bar.SetTidInfo(0);
5493 bar.SetStartingSequence(4095);
5495
5496 ++index;
5497 }
5498
5499 WifiTxVector tbTxVector{muBar.GetHeTbTxVector(staIds.front())};
5501 tbTxVector,
5503 .first);
5504
5505 WifiConstPsduMap psdus;
5506 WifiTxVector txVector{HePhy::GetHeMcs7(),
5507 0,
5509 NanoSeconds(800),
5510 1,
5511 1,
5512 0,
5514 false,
5515 false,
5516 false,
5517 m_bssColor};
5518
5519 auto bar = Create<Packet>();
5520 bar->AddHeader(muBar);
5521
5522 auto receiver = Mac48Address::GetBroadcast();
5523 if (staIds.size() == 1)
5524 {
5525 const auto aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5526 if (staIds.front() == aidSta1)
5527 {
5528 receiver = Mac48Address::ConvertFrom(m_sta1Dev->GetAddress());
5529 }
5530 else
5531 {
5532 NS_ASSERT(staIds.front() ==
5533 DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5534 receiver = Mac48Address::ConvertFrom(m_sta2Dev->GetAddress());
5535 }
5536 }
5537
5538 WifiMacHeader hdr;
5540 hdr.SetAddr1(receiver);
5541 hdr.SetAddr2(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5542 hdr.SetAddr3(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5543 hdr.SetDsNotTo();
5544 hdr.SetDsFrom();
5545 hdr.SetNoRetry();
5546 hdr.SetNoMoreFragments();
5547 auto psdu = Create<WifiPsdu>(bar, hdr);
5548
5549 auto nav = m_apDev->GetPhy()->GetSifs();
5550 const auto staId = staIds.front(); // either will do
5551 nav += SpectrumWifiPhy::CalculateTxDuration(GetBlockAckSize(BlockAckType::COMPRESSED),
5552 tbTxVector,
5554 staId);
5555 psdu->SetDuration(nav);
5556 psdus.insert(std::make_pair(SU_STA_ID, psdu));
5557
5558 m_phyAp->Send(psdus, txVector);
5559}
5560
5561void
5563 RxSignalInfo rxSignalInfo,
5564 const WifiTxVector& txVector,
5565 const std::vector<bool>& /*statusPerMpdu*/)
5566{
5567 NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5568 const auto rssi = rxSignalInfo.rssi;
5569 NS_ASSERT(psdu->GetNMpdus() == 1);
5570 const auto& hdr = psdu->GetHeader(0);
5571 NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5572 if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5573 {
5575 rssi,
5576 m_rssiSta1,
5577 m_tol,
5578 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5579 << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5580 }
5581 else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5582 {
5584 rssi,
5585 m_rssiSta2,
5586 m_tol,
5587 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5588 << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5589 }
5590 else
5591 {
5592 NS_ABORT_MSG("The receiver address is unknown");
5593 }
5594}
5595
5596void
5598{
5599 // Now that BA session has been established we can plug our method
5600 m_phyAp->SetReceiveOkCallback(
5602}
5603
5604void
5606{
5607 auto apNode = CreateObject<Node>();
5608 NodeContainer staNodes;
5609 staNodes.Create(2);
5610
5611 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5613 spectrumChannel->AddPropagationLossModel(lossModel);
5615 spectrumChannel->SetPropagationDelayModel(delayModel);
5616
5617 SpectrumWifiPhyHelper spectrumPhy;
5618 spectrumPhy.SetChannel(spectrumChannel);
5619 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5620 spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5621
5622 WifiHelper wifi;
5623 wifi.SetStandard(WIFI_STANDARD_80211ax);
5624 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5625 "DataMode",
5626 StringValue("HeMcs7"),
5627 "ControlMode",
5628 StringValue("HeMcs7"));
5629
5630 WifiMacHelper mac;
5631 mac.SetType("ns3::StaWifiMac");
5632 auto staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5633 WifiHelper::AssignStreams(staDevs, 0);
5634 m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5636 m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5638
5639 // Set the beacon interval long enough so that associated STAs may not consider link lost when
5640 // beacon generation is disabled during the actual tests. Having such a long interval also
5641 // avoids bloating logs with beacons during the set up phase.
5642 mac.SetType("ns3::ApWifiMac",
5643 "BeaconGeneration",
5644 BooleanValue(true),
5645 "BeaconInterval",
5646 TimeValue(MicroSeconds(1024 * 600)));
5647 m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5649 m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5652 // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5653 // set up for both STAs
5654
5655 MobilityHelper mobility;
5656 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5657 auto positionAlloc = CreateObject<ListPositionAllocator>();
5658 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5659 positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5660 positionAlloc->Add(
5661 Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5662 mobility.SetPositionAllocator(positionAlloc);
5663
5664 mobility.Install(apNode);
5665 mobility.Install(staNodes);
5666
5667 lossModel->SetDefaultLoss(50.0);
5668 lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5669 staNodes.Get(1)->GetObject<MobilityModel>(),
5670 56.0,
5671 true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5672}
5673
5674void
5676{
5677 m_phyAp->Dispose();
5678 m_phyAp = nullptr;
5679 m_apDev->Dispose();
5680 m_apDev = nullptr;
5681 m_sta1Dev->Dispose();
5682 m_sta1Dev = nullptr;
5683 m_sta2Dev->Dispose();
5684 m_sta2Dev = nullptr;
5685}
5686
5687void
5689{
5692 int64_t streamNumber = 0;
5693
5694 auto phySta1 = m_sta1Dev->GetPhy();
5695 auto phySta2 = m_sta2Dev->GetPhy();
5696
5697 m_phyAp->AssignStreams(streamNumber);
5698 phySta1->AssignStreams(streamNumber);
5699 phySta2->AssignStreams(streamNumber);
5700
5701 m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5702 m_phyAp->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerAp));
5703 m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5704
5705 phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5706 phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5707 phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5708
5709 phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5710 phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5711 phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5712
5713 Time relativeStart{};
5714 if (setupBa)
5715 {
5716 // Set up BA for each station once the association phase has ended
5717 // so that a BA session is established when the MU-BAR is received.
5720 this,
5721 m_sta1Dev->GetAddress());
5724 this,
5725 m_sta2Dev->GetAddress());
5726 relativeStart = MilliSeconds(1000);
5727 }
5728 else
5729 {
5730 auto apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5731 NS_ASSERT(apMac);
5732 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5733 }
5734
5735 Simulator::Schedule(relativeStart,
5737 this);
5738
5739 {
5740 // Verify that the RSSI from STA 1 is consistent with what was requested
5741 std::vector<uint16_t> staIds{1};
5742 Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5743 }
5744
5745 {
5746 // Verify that the RSSI from STA 2 is consistent with what was requested
5747 std::vector<uint16_t> staIds{2};
5748 Simulator::Schedule(relativeStart + MilliSeconds(20),
5750 this,
5751 staIds);
5752 }
5753
5754 {
5755 // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5756 std::vector<uint16_t> staIds{1, 2};
5757 Simulator::Schedule(relativeStart + MilliSeconds(40),
5759 this,
5760 staIds);
5761 }
5762
5763 Simulator::Stop(relativeStart + MilliSeconds(100));
5765}
5766
5767void
5769{
5770 // Power configurations
5771 m_txPowerAp = dBm_u{20}; // so as to have -30 and -36 dBm at STA 1 and STA 2 resp., since path
5772 // loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5773 m_txPowerStart = dBm_u{15};
5774
5775 // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5778
5779 // Test single power level
5780 {
5781 // STA power configurations: 15 dBm only
5782 m_txPowerEnd = dBm_u{15};
5783 m_txPowerLevels = 1;
5784
5785 // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5786 // regardless of the estimated path loss.
5787 m_rssiSta1 = dBm_u{-35}; // 15 dBm - 50 dB
5788 m_rssiSta2 = dBm_u{-41}; // 15 dBm - 56 dB
5789
5790 RunOne(true);
5791 }
5792
5793 // Test 2 dBm granularity
5794 {
5795 // STA power configurations: [15:2:25] dBm
5796 m_txPowerEnd = dBm_u{25};
5797 m_txPowerLevels = 6;
5798
5799 // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5800 // requested
5801 m_rssiSta1 = dBm_u{-29}; // 21 dBm - 50 dB
5802 m_rssiSta2 = dBm_u{-35}; // 21 dBm - 50 dB
5803
5804 RunOne(false);
5805 }
5806
5807 // Test 1 dBm granularity
5808 {
5809 // STA power configurations: [15:1:25] dBm
5810 m_txPowerEnd = dBm_u{25};
5811 m_txPowerLevels = 11;
5812
5813 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5814 m_rssiSta1 = dBm_u{-30}; // 20 dBm - 50 dB
5815 m_rssiSta2 = dBm_u{-36}; // 20 dBm - 56 dB
5816
5817 RunOne(false);
5818 }
5819
5820 // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5821 {
5822 // STA power configurations: [15:1:25] dBm
5823 m_txPowerEnd = dBm_u{25};
5824 m_txPowerLevels = 11;
5825
5826 // Requested UL RSSIs
5828 dBm_u{-28}; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5829 m_requestedRssiSta2 = dBm_u{-37}; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5830
5831 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5832 m_rssiSta1 = dBm_u{-28}; // 22 dBm - 50 dB
5833 m_rssiSta2 = dBm_u{-37}; // 19 dBm - 56 dB
5834
5835 RunOne(false);
5836 }
5837
5839}
5840
5841/**
5842 * @ingroup wifi-test
5843 * @ingroup tests
5844 *
5845 * @brief wifi PHY OFDMA Test Suite
5846 */
5848{
5849 public:
5851};
5852
5854 : TestSuite("wifi-phy-ofdma", Type::UNIT)
5855{
5856 AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5857 AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::Duration::QUICK);
5858 AddTestCase(new TestUlOfdmaPpduUid, TestCase::Duration::QUICK);
5859 AddTestCase(new TestMultipleHeTbPreambles, TestCase::Duration::QUICK);
5860 AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5861 AddTestCase(new TestPhyPaddingExclusion, TestCase::Duration::QUICK);
5862 AddTestCase(new TestUlOfdmaPowerControl, TestCase::Duration::QUICK);
5863}
5864
SpectrumWifiPhy used for testing OFDMA.
void SetTriggerFrameUid(uint64_t uid)
Since we assume trigger frame was previously received from AP, this is used to set its UID.
Ptr< const HePhy > GetHePhy() const
void(* TxPpduUidCallback)(uint64_t uid)
TracedCallback signature for UID of transmitted PPDU.
void SetPpduUid(uint64_t uid)
Set the global PPDU UID counter.
static TypeId GetTypeId()
Get the type ID.
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents()
Ptr< OfdmaTestHePhy > m_ofdmTestHePhy
Pointer to HE PHY instance used for OFDMA test.
void StartTx(Ptr< const WifiPpdu > ppdu) override
void DoDispose() override
Destructor implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
void Reset()
Reset data upon end of TX or RX.
Definition wifi-phy.cc:1967
TracedCallback< uint64_t > m_phyTxPpduUidTrace
Callback providing UID of the PPDU that is about to be transmitted.
void DoInitialize() override
Initialize() implementation.
Time GetEnergyDuration(Watt_u energy, WifiSpectrumBandInfo band)
Wrapper to InterferenceHelper method.
HE PHY slightly modified so as to return a given STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
OfdmaTestHePhy(uint16_t staId)
Constructor.
void SetGlobalPpduUid(uint64_t uid)
Set the global PPDU UID counter.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
uint16_t m_staId
ID of the STA to which this PHY belongs to.
PHY listener for OFDMA tests.
OfdmaTestPhyListener()=default
void NotifyRxEndError() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
bool m_lastRxSuccess
flag whether last RX has been successful
void NotifyRxStart(Time duration) override
Time GetLastRxStartNotification() const
Return the time at which the last RX start notification has been received.
void NotifySwitchingStart(Time duration) override
void NotifyWakeup() override
Notify listeners that we woke up.
uint32_t m_notifyRxStart
count number of RX start notifications
void Reset()
Reset function.
Time m_lastRxEnd
last time a RX end notification has been received
Time m_lastRxStart
last time a RX start notification has been received
Time GetLastRxEndNotification() const
Return the time at which the last RX end notification has been received.
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &) override
uint32_t m_notifyRxEnd
count number of RX end notifications
bool IsLastRxSuccess() const
Return whether last RX has been successful.
void NotifySleep() override
Notify listeners that we went to sleep.
uint32_t GetNumRxEndNotifications() const
Return the number of RX end notifications that has been received since the last reset.
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyTxStart(Time duration, dBm_u txPower) override
uint32_t GetNumRxStartNotifications() const
Return the number of RX start notifications that has been received since the last reset.
void NotifyOff() override
Notify listeners that we went to switch off.
void NotifyOn() override
Notify listeners that we went to switch on.
DL-OFDMA PHY puncturing test.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void DoRun() override
Implementation to actually run this TestCase.
Time m_expectedPpduDuration20Mhz
expected duration to send MU PPDU on 20 MHz RU
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
void ResetResults()
Reset the results.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
void RunOne()
Run one function.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2, const std::vector< bool > &puncturedSubchannels)
Send MU-PPDU function.
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 2.
Time m_expectedPpduDuration40Mhz
expected duration to send MU PPDU on 40 MHz RU
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void StopInterference()
Stop interference function.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 1.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint8_t m_indexSubchannel
Index of the subchannel (starting from 0) that should contain an interference and be punctured during...
uint32_t m_countRxSuccessSta1
count RX success for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 2.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
void RunOne()
Run one function.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 1.
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Time m_expectedPpduDuration
expected duration to send MU PPDU
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void RxSuccessSta3(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 3.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
uint32_t m_countRxSuccessSta3
count RX success for STA 3
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
uint32_t m_countRxBytesSta3
count RX bytes for STA 3
void RxFailureSta3(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 3.
void StopInterference()
Stop interference function.
void ResetResults()
Reset the results.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxSuccessSta1
count RX success for STA 1
void CheckResultsSta3(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 3.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
Send MU-PPDU function.
UL-OFDMA multiple RX events test.
WifiTxVector m_trigVector
TRIGVECTOR.
void RxHeTbPpdu(uint64_t uid, uint16_t staId, Watt_u txPower, size_t payloadSize)
Receive HE TB PPDU function.
Ptr< OfdmaSpectrumWifiPhy > m_phy
Phy.
void RxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void CheckHeTbPreambles(size_t nEvents, std::vector< uint64_t > uids)
Check the received HE TB preambles.
uint64_t m_totalBytesDropped
total number of dropped bytes
void CheckBytesDropped(size_t expectedBytesDropped)
Check the number of bytes dropped.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
PHY padding exclusion test.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
void DoRun() override
Implementation to actually run this TestCase.
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
void SetTrigVector(Time ppduDuration)
Set TRIGVECTOR for HE TB PPDU.
void Reset()
Reset function.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
void StopInterference()
Stop interference function.
void RunOne()
Run one function.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void ScheduleTest(Time delay, bool solicited, WifiPhyState expectedStateAtEnd, uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1, uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2, bool scheduleTxSta1=true, Time ulTimeDifference=Seconds(0), WifiPhyState expectedStateBeforeEnd=WifiPhyState::RX, TrigVectorInfo error=NONE)
Schedule test to perform.
std::shared_ptr< OfdmaTestPhyListener > m_apPhyStateListener
listener for AP PHY state transitions
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId, std::size_t index, uint8_t bssColor) const
Get TXVECTOR for HE TB PPDU.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification)
Check the the number of RX start notifications at the AP as well as the last time a RX start has been...
TrigVectorInfo
Erroneous info included in a TRIGVECTOR.
void SetBssColor(Ptr< WifiPhy > phy, uint8_t bssColor)
Set the BSS color.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void LogScenario(std::string log) const
Log scenario description.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor, bool incrementUid)
Send HE TB PPDU function.
void DoRun() override
Implementation to actually run this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void StopInterference()
Stop interference function.
void CheckOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, Watt_u expectedRxPower)
Check the received power for the OFDMA part of the HE TB PPDUs over the given band.
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void SetPsdLimit(Ptr< WifiPhy > phy, dBm_per_MHz_u psdLimit)
Set the PSD limit.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
void RunOne()
Run one function.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void CheckApRxEnd(uint32_t expectedNotifications, Time expectedLastNotification, bool expectedSuccess)
Check the the number of RX end notifications at the AP as well as the last time a RX end has been not...
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
void CheckNonOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, Watt_u expectedRxPower)
Check the received power for the non-OFDMA of the HE TB PPDUs over the given band.
void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE SU PPDU function.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void SetTrigVector(uint8_t bssColor, TrigVectorInfo error)
Set TRIGVECTOR for HE TB PPDU.
void SchedulePowerMeasurementChecks(Time delay, Watt_u rxPowerNonOfdmaRu1, Watt_u rxPowerNonOfdmaRu2, Watt_u rxPowerOfdmaRu1, Watt_u rxPowerOfdmaRu2)
Schedule power measurement related checks.
Time m_expectedPpduDuration
expected duration to send MU PPDU
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
UL-OFDMA power control test.
dBm_u m_requestedRssiSta2
requested RSSI from STA 2 at AP for HE TB PPDUs
void DoRun() override
Implementation to actually run this TestCase.
Ptr< WifiNetDevice > m_sta2Dev
network device of STA 2
dBm_u m_rssiSta2
expected RSSI from STA 2 at AP for HE TB PPDUs
dBm_u m_txPowerEnd
maximum transmission power for STAs
dBm_u m_txPowerStart
minimum transmission power for STAs
void SetupBa(Address destination)
Send a QoS Data packet to the destination station in order to set up a block Ack session (so that the...
Ptr< WifiNetDevice > m_sta1Dev
network device of STA 1
dBm_u m_rssiSta1
expected RSSI from STA 1 at AP for HE TB PPDUs
Ptr< WifiNetDevice > m_apDev
network device of AP
dBm_u m_requestedRssiSta1
requested RSSI from STA 1 at AP for HE TB PPDUs
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void ReplaceReceiveOkCallbackOfAp()
Replace the AP's callback on its PHY's ReceiveOkCallback by the ReceiveOkCallbackAtAp method.
dBm_u m_txPowerAp
transmit power of AP
uint8_t m_txPowerLevels
number of transmission power levels for STAs
dB_u m_tol
tolerance between received and expected RSSIs
void RunOne(bool setupBa)
Run one simulation with an optional BA session set up phase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void ReceiveOkCallbackAtAp(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive OK callback function at AP.
void SendMuBar(std::vector< uint16_t > staIds)
Send a MU BAR through the AP to the STAs listed in the provided vector.
UL-OFDMA PPDU UID attribution test.
void TxPpduSta1(uint64_t uid)
Transmitted PPDU information function for STA 1.
void ResetPpduUid()
Reset the global PPDU UID counter in WifiPhy.
void CheckUid(uint16_t staId, uint64_t expectedUid)
Check the UID of the transmitted PPDU.
void TxPpduAp(uint64_t uid)
Transmitted PPDU information function for AP.
void TxPpduSta2(uint64_t uid)
Transmitted PPDU information function for STA 2.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
uint64_t m_ppduUidAp
UID of PPDU transmitted by AP.
uint64_t m_ppduUidSta1
UID of PPDU transmitted by STA1.
uint64_t m_ppduUidSta2
UID of PPDU transmitted by STA2.
void DoRun() override
Implementation to actually run this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu()
Send MU-PPDU toward both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendTbPpdu()
Send TB-PPDU from both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
void SendSuPpdu(uint16_t txStaId)
Send SU-PPDU function.
wifi PHY OFDMA Test Suite
a polymophic address class
Definition address.h:90
Headers for BlockAckRequest.
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
Headers for Trigger frames.
CtrlTriggerUserInfoField & AddUserInfoField()
Append a new User Info field to this Trigger frame and return a non-const reference to it.
void SetApTxPower(int8_t power)
Set the AP TX Power subfield of the Common Info field.
WifiTxVector GetHeTbTxVector(uint16_t staId) const
Get the TX vector that the station with the given STA-ID will use to send the HE TB PPDU solicited by...
void SetType(TriggerFrameType type)
Set the Trigger frame type.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse subfield of the Common Info field.
void SetGiAndLtfType(Time guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
void SetMoreTF(bool more)
Set the More TF subfield of the Common Info field.
void SetUlBandwidth(MHz_u bw)
Set the bandwidth of the solicited HE TB PPDU.
User Info field of Trigger frames.
void SetAid12(uint16_t aid)
Set the AID12 subfield, which carries the 12 LSBs of the AID of the station for which this User Info ...
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
void SetUlMcs(uint8_t mcs)
Set the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
void SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader &bar)
Set the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlDcm(bool dcm)
Set the UL DCM subfield, which indicates whether or not DCM is used.
void SetSsAllocation(uint8_t startingSs, uint8_t nSs)
Set the SS Allocation subfield, which is present when the AID12 subfield is neither 0 nor 2045.
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
void SetRuAllocation(HeRu::RuSpec ru)
Set the RU Allocation subfield according to the specified RU.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
PHY entity for HE (11ax)
Definition he-phy.h:58
static WifiMode GetHeMcs9()
Return MCS 9 from HE MCS values.
static WifiMode GetHeMcs7()
Return MCS 7 from HE MCS values.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
Definition he-phy.cc:565
static std::pair< uint16_t, Time > ConvertHeTbPpduDurationToLSigLength(Time ppduDuration, const WifiTxVector &txVector, WifiPhyBand band)
Compute the L-SIG length value corresponding to the given HE TB PPDU duration.
Definition he-phy.cc:261
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Definition he-ppdu.h:106
@ PSD_NON_HE_PORTION
Non-HE portion of an HE PPDU.
Definition he-ppdu.h:105
RU Specification.
Definition he-ru.h:57
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition he-ru.cc:756
RuType
The different HE Resource Unit (RU) types.
Definition he-ru.h:32
@ RU_484_TONE
Definition he-ru.h:37
@ RU_996_TONE
Definition he-ru.h:38
@ RU_106_TONE
Definition he-ru.h:35
@ RU_242_TONE
Definition he-ru.h:36
an EUI-48 address
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
void Dispose()
Dispose of this Object.
Definition object.cc:247
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition phy-entity.cc:82
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition phy-entity.h:974
AttributeValue implementation for Pointer.
Ptr< T > Get() const
Definition pointer.h:223
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:594
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Make it easy to create and manage PHY objects for the spectrum model.
void SetChannel(const Ptr< SpectrumChannel > channel)
802.11 PHY layer model
void SetDevice(const Ptr< WifiNetDevice > device) override
Sets the device this PHY is associated with.
void StartRx(Ptr< SpectrumSignalParameters > rxParams, Ptr< const WifiSpectrumPhyInterface > interface)
Input method for delivering a signal from the spectrum channel and low-level PHY interface to this Sp...
void DoInitialize() override
Initialize() implementation.
MHz_u GetGuardBandwidth(MHz_u currentChannelWidth) const override
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
void DoDispose() override
Destructor implementation.
void StartTx(Ptr< const WifiPpdu > ppdu) override
Hold variables of type string.
Definition string.h:45
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
Forward calls to a chain of Callback.
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
Implements the IEEE 802.11 MAC header.
void SetNoMoreFragments()
Un-set the More Fragment bit in the Frame Control Field.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetDsFrom()
Set the From DS bit in the Frame Control field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetNoRetry()
Un-set the Retry bit in the Frame Control field.
create MAC layers for a ns3::WifiNetDevice.
void Set(std::string name, const AttributeValue &v)
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition wifi-phy.cc:678
void Send(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
This function is a wrapper for the Send variant that accepts a WifiConstPsduMap as first argument.
Definition wifi-phy.cc:1820
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition wifi-phy.cc:687
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > m_currentPreambleEvents
store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is be...
Definition wifi-phy.h:1361
std::tuple< uint8_t, MHz_u, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying a segment of an operating channel.
Definition wifi-phy.h:940
static Time GetPreambleDetectionDuration()
Definition wifi-phy.cc:1528
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition wifi-phy.cc:484
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition wifi-phy.cc:1009
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1587
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition wifi-phy.h:1384
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition wifi-phy.cc:490
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition wifi-phy.cc:1069
Ptr< Event > m_currentEvent
Hold the current event.
Definition wifi-phy.h:1359
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:760
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition wifi-phy.h:1364
void SetOperatingChannel(const WifiPhyOperatingChannel &channel)
If the standard for this object has not been set yet, store the channel settings corresponding to the...
Definition wifi-phy.cc:1135
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition wifi-phy.cc:708
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition wifi-phy.cc:653
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition wifi-phy.h:1346
void SetReceiveOkCallback(RxOkCallback callback)
Definition wifi-phy.cc:478
void Reset()
Reset data upon end of TX or RX.
Definition wifi-phy.cc:1967
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition wifi-phy.cc:1081
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition wifi-phy.cc:775
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition wifi-phy.cc:2363
receive notifications about PHY events.
static ConstIterator FindFirst(uint8_t number, MHz_u frequency, MHz_u width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first frequency segment matching the specified parameters.
This objects implements the PHY state machine of the Wifi device.
static Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(const std::vector< MHz_u > &centerFrequencies, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, const std::vector< WifiSpectrumBandIndices > &ru)
Create a transmit power spectral density corresponding to the OFDMA part of HE TB PPDUs for a given R...
static Ptr< SpectrumValue > CreateHeOfdmTxPowerSpectralDensity(MHz_u centerFrequency, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, dBr_u minInnerBand=dBr_u{-20}, dBr_u minOuterband=dBr_u{-28}, dBr_u lowestPoint=dBr_u{-40}, const std::vector< bool > &puncturedSubchannels={})
Create a transmit power spectral density corresponding to OFDM High Efficiency (HE) (802....
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetRu(HeRu::RuSpec ru, uint16_t staId)
Set the RU specification for the STA-ID.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition test.h:327
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1368
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1380
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1356
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPhyBand
Identifies the PHY band.
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Definition first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
WifiPhyState
The state of the PHY layer.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
std::vector< BandInfo > Bands
Container of BandInfo.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
Definition wifi-utils.h:135
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_CTL_BACKRESP
@ WIFI_MAC_QOSDATA
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
Definition wifi-utils.cc:33
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
Definition wifi-utils.cc:60
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
Definition wifi-utils.h:110
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
std::vector< uint16_t > RuAllocation
9 bits RU_ALLOCATION per 20 MHz
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:72
dBm_u rssi
RSSI.
Definition wifi-types.h:74
WifiSpectrumBandInfo structure containing info about a spectrum band.
static const MHz_u DEFAULT_FREQUENCY
static WifiPhyOfdmaTestSuite wifiPhyOfdmaTestSuite
the test suite
static const uint8_t DEFAULT_CHANNEL_NUMBER
static const WifiPhyBand DEFAULT_WIFI_BAND
static const MHz_u DEFAULT_CHANNEL_WIDTH
static const MHz_u DEFAULT_GUARD_WIDTH