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;
55static const MHz_u DEFAULT_CHANNEL_WIDTH = 20;
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 WifiTxVector txVector,
309 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 WifiTxVector txVector,
320 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 WifiTxVector txVector,
331 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 == 20)
487 {
488 ruType = HeRu::RU_106_TONE;
489 txVector.SetRuAllocation({96}, 0);
490 }
491 else if (m_channelWidth == 40)
492 {
493 ruType = HeRu::RU_242_TONE;
494 txVector.SetRuAllocation({192, 192}, 0);
495 }
496 else if (m_channelWidth == 80)
497 {
498 ruType = HeRu::RU_484_TONE;
499 txVector.SetRuAllocation({200, 200, 200, 200}, 0);
500 }
501 else if (m_channelWidth == 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 == 160 ? 1 : 2), m_channelWidth != 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 WifiTxVector txVector,
567 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 WifiTxVector txVector,
578 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 WifiTxVector txVector,
589 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(m_frequency * 1e6);
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 = (m_frequency - (m_channelWidth / 4)) * 1e6;
947 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
948 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
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 / ((m_channelWidth / 2) * 20e6);
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 = (m_frequency + (m_channelWidth / 4)) * 1e6;
1017 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
1018 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
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 / ((m_channelWidth / 2) * 20e6);
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 >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1057 this,
1058 m_phySta2,
1059 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1062 this,
1063 m_phySta3,
1064 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1065
1066 // One PSDU of 1000 bytes should have been successfully received by STA 1
1069 this,
1070 1,
1071 0,
1072 1000);
1073 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1074 // occupies RU 2)
1076 // No PSDU should have been received by STA3
1078
1080
1081 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1083
1084 // A strong non-wifi interference is generated on the full band during PSDU reception
1085 bandInfo.fc = m_frequency * 1e6;
1086 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
1087 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
1088 bands.clear();
1089 bands.push_back(bandInfo);
1090
1091 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1092 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1093 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
1094
1097 this,
1098 interferencePsdAll,
1099 MilliSeconds(100));
1100
1101 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1102 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1103 // even the PHY that has no PSDU addressed to it.
1106 this,
1107 m_phySta1,
1108 WifiPhyState::RX);
1111 this,
1112 m_phySta2,
1113 WifiPhyState::RX);
1116 this,
1117 m_phySta3,
1118 WifiPhyState::CCA_BUSY);
1121 this,
1122 m_phySta1,
1123 WifiPhyState::CCA_BUSY);
1126 this,
1127 m_phySta2,
1128 WifiPhyState::CCA_BUSY);
1131 this,
1132 m_phySta3,
1133 WifiPhyState::CCA_BUSY);
1134
1135 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1136 // occupies RU 1)
1138 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1139 // occupies RU 2)
1141 // No PSDU should have been received by STA3
1143
1145
1147}
1148
1149void
1151{
1152 m_frequency = 5180;
1153 m_channelWidth = 20;
1155 RunOne();
1156
1157 m_frequency = 5190;
1158 m_channelWidth = 40;
1160 RunOne();
1161
1162 m_frequency = 5210;
1163 m_channelWidth = 80;
1165 RunOne();
1166
1167 m_frequency = 5250;
1168 m_channelWidth = 160;
1170 RunOne();
1171
1173}
1174
1175/**
1176 * \ingroup wifi-test
1177 * \ingroup tests
1178 *
1179 * \brief DL-OFDMA PHY puncturing test
1180 */
1182{
1183 public:
1185
1186 private:
1187 void DoSetup() override;
1188 void DoTeardown() override;
1189 void DoRun() override;
1190
1191 /**
1192 * Receive success function for STA 1
1193 * \param psdu the PSDU
1194 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1195 * \param txVector the transmit vector
1196 * \param statusPerMpdu reception status per MPDU
1197 */
1199 RxSignalInfo rxSignalInfo,
1200 WifiTxVector txVector,
1201 const std::vector<bool> statusPerMpdu);
1202
1203 /**
1204 * Receive success function for STA 2
1205 * \param psdu the PSDU
1206 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1207 * \param txVector the transmit vector
1208 * \param statusPerMpdu reception status per MPDU
1209 */
1211 RxSignalInfo rxSignalInfo,
1212 WifiTxVector txVector,
1213 std::vector<bool> statusPerMpdu);
1214
1215 /**
1216 * Receive failure function for STA 1
1217 * \param psdu the PSDU
1218 */
1220
1221 /**
1222 * Receive failure function for STA 2
1223 * \param psdu the PSDU
1224 */
1226
1227 /**
1228 * Check the results for STA 1
1229 * \param expectedRxSuccess the expected number of RX success
1230 * \param expectedRxFailure the expected number of RX failures
1231 * \param expectedRxBytes the expected number of RX bytes
1232 */
1233 void CheckResultsSta1(uint32_t expectedRxSuccess,
1234 uint32_t expectedRxFailure,
1235 uint32_t expectedRxBytes);
1236
1237 /**
1238 * Check the results for STA 2
1239 * \param expectedRxSuccess the expected number of RX success
1240 * \param expectedRxFailure the expected number of RX failures
1241 * \param expectedRxBytes the expected number of RX bytes
1242 */
1243 void CheckResultsSta2(uint32_t expectedRxSuccess,
1244 uint32_t expectedRxFailure,
1245 uint32_t expectedRxBytes);
1246
1247 /**
1248 * Reset the results
1249 */
1250 void ResetResults();
1251
1252 /**
1253 * Send MU-PPDU function
1254 * \param rxStaId1 the ID of the recipient STA for the first PSDU
1255 * \param rxStaId2 the ID of the recipient STA for the second PSDU
1256 * \param puncturedSubchannels indicates for each subchannel whether it is punctured or not. if
1257 * empty, preamble puncturing is not used.
1258 */
1259 void SendMuPpdu(uint16_t rxStaId1,
1260 uint16_t rxStaId2,
1261 const std::vector<bool>& puncturedSubchannels);
1262
1263 /**
1264 * Generate interference function
1265 * \param interferencePsd the PSD of the interference to be generated
1266 * \param duration the duration of the interference
1267 */
1268 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1269
1270 /**
1271 * Stop interference function
1272 */
1273 void StopInterference();
1274
1275 /**
1276 * Run one function
1277 */
1278 void RunOne();
1279
1280 /**
1281 * Schedule now to check the PHY state
1282 * \param phy the PHY
1283 * \param expectedState the expected state of the PHY
1284 */
1285 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
1286
1287 /**
1288 * Check the PHY state now
1289 * \param phy the PHY
1290 * \param expectedState the expected state of the PHY
1291 */
1293
1294 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
1295 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
1296 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
1297 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
1298 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
1299 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
1300
1305
1306 MHz_u m_frequency; ///< frequency
1307 MHz_u m_channelWidth; ///< channel width
1308
1309 uint8_t m_indexSubchannel; ///< Index of the subchannel (starting from 0) that should contain an
1310 ///< interference and be punctured during the test run
1311
1312 Time m_expectedPpduDuration20Mhz; ///< expected duration to send MU PPDU on 20 MHz RU
1313 Time m_expectedPpduDuration40Mhz; ///< expected duration to send MU PPDU on 40 MHz RU
1314};
1315
1317 : TestCase("DL-OFDMA PHY puncturing test"),
1318 m_countRxSuccessSta1(0),
1319 m_countRxSuccessSta2(0),
1320 m_countRxFailureSta1(0),
1321 m_countRxFailureSta2(0),
1322 m_countRxBytesSta1(0),
1323 m_countRxBytesSta2(0),
1324 m_frequency(5210),
1325 m_channelWidth(80),
1326 m_indexSubchannel(0),
1327 m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1328 m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1329{
1330}
1331
1332void
1342
1343void
1345 uint16_t rxStaId2,
1346 const std::vector<bool>& puncturedSubchannels)
1347{
1348 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1349 WifiConstPsduMap psdus;
1350 WifiTxVector txVector{HePhy::GetHeMcs7(),
1351 0,
1353 NanoSeconds(800),
1354 1,
1355 1,
1356 0,
1358 false,
1359 false};
1360
1361 HeRu::RuType ruType =
1362 puncturedSubchannels.empty()
1364 : (puncturedSubchannels.at(1) ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1365 HeRu::RuSpec ru1(ruType, 1, true);
1366 txVector.SetRu(ru1, rxStaId1);
1367 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1368 txVector.SetNss(1, rxStaId1);
1369
1370 ruType = puncturedSubchannels.empty()
1372 : (puncturedSubchannels.at(1) ? HeRu::RU_484_TONE : HeRu::RU_242_TONE);
1373 HeRu::RuSpec ru2(ruType,
1374 ruType == HeRu::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1375 true);
1376 txVector.SetRu(ru2, rxStaId2);
1377 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1378 txVector.SetNss(1, rxStaId2);
1379
1380 std::vector<uint8_t> ruAlloc;
1381 if (puncturedSubchannels.empty())
1382 {
1383 std::fill_n(std::back_inserter(ruAlloc), 4, 200);
1384 }
1385 else
1386 {
1387 ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1388 ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
1389 ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1390 : (puncturedSubchannels.at(3) ? 192 : 200));
1391 ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1392 : (puncturedSubchannels.at(3) ? 113 : 200));
1393 }
1394
1395 txVector.SetRuAllocation(ruAlloc, 0);
1396 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1397
1398 Ptr<Packet> pkt1 = Create<Packet>(1000);
1399 WifiMacHeader hdr1;
1401 hdr1.SetQosTid(0);
1402 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1403 hdr1.SetSequenceNumber(1);
1404 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1405 psdus.insert(std::make_pair(rxStaId1, psdu1));
1406
1407 Ptr<Packet> pkt2 = Create<Packet>(1500);
1408 WifiMacHeader hdr2;
1410 hdr2.SetQosTid(0);
1411 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1412 hdr2.SetSequenceNumber(2);
1413 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1414 psdus.insert(std::make_pair(rxStaId2, psdu2));
1415
1416 if (!puncturedSubchannels.empty())
1417 {
1418 txVector.SetInactiveSubchannels(puncturedSubchannels);
1419 }
1420
1421 m_phyAp->Send(psdus, txVector);
1422}
1423
1424void
1426{
1427 NS_LOG_FUNCTION(this << duration);
1428 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
1429 m_phyInterferer->SetPeriod(duration);
1430 m_phyInterferer->Start();
1432}
1433
1434void
1440
1441void
1443 RxSignalInfo rxSignalInfo,
1444 WifiTxVector txVector,
1445 std::vector<bool> /*statusPerMpdu*/)
1446{
1447 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1449 m_countRxBytesSta1 += (psdu->GetSize() - 30);
1450}
1451
1452void
1454 RxSignalInfo rxSignalInfo,
1455 WifiTxVector txVector,
1456 std::vector<bool> /*statusPerMpdu*/)
1457{
1458 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1460 m_countRxBytesSta2 += (psdu->GetSize() - 30);
1461}
1462
1463void
1469
1470void
1476
1477void
1479 uint32_t expectedRxFailure,
1480 uint32_t expectedRxBytes)
1481{
1483 expectedRxSuccess,
1484 "The number of successfully received packets by STA 1 is not correct!");
1486 expectedRxFailure,
1487 "The number of unsuccessfuly received packets by STA 1 is not correct!");
1489 expectedRxBytes,
1490 "The number of bytes received by STA 1 is not correct!");
1491}
1492
1493void
1495 uint32_t expectedRxFailure,
1496 uint32_t expectedRxBytes)
1497{
1499 expectedRxSuccess,
1500 "The number of successfully received packets by STA 2 is not correct!");
1502 expectedRxFailure,
1503 "The number of unsuccessfuly received packets by STA 2 is not correct!");
1505 expectedRxBytes,
1506 "The number of bytes received by STA 2 is not correct!");
1507}
1508
1509void
1511{
1512 // This is needed to make sure PHY state will be checked as the last event if a state change
1513 // occurred at the exact same time as the check
1515}
1516
1517void
1519{
1520 WifiPhyState currentState;
1521 PointerValue ptr;
1522 phy->GetAttribute("State", ptr);
1524 currentState = state->GetState();
1525 NS_LOG_FUNCTION(this << currentState);
1526 NS_TEST_ASSERT_MSG_EQ(currentState,
1527 expectedState,
1528 "PHY State " << currentState << " does not match expected state "
1529 << expectedState << " at " << Simulator::Now());
1530}
1531
1532void
1534{
1537 lossModel->SetFrequency(m_frequency * 1e6);
1538 spectrumChannel->AddPropagationLossModel(lossModel);
1541 spectrumChannel->SetPropagationDelayModel(delayModel);
1542
1543 Ptr<Node> apNode = CreateObject<Node>();
1547 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1549 m_phyAp->SetErrorRateModel(apErrorModel);
1550 m_phyAp->SetDevice(apDev);
1551 m_phyAp->AddChannel(spectrumChannel);
1552 m_phyAp->ConfigureStandard(WIFI_STANDARD_80211ax);
1554 m_phyAp->SetMobility(apMobility);
1555 apDev->SetPhy(m_phyAp);
1556 apNode->AggregateObject(apMobility);
1557 apNode->AddDevice(apDev);
1558
1559 Ptr<Node> sta1Node = CreateObject<Node>();
1563 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1565 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1566 m_phySta1->SetDevice(sta1Dev);
1567 m_phySta1->AddChannel(spectrumChannel);
1573 m_phySta1->SetMobility(sta1Mobility);
1574 sta1Dev->SetPhy(m_phySta1);
1575 sta1Node->AggregateObject(sta1Mobility);
1576 sta1Node->AddDevice(sta1Dev);
1577
1578 Ptr<Node> sta2Node = CreateObject<Node>();
1582 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1584 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1585 m_phySta2->SetDevice(sta2Dev);
1586 m_phySta2->AddChannel(spectrumChannel);
1592 m_phySta2->SetMobility(sta2Mobility);
1593 sta2Dev->SetPhy(m_phySta2);
1594 sta2Node->AggregateObject(sta2Mobility);
1595 sta2Node->AddDevice(sta2Dev);
1596
1597 Ptr<Node> interfererNode = CreateObject<Node>();
1600 m_phyInterferer->SetDevice(interfererDev);
1601 m_phyInterferer->SetChannel(spectrumChannel);
1602 m_phyInterferer->SetDutyCycle(1);
1603 interfererNode->AddDevice(interfererDev);
1604}
1605
1606void
1608{
1609 m_phyAp->Dispose();
1610 m_phyAp = nullptr;
1611 m_phySta1->Dispose();
1612 m_phySta1 = nullptr;
1613 m_phySta2->Dispose();
1614 m_phySta2 = nullptr;
1616 m_phyInterferer = nullptr;
1617}
1618
1619void
1621{
1624 int64_t streamNumber = 0;
1625 m_phyAp->AssignStreams(streamNumber);
1626 m_phySta1->AssignStreams(streamNumber);
1627 m_phySta2->AssignStreams(streamNumber);
1628
1629 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
1634 ->number;
1635
1636 m_phyAp->SetOperatingChannel(
1642
1643 // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1644 // duration of the test run
1645 BandInfo bandInfo;
1646 bandInfo.fc = (m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20)) * 1e6;
1647 // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1648 // the border of another RU
1649 bandInfo.fl = bandInfo.fc - (5 * 1e6);
1650 bandInfo.fh = bandInfo.fc + (5 * 1e6);
1651 Bands bands;
1652 bands.push_back(bandInfo);
1653
1654 auto spectrumInterference = Create<SpectrumModel>(bands);
1655 auto interferencePsd = Create<SpectrumValue>(spectrumInterference);
1656 Watt_u interferencePower{0.1};
1657 *interferencePsd = interferencePower / 10e6;
1658
1661 this,
1662 interferencePsd,
1663 Seconds(3));
1664
1665 //---------------------------------------------------------------------------
1666 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1669 this,
1670 1,
1671 2,
1672 std::vector<bool>{});
1673
1674 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1675 // both PHYs should be back to IDLE at the same time.
1678 this,
1679 m_phySta1,
1680 WifiPhyState::RX);
1683 this,
1684 m_phySta2,
1685 WifiPhyState::RX);
1688 this,
1689 m_phySta1,
1690 WifiPhyState::IDLE);
1693 this,
1694 m_phySta2,
1695 WifiPhyState::IDLE);
1696
1697 if (m_indexSubchannel < 2) // interference in RU 1
1698 {
1699 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1702 this,
1703 0,
1704 1,
1705 0);
1706 // One PSDU of 1500 bytes should have been successfully received by STA 2
1709 this,
1710 1,
1711 0,
1712 1500);
1713 }
1714 else // interference in RU 2
1715 {
1716 // One PSDU of 1000 bytes should have been successfully received by STA 1
1719 this,
1720 1,
1721 0,
1722 1000);
1723 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1726 this,
1727 0,
1728 1,
1729 0);
1730 }
1731
1733
1734 //---------------------------------------------------------------------------
1735 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1736 // the punctured 20 MHz subchannel is the one that has interference
1737 std::vector<bool> puncturedSubchannels;
1738 const std::size_t num20MhzSubchannels = m_channelWidth / 20;
1739 for (std::size_t i = 0; i < num20MhzSubchannels; ++i)
1740 {
1741 if (i == m_indexSubchannel)
1742 {
1743 puncturedSubchannels.push_back(true);
1744 }
1745 else
1746 {
1747 puncturedSubchannels.push_back(false);
1748 }
1749 }
1752 this,
1753 1,
1754 2,
1755 puncturedSubchannels);
1756
1757 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1758 // both PHYs should be back to IDLE at the same time.
1761 this,
1762 m_phySta1,
1763 WifiPhyState::RX);
1766 this,
1767 m_phySta2,
1768 WifiPhyState::RX);
1771 this,
1772 m_phySta1,
1773 WifiPhyState::IDLE);
1776 this,
1777 m_phySta2,
1778 WifiPhyState::IDLE);
1779
1780 // One PSDU of 1000 bytes should have been successfully received by STA 1
1783 this,
1784 1,
1785 0,
1786 1000);
1787 // One PSDU of 1500 bytes should have been successfully received by STA 2
1790 this,
1791 1,
1792 0,
1793 1500);
1794
1796
1798}
1799
1800void
1802{
1803 // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1804 // cannot be punctured
1805 for (auto index : {1, 2, 3})
1806 {
1807 m_indexSubchannel = index;
1808 RunOne();
1809 }
1811}
1812
1813/**
1814 * \ingroup wifi-test
1815 * \ingroup tests
1816 *
1817 * \brief UL-OFDMA PPDU UID attribution test
1818 */
1820{
1821 public:
1823 ~TestUlOfdmaPpduUid() override;
1824
1825 private:
1826 void DoSetup() override;
1827 void DoTeardown() override;
1828 void DoRun() override;
1829
1830 /**
1831 * Transmitted PPDU information function for AP
1832 * \param uid the UID of the transmitted PPDU
1833 */
1834 void TxPpduAp(uint64_t uid);
1835 /**
1836 * Transmitted PPDU information function for STA 1
1837 * \param uid the UID of the transmitted PPDU
1838 */
1839 void TxPpduSta1(uint64_t uid);
1840 /**
1841 * Transmitted PPDU information function for STA 2
1842 * \param uid the UID of the transmitted PPDU
1843 */
1844 void TxPpduSta2(uint64_t uid);
1845 /**
1846 * Reset the global PPDU UID counter in WifiPhy
1847 */
1848 void ResetPpduUid();
1849
1850 /**
1851 * Send MU-PPDU toward both STAs.
1852 */
1853 void SendMuPpdu();
1854 /**
1855 * Send TB-PPDU from both STAs.
1856 */
1857 void SendTbPpdu();
1858 /**
1859 * Send SU-PPDU function
1860 * \param txStaId the ID of the sending STA
1861 */
1862 void SendSuPpdu(uint16_t txStaId);
1863
1864 /**
1865 * Check the UID of the transmitted PPDU
1866 * \param staId the STA-ID of the PHY (0 for AP)
1867 * \param expectedUid the expected UID
1868 */
1869 void CheckUid(uint16_t staId, uint64_t expectedUid);
1870
1874
1875 uint64_t m_ppduUidAp; ///< UID of PPDU transmitted by AP
1876 uint64_t m_ppduUidSta1; ///< UID of PPDU transmitted by STA1
1877 uint64_t m_ppduUidSta2; ///< UID of PPDU transmitted by STA2
1878};
1879
1881 : TestCase("UL-OFDMA PPDU UID attribution test"),
1882 m_ppduUidAp(UINT64_MAX),
1883 m_ppduUidSta1(UINT64_MAX),
1884 m_ppduUidSta2(UINT64_MAX)
1885{
1886}
1887
1891
1892void
1894{
1897 lossModel->SetFrequency(DEFAULT_FREQUENCY);
1898 spectrumChannel->AddPropagationLossModel(lossModel);
1901 spectrumChannel->SetPropagationDelayModel(delayModel);
1902
1903 Ptr<Node> apNode = CreateObject<Node>();
1907 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1909 m_phyAp->SetErrorRateModel(apErrorModel);
1910 m_phyAp->AddChannel(spectrumChannel);
1912 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
1917 ->number;
1920 m_phyAp->SetDevice(apDev);
1924 m_phyAp->SetMobility(apMobility);
1925 apDev->SetPhy(m_phyAp);
1926 apNode->AggregateObject(apMobility);
1927 apNode->AddDevice(apDev);
1928 apDev->SetStandard(WIFI_STANDARD_80211ax);
1929 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1930
1931 Ptr<Node> sta1Node = CreateObject<Node>();
1935 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1937 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1938 m_phySta1->AddChannel(spectrumChannel);
1942 m_phySta1->SetDevice(sta1Dev);
1946 m_phySta1->SetMobility(sta1Mobility);
1947 sta1Dev->SetPhy(m_phySta1);
1948 sta1Node->AggregateObject(sta1Mobility);
1949 sta1Node->AddDevice(sta1Dev);
1950
1951 Ptr<Node> sta2Node = CreateObject<Node>();
1955 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1957 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1958 m_phySta2->AddChannel(spectrumChannel);
1962 m_phySta2->SetDevice(sta2Dev);
1966 m_phySta2->SetMobility(sta2Mobility);
1967 sta2Dev->SetPhy(m_phySta2);
1968 sta2Node->AggregateObject(sta2Mobility);
1969 sta2Node->AddDevice(sta2Dev);
1970}
1971
1972void
1974{
1975 m_phyAp->Dispose();
1976 m_phyAp = nullptr;
1977 m_phySta1->Dispose();
1978 m_phySta1 = nullptr;
1979 m_phySta2->Dispose();
1980 m_phySta2 = nullptr;
1981}
1982
1983void
1984TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
1985{
1986 uint64_t uid;
1987 std::string device;
1988 switch (staId)
1989 {
1990 case 0:
1991 uid = m_ppduUidAp;
1992 device = "AP";
1993 break;
1994 case 1:
1995 uid = m_ppduUidSta1;
1996 device = "STA1";
1997 break;
1998 case 2:
1999 uid = m_ppduUidSta2;
2000 device = "STA2";
2001 break;
2002 default:
2003 NS_ABORT_MSG("Unexpected STA-ID");
2004 }
2006 expectedUid,
2007 "UID " << uid << " does not match expected one " << expectedUid << " for "
2008 << device << " at " << Simulator::Now());
2009}
2010
2011void
2013{
2014 NS_LOG_FUNCTION(this << uid);
2015 m_ppduUidAp = uid;
2016}
2017
2018void
2020{
2021 NS_LOG_FUNCTION(this << uid);
2022 m_ppduUidSta1 = uid;
2023}
2024
2025void
2027{
2028 NS_LOG_FUNCTION(this << uid);
2029 m_ppduUidSta2 = uid;
2030}
2031
2032void
2034{
2035 NS_LOG_FUNCTION(this);
2036 m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2037}
2038
2039void
2041{
2042 WifiConstPsduMap psdus;
2043 WifiTxVector txVector{HePhy::GetHeMcs7(),
2044 0,
2046 NanoSeconds(800),
2047 1,
2048 1,
2049 0,
2051 false,
2052 false};
2053
2054 uint16_t rxStaId1 = 1;
2055 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2056 txVector.SetRu(ru1, rxStaId1);
2057 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2058 txVector.SetNss(1, rxStaId1);
2059
2060 uint16_t rxStaId2 = 2;
2061 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2062 txVector.SetRu(ru2, rxStaId2);
2063 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2064 txVector.SetNss(1, rxStaId2);
2065 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2066 txVector.SetRuAllocation({96}, 0);
2067
2068 Ptr<Packet> pkt1 = Create<Packet>(1000);
2069 WifiMacHeader hdr1;
2071 hdr1.SetQosTid(0);
2072 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2073 hdr1.SetSequenceNumber(1);
2074 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2075 psdus.insert(std::make_pair(rxStaId1, psdu1));
2076
2077 Ptr<Packet> pkt2 = Create<Packet>(1500);
2078 WifiMacHeader hdr2;
2080 hdr2.SetQosTid(0);
2081 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2082 hdr2.SetSequenceNumber(2);
2083 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2084 psdus.insert(std::make_pair(rxStaId2, psdu2));
2085
2086 m_phyAp->Send(psdus, txVector);
2087}
2088
2089void
2091{
2092 WifiConstPsduMap psdus1;
2093 WifiConstPsduMap psdus2;
2094
2095 WifiTxVector txVector1{HePhy::GetHeMcs7(),
2096 0,
2098 NanoSeconds(1600),
2099 1,
2100 1,
2101 0,
2103 false,
2104 false};
2105 WifiTxVector txVector2{txVector1};
2106 WifiTxVector trigVector{txVector2};
2107
2108 uint16_t rxStaId1 = 1;
2109 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2110 txVector1.SetRu(ru1, rxStaId1);
2111 txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2112 txVector1.SetNss(1, rxStaId1);
2113 trigVector.SetRu(ru1, rxStaId1);
2114 trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2115 trigVector.SetNss(1, rxStaId1);
2116
2117 auto pkt1 = Create<Packet>(1000);
2118 WifiMacHeader hdr1;
2120 hdr1.SetQosTid(0);
2121 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2122 hdr1.SetSequenceNumber(1);
2123 auto psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2124 psdus1.insert(std::make_pair(rxStaId1, psdu1));
2125
2126 uint16_t rxStaId2 = 2;
2127 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, false);
2128 txVector2.SetRu(ru2, rxStaId2);
2129 txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2130 txVector2.SetNss(1, rxStaId2);
2131 trigVector.SetRu(ru2, rxStaId2);
2132 trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2133 trigVector.SetNss(1, rxStaId2);
2134
2135 auto pkt2 = Create<Packet>(1500);
2136 WifiMacHeader hdr2;
2138 hdr2.SetQosTid(0);
2139 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2140 hdr2.SetSequenceNumber(2);
2141 auto psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2142 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2143
2144 const auto txDuration1 = m_phySta1->CalculateTxDuration(psdu1->GetSize(),
2145 txVector1,
2147 rxStaId1);
2148 const auto txDuration2 = m_phySta2->CalculateTxDuration(psdu2->GetSize(),
2149 txVector2,
2151 rxStaId2);
2152 const auto txDuration = std::max(txDuration1, txDuration2);
2153
2154 txVector1.SetLength(
2156 .first);
2157 txVector2.SetLength(
2159 .first);
2160
2162 hePhyAp->SetTrigVector(trigVector, txDuration);
2163
2164 m_phySta1->Send(psdus1, txVector1);
2165 m_phySta2->Send(psdus2, txVector2);
2166}
2167
2168void
2170{
2171 WifiConstPsduMap psdus;
2172 WifiTxVector txVector{HePhy::GetHeMcs7(),
2173 0,
2175 NanoSeconds(800),
2176 1,
2177 1,
2178 0,
2180 false,
2181 false};
2182
2183 auto pkt = Create<Packet>(1000);
2184 WifiMacHeader hdr;
2186 hdr.SetQosTid(0);
2188 hdr.SetSequenceNumber(1);
2189 auto psdu = Create<WifiPsdu>(pkt, hdr);
2190 psdus.insert(std::make_pair(SU_STA_ID, psdu));
2191
2192 switch (txStaId)
2193 {
2194 case 0:
2195 m_phyAp->Send(psdus, txVector);
2196 break;
2197 case 1:
2198 m_phySta1->Send(psdus, txVector);
2199 break;
2200 case 2:
2201 m_phySta2->Send(psdus, txVector);
2202 break;
2203 default:
2204 NS_ABORT_MSG("Unexpected STA-ID");
2205 }
2206}
2207
2208void
2210{
2213 int64_t streamNumber = 0;
2214 m_phyAp->AssignStreams(streamNumber);
2215 m_phySta1->AssignStreams(streamNumber);
2216 m_phySta2->AssignStreams(streamNumber);
2217
2218 // Reset PPDU UID so as not to be dependent on previously executed test cases,
2219 // since global attribute will be changed).
2220 ResetPpduUid();
2221
2222 // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2223 // PPDU UID should be equal to 0 (the first counter value).
2226
2227 // Send HE SU PPDU from AP.
2228 // PPDU UID should be incremented since this is a new PPDU.
2231
2232 // Send HE TB PPDU from STAs to AP.
2233 // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2234 // preceding correctly received PPDU (which normally contains the trigger frame).
2238
2239 // Send HE SU PPDU from STA1.
2240 // PPDU UID should be incremented since this is a new PPDU.
2243
2246}
2247
2248/**
2249 * \ingroup wifi-test
2250 * \ingroup tests
2251 *
2252 * \brief UL-OFDMA multiple RX events test
2253 */
2255{
2256 public:
2258 ~TestMultipleHeTbPreambles() override;
2259
2260 private:
2261 void DoSetup() override;
2262 void DoTeardown() override;
2263 void DoRun() override;
2264
2265 /**
2266 * Receive HE TB PPDU function.
2267 *
2268 * \param uid the UID used to identify a set of HE TB PPDUs belonging to the same UL-MU
2269 * transmission
2270 * \param staId the STA ID
2271 * \param txPower the TX power
2272 * \param payloadSize the size of the payload in bytes
2273 */
2274 void RxHeTbPpdu(uint64_t uid, uint16_t staId, Watt_u txPower, size_t payloadSize);
2275
2276 /**
2277 * Receive OFDMA part of HE TB PPDU function.
2278 * Immediately schedules DoRxHeTbPpduOfdmaPart.
2279 *
2280 * \param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2281 */
2283 /**
2284 * Receive OFDMA part of HE TB PPDU function.
2285 * Actual reception call.
2286 *
2287 * \param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2288 */
2290
2291 /**
2292 * RX dropped function
2293 * \param p the packet
2294 * \param reason the reason
2295 */
2297
2298 /**
2299 * Reset function
2300 */
2301 void Reset();
2302
2303 /**
2304 * Check the received HE TB preambles
2305 * \param nEvents the number of events created by the PHY
2306 * \param uids the vector of expected UIDs
2307 */
2308 void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2309
2310 /**
2311 * Check the number of bytes dropped
2312 * \param expectedBytesDropped the expected number of bytes dropped
2313 */
2314 void CheckBytesDropped(size_t expectedBytesDropped);
2315
2317
2318 uint64_t m_totalBytesDropped; ///< total number of dropped bytes
2320};
2321
2323 : TestCase("UL-OFDMA multiple RX events test"),
2324 m_totalBytesDropped(0),
2325 m_trigVector(HePhy::GetHeMcs7(),
2326 0,
2328 NanoSeconds(1600),
2329 1,
2330 1,
2331 0,
2333 false,
2334 false)
2335{
2336}
2337
2341
2342void
2344{
2345 NS_LOG_FUNCTION(this);
2347 // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2348 m_phy->Reset();
2350}
2351
2352void
2354{
2355 NS_LOG_FUNCTION(this << p << reason);
2356 m_totalBytesDropped += (p->GetSize() - 30);
2357}
2358
2359void
2360TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2361{
2362 auto events = m_phy->GetCurrentPreambleEvents();
2363 NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2364 for (const auto& uid : uids)
2365 {
2366 auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2367 auto it = events.find(pair);
2368 bool found = (it != events.end());
2370 true,
2371 "HE TB PPDU with UID " << uid << " has not been received!");
2372 }
2373}
2374
2375void
2377{
2379 expectedBytesDropped,
2380 "The number of dropped bytes is not correct!");
2381}
2382
2383void
2385 uint16_t staId,
2386 Watt_u txPower,
2387 size_t payloadSize)
2388{
2389 WifiConstPsduMap psdus;
2390 WifiTxVector txVector{HePhy::GetHeMcs7(),
2391 0,
2393 NanoSeconds(1600),
2394 1,
2395 1,
2396 0,
2398 false,
2399 false};
2400
2401 HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2402 txVector.SetRu(ru, staId);
2403 txVector.SetMode(HePhy::GetHeMcs7(), staId);
2404 txVector.SetNss(1, staId);
2405
2406 m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2407
2408 auto pkt = Create<Packet>(payloadSize);
2409 WifiMacHeader hdr;
2411 hdr.SetQosTid(0);
2412 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2413 hdr.SetSequenceNumber(1);
2414 auto psdu = Create<WifiPsdu>(pkt, hdr);
2415 psdus.insert(std::make_pair(staId, psdu));
2416
2417 auto ppduDuration =
2418 m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand(), staId);
2419 auto ppdu = Create<HePpdu>(psdus,
2420 txVector,
2422 ppduDuration,
2423 uid,
2425
2426 // Send non-OFDMA part
2427 const auto nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonHeDurationForHeTb(txVector);
2428 const auto centerFrequency =
2429 m_phy->GetHePhy()->GetCenterFrequenciesForNonHePart(ppdu, staId).front();
2430 MHz_u ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2431 MHz_u channelWidth = ruWidth < 20 ? 20 : ruWidth;
2433 centerFrequency,
2434 channelWidth,
2435 txPower,
2436 m_phy->GetGuardBandwidth(channelWidth));
2437 auto rxParams = Create<WifiSpectrumSignalParameters>();
2438 rxParams->psd = rxPsd;
2439 rxParams->txPhy = nullptr;
2440 rxParams->duration = nonOfdmaDuration;
2441 rxParams->ppdu = ppdu;
2442
2443 uint16_t length;
2444 std::tie(length, ppduDuration) =
2446 txVector.SetLength(length);
2447 m_trigVector.SetLength(length);
2449 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2450 ppdu->ResetTxVector();
2451 m_phy->StartRx(rxParams, nullptr);
2452
2453 // Schedule OFDMA part
2454 auto ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2455 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2456 const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2457 auto rxPsdOfdma =
2460 txPower,
2462 band.indices);
2463 auto rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2464 rxParamsOfdma->psd = rxPsd;
2465 rxParamsOfdma->txPhy = nullptr;
2466 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2467 rxParamsOfdma->ppdu = ppduOfdma;
2468 Simulator::Schedule(nonOfdmaDuration,
2470 this,
2471 rxParamsOfdma);
2472}
2473
2474void
2479
2480void
2482{
2483 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2484 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2485 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2486 m_phy->StartRx(rxParamsOfdma, nullptr);
2487}
2488
2489void
2491{
2495 dev->SetStandard(WIFI_STANDARD_80211ax);
2500 "Txop",
2501 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
2502 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2503 dev->SetMac(mac);
2504 m_phy->SetInterferenceHelper(interferenceHelper);
2505 m_phy->SetErrorRateModel(error);
2506 m_phy->AddChannel(spectrumChannel);
2511 0});
2512 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2514 m_phy->SetDevice(dev);
2515 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2517 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2518 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2519 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2521 heConfiguration->SetMaxTbPpduDelay(NanoSeconds(400));
2522 dev->SetHeConfiguration(heConfiguration);
2523 dev->SetPhy(m_phy);
2524 node->AddDevice(dev);
2525}
2526
2527void
2529{
2530 m_phy->Dispose();
2531 m_phy = nullptr;
2532}
2533
2534void
2536{
2539 int64_t streamNumber = 0;
2540 m_phy->AssignStreams(streamNumber);
2541
2542 Watt_u txPower{0.01};
2543
2544 {
2545 // Verify a single UL MU transmission with two stations belonging to the same BSS
2546 std::vector<uint64_t> uids{0};
2549 this,
2550 uids[0],
2551 1,
2552 txPower,
2553 1001);
2556 this,
2557 uids[0],
2558 2,
2559 txPower,
2560 1002);
2561 // Check that we received a single UL MU transmission with the corresponding UID
2564 this,
2565 1,
2566 uids);
2568 }
2569
2570 {
2571 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2572 // the second transmission arrives during the preamble detection window and with half the
2573 // power of the first transmission.
2574 std::vector<uint64_t> uids{1, 2};
2577 this,
2578 uids[0],
2579 1,
2580 txPower,
2581 1001);
2584 this,
2585 uids[0],
2586 2,
2587 txPower,
2588 1002);
2591 this,
2592 uids[1],
2593 1,
2594 txPower / 2,
2595 1003);
2598 this,
2599 uids[1],
2600 2,
2601 txPower / 2,
2602 1004);
2603 // Check that we received the correct reception of 2 UL MU transmissions with the
2604 // corresponding UIDs
2607 this,
2608 2,
2609 uids);
2611 // TODO: verify PPDUs from second UL MU transmission are dropped
2612 }
2613
2614 {
2615 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2616 // the second transmission arrives during the preamble detection window and with twice the
2617 // power of the first transmission.
2618 std::vector<uint64_t> uids{3, 4};
2621 this,
2622 uids[0],
2623 1,
2624 txPower / 2,
2625 1001);
2628 this,
2629 uids[0],
2630 2,
2631 txPower / 2,
2632 1002);
2635 this,
2636 uids[1],
2637 1,
2638 txPower,
2639 1003);
2642 this,
2643 uids[1],
2644 2,
2645 txPower,
2646 1004);
2647 // Check that we received the correct reception of 2 UL MU transmissions with the
2648 // corresponding UIDs
2651 this,
2652 2,
2653 uids);
2655 // TODO: verify PPDUs from first UL MU transmission are dropped
2656 }
2657
2658 {
2659 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2660 // the second transmission arrives during PHY header reception and with the same power as
2661 // the first transmission.
2662 std::vector<uint64_t> uids{5, 6};
2665 this,
2666 uids[0],
2667 1,
2668 txPower,
2669 1001);
2672 this,
2673 uids[0],
2674 2,
2675 txPower,
2676 1002);
2679 this,
2680 uids[1],
2681 1,
2682 txPower,
2683 1003);
2686 this,
2687 uids[1],
2688 2,
2689 txPower,
2690 1004);
2691 // Check that we received the correct reception of the first UL MU transmission with the
2692 // corresponding UID (second one dropped)
2695 this,
2696 1,
2697 std::vector<uint64_t>{uids[0]});
2698 // The packets of the second UL MU transmission should have been dropped
2701 this,
2702 1003 + 1004);
2704 }
2705
2706 {
2707 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2708 // BSS, where the second transmission arrives during payload reception and with the same
2709 // power as the first transmission.
2710 std::vector<uint64_t> uids{7, 8};
2713 this,
2714 uids[0],
2715 1,
2716 txPower,
2717 1001);
2720 this,
2721 uids[0],
2722 2,
2723 txPower,
2724 1002);
2727 this,
2728 uids[1],
2729 1,
2730 txPower,
2731 1003);
2734 this,
2735 uids[1],
2736 2,
2737 txPower,
2738 1004);
2739 // Check that we received the correct reception of the first UL MU transmission with the
2740 // corresponding UID (second one dropped)
2743 this,
2744 1,
2745 std::vector<uint64_t>{uids[0]});
2746 // The packets of the second UL MU transmission should have been dropped
2749 this,
2750 1003 + 1004);
2752 }
2753
2754 {
2755 // Verify the correct reception of a single UL MU transmission with two stations belonging
2756 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2757 // the configured delay spread of 400ns
2758 std::vector<uint64_t> uids{9};
2761 this,
2762 uids[0],
2763 1,
2764 txPower,
2765 1001);
2768 this,
2769 uids[0],
2770 2,
2771 txPower,
2772 1002);
2773 // Check that we received a single UL MU transmission with the corresponding UID
2776 this,
2777 1,
2778 uids);
2779 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2780 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2781 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2782 // second packet of 1002 bytes is dropped as well.
2785 this,
2786 1001 + 1002);
2788 }
2789
2792}
2793
2794/**
2795 * \ingroup wifi-test
2796 * \ingroup tests
2797 *
2798 * \brief PHY listener for OFDMA tests
2799 */
2801{
2802 public:
2804
2805 void NotifyRxStart(Time duration) override
2806 {
2807 NS_LOG_FUNCTION(this << duration);
2810 m_lastRxSuccess = false;
2811 }
2812
2813 void NotifyRxEndOk() override
2814 {
2815 NS_LOG_FUNCTION(this);
2817 ++m_notifyRxEnd;
2818 m_lastRxSuccess = true;
2819 }
2820
2821 void NotifyRxEndError() override
2822 {
2823 NS_LOG_FUNCTION(this);
2825 ++m_notifyRxEnd;
2826 m_lastRxSuccess = false;
2827 }
2828
2829 void NotifyTxStart(Time duration, dBm_u txPower) override
2830 {
2831 NS_LOG_FUNCTION(this << duration << txPower);
2832 }
2833
2835 WifiChannelListType channelType,
2836 const std::vector<Time>& /*per20MhzDurations*/) override
2837 {
2838 NS_LOG_FUNCTION(this << duration << channelType);
2839 }
2840
2841 void NotifySwitchingStart(Time duration) override
2842 {
2843 }
2844
2845 void NotifySleep() override
2846 {
2847 }
2848
2849 void NotifyOff() override
2850 {
2851 }
2852
2853 void NotifyWakeup() override
2854 {
2855 }
2856
2857 void NotifyOn() override
2858 {
2859 }
2860
2861 /**
2862 * Reset function.
2863 */
2864 void Reset()
2865 {
2866 m_notifyRxStart = 0;
2867 m_notifyRxEnd = 0;
2869 m_lastRxEnd = Seconds(0);
2870 m_lastRxSuccess = false;
2871 }
2872
2873 /**
2874 * Return the number of RX start notifications that has been received since the last reset.
2875 * \return the number of RX start notifications that has been received
2876 */
2878 {
2879 return m_notifyRxStart;
2880 }
2881
2882 /**
2883 * Return the number of RX end notifications that has been received since the last reset.
2884 * \return the number of RX end notifications that has been received
2885 */
2887 {
2888 return m_notifyRxEnd;
2889 }
2890
2891 /**
2892 * Return the time at which the last RX start notification has been received.
2893 * \return the time at which the last RX start notification has been received
2894 */
2896 {
2897 return m_lastRxStart;
2898 }
2899
2900 /**
2901 * Return the time at which the last RX end notification has been received.
2902 * \return the time at which the last RX end notification has been received
2903 */
2905 {
2906 return m_lastRxEnd;
2907 }
2908
2909 /**
2910 * Return whether last RX has been successful.
2911 * \return true if last RX has been successful, false otherwise
2912 */
2913 bool IsLastRxSuccess() const
2914 {
2915 return m_lastRxSuccess;
2916 }
2917
2918 private:
2919 uint32_t m_notifyRxStart{0}; ///< count number of RX start notifications
2920 uint32_t m_notifyRxEnd{0}; ///< count number of RX end notifications
2921 Time m_lastRxStart{Seconds(0)}; ///< last time a RX start notification has been received
2922 Time m_lastRxEnd{Seconds(0)}; ///< last time a RX end notification has been received
2923 bool m_lastRxSuccess{false}; ///< flag whether last RX has been successful
2924};
2925
2926/**
2927 * \ingroup wifi-test
2928 * \ingroup tests
2929 *
2930 * \brief UL-OFDMA PHY test
2931 */
2933{
2934 public:
2935 /**
2936 * Erroneous info included in a TRIGVECTOR
2937 */
2945
2947 ~TestUlOfdmaPhyTransmission() override;
2948
2949 private:
2950 void DoSetup() override;
2951 void DoTeardown() override;
2952 void DoRun() override;
2953
2954 /**
2955 * Get TXVECTOR for HE TB PPDU.
2956 * \param txStaId the ID of the TX STA
2957 * \param index the RU index used for the transmission
2958 * \param bssColor the BSS color of the TX STA
2959 * \return the TXVECTOR for HE TB PPDU
2960 */
2961 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2962 std::size_t index,
2963 uint8_t bssColor) const;
2964 /**
2965 * Set TRIGVECTOR for HE TB PPDU
2966 *
2967 * \param bssColor the BSS color of the TX STA
2968 * \param error the erroneous info (if any) in the TRIGVECTOR to set
2969 */
2970 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2971 /**
2972 * Send HE TB PPDU function
2973 * \param txStaId the ID of the TX STA
2974 * \param index the RU index used for the transmission
2975 * \param payloadSize the size of the payload in bytes
2976 * \param uid the UID of the trigger frame that is initiating this transmission
2977 * \param bssColor the BSS color of the TX STA
2978 * \param incrementUid whether UID shall be incremented
2979 */
2980 void SendHeTbPpdu(uint16_t txStaId,
2981 std::size_t index,
2982 std::size_t payloadSize,
2983 uint64_t uid,
2984 uint8_t bssColor,
2985 bool incrementUid);
2986
2987 /**
2988 * Send HE SU PPDU function
2989 * \param txStaId the ID of the TX STA
2990 * \param payloadSize the size of the payload in bytes
2991 * \param uid the UID of the trigger frame that is initiating this transmission
2992 * \param bssColor the BSS color of the TX STA
2993 */
2994 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
2995
2996 /**
2997 * Set the BSS color
2998 * \param phy the PHY
2999 * \param bssColor the BSS color
3000 */
3001 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3002
3003 /**
3004 * Set the PSD limit
3005 * \param phy the PHY
3006 * \param psdLimit the PSD limit
3007 */
3008 void SetPsdLimit(Ptr<WifiPhy> phy, dBm_per_MHz_u psdLimit);
3009
3010 /**
3011 * Generate interference function
3012 * \param interferencePsd the PSD of the interference to be generated
3013 * \param duration the duration of the interference
3014 */
3015 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3016 /**
3017 * Stop interference function
3018 */
3019 void StopInterference();
3020
3021 /**
3022 * Run one function
3023 */
3024 void RunOne();
3025
3026 /**
3027 * Check the received PSDUs from STA1
3028 * \param expectedSuccess the expected number of success
3029 * \param expectedFailures the expected number of failures
3030 * \param expectedBytes the expected number of bytes
3031 */
3032 void CheckRxFromSta1(uint32_t expectedSuccess,
3033 uint32_t expectedFailures,
3034 uint32_t expectedBytes);
3035
3036 /**
3037 * Check the received PSDUs from STA2
3038 * \param expectedSuccess the expected number of success
3039 * \param expectedFailures the expected number of failures
3040 * \param expectedBytes the expected number of bytes
3041 */
3042 void CheckRxFromSta2(uint32_t expectedSuccess,
3043 uint32_t expectedFailures,
3044 uint32_t expectedBytes);
3045
3046 /**
3047 * Check the received power for the non-OFDMA of the HE TB PPDUs over the given band
3048 * \param phy the PHY
3049 * \param band the indices of the band over which the power is measured
3050 * \param expectedRxPower the expected received power
3051 */
3054 Watt_u expectedRxPower);
3055 /**
3056 * Check the received power for the OFDMA part of the HE TB PPDUs over the given band
3057 * \param phy the PHY
3058 * \param band the indices of the band over which the power is measured
3059 * \param expectedRxPower the expected received power
3060 */
3063 Watt_u expectedRxPower);
3064
3065 /**
3066 * Verify all events are cleared at end of TX or RX
3067 */
3068 void VerifyEventsCleared();
3069
3070 /**
3071 * Check the PHY state
3072 * \param phy the PHY
3073 * \param expectedState the expected state of the PHY
3074 */
3075 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
3076 /// \copydoc CheckPhyState
3078
3079 /**
3080 * Check the the number of RX start notifications at the AP as well as the last time a RX start
3081 * has been notified
3082 * \param expectedNotifications the expected number of RX start notifications at the AP
3083 * \param expectedLastNotification the expected time of the last RX start notification at the AP
3084 */
3085 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3086 /**
3087 * Check the the number of RX end notifications at the AP as well as the last time a RX end has
3088 * been notified
3089 * \param expectedNotifications the expected number of RX end notifications at the AP
3090 * \param expectedLastNotification the expected time of the last RX end notification at the AP
3091 * \param expectedSuccess true if the last RX notification indicates a success, false otherwise
3092 */
3093 void CheckApRxEnd(uint32_t expectedNotifications,
3094 Time expectedLastNotification,
3095 bool expectedSuccess);
3096
3097 /**
3098 * Reset function
3099 */
3100 void Reset();
3101
3102 /**
3103 * Receive success function
3104 * \param psdu the PSDU
3105 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
3106 * \param txVector the transmit vector
3107 * \param statusPerMpdu reception status per MPDU
3108 */
3110 RxSignalInfo rxSignalInfo,
3111 WifiTxVector txVector,
3112 std::vector<bool> statusPerMpdu);
3113
3114 /**
3115 * Receive failure function
3116 * \param psdu the PSDU
3117 */
3118 void RxFailure(Ptr<const WifiPsdu> psdu);
3119
3120 /**
3121 * Schedule test to perform.
3122 * The interference generation should be scheduled apart.
3123 *
3124 * \param delay the reference delay to schedule the events
3125 * \param solicited flag indicating if HE TB PPDUs were solicited by the AP
3126 * \param expectedStateAtEnd the expected state of the PHY at the end of the reception
3127 * \param expectedSuccessFromSta1 the expected number of success from STA 1
3128 * \param expectedFailuresFromSta1 the expected number of failures from STA 1
3129 * \param expectedBytesFromSta1 the expected number of bytes from STA 1
3130 * \param expectedSuccessFromSta2 the expected number of success from STA 2
3131 * \param expectedFailuresFromSta2 the expected number of failures from STA 2
3132 * \param expectedBytesFromSta2 the expected number of bytes from STA 2
3133 * \param scheduleTxSta1 flag indicating to schedule a HE TB PPDU from STA 1
3134 * \param ulTimeDifference delay between HE TB PPDU from STA 1 and HE TB PPDU from STA 2
3135 * are received
3136 * \param expectedStateBeforeEnd the expected state of the PHY before the end of the
3137 * transmission
3138 * \param error the erroneous info (if any) in the TRIGVECTOR to set
3139 */
3140 void ScheduleTest(Time delay,
3141 bool solicited,
3142 WifiPhyState expectedStateAtEnd,
3143 uint32_t expectedSuccessFromSta1,
3144 uint32_t expectedFailuresFromSta1,
3145 uint32_t expectedBytesFromSta1,
3146 uint32_t expectedSuccessFromSta2,
3147 uint32_t expectedFailuresFromSta2,
3148 uint32_t expectedBytesFromSta2,
3149 bool scheduleTxSta1 = true,
3150 Time ulTimeDifference = Seconds(0),
3151 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3152 TrigVectorInfo error = NONE);
3153
3154 /**
3155 * Schedule power measurement related checks.
3156 *
3157 * \param delay the reference delay used to schedule the events
3158 * \param rxPowerNonOfdmaRu1 the received power on the non-OFDMA part of RU1
3159 * \param rxPowerNonOfdmaRu2 the received power on the non-OFDMA part of RU2
3160 * \param rxPowerOfdmaRu1 the received power on RU1
3161 * \param rxPowerOfdmaRu2 the received power on RU2
3162 */
3164 Watt_u rxPowerNonOfdmaRu1,
3165 Watt_u rxPowerNonOfdmaRu2,
3166 Watt_u rxPowerOfdmaRu1,
3167 Watt_u rxPowerOfdmaRu2);
3168 /**
3169 * Log scenario description
3170 *
3171 * \param log the scenario description to add to log
3172 */
3173 void LogScenario(std::string log) const;
3174
3179
3180 std::shared_ptr<OfdmaTestPhyListener>
3181 m_apPhyStateListener; ///< listener for AP PHY state transitions
3182
3184
3185 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
3186 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
3187 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
3188 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
3189 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
3190 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
3191
3192 MHz_u m_frequency; ///< frequency
3193 MHz_u m_channelWidth; ///< channel width
3194 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
3195};
3196
3198 : TestCase("UL-OFDMA PHY test"),
3199 m_countRxSuccessFromSta1(0),
3200 m_countRxSuccessFromSta2(0),
3201 m_countRxFailureFromSta1(0),
3202 m_countRxFailureFromSta2(0),
3203 m_countRxBytesFromSta1(0),
3204 m_countRxBytesFromSta2(0),
3205 m_frequency(DEFAULT_FREQUENCY),
3206 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3207 m_expectedPpduDuration(NanoSeconds(271200))
3208{
3209}
3210
3211void
3213 std::size_t payloadSize,
3214 uint64_t uid,
3215 uint8_t bssColor)
3216{
3217 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3218 WifiConstPsduMap psdus;
3219
3220 WifiTxVector txVector{HePhy::GetHeMcs7(),
3221 0,
3223 NanoSeconds(800),
3224 1,
3225 1,
3226 0,
3228 false,
3229 false,
3230 false,
3231 bssColor};
3232
3233 auto pkt = Create<Packet>(payloadSize);
3234 WifiMacHeader hdr;
3236 hdr.SetQosTid(0);
3237 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3238 std::ostringstream addr;
3239 addr << "00:00:00:00:00:0" << txStaId;
3240 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3241 hdr.SetSequenceNumber(1);
3242 auto psdu = Create<WifiPsdu>(pkt, hdr);
3243 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3244
3246 if (txStaId == 1)
3247 {
3248 phy = m_phySta1;
3249 }
3250 else if (txStaId == 2)
3251 {
3252 phy = m_phySta2;
3253 }
3254 else if (txStaId == 3)
3255 {
3256 phy = m_phySta3;
3257 }
3258 else if (txStaId == 0)
3259 {
3260 phy = m_phyAp;
3261 }
3262 phy->SetPpduUid(uid);
3263 phy->Send(psdus, txVector);
3264}
3265
3268 std::size_t index,
3269 uint8_t bssColor) const
3270{
3271 WifiTxVector txVector{HePhy::GetHeMcs7(),
3272 0,
3274 NanoSeconds(1600),
3275 1,
3276 1,
3277 0,
3279 false,
3280 false,
3281 false,
3282 bssColor};
3283
3284 auto ruType = HeRu::RU_106_TONE;
3285 if (m_channelWidth == 20)
3286 {
3287 ruType = HeRu::RU_106_TONE;
3288 }
3289 else if (m_channelWidth == 40)
3290 {
3291 ruType = HeRu::RU_242_TONE;
3292 }
3293 else if (m_channelWidth == 80)
3294 {
3295 ruType = HeRu::RU_484_TONE;
3296 }
3297 else if (m_channelWidth == 160)
3298 {
3299 ruType = HeRu::RU_996_TONE;
3300 }
3301 else
3302 {
3303 NS_ASSERT_MSG(false, "Unsupported channel width");
3304 }
3305
3306 auto primary80MHz = true;
3307 if (m_channelWidth == 160 && index == 2)
3308 {
3309 primary80MHz = false;
3310 index = 1;
3311 }
3312 HeRu::RuSpec ru(ruType, index, primary80MHz);
3313 txVector.SetRu(ru, txStaId);
3314 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3315 txVector.SetNss(1, txStaId);
3316 return txVector;
3317}
3318
3319void
3321{
3322 auto channelWidth = m_channelWidth;
3323 if (error == CHANNEL_WIDTH)
3324 {
3325 channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
3326 }
3327
3328 WifiTxVector txVector(HePhy::GetHeMcs7(),
3329 0,
3331 NanoSeconds(1600),
3332 1,
3333 1,
3334 0,
3335 channelWidth,
3336 false,
3337 false,
3338 false,
3339 bssColor);
3340
3342 if (channelWidth == 20)
3343 {
3344 ruType = HeRu::RU_106_TONE;
3345 }
3346 else if (channelWidth == 40)
3347 {
3348 ruType = HeRu::RU_242_TONE;
3349 }
3350 else if (channelWidth == 80)
3351 {
3352 ruType = HeRu::RU_484_TONE;
3353 }
3354 else if (channelWidth == 160)
3355 {
3356 ruType = HeRu::RU_996_TONE;
3357 }
3358 else
3359 {
3360 NS_ASSERT_MSG(false, "Unsupported channel width");
3361 }
3362
3363 uint16_t aid1 = (error == AID ? 3 : 1);
3364 uint16_t aid2 = (error == AID ? 4 : 2);
3365
3366 HeRu::RuSpec ru1(ruType, 1, true);
3367 txVector.SetRu(ru1, aid1);
3368 txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3369 txVector.SetNss(1, aid1);
3370
3371 HeRu::RuSpec ru2(ruType, (channelWidth == 160 ? 1 : 2), (channelWidth != 160));
3372 txVector.SetRu(ru2, aid2);
3373 txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3374 txVector.SetNss(1, aid2);
3375
3376 uint16_t length;
3377 std::tie(length, m_expectedPpduDuration) =
3379 txVector,
3380 m_phyAp->GetPhyBand());
3381 if (error == UL_LENGTH)
3382 {
3383 ++length;
3384 }
3385 txVector.SetLength(length);
3387 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3388}
3389
3390void
3392 std::size_t index,
3393 std::size_t payloadSize,
3394 uint64_t uid,
3395 uint8_t bssColor,
3396 bool incrementUid)
3397{
3398 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3399 WifiConstPsduMap psdus;
3400
3401 if (incrementUid)
3402 {
3403 ++uid;
3404 }
3405
3406 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3407 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3408 WifiMacHeader hdr;
3410 hdr.SetQosTid(0);
3411 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3412 std::ostringstream addr;
3413 addr << "00:00:00:00:00:0" << txStaId;
3414 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3415 hdr.SetSequenceNumber(1);
3416 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3417 psdus.insert(std::make_pair(txStaId, psdu));
3418
3420 if (txStaId == 1)
3421 {
3422 phy = m_phySta1;
3423 }
3424 else if (txStaId == 2)
3425 {
3426 phy = m_phySta2;
3427 }
3428 else if (txStaId == 3)
3429 {
3430 phy = m_phySta3;
3431 }
3432
3433 Time txDuration =
3434 phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
3435 txVector.SetLength(
3436 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3437
3438 phy->SetPpduUid(uid);
3439 phy->Send(psdus, txVector);
3440}
3441
3442void
3444{
3445 NS_LOG_FUNCTION(this << duration);
3446 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
3447 m_phyInterferer->SetPeriod(duration);
3448 m_phyInterferer->Start();
3450}
3451
3452void
3457
3461
3462void
3464 RxSignalInfo rxSignalInfo,
3465 WifiTxVector txVector,
3466 std::vector<bool> /*statusPerMpdu*/)
3467{
3468 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3469 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3470 {
3472 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3473 }
3474 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3475 {
3477 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3478 }
3479}
3480
3481void
3483{
3484 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3485 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3486 {
3488 }
3489 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3490 {
3492 }
3493}
3494
3495void
3497 uint32_t expectedFailures,
3498 uint32_t expectedBytes)
3499{
3501 expectedSuccess,
3502 "The number of successfully received packets from STA 1 is not correct!");
3505 expectedFailures,
3506 "The number of unsuccessfuly received packets from STA 1 is not correct!");
3508 expectedBytes,
3509 "The number of bytes received from STA 1 is not correct!");
3510}
3511
3512void
3514 uint32_t expectedFailures,
3515 uint32_t expectedBytes)
3516{
3518 expectedSuccess,
3519 "The number of successfully received packets from STA 2 is not correct!");
3522 expectedFailures,
3523 "The number of unsuccessfuly received packets from STA 2 is not correct!");
3525 expectedBytes,
3526 "The number of bytes received from STA 2 is not correct!");
3527}
3528
3529void
3532 Watt_u expectedRxPower)
3533{
3534 auto event = phy->GetCurrentEvent();
3535 NS_ASSERT(event);
3536 auto rxPower = event->GetRxPower(band);
3537 NS_LOG_FUNCTION(this << band << expectedRxPower << rxPower);
3538 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3540 expectedRxPower,
3541 5e-3,
3542 "RX power " << rxPower << " over (" << band
3543 << ") does not match expected power " << expectedRxPower
3544 << " at " << Simulator::Now());
3545}
3546
3547void
3550 Watt_u expectedRxPower)
3551{
3552 /**
3553 * The current event cannot be used since it points to the preamble part of the HE TB PPDU.
3554 * We will have to check if the expected power is indeed the max power returning a positive
3555 * duration when calling GetEnergyDuration.
3556 */
3557 NS_LOG_FUNCTION(this << band << expectedRxPower);
3558 double step = 5e-3;
3559 if (expectedRxPower > 0.0)
3560 {
3562 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3563 true,
3564 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3565 << Simulator::Now());
3567 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3568 false,
3569 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3570 << Simulator::Now());
3571 }
3572 else
3573 {
3575 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3576 false,
3577 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3578 << Simulator::Now());
3579 }
3580}
3581
3582void
3584{
3586 nullptr,
3587 "m_currentEvent for AP was not cleared");
3589 nullptr,
3590 "m_currentEvent for STA 1 was not cleared");
3592 nullptr,
3593 "m_currentEvent for STA 2 was not cleared");
3594}
3595
3596void
3598{
3599 // This is needed to make sure PHY state will be checked as the last event if a state change
3600 // occurred at the exact same time as the check
3602}
3603
3604void
3606 WifiPhyState expectedState)
3607{
3608 WifiPhyState currentState;
3609 PointerValue ptr;
3610 phy->GetAttribute("State", ptr);
3612 currentState = state->GetState();
3613 NS_LOG_FUNCTION(this << currentState);
3614 NS_TEST_ASSERT_MSG_EQ(currentState,
3615 expectedState,
3616 "PHY State " << currentState << " does not match expected state "
3617 << expectedState << " at " << Simulator::Now());
3618}
3619
3620void
3622 Time expectedLastNotification)
3623{
3625 expectedNotifications,
3626 "Number of RX start notifications "
3628 << " does not match expected count " << expectedNotifications
3629 << " for AP at " << Simulator::Now());
3631 expectedLastNotification,
3632 "Last time RX start notification has been received "
3634 << " does not match expected time " << expectedLastNotification
3635 << " for AP at " << Simulator::Now());
3636}
3637
3638void
3640 Time expectedLastNotification,
3641 bool expectedSuccess)
3642{
3644 expectedNotifications,
3645 "Number of RX end notifications "
3647 << " does not match expected count " << expectedNotifications
3648 << " for AP at " << Simulator::Now());
3650 expectedLastNotification,
3651 "Last time RX end notification has been received "
3653 << " does not match expected time " << expectedLastNotification
3654 << " for AP at " << Simulator::Now());
3656 expectedSuccess,
3657 "Last time RX end notification indicated a "
3658 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3659 << " but expected a " << (expectedSuccess ? "success" : "failure")
3660 << " for AP at " << Simulator::Now());
3661}
3662
3663void
3678
3679void
3681{
3682 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3683 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3684 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3685}
3686
3687void
3689{
3690 NS_LOG_FUNCTION(this << phy << psdLimit);
3691 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3692}
3693
3694void
3696{
3699 lossModel->SetFrequency(m_frequency);
3700 spectrumChannel->AddPropagationLossModel(lossModel);
3703 spectrumChannel->SetPropagationDelayModel(delayModel);
3704
3705 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3707 preambleDetectionModel->SetAttribute(
3708 "MinimumRssi",
3710 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3711 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3712
3713 Ptr<Node> apNode = CreateObject<Node>();
3715 apDev->SetStandard(WIFI_STANDARD_80211ax);
3717 "Txop",
3718 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
3719 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3720 apDev->SetMac(apMac);
3723 apDev->SetHeConfiguration(heConfiguration);
3725 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3727 m_phyAp->SetErrorRateModel(apErrorModel);
3728 m_phyAp->SetDevice(apDev);
3729 m_phyAp->AddChannel(spectrumChannel);
3733 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3735 m_phyAp->SetMobility(apMobility);
3736 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3738 apDev->SetPhy(m_phyAp);
3739 apMac->SetWifiPhys({m_phyAp});
3740 apNode->AggregateObject(apMobility);
3741 apNode->AddDevice(apDev);
3742
3743 Ptr<Node> sta1Node = CreateObject<Node>();
3745 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
3746 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3749 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3751 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3752 m_phySta1->SetDevice(sta1Dev);
3753 m_phySta1->AddChannel(spectrumChannel);
3755 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3757 m_phySta1->SetMobility(sta1Mobility);
3758 sta1Dev->SetPhy(m_phySta1);
3759 sta1Node->AggregateObject(sta1Mobility);
3760 sta1Node->AddDevice(sta1Dev);
3761
3762 Ptr<Node> sta2Node = CreateObject<Node>();
3764 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
3765 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3768 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3770 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3771 m_phySta2->SetDevice(sta2Dev);
3772 m_phySta2->AddChannel(spectrumChannel);
3774 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3776 m_phySta2->SetMobility(sta2Mobility);
3777 sta2Dev->SetPhy(m_phySta2);
3778 sta2Node->AggregateObject(sta2Mobility);
3779 sta2Node->AddDevice(sta2Dev);
3780
3781 Ptr<Node> sta3Node = CreateObject<Node>();
3783 sta3Dev->SetStandard(WIFI_STANDARD_80211ax);
3784 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3787 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3789 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3790 m_phySta3->SetDevice(sta3Dev);
3791 m_phySta3->AddChannel(spectrumChannel);
3793 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3795 m_phySta3->SetMobility(sta3Mobility);
3796 sta3Dev->SetPhy(m_phySta3);
3797 sta3Node->AggregateObject(sta3Mobility);
3798 sta3Node->AddDevice(sta3Dev);
3799
3800 Ptr<Node> interfererNode = CreateObject<Node>();
3803 m_phyInterferer->SetDevice(interfererDev);
3804 m_phyInterferer->SetChannel(spectrumChannel);
3805 m_phyInterferer->SetDutyCycle(1);
3806 interfererNode->AddDevice(interfererDev);
3807
3808 // Configure power attributes of all wifi devices
3809 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3810 for (auto& phy : phys)
3811 {
3812 phy->SetAttribute("TxGain", DoubleValue(1.0));
3813 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3814 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3815 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3816 phy->SetAttribute("RxGain", DoubleValue(2.0));
3817 // test assumes no rejection power for simplicity
3818 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3819 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3820 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3821 }
3822}
3823
3824void
3826{
3827 m_phyAp->Dispose();
3828 m_phyAp = nullptr;
3829 m_phySta1->Dispose();
3830 m_phySta1 = nullptr;
3831 m_phySta2->Dispose();
3832 m_phySta2 = nullptr;
3833 m_phySta3->Dispose();
3834 m_phySta3 = nullptr;
3836 m_phyInterferer = nullptr;
3837}
3838
3839void
3841{
3842 NS_LOG_INFO(log);
3843}
3844
3845void
3847 bool solicited,
3848 WifiPhyState expectedStateAtEnd,
3849 uint32_t expectedSuccessFromSta1,
3850 uint32_t expectedFailuresFromSta1,
3851 uint32_t expectedBytesFromSta1,
3852 uint32_t expectedSuccessFromSta2,
3853 uint32_t expectedFailuresFromSta2,
3854 uint32_t expectedBytesFromSta2,
3855 bool scheduleTxSta1,
3856 Time ulTimeDifference,
3857 WifiPhyState expectedStateBeforeEnd,
3858 TrigVectorInfo error)
3859{
3860 static uint64_t uid = 0;
3861
3862 // AP sends an SU packet preceding HE TB PPDUs
3865 this,
3866 0,
3867 50,
3868 ++uid,
3869 0);
3870 if (!solicited)
3871 {
3872 // UID of TB PPDUs will be different than the one of the preceding frame
3873 ++uid;
3874 }
3875 else
3876 {
3878 }
3879 // STA1 and STA2 send MU UL PPDUs addressed to AP
3882 m_apPhyStateListener.get());
3883 if (scheduleTxSta1)
3884 {
3885 Simulator::Schedule(delay,
3887 this,
3888 1,
3889 1,
3890 1000,
3891 uid,
3892 0,
3893 false);
3894 }
3895 Simulator::Schedule(delay + ulTimeDifference,
3897 this,
3898 2,
3899 2,
3900 1001,
3901 uid,
3902 0,
3903 false);
3904
3905 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3908 this,
3909 m_phyAp,
3910 expectedStateBeforeEnd);
3911 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3913 this,
3914 m_phyAp,
3915 expectedStateAtEnd);
3916 // TODO: add checks on TX stop for STAs
3917
3918 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3919 expectedFailuresFromSta2 >
3920 0)
3921 {
3922 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3923 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3924 // The expected time at which the reception is started corresponds to the time at which the
3925 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3926 const Time expectedPayloadStart = delay + MicroSeconds(48);
3927 // The expected time at which the reception is terminated corresponds to the time at which
3928 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3929 // received HE TB PPDU and the last received HE TB PPDU.
3930 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3931 // At the end of the transmission, verify that a single RX start notification shall have
3932 // been notified when the reception of the first HE RB PPDU starts.
3933 Simulator::Schedule(expectedPayloadEnd,
3935 this,
3936 1,
3937 Simulator::Now() + expectedPayloadStart);
3938 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3939 // notification shall have been notified when the reception of the last HE RB PPDU ends
3940 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3942 this,
3943 1,
3944 Simulator::Now() + expectedPayloadEnd,
3945 isSuccess);
3946 }
3947
3948 delay += MilliSeconds(100);
3949 // Check reception state from STA 1
3950 Simulator::Schedule(delay,
3952 this,
3953 expectedSuccessFromSta1,
3954 expectedFailuresFromSta1,
3955 expectedBytesFromSta1);
3956 // Check reception state from STA 2
3957 Simulator::Schedule(delay,
3959 this,
3960 expectedSuccessFromSta2,
3961 expectedFailuresFromSta2,
3962 expectedBytesFromSta2);
3963 // Verify events data have been cleared
3965
3966 delay += MilliSeconds(100);
3968}
3969
3970void
3972 Watt_u rxPowerNonOfdmaRu1,
3973 Watt_u rxPowerNonOfdmaRu2,
3974 Watt_u rxPowerOfdmaRu1,
3975 Watt_u rxPowerOfdmaRu2)
3976{
3977 const auto detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3978 const auto txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3979 const auto txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3980 const auto hePhy = m_phyAp->GetHePhy();
3981 const auto nonOfdmaDuration = hePhy->CalculateNonHeDurationForHeTb(txVectorSta2);
3982 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonHeDurationForHeTb(txVectorSta1));
3983
3984 std::vector<Watt_u> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3985 std::vector<WifiSpectrumBandInfo> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3986 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
3987 std::vector<Watt_u> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
3988 std::vector<WifiSpectrumBandInfo> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
3989 hePhy->GetRuBandForRx(txVectorSta2, 2)};
3990
3991 for (uint8_t i = 0; i < 2; ++i)
3992 {
3993 /**
3994 * Perform checks at AP
3995 */
3996 // Check received power on non-OFDMA portion
3998 delay + detectionDuration +
3999 NanoSeconds(1), // just after beginning of portion (once event is stored)
4001 this,
4002 m_phyAp,
4003 nonOfdmaBand[i],
4004 rxPowerNonOfdma[i]);
4005 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4007 this,
4008 m_phyAp,
4009 nonOfdmaBand[i],
4010 rxPowerNonOfdma[i]);
4011 // Check received power on OFDMA portion
4012 Simulator::Schedule(delay + nonOfdmaDuration +
4013 NanoSeconds(1), // just after beginning of portion
4015 this,
4016 m_phyAp,
4017 ofdmaBand[i],
4018 rxPowerOfdma[i]);
4020 NanoSeconds(1), // just before end of portion
4022 this,
4023 m_phyAp,
4024 ofdmaBand[i],
4025 rxPowerOfdma[i]);
4026
4027 /**
4028 * Perform checks for non-transmitting STA (STA 3).
4029 * Cannot use CheckNonOfdmaRxPower method since current event may be reset if
4030 * preamble not detected (e.g. not on primary).
4031 */
4032 // Check received power on non-OFDMA portion
4034 delay + detectionDuration +
4035 NanoSeconds(1), // just after beginning of portion (once event is stored)
4037 this,
4038 m_phySta3,
4039 nonOfdmaBand[i],
4040 rxPowerNonOfdma[i]);
4041 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4043 this,
4044 m_phySta3,
4045 nonOfdmaBand[i],
4046 rxPowerNonOfdma[i]);
4047 // Check received power on OFDMA portion
4048 Simulator::Schedule(delay + nonOfdmaDuration +
4049 NanoSeconds(1), // just after beginning of portion
4051 this,
4052 m_phySta3,
4053 ofdmaBand[i],
4054 rxPowerOfdma[i]);
4056 NanoSeconds(1), // just before end of portion
4058 this,
4059 m_phySta3,
4060 ofdmaBand[i],
4061 rxPowerOfdma[i]);
4062 }
4063
4064 if (rxPowerOfdmaRu1 != 0.0)
4065 {
4066 /**
4067 * Perform checks for transmitting STA (STA 2) to ensure it has correctly logged
4068 * power received from other transmitting STA (STA 1).
4069 * Cannot use CheckNonOfdmaRxPower method since current event not set.
4070 */
4071 const auto rxPowerNonOfdmaSta1Only =
4072 (m_channelWidth >= 40)
4073 ? rxPowerNonOfdma[0]
4074 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4075 // Check received power on non-OFDMA portion
4077 delay + detectionDuration +
4078 NanoSeconds(1), // just after beginning of portion (once event is stored)
4080 this,
4081 m_phySta2,
4082 nonOfdmaBand[0],
4083 rxPowerNonOfdmaSta1Only);
4084 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4086 this,
4087 m_phySta2,
4088 nonOfdmaBand[0],
4089 rxPowerNonOfdmaSta1Only);
4090 // Check received power on OFDMA portion
4091 Simulator::Schedule(delay + nonOfdmaDuration +
4092 NanoSeconds(1), // just after beginning of portion
4094 this,
4095 m_phySta2,
4096 ofdmaBand[0],
4097 rxPowerOfdma[0]);
4099 NanoSeconds(1), // just before end of portion
4101 this,
4102 m_phySta2,
4103 ofdmaBand[0],
4104 rxPowerOfdma[0]);
4105 }
4106}
4107
4108void
4110{
4113 int64_t streamNumber = 0;
4114 m_phyAp->AssignStreams(streamNumber);
4115 m_phySta1->AssignStreams(streamNumber);
4116 m_phySta2->AssignStreams(streamNumber);
4117 m_phySta3->AssignStreams(streamNumber);
4118
4119 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
4124 ->number;
4125
4134
4135 Time delay = Seconds(0.0);
4137 delay += Seconds(1.0);
4138
4139 /**
4140 * In all the following tests, 2 HE TB PPDUs of the same UL MU transmission
4141 * are sent on RU 1 for STA 1 and RU 2 for STA 2.
4142 * The difference between solicited and unsolicited lies in that their PPDU
4143 * ID correspond to the one of the immediately preceding HE SU PPDU (thus
4144 * mimicking trigger frame reception).
4145 */
4146
4147 //---------------------------------------------------------------------------
4148 // Verify that both solicited HE TB PPDUs have been corrected received
4149 Simulator::Schedule(delay,
4151 this,
4152 "Reception of solicited HE TB PPDUs");
4153 ScheduleTest(delay,
4154 true,
4155 WifiPhyState::IDLE,
4156 1,
4157 0,
4158 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4159 1,
4160 0,
4161 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4162 delay += Seconds(1.0);
4163
4164 //---------------------------------------------------------------------------
4165 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4166 // corrected received
4168 delay,
4170 this,
4171 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4172 ScheduleTest(delay,
4173 true,
4174 WifiPhyState::IDLE,
4175 1,
4176 0,
4177 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4178 1,
4179 0,
4180 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4181 true,
4182 NanoSeconds(100));
4183 delay += Seconds(1.0);
4184
4185 //---------------------------------------------------------------------------
4186 // Verify that no unsolicited HE TB PPDU is received
4187 Simulator::Schedule(delay,
4189 this,
4190 "Dropping of unsolicited HE TB PPDUs");
4191 ScheduleTest(delay,
4192 false,
4193 WifiPhyState::IDLE,
4194 0,
4195 0,
4196 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4197 0,
4198 0,
4199 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4200 true,
4201 Seconds(0),
4202 WifiPhyState::CCA_BUSY);
4203 delay += Seconds(1.0);
4204
4205 //---------------------------------------------------------------------------
4206 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4207 Simulator::Schedule(delay,
4209 this,
4210 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4211 ScheduleTest(delay,
4212 true,
4213 WifiPhyState::IDLE,
4214 0,
4215 0,
4216 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4217 0,
4218 0,
4219 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4220 true,
4221 Seconds(0),
4222 WifiPhyState::CCA_BUSY,
4224 delay += Seconds(1.0);
4225
4226 //---------------------------------------------------------------------------
4227 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4228 Simulator::Schedule(delay,
4230 this,
4231 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4232 ScheduleTest(delay,
4233 true,
4234 WifiPhyState::IDLE,
4235 0,
4236 0,
4237 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4238 0,
4239 0,
4240 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4241 true,
4242 Seconds(0),
4243 WifiPhyState::CCA_BUSY,
4244 UL_LENGTH);
4245 delay += Seconds(1.0);
4246
4247 //---------------------------------------------------------------------------
4248 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4249 Simulator::Schedule(delay,
4251 this,
4252 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4253 ScheduleTest(delay,
4254 true,
4255 WifiPhyState::IDLE,
4256 0,
4257 0,
4258 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4259 0,
4260 0,
4261 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4262 true,
4263 Seconds(0),
4264 WifiPhyState::CCA_BUSY,
4265 AID);
4266 delay += Seconds(1.0);
4267
4268 //---------------------------------------------------------------------------
4269 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4270 // impacted
4272 delay,
4274 this,
4275 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4276 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4277 BandInfo bandInfo;
4278 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
4279 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4280 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4281 Bands bands;
4282 bands.push_back(bandInfo);
4283
4284 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4285 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4286 Watt_u interferencePower{0.1};
4287 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
4288
4291 this,
4292 interferencePsdRu1,
4293 MilliSeconds(100));
4295 delay,
4296 true,
4297 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4298 // interference
4299 0,
4300 1,
4301 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4302 1,
4303 0,
4304 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4305 delay += Seconds(1.0);
4306
4307 //---------------------------------------------------------------------------
4308 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4309 // impacted
4311 delay,
4313 this,
4314 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4315 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4316 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
4317 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4318 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4319 bands.clear();
4320 bands.push_back(bandInfo);
4321
4322 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4323 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4324 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
4325
4328 this,
4329 interferencePsdRu2,
4330 MilliSeconds(100));
4331 ScheduleTest(delay,
4332 true,
4333 (m_channelWidth >= 40)
4334 ? WifiPhyState::IDLE
4335 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4336 // generated in its primary channel
4337 1,
4338 0,
4339 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4340 0,
4341 1,
4342 0); // Reception of the PSDU from STA 2 should have failed (since interference
4343 // occupies RU 2)
4344 delay += Seconds(1.0);
4345
4346 //---------------------------------------------------------------------------
4347 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4348 // been impacted
4349 Simulator::Schedule(delay,
4351 this,
4352 "Reception of solicited HE TB PPDUs with interference on the full band "
4353 "during PSDU reception");
4354 // A strong non-wifi interference is generated on the full band during PSDU reception
4355 bandInfo.fc = m_frequency * 1e6;
4356 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
4357 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
4358 bands.clear();
4359 bands.push_back(bandInfo);
4360
4361 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4362 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4363 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
4364
4367 this,
4368 interferencePsdAll,
4369 MilliSeconds(100));
4371 delay,
4372 true,
4373 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4374 // interference
4375 0,
4376 1,
4377 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4378 0,
4379 1,
4380 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4381 // 2)
4382 delay += Seconds(1.0);
4383
4384 //---------------------------------------------------------------------------
4385 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4386 // solicited HE TB PPDUs have been impacted if they are on the same
4387 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4388 Simulator::Schedule(delay,
4390 this,
4391 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4392 "1 during PSDU reception");
4393 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4396 this,
4397 3,
4398 1,
4399 1002,
4400 1,
4401 0,
4402 false);
4403 // Expected figures from STA 2
4404 uint32_t succ;
4405 uint32_t fail;
4406 uint32_t bytes;
4407 if (m_channelWidth > 20)
4408 {
4409 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4410 // interference from STA 3 on distinct 20 MHz channel)
4411 succ = 1;
4412 fail = 0;
4413 bytes = 1001;
4414 }
4415 else
4416 {
4417 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4418 // same 20 MHz channel)
4419 succ = 0;
4420 fail = 1;
4421 bytes = 0;
4422 }
4423 ScheduleTest(delay,
4424 true,
4425 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4426 // interference on measurement channel width
4427 0,
4428 1,
4429 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4430 // STA 3 on same 20 MHz channel)
4431 succ,
4432 fail,
4433 bytes);
4434 delay += Seconds(1.0);
4435
4436 //---------------------------------------------------------------------------
4437 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4438 // solicited HE TB PPDUs have been impacted if they are on the same
4439 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4440 Simulator::Schedule(delay,
4442 this,
4443 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4444 "2 during PSDU reception");
4445 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4448 this,
4449 3,
4450 2,
4451 1002,
4452 1,
4453 0,
4454 false);
4455 // Expected figures from STA 1
4456 if (m_channelWidth > 20)
4457 {
4458 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4459 // interference from STA 3 on distinct 20 MHz channel)
4460 succ = 1;
4461 fail = 0;
4462 bytes = 1000;
4463 }
4464 else
4465 {
4466 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4467 // same 20 MHz channel)
4468 succ = 0;
4469 fail = 1;
4470 bytes = 0;
4471 }
4472 ScheduleTest(delay,
4473 true,
4474 (m_channelWidth >= 40)
4475 ? WifiPhyState::IDLE
4476 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4477 // TB PPDU on primary channel
4478 succ,
4479 fail,
4480 bytes,
4481 0,
4482 1,
4483 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4484 // STA 3 on same 20 MHz channel)
4485 delay += Seconds(1.0);
4486
4487 //---------------------------------------------------------------------------
4488 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4489 // impacted
4491 delay,
4493 this,
4494 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4495 // One HE SU arrives at AP during the 400ns window
4496 Simulator::Schedule(delay + NanoSeconds(300),
4498 this,
4499 3,
4500 1002,
4501 1,
4502 0);
4504 delay,
4505 true,
4506 WifiPhyState::IDLE,
4507 0,
4508 1,
4509 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4510 0,
4511 1,
4512 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4513 delay += Seconds(1.0);
4514
4515 //---------------------------------------------------------------------------
4516 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4517 // received
4518 Simulator::Schedule(delay,
4520 this,
4521 "Reception of solicited HE TB PPDU only on RU 2");
4522 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4523 // otherwise
4526 this,
4527 m_phySta3,
4528 (m_channelWidth >= 40)
4529 ? WifiPhyState::IDLE
4530 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4531 // IDLE if HE TB PPDU on primary channel
4532 ScheduleTest(delay,
4533 true,
4534 WifiPhyState::IDLE,
4535 0,
4536 0,
4537 0, // No transmission scheduled for STA 1
4538 1,
4539 0,
4540 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4541 false,
4542 Seconds(0),
4543 WifiPhyState::RX); // Measurement channel is total channel width
4544 delay += Seconds(1.0);
4545
4546 //---------------------------------------------------------------------------
4547 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4548 Simulator::Schedule(delay,
4550 this,
4551 "Measure power for reception of HE TB PPDU only on RU 2");
4552 auto rxPower =
4553 DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4555 (m_channelWidth >= 40) ? 0.0 : rxPower,
4556 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4557 0.0,
4558 rxPower);
4559 ScheduleTest(delay,
4560 true,
4561 WifiPhyState::IDLE,
4562 0,
4563 0,
4564 0, // No transmission scheduled for STA 1
4565 1,
4566 0,
4567 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4568 false,
4569 Seconds(0),
4570 WifiPhyState::RX); // Measurement channel is total channel width
4571 delay += Seconds(1.0);
4572
4573 //---------------------------------------------------------------------------
4574 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4575 // limitation enforced
4577 delay,
4579 this,
4580 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4581 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4582 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4583 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4585 this,
4586 m_phySta2,
4587 3.0);
4588
4589 rxPower = (m_channelWidth > 40)
4590 ? DbmToW(19)
4591 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4592 // transmitted only on one 20 MHz channel
4593 auto rxPowerOfdma = rxPower;
4594 if (m_channelWidth <= 40)
4595 {
4596 rxPowerOfdma = (m_channelWidth == 20)
4597 ? DbmToW(14.0309) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4598 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4599 }
4601 (m_channelWidth >= 40) ? 0.0 : rxPower,
4602 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4603 0.0,
4604 rxPowerOfdma);
4605
4606 // Reset PSD limitation once HE TB has been sent
4609 this,
4610 m_phySta2,
4611 100.0);
4612 ScheduleTest(delay,
4613 true,
4614 WifiPhyState::IDLE,
4615 0,
4616 0,
4617 0, // No transmission scheduled for STA 1
4618 1,
4619 0,
4620 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4621 false,
4622 Seconds(0),
4623 WifiPhyState::RX); // Measurement channel is total channel width
4624 delay += Seconds(1.0);
4625
4626 //---------------------------------------------------------------------------
4627 // Measure the power of 2 solicited HE TB PPDU from both STAs
4628 Simulator::Schedule(delay,
4630 this,
4631 "Measure power for reception of HE TB PPDU on both RUs");
4632 rxPower = DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4633 const auto rxPowerNonOfdma =
4634 (m_channelWidth >= 40) ? rxPower
4635 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4636 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4637 ScheduleTest(delay,
4638 true,
4639 WifiPhyState::IDLE,
4640 1,
4641 0,
4642 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4643 1,
4644 0,
4645 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4646 delay += Seconds(1.0);
4647
4648 //---------------------------------------------------------------------------
4649 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4650 // ongoing)
4651 Simulator::Schedule(delay,
4653 this,
4654 "Reception of an HE TB PPDU from another BSS");
4655 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4657 Simulator::Schedule(delay + MilliSeconds(100),
4659 this,
4660 3,
4661 1,
4662 1002,
4663 1,
4664 2,
4665 false);
4666
4667 // Verify events data have been cleared
4668 Simulator::Schedule(delay + MilliSeconds(200),
4670 this);
4671
4673 delay += Seconds(1.0);
4674
4675 //---------------------------------------------------------------------------
4676 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4677 // corrected received
4679 delay,
4681 this,
4682 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4683 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4687 this,
4688 3,
4689 1,
4690 1002,
4691 1,
4692 2,
4693 true);
4694 ScheduleTest(delay,
4695 true,
4696 WifiPhyState::CCA_BUSY,
4697 1,
4698 0,
4699 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4700 1,
4701 0,
4702 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4703 true,
4704 NanoSeconds(200));
4705 delay += Seconds(1.0);
4706
4708}
4709
4710void
4712{
4713 m_frequency = 5180;
4714 m_channelWidth = 20;
4716 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4717 RunOne();
4718
4719 m_frequency = 5190;
4720 m_channelWidth = 40;
4722 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4723 RunOne();
4724
4725 m_frequency = 5210;
4726 m_channelWidth = 80;
4728 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4729 RunOne();
4730
4731 m_frequency = 5250;
4732 m_channelWidth = 160;
4734 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4735 RunOne();
4736
4738}
4739
4740/**
4741 * \ingroup wifi-test
4742 * \ingroup tests
4743 *
4744 * \brief PHY padding exclusion test
4745 */
4747{
4748 public:
4750 ~TestPhyPaddingExclusion() override;
4751
4752 private:
4753 void DoSetup() override;
4754 void DoTeardown() override;
4755 void DoRun() override;
4756
4757 /**
4758 * Send HE TB PPDU function
4759 * \param txStaId the ID of the TX STA
4760 * \param index the RU index used for the transmission
4761 * \param payloadSize the size of the payload in bytes
4762 * \param txDuration the duration of the PPDU
4763 */
4764 void SendHeTbPpdu(uint16_t txStaId,
4765 std::size_t index,
4766 std::size_t payloadSize,
4767 Time txDuration);
4768 /**
4769 * Set TRIGVECTOR for HE TB PPDU
4770 *
4771 * \param ppduDuration the duration of the HE TB PPDU
4772 */
4773 void SetTrigVector(Time ppduDuration);
4774
4775 /**
4776 * Generate interference function
4777 * \param interferencePsd the PSD of the interference to be generated
4778 * \param duration the duration of the interference
4779 */
4780 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4781 /**
4782 * Stop interference function
4783 */
4784 void StopInterference();
4785
4786 /**
4787 * Run one function
4788 */
4789 void RunOne();
4790
4791 /**
4792 * Check the received PSDUs from STA1
4793 * \param expectedSuccess the expected number of success
4794 * \param expectedFailures the expected number of failures
4795 * \param expectedBytes the expected number of bytes
4796 */
4797 void CheckRxFromSta1(uint32_t expectedSuccess,
4798 uint32_t expectedFailures,
4799 uint32_t expectedBytes);
4800
4801 /**
4802 * Check the received PSDUs from STA2
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 CheckRxFromSta2(uint32_t expectedSuccess,
4808 uint32_t expectedFailures,
4809 uint32_t expectedBytes);
4810
4811 /**
4812 * Verify all events are cleared at end of TX or RX
4813 */
4814 void VerifyEventsCleared();
4815
4816 /**
4817 * Check the PHY state
4818 * \param phy the PHY
4819 * \param expectedState the expected state of the PHY
4820 */
4821 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
4822 /// \copydoc CheckPhyState
4824
4825 /**
4826 * Reset function
4827 */
4828 void Reset();
4829
4830 /**
4831 * Receive success function
4832 * \param psdu the PSDU
4833 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
4834 * \param txVector the transmit vector
4835 * \param statusPerMpdu reception status per MPDU
4836 */
4838 RxSignalInfo rxSignalInfo,
4839 WifiTxVector txVector,
4840 std::vector<bool> statusPerMpdu);
4841
4842 /**
4843 * Receive failure function
4844 * \param psdu the PSDU
4845 */
4846 void RxFailure(Ptr<const WifiPsdu> psdu);
4847
4851
4853
4854 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
4855 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
4856 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
4857 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
4858 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
4859 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
4860};
4861
4863 : TestCase("PHY padding exclusion test"),
4864 m_countRxSuccessFromSta1(0),
4865 m_countRxSuccessFromSta2(0),
4866 m_countRxFailureFromSta1(0),
4867 m_countRxFailureFromSta2(0),
4868 m_countRxBytesFromSta1(0),
4869 m_countRxBytesFromSta2(0)
4870{
4871}
4872
4873void
4875 std::size_t index,
4876 std::size_t payloadSize,
4877 Time txDuration)
4878{
4879 WifiConstPsduMap psdus;
4880
4881 WifiTxVector txVector{HePhy::GetHeMcs7(),
4882 0,
4884 NanoSeconds(1600),
4885 1,
4886 1,
4887 0,
4889 false,
4890 false,
4891 true};
4892
4893 HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4894 txVector.SetRu(ru, txStaId);
4895 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4896 txVector.SetNss(1, txStaId);
4897
4898 auto pkt = Create<Packet>(payloadSize);
4899 WifiMacHeader hdr;
4901 hdr.SetQosTid(0);
4902 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4903 std::ostringstream addr;
4904 addr << "00:00:00:00:00:0" << txStaId;
4905 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4906 hdr.SetSequenceNumber(1);
4907 auto psdu = Create<WifiPsdu>(pkt, hdr);
4908 psdus.insert(std::make_pair(txStaId, psdu));
4909
4911 if (txStaId == 1)
4912 {
4913 phy = m_phySta1;
4914 }
4915 else if (txStaId == 2)
4916 {
4917 phy = m_phySta2;
4918 }
4919
4920 txVector.SetLength(
4921 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4922
4923 phy->SetPpduUid(0);
4924 phy->Send(psdus, txVector);
4925}
4926
4927void
4929{
4930 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
4931 m_phyInterferer->SetPeriod(duration);
4932 m_phyInterferer->Start();
4934}
4935
4936void
4941
4945
4946void
4948 RxSignalInfo rxSignalInfo,
4949 WifiTxVector txVector,
4950 std::vector<bool> /*statusPerMpdu*/)
4951{
4952 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
4953 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4954 {
4956 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
4957 }
4958 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4959 {
4961 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
4962 }
4963}
4964
4965void
4967{
4968 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
4969 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4970 {
4972 }
4973 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4974 {
4976 }
4977}
4978
4979void
4981 uint32_t expectedFailures,
4982 uint32_t expectedBytes)
4983{
4985 expectedSuccess,
4986 "The number of successfully received packets from STA 1 is not correct!");
4989 expectedFailures,
4990 "The number of unsuccessfuly received packets from STA 1 is not correct!");
4992 expectedBytes,
4993 "The number of bytes received from STA 1 is not correct!");
4994}
4995
4996void
4998 uint32_t expectedFailures,
4999 uint32_t expectedBytes)
5000{
5002 expectedSuccess,
5003 "The number of successfully received packets from STA 2 is not correct!");
5006 expectedFailures,
5007 "The number of unsuccessfuly received packets from STA 2 is not correct!");
5009 expectedBytes,
5010 "The number of bytes received from STA 2 is not correct!");
5011}
5012
5013void
5015{
5017 nullptr,
5018 "m_currentEvent for AP was not cleared");
5020 nullptr,
5021 "m_currentEvent for STA 1 was not cleared");
5023 nullptr,
5024 "m_currentEvent for STA 2 was not cleared");
5025}
5026
5027void
5029{
5030 // This is needed to make sure PHY state will be checked as the last event if a state change
5031 // occurred at the exact same time as the check
5033}
5034
5035void
5037{
5038 WifiPhyState currentState = phy->GetState()->GetState();
5039 NS_LOG_FUNCTION(this << currentState);
5040 NS_TEST_ASSERT_MSG_EQ(currentState,
5041 expectedState,
5042 "PHY State " << currentState << " does not match expected state "
5043 << expectedState << " at " << Simulator::Now());
5044}
5045
5046void
5059
5060void
5062{
5065 int64_t streamNumber = 0;
5066
5069 lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
5070 spectrumChannel->AddPropagationLossModel(lossModel);
5073 spectrumChannel->SetPropagationDelayModel(delayModel);
5074
5075 Ptr<Node> apNode = CreateObject<Node>();
5078 "Txop",
5079 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
5080 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5081 apDev->SetMac(apMac);
5084 apDev->SetHeConfiguration(heConfiguration);
5086 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5088 m_phyAp->SetErrorRateModel(apErrorModel);
5089 m_phyAp->SetDevice(apDev);
5090 m_phyAp->AddChannel(spectrumChannel);
5092 m_phyAp->AssignStreams(streamNumber);
5093 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
5098 ->number;
5099
5105 m_phyAp->SetMobility(apMobility);
5106 apDev->SetPhy(m_phyAp);
5107 apDev->SetStandard(WIFI_STANDARD_80211ax);
5108 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5109 apMac->SetWifiPhys({m_phyAp});
5110 apNode->AggregateObject(apMobility);
5111 apNode->AddDevice(apDev);
5112
5113 Ptr<Node> sta1Node = CreateObject<Node>();
5117 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5119 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5120 m_phySta1->SetDevice(sta1Dev);
5121 m_phySta1->AddChannel(spectrumChannel);
5123 m_phySta1->AssignStreams(streamNumber);
5127 m_phySta1->SetMobility(sta1Mobility);
5128 sta1Dev->SetPhy(m_phySta1);
5129 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
5130 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5131 sta1Node->AggregateObject(sta1Mobility);
5132 sta1Node->AddDevice(sta1Dev);
5133
5134 Ptr<Node> sta2Node = CreateObject<Node>();
5138 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5140 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5141 m_phySta2->SetDevice(sta2Dev);
5142 m_phySta2->AddChannel(spectrumChannel);
5144 m_phySta2->AssignStreams(streamNumber);
5148 m_phySta2->SetMobility(sta2Mobility);
5149 sta2Dev->SetPhy(m_phySta2);
5150 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
5151 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5152 sta2Node->AggregateObject(sta2Mobility);
5153 sta2Node->AddDevice(sta2Dev);
5154
5155 Ptr<Node> interfererNode = CreateObject<Node>();
5158 m_phyInterferer->SetDevice(interfererDev);
5159 m_phyInterferer->SetChannel(spectrumChannel);
5160 m_phyInterferer->SetDutyCycle(1);
5161 interfererNode->AddDevice(interfererDev);
5162}
5163
5164void
5166{
5167 m_phyAp->Dispose();
5168 m_phyAp = nullptr;
5169 m_phySta1->Dispose();
5170 m_phySta1 = nullptr;
5171 m_phySta2->Dispose();
5172 m_phySta2 = nullptr;
5174 m_phyInterferer = nullptr;
5175}
5176
5177void
5179{
5180 WifiTxVector trigVector{HePhy::GetHeMcs7(),
5181 0,
5183 NanoSeconds(1600),
5184 1,
5185 1,
5186 0,
5188 false,
5189 false,
5190 true};
5191 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5192 trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5193 trigVector.SetNss(1, 1);
5194 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5195 trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5196 trigVector.SetNss(1, 2);
5197 uint16_t length;
5198 std::tie(length, ppduDuration) =
5200 trigVector.SetLength(length);
5202 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5203}
5204
5205void
5207{
5208 Time expectedPpduDuration = NanoSeconds(292800);
5209 Time ppduWithPaddingDuration =
5210 expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5211
5213
5214 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5217 this,
5218 1,
5219 1,
5220 1000,
5221 ppduWithPaddingDuration);
5224 this,
5225 2,
5226 2,
5227 1001,
5228 ppduWithPaddingDuration);
5229
5230 // Set TRIGVECTOR on AP
5233 this,
5234 ppduWithPaddingDuration);
5235
5236 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5237 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration - NanoSeconds(1),
5239 this,
5240 m_phyAp,
5241 WifiPhyState::RX);
5242 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration,
5244 this,
5245 m_phyAp,
5246 WifiPhyState::IDLE);
5247
5248 // One PSDU of 1000 bytes should have been successfully received from STA 1
5250 // One PSDU of 1001 bytes should have been successfully received from STA 2
5252 // Verify events data have been cleared
5254
5256
5257 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5260 this,
5261 1,
5262 1,
5263 1000,
5264 ppduWithPaddingDuration);
5267 this,
5268 2,
5269 2,
5270 1001,
5271 ppduWithPaddingDuration);
5272
5273 // Set TRIGVECTOR on AP
5276 this,
5277 ppduWithPaddingDuration);
5278
5279 // A strong non-wifi interference is generated on RU 1 during padding reception
5280 BandInfo bandInfo;
5281 bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
5282 bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5283 bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5284 Bands bands;
5285 bands.push_back(bandInfo);
5286
5287 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5288 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5289 Watt_u interferencePower{0.1};
5290 *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
5291
5292 Simulator::Schedule(Seconds(2.0) + MicroSeconds(50) + expectedPpduDuration,
5294 this,
5295 interferencePsdRu1,
5296 MilliSeconds(100));
5297
5298 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5299 // CCA_BUSY instead of IDLE due to the interference)
5300 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration - NanoSeconds(1),
5302 this,
5303 m_phyAp,
5304 WifiPhyState::RX);
5305 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration,
5307 this,
5308 m_phyAp,
5309 WifiPhyState::CCA_BUSY);
5310
5311 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5312 // occupies RU 1 after payload, during PHY padding)
5314 // One PSDU of 1001 bytes should have been successfully received from STA 2
5316 // Verify events data have been cleared
5318
5320
5322
5324}
5325
5326/**
5327 * \ingroup wifi-test
5328 * \ingroup tests
5329 *
5330 * \brief UL-OFDMA power control test
5331 */
5333{
5334 public:
5336 ~TestUlOfdmaPowerControl() override;
5337
5338 private:
5339 void DoSetup() override;
5340 void DoTeardown() override;
5341 void DoRun() override;
5342
5343 /**
5344 * Send a MU BAR through the AP to the STAs listed in the provided vector.
5345 *
5346 * \param staIds the vector of STA-IDs of STAs to address the MU-BAR to
5347 */
5348 void SendMuBar(std::vector<uint16_t> staIds);
5349
5350 /**
5351 * Send a QoS Data packet to the destination station in order
5352 * to set up a block Ack session (so that the MU-BAR may have a reply).
5353 *
5354 * \param destination the address of the destination station
5355 */
5356 void SetupBa(Address destination);
5357
5358 /**
5359 * Run one simulation with an optional BA session set up phase.
5360 *
5361 * \param setupBa true if BA session should be set up (i.e. upon first run),
5362 * false otherwise
5363 */
5364 void RunOne(bool setupBa);
5365
5366 /**
5367 * Replace the AP's callback on its PHY's ReceiveOkCallback
5368 * by the ReceiveOkCallbackAtAp method.
5369 */
5371
5372 /**
5373 * Receive OK callback function at AP.
5374 * This method will be plugged into the AP PHY's ReceiveOkCallback once the
5375 * block Ack session has been set up. This is done in the Reset function.
5376 * \param psdu the PSDU
5377 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
5378 * \param txVector the TXVECTOR used for the packet
5379 * \param statusPerMpdu reception status per MPDU
5380 */
5382 RxSignalInfo rxSignalInfo,
5383 WifiTxVector txVector,
5384 std::vector<bool> statusPerMpdu);
5385
5386 uint8_t m_bssColor; ///< BSS color
5387
5388 Ptr<WifiNetDevice> m_apDev; ///< network device of AP
5389 Ptr<WifiNetDevice> m_sta1Dev; ///< network device of STA 1
5390 Ptr<WifiNetDevice> m_sta2Dev; ///< network device of STA 2
5391
5393
5394 dBm_u m_txPowerAp; ///< transmit power of AP
5395 dBm_u m_txPowerStart; ///< minimum transmission power for STAs
5396 dBm_u m_txPowerEnd; ///< maximum transmission power for STAs
5397 uint8_t m_txPowerLevels; ///< number of transmission power levels for STAs
5398
5399 dBm_u m_requestedRssiSta1; ///< requested RSSI from STA 1 at AP for HE TB PPDUs
5400 dBm_u m_requestedRssiSta2; ///< requested RSSI from STA 2 at AP for HE TB PPDUs
5401
5402 dBm_u m_rssiSta1; ///< expected RSSI from STA 1 at AP for HE TB PPDUs
5403 dBm_u m_rssiSta2; ///< expected RSSI from STA 2 at AP for HE TB PPDUs
5404
5405 dB_u m_tol; ///< tolerance between received and expected RSSIs
5406};
5407
5409 : TestCase("UL-OFDMA power control test"),
5410 m_bssColor(1),
5411 m_txPowerAp(0),
5412 m_txPowerStart(0),
5413 m_txPowerEnd(0),
5414 m_txPowerLevels(0),
5415 m_requestedRssiSta1(0),
5416 m_requestedRssiSta2(0),
5417 m_rssiSta1(0),
5418 m_rssiSta2(0),
5419 m_tol(0.1)
5420{
5421}
5422
5424{
5425 m_phyAp = nullptr;
5426 m_apDev = nullptr;
5427 m_sta1Dev = nullptr;
5428 m_sta2Dev = nullptr;
5429}
5430
5431void
5433{
5434 // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5435 Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5436 m_apDev->Send(pkt, destination, 0);
5437}
5438
5439void
5440TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5441{
5442 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5443
5444 // Build MU-BAR trigger frame
5445 CtrlTriggerHeader muBar;
5446 muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5447 muBar.SetMoreTF(true);
5448 muBar.SetCsRequired(true);
5450 muBar.SetGiAndLtfType(NanoSeconds(1600), 2);
5451 muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5452 muBar.SetUlSpatialReuse(60500);
5453
5454 HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5455 std::size_t index = 1;
5456 int8_t ulTargetRssi = -40; // will be overwritten
5457 for (const auto& staId : staIds)
5458 {
5460 ui.SetAid12(staId);
5461 ui.SetRuAllocation({ru, index, true});
5462 ui.SetUlFecCodingType(true);
5463 ui.SetUlMcs(7);
5464 ui.SetUlDcm(false);
5465 ui.SetSsAllocation(1, 1);
5466 if (staId == 1)
5467 {
5468 ulTargetRssi = m_requestedRssiSta1;
5469 }
5470 else if (staId == 2)
5471 {
5472 ulTargetRssi = m_requestedRssiSta2;
5473 }
5474 else
5475 {
5476 NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5477 }
5478 ui.SetUlTargetRssi(ulTargetRssi);
5479
5482 bar.SetTidInfo(0);
5483 bar.SetStartingSequence(4095);
5485
5486 ++index;
5487 }
5488
5489 WifiTxVector tbTxVector{muBar.GetHeTbTxVector(staIds.front())};
5491 tbTxVector,
5493 .first);
5494
5495 WifiConstPsduMap psdus;
5496 WifiTxVector txVector{HePhy::GetHeMcs7(),
5497 0,
5499 NanoSeconds(800),
5500 1,
5501 1,
5502 0,
5504 false,
5505 false,
5506 false,
5507 m_bssColor};
5508
5509 auto bar = Create<Packet>();
5510 bar->AddHeader(muBar);
5511
5512 auto receiver = Mac48Address::GetBroadcast();
5513 if (staIds.size() == 1)
5514 {
5515 const auto aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5516 if (staIds.front() == aidSta1)
5517 {
5518 receiver = Mac48Address::ConvertFrom(m_sta1Dev->GetAddress());
5519 }
5520 else
5521 {
5522 NS_ASSERT(staIds.front() ==
5523 DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5524 receiver = Mac48Address::ConvertFrom(m_sta2Dev->GetAddress());
5525 }
5526 }
5527
5528 WifiMacHeader hdr;
5530 hdr.SetAddr1(receiver);
5531 hdr.SetAddr2(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5532 hdr.SetAddr3(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5533 hdr.SetDsNotTo();
5534 hdr.SetDsFrom();
5535 hdr.SetNoRetry();
5536 hdr.SetNoMoreFragments();
5537 auto psdu = Create<WifiPsdu>(bar, hdr);
5538
5539 auto nav = m_apDev->GetPhy()->GetSifs();
5540 const auto staId = staIds.front(); // either will do
5541 nav += m_phyAp->CalculateTxDuration(GetBlockAckSize(BlockAckType::COMPRESSED),
5542 tbTxVector,
5544 staId);
5545 psdu->SetDuration(nav);
5546 psdus.insert(std::make_pair(SU_STA_ID, psdu));
5547
5548 m_phyAp->Send(psdus, txVector);
5549}
5550
5551void
5553 RxSignalInfo rxSignalInfo,
5554 WifiTxVector txVector,
5555 std::vector<bool> /*statusPerMpdu*/)
5556{
5557 NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5558 const auto rssi = rxSignalInfo.rssi;
5559 NS_ASSERT(psdu->GetNMpdus() == 1);
5560 const auto& hdr = psdu->GetHeader(0);
5561 NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5562 if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5563 {
5565 rssi,
5566 m_rssiSta1,
5567 m_tol,
5568 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5569 << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5570 }
5571 else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5572 {
5574 rssi,
5575 m_rssiSta2,
5576 m_tol,
5577 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5578 << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5579 }
5580 else
5581 {
5582 NS_ABORT_MSG("The receiver address is unknown");
5583 }
5584}
5585
5586void
5588{
5589 // Now that BA session has been established we can plug our method
5590 m_phyAp->SetReceiveOkCallback(
5592}
5593
5594void
5596{
5597 auto apNode = CreateObject<Node>();
5598 NodeContainer staNodes;
5599 staNodes.Create(2);
5600
5601 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5603 spectrumChannel->AddPropagationLossModel(lossModel);
5605 spectrumChannel->SetPropagationDelayModel(delayModel);
5606
5607 SpectrumWifiPhyHelper spectrumPhy;
5608 spectrumPhy.SetChannel(spectrumChannel);
5609 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5610 spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5611
5612 WifiHelper wifi;
5613 wifi.SetStandard(WIFI_STANDARD_80211ax);
5614 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5615 "DataMode",
5616 StringValue("HeMcs7"),
5617 "ControlMode",
5618 StringValue("HeMcs7"));
5619
5620 WifiMacHelper mac;
5621 mac.SetType("ns3::StaWifiMac");
5622 auto staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5623 WifiHelper::AssignStreams(staDevs, 0);
5624 m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5626 m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5628
5629 // Set the beacon interval long enough so that associated STAs may not consider link lost when
5630 // beacon generation is disabled during the actual tests. Having such a long interval also
5631 // avoids bloating logs with beacons during the set up phase.
5632 mac.SetType("ns3::ApWifiMac",
5633 "BeaconGeneration",
5634 BooleanValue(true),
5635 "BeaconInterval",
5636 TimeValue(MicroSeconds(1024 * 600)));
5637 m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5639 m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5642 // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5643 // set up for both STAs
5644
5645 MobilityHelper mobility;
5646 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5647 auto positionAlloc = CreateObject<ListPositionAllocator>();
5648 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5649 positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5650 positionAlloc->Add(
5651 Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5652 mobility.SetPositionAllocator(positionAlloc);
5653
5654 mobility.Install(apNode);
5655 mobility.Install(staNodes);
5656
5657 lossModel->SetDefaultLoss(50.0);
5658 lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5659 staNodes.Get(1)->GetObject<MobilityModel>(),
5660 56.0,
5661 true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5662}
5663
5664void
5666{
5667 m_phyAp->Dispose();
5668 m_phyAp = nullptr;
5669 m_apDev->Dispose();
5670 m_apDev = nullptr;
5671 m_sta1Dev->Dispose();
5672 m_sta1Dev = nullptr;
5673 m_sta2Dev->Dispose();
5674 m_sta2Dev = nullptr;
5675}
5676
5677void
5679{
5682 int64_t streamNumber = 0;
5683
5684 auto phySta1 = m_sta1Dev->GetPhy();
5685 auto phySta2 = m_sta2Dev->GetPhy();
5686
5687 m_phyAp->AssignStreams(streamNumber);
5688 phySta1->AssignStreams(streamNumber);
5689 phySta2->AssignStreams(streamNumber);
5690
5691 m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5692 m_phyAp->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerAp));
5693 m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5694
5695 phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5696 phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5697 phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5698
5699 phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5700 phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5701 phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5702
5703 Time relativeStart{};
5704 if (setupBa)
5705 {
5706 // Set up BA for each station once the association phase has ended
5707 // so that a BA session is established when the MU-BAR is received.
5710 this,
5711 m_sta1Dev->GetAddress());
5714 this,
5715 m_sta2Dev->GetAddress());
5716 relativeStart = MilliSeconds(1000);
5717 }
5718 else
5719 {
5720 auto apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5721 NS_ASSERT(apMac);
5722 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5723 }
5724
5725 Simulator::Schedule(relativeStart,
5727 this);
5728
5729 {
5730 // Verify that the RSSI from STA 1 is consistent with what was requested
5731 std::vector<uint16_t> staIds{1};
5732 Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5733 }
5734
5735 {
5736 // Verify that the RSSI from STA 2 is consistent with what was requested
5737 std::vector<uint16_t> staIds{2};
5738 Simulator::Schedule(relativeStart + MilliSeconds(20),
5740 this,
5741 staIds);
5742 }
5743
5744 {
5745 // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5746 std::vector<uint16_t> staIds{1, 2};
5747 Simulator::Schedule(relativeStart + MilliSeconds(40),
5749 this,
5750 staIds);
5751 }
5752
5753 Simulator::Stop(relativeStart + MilliSeconds(100));
5755}
5756
5757void
5759{
5760 // Power configurations
5761 m_txPowerAp = 20; // dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
5762 // since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5763 m_txPowerStart = 15; // dBm
5764
5765 // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5766 m_requestedRssiSta1 = -30.0;
5767 m_requestedRssiSta2 = -36.0;
5768
5769 // Test single power level
5770 {
5771 // STA power configurations: 15 dBm only
5772 m_txPowerEnd = 15;
5773 m_txPowerLevels = 1;
5774
5775 // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5776 // regardless of the estimated path loss.
5777 m_rssiSta1 = -35.0; // 15 dBm - 50 dB
5778 m_rssiSta2 = -41.0; // 15 dBm - 56 dB
5779
5780 RunOne(true);
5781 }
5782
5783 // Test 2 dBm granularity
5784 {
5785 // STA power configurations: [15:2:25] dBm
5786 m_txPowerEnd = 25;
5787 m_txPowerLevels = 6;
5788
5789 // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5790 // requested
5791 m_rssiSta1 = -29.0; // 21 dBm - 50 dB
5792 m_rssiSta2 = -35.0; // 21 dBm - 50 dB
5793
5794 RunOne(false);
5795 }
5796
5797 // Test 1 dBm granularity
5798 {
5799 // STA power configurations: [15:1:25] dBm
5800 m_txPowerEnd = 25;
5801 m_txPowerLevels = 11;
5802
5803 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5804 m_rssiSta1 = -30.0; // 20 dBm - 50 dB
5805 m_rssiSta2 = -36.0; // 20 dBm - 56 dB
5806
5807 RunOne(false);
5808 }
5809
5810 // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5811 {
5812 // STA power configurations: [15:1:25] dBm
5813 m_txPowerEnd = 25;
5814 m_txPowerLevels = 11;
5815
5816 // Requested UL RSSIs
5817 m_requestedRssiSta1 = -28.0; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5818 m_requestedRssiSta2 = -37.0; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5819
5820 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5821 m_rssiSta1 = -28.0; // 22 dBm - 50 dB
5822 m_rssiSta2 = -37.0; // 19 dBm - 56 dB
5823
5824 RunOne(false);
5825 }
5826
5828}
5829
5830/**
5831 * \ingroup wifi-test
5832 * \ingroup tests
5833 *
5834 * \brief wifi PHY OFDMA Test Suite
5835 */
5837{
5838 public:
5840};
5841
5843 : TestSuite("wifi-phy-ofdma", Type::UNIT)
5844{
5845 AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5846 AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::Duration::QUICK);
5847 AddTestCase(new TestUlOfdmaPpduUid, TestCase::Duration::QUICK);
5848 AddTestCase(new TestMultipleHeTbPreambles, TestCase::Duration::QUICK);
5849 AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5850 AddTestCase(new TestPhyPaddingExclusion, TestCase::Duration::QUICK);
5851 AddTestCase(new TestUlOfdmaPowerControl, TestCase::Duration::QUICK);
5852}
5853
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:1939
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
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 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 RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, const std::vector< bool > statusPerMpdu)
Receive success function for STA 1.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
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.
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 RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
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 RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function 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.
void RxSuccessSta3(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for 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 SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success 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 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 RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
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 ReceiveOkCallbackAtAp(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive OK callback function at AP.
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 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:964
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:48
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:672
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:1792
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition wifi-phy.cc:681
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:1337
std::tuple< uint8_t, MHz_u, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying a segment of an operating channel.
Definition wifi-phy.h:919
static Time GetPreambleDetectionDuration()
Definition wifi-phy.cc:1513
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition wifi-phy.cc:478
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition wifi-phy.cc:1003
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1572
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition wifi-phy.h:1360
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition wifi-phy.cc:484
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition wifi-phy.cc:1063
Ptr< Event > m_currentEvent
Hold the current event.
Definition wifi-phy.h:1335
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:754
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition wifi-phy.h:1340
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:1129
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition wifi-phy.cc:702
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition wifi-phy.cc:647
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition wifi-phy.h:1322
void SetReceiveOkCallback(RxOkCallback callback)
Definition wifi-phy.cc:472
void Reset()
Reset data upon end of TX or RX.
Definition wifi-phy.cc:1939
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition wifi-phy.cc:1075
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition wifi-phy.cc:769
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:2330
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=-20, dBr_u minOuterband=-28, dBr_u lowestPoint=-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:1332
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
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.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
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
@ 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:31
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
Definition wifi-utils.cc:58
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
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