A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-phy-ofdma-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 University of Washington
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "ns3/ap-wifi-mac.h"
10#include "ns3/boolean.h"
11#include "ns3/constant-position-mobility-model.h"
12#include "ns3/ctrl-headers.h"
13#include "ns3/double.h"
14#include "ns3/he-configuration.h"
15#include "ns3/he-phy.h"
16#include "ns3/he-ppdu.h"
17#include "ns3/interference-helper.h"
18#include "ns3/log.h"
19#include "ns3/mobility-helper.h"
20#include "ns3/multi-model-spectrum-channel.h"
21#include "ns3/nist-error-rate-model.h"
22#include "ns3/node.h"
23#include "ns3/non-communicating-net-device.h"
24#include "ns3/pointer.h"
25#include "ns3/rng-seed-manager.h"
26#include "ns3/simulator.h"
27#include "ns3/spectrum-wifi-helper.h"
28#include "ns3/spectrum-wifi-phy.h"
29#include "ns3/sta-wifi-mac.h"
30#include "ns3/string.h"
31#include "ns3/test.h"
32#include "ns3/threshold-preamble-detection-model.h"
33#include "ns3/txop.h"
34#include "ns3/waveform-generator.h"
35#include "ns3/wifi-mac-header.h"
36#include "ns3/wifi-net-device.h"
37#include "ns3/wifi-phy-listener.h"
38#include "ns3/wifi-psdu.h"
39#include "ns3/wifi-spectrum-phy-interface.h"
40#include "ns3/wifi-spectrum-signal-parameters.h"
41#include "ns3/wifi-spectrum-value-helper.h"
42#include "ns3/wifi-utils.h"
43
44#include <algorithm>
45#include <iterator>
46#include <memory>
47
48using namespace ns3;
49
50NS_LOG_COMPONENT_DEFINE("WifiPhyOfdmaTest");
51
52static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
53static const MHz_u DEFAULT_FREQUENCY{5180};
57 DEFAULT_CHANNEL_WIDTH; // expanded to channel width to model spectrum mask
58
59/**
60 * HE PHY slightly modified so as to return a given
61 * STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
62 */
63class OfdmaTestHePhy : public HePhy
64{
65 public:
66 /**
67 * Constructor
68 *
69 * @param staId the ID of the STA to which this PHY belongs to
70 */
71 OfdmaTestHePhy(uint16_t staId);
72 ~OfdmaTestHePhy() override;
73
74 /**
75 * Return the STA ID that has been assigned to the station this PHY belongs to.
76 * This is typically called for MU PPDUs, in order to pick the correct PSDU.
77 *
78 * @param ppdu the PPDU for which the STA ID is requested
79 * @return the STA ID
80 */
81 uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
82
83 /**
84 * Set the global PPDU UID counter.
85 *
86 * @param uid the value to which the global PPDU UID counter should be set
87 */
88 void SetGlobalPpduUid(uint64_t uid);
89
90 private:
91 uint16_t m_staId; ///< ID of the STA to which this PHY belongs to
92
93 // end of class OfdmaTestHePhy
94};
95
97 : HePhy(),
98 m_staId(staId)
99{
100}
101
105
106uint16_t
108{
109 if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
110 {
111 return m_staId;
112 }
113 return HePhy::GetStaId(ppdu);
114}
115
116void
118{
119 m_globalPpduUid = uid;
120}
121
122/**
123 * SpectrumWifiPhy used for testing OFDMA.
124 */
126{
127 public:
128 /**
129 * @brief Get the type ID.
130 * @return the object TypeId
131 */
132 static TypeId GetTypeId();
133 /**
134 * Constructor
135 *
136 * @param staId the ID of the STA to which this PHY belongs to
137 */
138 OfdmaSpectrumWifiPhy(uint16_t staId);
139 ~OfdmaSpectrumWifiPhy() override;
140
141 void DoInitialize() override;
142 void DoDispose() override;
143
144 using WifiPhy::Reset;
145 void StartTx(Ptr<const WifiPpdu> ppdu) override;
146
147 /**
148 * TracedCallback signature for UID of transmitted PPDU.
149 *
150 * @param uid the UID of the transmitted PPDU
151 */
152 typedef void (*TxPpduUidCallback)(uint64_t uid);
153
154 /**
155 * Set the global PPDU UID counter.
156 *
157 * @param uid the value to which the global PPDU UID counter should be set
158 */
159 void SetPpduUid(uint64_t uid);
160
161 /**
162 * Since we assume trigger frame was previously received from AP, this is used to set its UID
163 *
164 * @param uid the PPDU UID of the trigger frame
165 */
166 void SetTriggerFrameUid(uint64_t uid);
167
168 /**
169 * @return the current preamble events map
170 */
171 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
172 /**
173 * @return the current event
174 */
176
177 /**
178 * Wrapper to InterferenceHelper method.
179 *
180 * @param energy the minimum energy requested
181 * @param band identify the requested band
182 *
183 * @returns the expected amount of time the observed
184 * energy on the medium for a given band will
185 * be higher than the requested threshold.
186 */
188
189 /**
190 * @return a const pointer to the HE PHY instance
191 */
193
194 private:
195 /// Pointer to HE PHY instance used for OFDMA test
197
198 /// Callback providing UID of the PPDU that is about to be transmitted
200
201 // end of class OfdmaSpectrumWifiPhy
202};
203
204TypeId
206{
207 static TypeId tid =
208 TypeId("ns3::OfdmaSpectrumWifiPhy")
210 .SetGroupName("Wifi")
211 .AddTraceSource("TxPpduUid",
212 "UID of the PPDU to be transmitted",
214 "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
215 return tid;
216}
217
224
228
229void
231{
232 // Replace HE PHY instance with test instance
235}
236
237void
243
244void
250
251void
256
257void
263
264std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
269
275
276Time
278{
279 return m_interference->GetEnergyDuration(energy, band);
280}
281
287
288/**
289 * @ingroup wifi-test
290 * @ingroup tests
291 *
292 * @brief DL-OFDMA PHY test
293 */
295{
296 public:
299
300 private:
301 void DoSetup() override;
302 void DoTeardown() override;
303 void DoRun() override;
304
305 /**
306 * Receive success function for STA 1
307 * @param psdu the PSDU
308 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
309 * @param txVector the transmit vector
310 * @param statusPerMpdu reception status per MPDU
311 */
313 RxSignalInfo rxSignalInfo,
314 const WifiTxVector& txVector,
315 const std::vector<bool>& statusPerMpdu);
316 /**
317 * Receive success function for STA 2
318 * @param psdu the PSDU
319 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
320 * @param txVector the transmit vector
321 * @param statusPerMpdu reception status per MPDU
322 */
324 RxSignalInfo rxSignalInfo,
325 const WifiTxVector& txVector,
326 const std::vector<bool>& statusPerMpdu);
327 /**
328 * Receive success function for STA 3
329 * @param psdu the PSDU
330 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
331 * @param txVector the transmit vector
332 * @param statusPerMpdu reception status per MPDU
333 */
335 RxSignalInfo rxSignalInfo,
336 const WifiTxVector& txVector,
337 const std::vector<bool>& statusPerMpdu);
338
339 /**
340 * Receive failure function for STA 1
341 * @param psdu the PSDU
342 */
344 /**
345 * Receive failure function for STA 2
346 * @param psdu the PSDU
347 */
349 /**
350 * Receive failure function for STA 3
351 * @param psdu the PSDU
352 */
354
355 /**
356 * Check the results for STA 1
357 * @param expectedRxSuccess the expected number of RX success
358 * @param expectedRxFailure the expected number of RX failures
359 * @param expectedRxBytes the expected number of RX bytes
360 */
361 void CheckResultsSta1(uint32_t expectedRxSuccess,
362 uint32_t expectedRxFailure,
363 uint32_t expectedRxBytes);
364 /**
365 * Check the results for STA 2
366 * @param expectedRxSuccess the expected number of RX success
367 * @param expectedRxFailure the expected number of RX failures
368 * @param expectedRxBytes the expected number of RX bytes
369 */
370 void CheckResultsSta2(uint32_t expectedRxSuccess,
371 uint32_t expectedRxFailure,
372 uint32_t expectedRxBytes);
373 /**
374 * Check the results for STA 3
375 * @param expectedRxSuccess the expected number of RX success
376 * @param expectedRxFailure the expected number of RX failures
377 * @param expectedRxBytes the expected number of RX bytes
378 */
379 void CheckResultsSta3(uint32_t expectedRxSuccess,
380 uint32_t expectedRxFailure,
381 uint32_t expectedRxBytes);
382
383 /**
384 * Reset the results
385 */
386 void ResetResults();
387
388 /**
389 * Send MU-PPDU function
390 * @param rxStaId1 the ID of the recipient STA for the first PSDU
391 * @param rxStaId2 the ID of the recipient STA for the second PSDU
392 */
393 void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
394
395 /**
396 * Generate interference function
397 * @param interferencePsd the PSD of the interference to be generated
398 * @param duration the duration of the interference
399 */
400 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
401 /**
402 * Stop interference function
403 */
404 void StopInterference();
405
406 /**
407 * Run one function
408 */
409 void RunOne();
410
411 /**
412 * Schedule now to check the PHY state
413 * @param phy the PHY
414 * @param expectedState the expected state of the PHY
415 */
417 /**
418 * Check the PHY state now
419 * @param phy the PHY
420 * @param expectedState the expected state of the PHY
421 */
423
424 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
425 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
426 uint32_t m_countRxSuccessSta3; ///< count RX success for STA 3
427 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
428 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
429 uint32_t m_countRxFailureSta3; ///< count RX failure for STA 3
430 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
431 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
432 uint32_t m_countRxBytesSta3; ///< count RX bytes for STA 3
433
439
440 MHz_u m_frequency; ///< frequency
441 MHz_u m_channelWidth; ///< channel width
442 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
443};
444
446 : TestCase("DL-OFDMA PHY test"),
447 m_countRxSuccessSta1(0),
448 m_countRxSuccessSta2(0),
449 m_countRxSuccessSta3(0),
450 m_countRxFailureSta1(0),
451 m_countRxFailureSta2(0),
452 m_countRxFailureSta3(0),
453 m_countRxBytesSta1(0),
454 m_countRxBytesSta2(0),
455 m_countRxBytesSta3(0),
456 m_frequency(DEFAULT_FREQUENCY),
457 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
458 m_expectedPpduDuration(NanoSeconds(306400))
459{
460}
461
462void
475
476void
477TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
478{
479 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
480 WifiConstPsduMap psdus;
482 0,
484 NanoSeconds(800),
485 1,
486 1,
487 0,
489 false,
490 false};
492 if (m_channelWidth == MHz_u{20})
493 {
494 ruType = HeRu::RU_106_TONE;
495 txVector.SetRuAllocation({96}, 0);
496 }
497 else if (m_channelWidth == MHz_u{40})
498 {
499 ruType = HeRu::RU_242_TONE;
500 txVector.SetRuAllocation({192, 192}, 0);
501 }
502 else if (m_channelWidth == MHz_u{80})
503 {
504 ruType = HeRu::RU_484_TONE;
505 txVector.SetRuAllocation({200, 200, 200, 200}, 0);
506 }
507 else if (m_channelWidth == MHz_u{160})
508 {
509 ruType = HeRu::RU_996_TONE;
510 txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208}, 0);
511 }
512 else
513 {
514 NS_ASSERT_MSG(false, "Unsupported channel width");
515 }
516
517 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
518
519 HeRu::RuSpec ru1(ruType, 1, true);
520 txVector.SetRu(ru1, rxStaId1);
521 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
522 txVector.SetNss(1, rxStaId1);
523
524 HeRu::RuSpec ru2(ruType, (m_channelWidth == MHz_u{160} ? 1 : 2), m_channelWidth != MHz_u{160});
525 txVector.SetRu(ru2, rxStaId2);
526 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
527 txVector.SetNss(1, rxStaId2);
528
529 Ptr<Packet> pkt1 = Create<Packet>(1000);
530 WifiMacHeader hdr1;
532 hdr1.SetQosTid(0);
533 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
534 hdr1.SetSequenceNumber(1);
535 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
536 psdus.insert(std::make_pair(rxStaId1, psdu1));
537
538 Ptr<Packet> pkt2 = Create<Packet>(1500);
539 WifiMacHeader hdr2;
541 hdr2.SetQosTid(0);
542 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
543 hdr2.SetSequenceNumber(2);
544 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
545 psdus.insert(std::make_pair(rxStaId2, psdu2));
546
547 m_phyAp->Send(psdus, txVector);
548}
549
550void
552{
553 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
554 m_phyInterferer->SetPeriod(duration);
555 m_phyInterferer->Start();
557}
558
559void
564
568
569void
571 RxSignalInfo rxSignalInfo,
572 const WifiTxVector& txVector,
573 const std::vector<bool>& /*statusPerMpdu*/)
574{
575 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
577 m_countRxBytesSta1 += (psdu->GetSize() - 30);
578}
579
580void
582 RxSignalInfo rxSignalInfo,
583 const WifiTxVector& txVector,
584 const std::vector<bool>& /*statusPerMpdu*/)
585{
586 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
588 m_countRxBytesSta2 += (psdu->GetSize() - 30);
589}
590
591void
593 RxSignalInfo rxSignalInfo,
594 const WifiTxVector& txVector,
595 const std::vector<bool>& /*statusPerMpdu*/)
596{
597 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
599 m_countRxBytesSta3 += (psdu->GetSize() - 30);
600}
601
602void
608
609void
615
616void
622
623void
625 uint32_t expectedRxFailure,
626 uint32_t expectedRxBytes)
627{
629 expectedRxSuccess,
630 "The number of successfully received packets by STA 1 is not correct!");
632 expectedRxFailure,
633 "The number of unsuccessfuly received packets by STA 1 is not correct!");
635 expectedRxBytes,
636 "The number of bytes received by STA 1 is not correct!");
637}
638
639void
641 uint32_t expectedRxFailure,
642 uint32_t expectedRxBytes)
643{
645 expectedRxSuccess,
646 "The number of successfully received packets by STA 2 is not correct!");
648 expectedRxFailure,
649 "The number of unsuccessfuly received packets by STA 2 is not correct!");
651 expectedRxBytes,
652 "The number of bytes received by STA 2 is not correct!");
653}
654
655void
657 uint32_t expectedRxFailure,
658 uint32_t expectedRxBytes)
659{
661 expectedRxSuccess,
662 "The number of successfully received packets by STA 3 is not correct!");
664 expectedRxFailure,
665 "The number of unsuccessfuly received packets by STA 3 is not correct!");
667 expectedRxBytes,
668 "The number of bytes received by STA 3 is not correct!");
669}
670
671void
673{
674 // This is needed to make sure PHY state will be checked as the last event if a state change
675 // occurred at the exact same time as the check
677}
678
679void
681 WifiPhyState expectedState)
682{
683 WifiPhyState currentState;
684 PointerValue ptr;
685 phy->GetAttribute("State", ptr);
687 currentState = state->GetState();
688 NS_LOG_FUNCTION(this << currentState);
689 NS_TEST_ASSERT_MSG_EQ(currentState,
690 expectedState,
691 "PHY State " << currentState << " does not match expected state "
692 << expectedState << " at " << Simulator::Now());
693}
694
695void
697{
700 lossModel->SetFrequency(MHzToHz(m_frequency));
701 spectrumChannel->AddPropagationLossModel(lossModel);
704 spectrumChannel->SetPropagationDelayModel(delayModel);
705
706 Ptr<Node> apNode = CreateObject<Node>();
710 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
712 m_phyAp->SetErrorRateModel(apErrorModel);
713 m_phyAp->SetDevice(apDev);
714 m_phyAp->AddChannel(spectrumChannel);
715 m_phyAp->ConfigureStandard(WIFI_STANDARD_80211ax);
717 m_phyAp->SetMobility(apMobility);
718 apDev->SetPhy(m_phyAp);
719 apNode->AggregateObject(apMobility);
720 apNode->AddDevice(apDev);
721
722 Ptr<Node> sta1Node = CreateObject<Node>();
726 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
728 m_phySta1->SetErrorRateModel(sta1ErrorModel);
729 m_phySta1->SetDevice(sta1Dev);
730 m_phySta1->AddChannel(spectrumChannel);
736 m_phySta1->SetMobility(sta1Mobility);
737 sta1Dev->SetPhy(m_phySta1);
738 sta1Node->AggregateObject(sta1Mobility);
739 sta1Node->AddDevice(sta1Dev);
740
741 Ptr<Node> sta2Node = CreateObject<Node>();
745 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
747 m_phySta2->SetErrorRateModel(sta2ErrorModel);
748 m_phySta2->SetDevice(sta2Dev);
749 m_phySta2->AddChannel(spectrumChannel);
755 m_phySta2->SetMobility(sta2Mobility);
756 sta2Dev->SetPhy(m_phySta2);
757 sta2Node->AggregateObject(sta2Mobility);
758 sta2Node->AddDevice(sta2Dev);
759
760 Ptr<Node> sta3Node = CreateObject<Node>();
764 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
766 m_phySta3->SetErrorRateModel(sta3ErrorModel);
767 m_phySta3->SetDevice(sta3Dev);
768 m_phySta3->AddChannel(spectrumChannel);
774 m_phySta3->SetMobility(sta3Mobility);
775 sta3Dev->SetPhy(m_phySta3);
776 sta3Node->AggregateObject(sta3Mobility);
777 sta3Node->AddDevice(sta3Dev);
778
779 Ptr<Node> interfererNode = CreateObject<Node>();
782 m_phyInterferer->SetDevice(interfererDev);
783 m_phyInterferer->SetChannel(spectrumChannel);
784 m_phyInterferer->SetDutyCycle(1);
785 interfererNode->AddDevice(interfererDev);
786}
787
788void
790{
791 m_phyAp->Dispose();
792 m_phyAp = nullptr;
794 m_phySta1 = nullptr;
796 m_phySta2 = nullptr;
798 m_phySta3 = nullptr;
800 m_phyInterferer = nullptr;
801}
802
803void
805{
808 int64_t streamNumber = 0;
809 m_phyAp->AssignStreams(streamNumber);
810 m_phySta1->AssignStreams(streamNumber);
811 m_phySta2->AssignStreams(streamNumber);
812 m_phySta3->AssignStreams(streamNumber);
813
814 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
819 ->number;
820
821 m_phyAp->SetOperatingChannel(
829
831
832 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
833 // Each STA should receive its PSDU.
835
836 // Since it takes m_expectedPpduDuration to transmit the PPDU,
837 // all 3 PHYs should be back to IDLE at the same time,
838 // even the PHY that has no PSDU addressed to it.
841 this,
842 m_phySta1,
843 WifiPhyState::RX);
846 this,
847 m_phySta2,
848 WifiPhyState::RX);
851 this,
852 m_phySta3,
853 WifiPhyState::CCA_BUSY);
856 this,
857 m_phySta1,
858 WifiPhyState::IDLE);
861 this,
862 m_phySta2,
863 WifiPhyState::IDLE);
866 this,
867 m_phySta3,
868 WifiPhyState::IDLE);
869
870 // One PSDU of 1000 bytes should have been successfully received by STA 1
873 this,
874 1,
875 0,
876 1000);
877 // One PSDU of 1500 bytes should have been successfully received by STA 2
880 this,
881 1,
882 0,
883 1500);
884 // No PSDU should have been received by STA 3
886
888
889 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
890 // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
891 // but should keep its PHY busy during all PPDU duration.
893
894 // Since it takes m_expectedPpduDuration to transmit the PPDU,
895 // all 3 PHYs should be back to IDLE at the same time,
896 // even the PHY that has no PSDU addressed to it.
899 this,
900 m_phySta1,
901 WifiPhyState::RX);
904 this,
905 m_phySta2,
906 WifiPhyState::CCA_BUSY);
909 this,
910 m_phySta3,
911 WifiPhyState::RX);
914 this,
915 m_phySta1,
916 WifiPhyState::IDLE);
919 this,
920 m_phySta2,
921 WifiPhyState::IDLE);
924 this,
925 m_phySta3,
926 WifiPhyState::IDLE);
927
928 // One PSDU of 1000 bytes should have been successfully received by STA 1
931 this,
932 1,
933 0,
934 1000);
935 // No PSDU should have been received by STA 2
937 // One PSDU of 1500 bytes should have been successfully received by STA 3
940 this,
941 1,
942 0,
943 1500);
944
946
947 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
949
950 // A strong non-wifi interference is generated on RU 1 during PSDU reception
951 BandInfo bandInfo;
952 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 4));
953 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
954 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
955 Bands bands;
956 bands.push_back(bandInfo);
957
958 auto SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
959 auto interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
960 Watt_u interferencePower{0.1};
961 *interferencePsdRu1 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
962
965 this,
966 interferencePsdRu1,
967 MilliSeconds(100));
968
969 // Since it takes m_expectedPpduDuration to transmit the PPDU,
970 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
971 // even the PHY that has no PSDU addressed to it.
974 this,
975 m_phySta1,
976 WifiPhyState::RX);
979 this,
980 m_phySta2,
981 WifiPhyState::RX);
984 this,
985 m_phySta3,
986 WifiPhyState::CCA_BUSY);
989 this,
990 m_phySta1,
991 WifiPhyState::CCA_BUSY);
994 this,
995 m_phySta2,
996 WifiPhyState::CCA_BUSY);
999 this,
1000 m_phySta3,
1001 WifiPhyState::CCA_BUSY);
1002
1003 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1004 // occupies RU 1)
1006 // One PSDU of 1500 bytes should have been successfully received by STA 2
1009 this,
1010 1,
1011 0,
1012 1500);
1013 // No PSDU should have been received by STA3
1015
1017
1018 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1020
1021 // A strong non-wifi interference is generated on RU 2 during PSDU reception
1022 bandInfo.fc = MHzToHz(m_frequency + (m_channelWidth / 4));
1023 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
1024 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
1025 bands.clear();
1026 bands.push_back(bandInfo);
1027
1028 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1029 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1030 *interferencePsdRu2 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
1031
1034 this,
1035 interferencePsdRu2,
1036 MilliSeconds(100));
1037
1038 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1039 // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1040 // same time, even the PHY that has no PSDU addressed to it.
1043 this,
1044 m_phySta1,
1045 WifiPhyState::RX);
1048 this,
1049 m_phySta2,
1050 WifiPhyState::RX);
1053 this,
1054 m_phySta3,
1055 WifiPhyState::CCA_BUSY);
1058 this,
1059 m_phySta1,
1060 (m_channelWidth >= MHz_u{40}) ? WifiPhyState::IDLE
1061 : WifiPhyState::CCA_BUSY);
1064 this,
1065 m_phySta2,
1066 (m_channelWidth >= MHz_u{40}) ? WifiPhyState::IDLE
1067 : WifiPhyState::CCA_BUSY);
1070 this,
1071 m_phySta3,
1072 (m_channelWidth >= MHz_u{40}) ? WifiPhyState::IDLE
1073 : WifiPhyState::CCA_BUSY);
1074
1075 // One PSDU of 1000 bytes should have been successfully received by STA 1
1078 this,
1079 1,
1080 0,
1081 1000);
1082 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1083 // occupies RU 2)
1085 // No PSDU should have been received by STA3
1087
1089
1090 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1092
1093 // A strong non-wifi interference is generated on the full band during PSDU reception
1094 bandInfo.fc = MHzToHz(m_frequency);
1095 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 2);
1096 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 2);
1097 bands.clear();
1098 bands.push_back(bandInfo);
1099
1100 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1101 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1102 *interferencePsdAll = interferencePower / (MHzToHz(m_channelWidth) * 20);
1103
1106 this,
1107 interferencePsdAll,
1108 MilliSeconds(100));
1109
1110 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1111 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1112 // even the PHY that has no PSDU addressed to it.
1115 this,
1116 m_phySta1,
1117 WifiPhyState::RX);
1120 this,
1121 m_phySta2,
1122 WifiPhyState::RX);
1125 this,
1126 m_phySta3,
1127 WifiPhyState::CCA_BUSY);
1130 this,
1131 m_phySta1,
1132 WifiPhyState::CCA_BUSY);
1135 this,
1136 m_phySta2,
1137 WifiPhyState::CCA_BUSY);
1140 this,
1141 m_phySta3,
1142 WifiPhyState::CCA_BUSY);
1143
1144 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1145 // occupies RU 1)
1147 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1148 // occupies RU 2)
1150 // No PSDU should have been received by STA3
1152
1154
1156}
1157
1158void
1160{
1161 m_frequency = MHz_u{5180};
1162 m_channelWidth = MHz_u{20};
1164 RunOne();
1165
1166 m_frequency = MHz_u{5190};
1167 m_channelWidth = MHz_u{40};
1169 RunOne();
1170
1171 m_frequency = MHz_u{5210};
1172 m_channelWidth = MHz_u{80};
1174 RunOne();
1175
1176 m_frequency = MHz_u{5250};
1177 m_channelWidth = MHz_u{160};
1179 RunOne();
1180
1182}
1183
1184/**
1185 * @ingroup wifi-test
1186 * @ingroup tests
1187 *
1188 * @brief DL-OFDMA PHY puncturing test
1189 */
1191{
1192 public:
1194
1195 private:
1196 void DoSetup() override;
1197 void DoTeardown() override;
1198 void DoRun() override;
1199
1200 /**
1201 * Receive success function for STA 1
1202 * @param psdu the PSDU
1203 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1204 * @param txVector the transmit vector
1205 * @param statusPerMpdu reception status per MPDU
1206 */
1208 RxSignalInfo rxSignalInfo,
1209 const WifiTxVector& txVector,
1210 const std::vector<bool>& statusPerMpdu);
1211
1212 /**
1213 * Receive success function for STA 2
1214 * @param psdu the PSDU
1215 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1216 * @param txVector the transmit vector
1217 * @param statusPerMpdu reception status per MPDU
1218 */
1220 RxSignalInfo rxSignalInfo,
1221 const WifiTxVector& txVector,
1222 const std::vector<bool>& statusPerMpdu);
1223
1224 /**
1225 * Receive failure function for STA 1
1226 * @param psdu the PSDU
1227 */
1229
1230 /**
1231 * Receive failure function for STA 2
1232 * @param psdu the PSDU
1233 */
1235
1236 /**
1237 * Check the results for STA 1
1238 * @param expectedRxSuccess the expected number of RX success
1239 * @param expectedRxFailure the expected number of RX failures
1240 * @param expectedRxBytes the expected number of RX bytes
1241 */
1242 void CheckResultsSta1(uint32_t expectedRxSuccess,
1243 uint32_t expectedRxFailure,
1244 uint32_t expectedRxBytes);
1245
1246 /**
1247 * Check the results for STA 2
1248 * @param expectedRxSuccess the expected number of RX success
1249 * @param expectedRxFailure the expected number of RX failures
1250 * @param expectedRxBytes the expected number of RX bytes
1251 */
1252 void CheckResultsSta2(uint32_t expectedRxSuccess,
1253 uint32_t expectedRxFailure,
1254 uint32_t expectedRxBytes);
1255
1256 /**
1257 * Reset the results
1258 */
1259 void ResetResults();
1260
1261 /**
1262 * Send MU-PPDU function
1263 * @param rxStaId1 the ID of the recipient STA for the first PSDU
1264 * @param rxStaId2 the ID of the recipient STA for the second PSDU
1265 * @param puncturedSubchannels indicates for each subchannel whether it is punctured or not. if
1266 * empty, preamble puncturing is not used.
1267 */
1268 void SendMuPpdu(uint16_t rxStaId1,
1269 uint16_t rxStaId2,
1270 const std::vector<bool>& puncturedSubchannels);
1271
1272 /**
1273 * Generate interference function
1274 * @param interferencePsd the PSD of the interference to be generated
1275 * @param duration the duration of the interference
1276 */
1277 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1278
1279 /**
1280 * Stop interference function
1281 */
1282 void StopInterference();
1283
1284 /**
1285 * Run one function
1286 */
1287 void RunOne();
1288
1289 /**
1290 * Schedule now to check the PHY state
1291 * @param phy the PHY
1292 * @param expectedState the expected state of the PHY
1293 */
1294 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
1295
1296 /**
1297 * Check the PHY state now
1298 * @param phy the PHY
1299 * @param expectedState the expected state of the PHY
1300 */
1302
1303 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
1304 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
1305 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
1306 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
1307 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
1308 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
1309
1314
1315 MHz_u m_frequency; ///< frequency
1316 MHz_u m_channelWidth; ///< channel width
1317
1318 uint8_t m_indexSubchannel; ///< Index of the subchannel (starting from 0) that should contain an
1319 ///< interference and be punctured during the test run
1320
1321 Time m_expectedPpduDuration20Mhz; ///< expected duration to send MU PPDU on 20 MHz RU
1322 Time m_expectedPpduDuration40Mhz; ///< expected duration to send MU PPDU on 40 MHz RU
1323};
1324
1326 : TestCase("DL-OFDMA PHY puncturing test"),
1327 m_countRxSuccessSta1(0),
1328 m_countRxSuccessSta2(0),
1329 m_countRxFailureSta1(0),
1330 m_countRxFailureSta2(0),
1331 m_countRxBytesSta1(0),
1332 m_countRxBytesSta2(0),
1333 m_frequency(MHz_u{5210}),
1334 m_channelWidth(MHz_u{80}),
1335 m_indexSubchannel(0),
1336 m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1337 m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1338{
1339}
1340
1341void
1351
1352void
1354 uint16_t rxStaId2,
1355 const std::vector<bool>& puncturedSubchannels)
1356{
1357 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1358 WifiConstPsduMap psdus;
1359 WifiTxVector txVector{HePhy::GetHeMcs7(),
1360 0,
1362 NanoSeconds(800),
1363 1,
1364 1,
1365 0,
1367 false,
1368 false};
1369
1370 HeRu::RuType ruType =
1371 puncturedSubchannels.empty()
1373 : (puncturedSubchannels.at(1) ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1374 HeRu::RuSpec ru1(ruType, 1, true);
1375 txVector.SetRu(ru1, rxStaId1);
1376 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1377 txVector.SetNss(1, rxStaId1);
1378
1379 ruType = puncturedSubchannels.empty()
1381 : (puncturedSubchannels.at(1) ? HeRu::RU_484_TONE : HeRu::RU_242_TONE);
1382 HeRu::RuSpec ru2(ruType,
1383 ruType == HeRu::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1384 true);
1385 txVector.SetRu(ru2, rxStaId2);
1386 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1387 txVector.SetNss(1, rxStaId2);
1388
1389 RuAllocation ruAlloc;
1390 if (puncturedSubchannels.empty())
1391 {
1392 std::fill_n(std::back_inserter(ruAlloc), 4, 200);
1393 }
1394 else
1395 {
1396 ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1397 ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
1398 ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1399 : (puncturedSubchannels.at(3) ? 192 : 200));
1400 ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1401 : (puncturedSubchannels.at(3) ? 113 : 200));
1402 }
1403
1404 txVector.SetRuAllocation(ruAlloc, 0);
1405 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1406
1407 Ptr<Packet> pkt1 = Create<Packet>(1000);
1408 WifiMacHeader hdr1;
1410 hdr1.SetQosTid(0);
1411 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1412 hdr1.SetSequenceNumber(1);
1413 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1414 psdus.insert(std::make_pair(rxStaId1, psdu1));
1415
1416 Ptr<Packet> pkt2 = Create<Packet>(1500);
1417 WifiMacHeader hdr2;
1419 hdr2.SetQosTid(0);
1420 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1421 hdr2.SetSequenceNumber(2);
1422 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1423 psdus.insert(std::make_pair(rxStaId2, psdu2));
1424
1425 if (!puncturedSubchannels.empty())
1426 {
1427 txVector.SetInactiveSubchannels(puncturedSubchannels);
1428 }
1429
1430 m_phyAp->Send(psdus, txVector);
1431}
1432
1433void
1435{
1436 NS_LOG_FUNCTION(this << duration);
1437 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
1438 m_phyInterferer->SetPeriod(duration);
1439 m_phyInterferer->Start();
1441}
1442
1443void
1449
1450void
1452 RxSignalInfo rxSignalInfo,
1453 const WifiTxVector& txVector,
1454 const std::vector<bool>& /*statusPerMpdu*/)
1455{
1456 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1458 m_countRxBytesSta1 += (psdu->GetSize() - 30);
1459}
1460
1461void
1463 RxSignalInfo rxSignalInfo,
1464 const WifiTxVector& txVector,
1465 const std::vector<bool>& /*statusPerMpdu*/)
1466{
1467 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1469 m_countRxBytesSta2 += (psdu->GetSize() - 30);
1470}
1471
1472void
1478
1479void
1485
1486void
1488 uint32_t expectedRxFailure,
1489 uint32_t expectedRxBytes)
1490{
1492 expectedRxSuccess,
1493 "The number of successfully received packets by STA 1 is not correct!");
1495 expectedRxFailure,
1496 "The number of unsuccessfuly received packets by STA 1 is not correct!");
1498 expectedRxBytes,
1499 "The number of bytes received by STA 1 is not correct!");
1500}
1501
1502void
1504 uint32_t expectedRxFailure,
1505 uint32_t expectedRxBytes)
1506{
1508 expectedRxSuccess,
1509 "The number of successfully received packets by STA 2 is not correct!");
1511 expectedRxFailure,
1512 "The number of unsuccessfuly received packets by STA 2 is not correct!");
1514 expectedRxBytes,
1515 "The number of bytes received by STA 2 is not correct!");
1516}
1517
1518void
1520{
1521 // This is needed to make sure PHY state will be checked as the last event if a state change
1522 // occurred at the exact same time as the check
1524}
1525
1526void
1528{
1529 WifiPhyState currentState;
1530 PointerValue ptr;
1531 phy->GetAttribute("State", ptr);
1533 currentState = state->GetState();
1534 NS_LOG_FUNCTION(this << currentState);
1535 NS_TEST_ASSERT_MSG_EQ(currentState,
1536 expectedState,
1537 "PHY State " << currentState << " does not match expected state "
1538 << expectedState << " at " << Simulator::Now());
1539}
1540
1541void
1543{
1546 lossModel->SetFrequency(MHzToHz(m_frequency));
1547 spectrumChannel->AddPropagationLossModel(lossModel);
1550 spectrumChannel->SetPropagationDelayModel(delayModel);
1551
1552 Ptr<Node> apNode = CreateObject<Node>();
1556 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1558 m_phyAp->SetErrorRateModel(apErrorModel);
1559 m_phyAp->SetDevice(apDev);
1560 m_phyAp->AddChannel(spectrumChannel);
1561 m_phyAp->ConfigureStandard(WIFI_STANDARD_80211ax);
1563 m_phyAp->SetMobility(apMobility);
1564 apDev->SetPhy(m_phyAp);
1565 apNode->AggregateObject(apMobility);
1566 apNode->AddDevice(apDev);
1567
1568 Ptr<Node> sta1Node = CreateObject<Node>();
1572 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1574 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1575 m_phySta1->SetDevice(sta1Dev);
1576 m_phySta1->AddChannel(spectrumChannel);
1582 m_phySta1->SetMobility(sta1Mobility);
1583 sta1Dev->SetPhy(m_phySta1);
1584 sta1Node->AggregateObject(sta1Mobility);
1585 sta1Node->AddDevice(sta1Dev);
1586
1587 Ptr<Node> sta2Node = CreateObject<Node>();
1591 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1593 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1594 m_phySta2->SetDevice(sta2Dev);
1595 m_phySta2->AddChannel(spectrumChannel);
1601 m_phySta2->SetMobility(sta2Mobility);
1602 sta2Dev->SetPhy(m_phySta2);
1603 sta2Node->AggregateObject(sta2Mobility);
1604 sta2Node->AddDevice(sta2Dev);
1605
1606 Ptr<Node> interfererNode = CreateObject<Node>();
1609 m_phyInterferer->SetDevice(interfererDev);
1610 m_phyInterferer->SetChannel(spectrumChannel);
1611 m_phyInterferer->SetDutyCycle(1);
1612 interfererNode->AddDevice(interfererDev);
1613}
1614
1615void
1617{
1618 m_phyAp->Dispose();
1619 m_phyAp = nullptr;
1620 m_phySta1->Dispose();
1621 m_phySta1 = nullptr;
1622 m_phySta2->Dispose();
1623 m_phySta2 = nullptr;
1625 m_phyInterferer = nullptr;
1626}
1627
1628void
1630{
1633 int64_t streamNumber = 0;
1634 m_phyAp->AssignStreams(streamNumber);
1635 m_phySta1->AssignStreams(streamNumber);
1636 m_phySta2->AssignStreams(streamNumber);
1637
1638 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
1643 ->number;
1644
1645 m_phyAp->SetOperatingChannel(
1651
1652 // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1653 // duration of the test run
1654 BandInfo bandInfo;
1655 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20));
1656 // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1657 // the border of another RU
1658 bandInfo.fl = bandInfo.fc - MHzToHz(5);
1659 bandInfo.fh = bandInfo.fc + MHzToHz(5);
1660 Bands bands;
1661 bands.push_back(bandInfo);
1662
1663 auto spectrumInterference = Create<SpectrumModel>(bands);
1664 auto interferencePsd = Create<SpectrumValue>(spectrumInterference);
1665 Watt_u interferencePower{0.1};
1666 *interferencePsd = interferencePower / 10e6;
1667
1670 this,
1671 interferencePsd,
1672 Seconds(3));
1673
1674 //---------------------------------------------------------------------------
1675 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1678 this,
1679 1,
1680 2,
1681 std::vector<bool>{});
1682
1683 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1684 // both PHYs should be back to IDLE at the same time.
1687 this,
1688 m_phySta1,
1689 WifiPhyState::RX);
1692 this,
1693 m_phySta2,
1694 WifiPhyState::RX);
1697 this,
1698 m_phySta1,
1699 WifiPhyState::IDLE);
1702 this,
1703 m_phySta2,
1704 WifiPhyState::IDLE);
1705
1706 if (m_indexSubchannel < 2) // interference in RU 1
1707 {
1708 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1711 this,
1712 0,
1713 1,
1714 0);
1715 // One PSDU of 1500 bytes should have been successfully received by STA 2
1718 this,
1719 1,
1720 0,
1721 1500);
1722 }
1723 else // interference in RU 2
1724 {
1725 // One PSDU of 1000 bytes should have been successfully received by STA 1
1728 this,
1729 1,
1730 0,
1731 1000);
1732 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1735 this,
1736 0,
1737 1,
1738 0);
1739 }
1740
1742
1743 //---------------------------------------------------------------------------
1744 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1745 // the punctured 20 MHz subchannel is the one that has interference
1746 std::vector<bool> puncturedSubchannels;
1747 const auto num20MhzSubchannels = Count20MHzSubchannels(m_channelWidth);
1748 for (std::size_t i = 0; i < num20MhzSubchannels; ++i)
1749 {
1750 if (i == m_indexSubchannel)
1751 {
1752 puncturedSubchannels.push_back(true);
1753 }
1754 else
1755 {
1756 puncturedSubchannels.push_back(false);
1757 }
1758 }
1761 this,
1762 1,
1763 2,
1764 puncturedSubchannels);
1765
1766 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1767 // both PHYs should be back to IDLE at the same time.
1770 this,
1771 m_phySta1,
1772 WifiPhyState::RX);
1775 this,
1776 m_phySta2,
1777 WifiPhyState::RX);
1780 this,
1781 m_phySta1,
1782 WifiPhyState::IDLE);
1785 this,
1786 m_phySta2,
1787 WifiPhyState::IDLE);
1788
1789 // One PSDU of 1000 bytes should have been successfully received by STA 1
1792 this,
1793 1,
1794 0,
1795 1000);
1796 // One PSDU of 1500 bytes should have been successfully received by STA 2
1799 this,
1800 1,
1801 0,
1802 1500);
1803
1805
1807}
1808
1809void
1811{
1812 // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1813 // cannot be punctured
1814 for (auto index : {1, 2, 3})
1815 {
1816 m_indexSubchannel = index;
1817 RunOne();
1818 }
1820}
1821
1822/**
1823 * @ingroup wifi-test
1824 * @ingroup tests
1825 *
1826 * @brief UL-OFDMA PPDU UID attribution test
1827 */
1829{
1830 public:
1832 ~TestUlOfdmaPpduUid() override;
1833
1834 private:
1835 void DoSetup() override;
1836 void DoTeardown() override;
1837 void DoRun() override;
1838
1839 /**
1840 * Transmitted PPDU information function for AP
1841 * @param uid the UID of the transmitted PPDU
1842 */
1843 void TxPpduAp(uint64_t uid);
1844 /**
1845 * Transmitted PPDU information function for STA 1
1846 * @param uid the UID of the transmitted PPDU
1847 */
1848 void TxPpduSta1(uint64_t uid);
1849 /**
1850 * Transmitted PPDU information function for STA 2
1851 * @param uid the UID of the transmitted PPDU
1852 */
1853 void TxPpduSta2(uint64_t uid);
1854 /**
1855 * Reset the global PPDU UID counter in WifiPhy
1856 */
1857 void ResetPpduUid();
1858
1859 /**
1860 * Send MU-PPDU toward both STAs.
1861 */
1862 void SendMuPpdu();
1863 /**
1864 * Send TB-PPDU from both STAs.
1865 */
1866 void SendTbPpdu();
1867 /**
1868 * Send SU-PPDU function
1869 * @param txStaId the ID of the sending STA
1870 */
1871 void SendSuPpdu(uint16_t txStaId);
1872
1873 /**
1874 * Check the UID of the transmitted PPDU
1875 * @param staId the STA-ID of the PHY (0 for AP)
1876 * @param expectedUid the expected UID
1877 */
1878 void CheckUid(uint16_t staId, uint64_t expectedUid);
1879
1883
1884 uint64_t m_ppduUidAp; ///< UID of PPDU transmitted by AP
1885 uint64_t m_ppduUidSta1; ///< UID of PPDU transmitted by STA1
1886 uint64_t m_ppduUidSta2; ///< UID of PPDU transmitted by STA2
1887};
1888
1890 : TestCase("UL-OFDMA PPDU UID attribution test"),
1891 m_ppduUidAp(UINT64_MAX),
1892 m_ppduUidSta1(UINT64_MAX),
1893 m_ppduUidSta2(UINT64_MAX)
1894{
1895}
1896
1900
1901void
1903{
1906 lossModel->SetFrequency(DEFAULT_FREQUENCY);
1907 spectrumChannel->AddPropagationLossModel(lossModel);
1910 spectrumChannel->SetPropagationDelayModel(delayModel);
1911
1912 Ptr<Node> apNode = CreateObject<Node>();
1916 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1918 m_phyAp->SetErrorRateModel(apErrorModel);
1919 m_phyAp->AddChannel(spectrumChannel);
1921 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
1926 ->number;
1929 m_phyAp->SetDevice(apDev);
1933 m_phyAp->SetMobility(apMobility);
1934 apDev->SetPhy(m_phyAp);
1935 apNode->AggregateObject(apMobility);
1936 apNode->AddDevice(apDev);
1937 apDev->SetStandard(WIFI_STANDARD_80211ax);
1938 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1939
1940 Ptr<Node> sta1Node = CreateObject<Node>();
1944 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1946 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1947 m_phySta1->AddChannel(spectrumChannel);
1951 m_phySta1->SetDevice(sta1Dev);
1955 m_phySta1->SetMobility(sta1Mobility);
1956 sta1Dev->SetPhy(m_phySta1);
1957 sta1Node->AggregateObject(sta1Mobility);
1958 sta1Node->AddDevice(sta1Dev);
1959
1960 Ptr<Node> sta2Node = CreateObject<Node>();
1964 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1966 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1967 m_phySta2->AddChannel(spectrumChannel);
1971 m_phySta2->SetDevice(sta2Dev);
1975 m_phySta2->SetMobility(sta2Mobility);
1976 sta2Dev->SetPhy(m_phySta2);
1977 sta2Node->AggregateObject(sta2Mobility);
1978 sta2Node->AddDevice(sta2Dev);
1979}
1980
1981void
1983{
1984 m_phyAp->Dispose();
1985 m_phyAp = nullptr;
1986 m_phySta1->Dispose();
1987 m_phySta1 = nullptr;
1988 m_phySta2->Dispose();
1989 m_phySta2 = nullptr;
1990}
1991
1992void
1993TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
1994{
1995 uint64_t uid;
1996 std::string device;
1997 switch (staId)
1998 {
1999 case 0:
2000 uid = m_ppduUidAp;
2001 device = "AP";
2002 break;
2003 case 1:
2004 uid = m_ppduUidSta1;
2005 device = "STA1";
2006 break;
2007 case 2:
2008 uid = m_ppduUidSta2;
2009 device = "STA2";
2010 break;
2011 default:
2012 NS_ABORT_MSG("Unexpected STA-ID");
2013 }
2015 expectedUid,
2016 "UID " << uid << " does not match expected one " << expectedUid << " for "
2017 << device << " at " << Simulator::Now());
2018}
2019
2020void
2022{
2023 NS_LOG_FUNCTION(this << uid);
2024 m_ppduUidAp = uid;
2025}
2026
2027void
2029{
2030 NS_LOG_FUNCTION(this << uid);
2031 m_ppduUidSta1 = uid;
2032}
2033
2034void
2036{
2037 NS_LOG_FUNCTION(this << uid);
2038 m_ppduUidSta2 = uid;
2039}
2040
2041void
2043{
2044 NS_LOG_FUNCTION(this);
2045 m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2046}
2047
2048void
2050{
2051 WifiConstPsduMap psdus;
2052 WifiTxVector txVector{HePhy::GetHeMcs7(),
2053 0,
2055 NanoSeconds(800),
2056 1,
2057 1,
2058 0,
2060 false,
2061 false};
2062
2063 uint16_t rxStaId1 = 1;
2064 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2065 txVector.SetRu(ru1, rxStaId1);
2066 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2067 txVector.SetNss(1, rxStaId1);
2068
2069 uint16_t rxStaId2 = 2;
2070 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2071 txVector.SetRu(ru2, rxStaId2);
2072 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2073 txVector.SetNss(1, rxStaId2);
2074 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2075 txVector.SetRuAllocation({96}, 0);
2076
2077 Ptr<Packet> pkt1 = Create<Packet>(1000);
2078 WifiMacHeader hdr1;
2080 hdr1.SetQosTid(0);
2081 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2082 hdr1.SetSequenceNumber(1);
2083 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2084 psdus.insert(std::make_pair(rxStaId1, psdu1));
2085
2086 Ptr<Packet> pkt2 = Create<Packet>(1500);
2087 WifiMacHeader hdr2;
2089 hdr2.SetQosTid(0);
2090 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2091 hdr2.SetSequenceNumber(2);
2092 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2093 psdus.insert(std::make_pair(rxStaId2, psdu2));
2094
2095 m_phyAp->Send(psdus, txVector);
2096}
2097
2098void
2100{
2101 WifiConstPsduMap psdus1;
2102 WifiConstPsduMap psdus2;
2103
2104 WifiTxVector txVector1{HePhy::GetHeMcs7(),
2105 0,
2107 NanoSeconds(1600),
2108 1,
2109 1,
2110 0,
2112 false,
2113 false};
2114 WifiTxVector txVector2{txVector1};
2115 WifiTxVector trigVector{txVector2};
2116
2117 uint16_t rxStaId1 = 1;
2118 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2119 txVector1.SetRu(ru1, rxStaId1);
2120 txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2121 txVector1.SetNss(1, rxStaId1);
2122 trigVector.SetRu(ru1, rxStaId1);
2123 trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2124 trigVector.SetNss(1, rxStaId1);
2125
2126 auto pkt1 = Create<Packet>(1000);
2127 WifiMacHeader hdr1;
2129 hdr1.SetQosTid(0);
2130 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2131 hdr1.SetSequenceNumber(1);
2132 auto psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2133 psdus1.insert(std::make_pair(rxStaId1, psdu1));
2134
2135 uint16_t rxStaId2 = 2;
2136 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, false);
2137 txVector2.SetRu(ru2, rxStaId2);
2138 txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2139 txVector2.SetNss(1, rxStaId2);
2140 trigVector.SetRu(ru2, rxStaId2);
2141 trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2142 trigVector.SetNss(1, rxStaId2);
2143
2144 auto pkt2 = Create<Packet>(1500);
2145 WifiMacHeader hdr2;
2147 hdr2.SetQosTid(0);
2148 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2149 hdr2.SetSequenceNumber(2);
2150 auto psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2151 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2152
2153 const auto txDuration1 = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu1->GetSize(),
2154 txVector1,
2156 rxStaId1);
2157 const auto txDuration2 = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu2->GetSize(),
2158 txVector2,
2160 rxStaId2);
2161 const auto txDuration = std::max(txDuration1, txDuration2);
2162
2163 txVector1.SetLength(
2165 .first);
2166 txVector2.SetLength(
2168 .first);
2169
2171 hePhyAp->SetTrigVector(trigVector, txDuration);
2172
2173 m_phySta1->Send(psdus1, txVector1);
2174 m_phySta2->Send(psdus2, txVector2);
2175}
2176
2177void
2179{
2180 WifiConstPsduMap psdus;
2181 WifiTxVector txVector{HePhy::GetHeMcs7(),
2182 0,
2184 NanoSeconds(800),
2185 1,
2186 1,
2187 0,
2189 false,
2190 false};
2191
2192 auto pkt = Create<Packet>(1000);
2193 WifiMacHeader hdr;
2195 hdr.SetQosTid(0);
2197 hdr.SetSequenceNumber(1);
2198 auto psdu = Create<WifiPsdu>(pkt, hdr);
2199 psdus.insert(std::make_pair(SU_STA_ID, psdu));
2200
2201 switch (txStaId)
2202 {
2203 case 0:
2204 m_phyAp->Send(psdus, txVector);
2205 break;
2206 case 1:
2207 m_phySta1->Send(psdus, txVector);
2208 break;
2209 case 2:
2210 m_phySta2->Send(psdus, txVector);
2211 break;
2212 default:
2213 NS_ABORT_MSG("Unexpected STA-ID");
2214 }
2215}
2216
2217void
2219{
2222 int64_t streamNumber = 0;
2223 m_phyAp->AssignStreams(streamNumber);
2224 m_phySta1->AssignStreams(streamNumber);
2225 m_phySta2->AssignStreams(streamNumber);
2226
2227 // Reset PPDU UID so as not to be dependent on previously executed test cases,
2228 // since global attribute will be changed).
2229 ResetPpduUid();
2230
2231 // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2232 // PPDU UID should be equal to 0 (the first counter value).
2235
2236 // Send HE SU PPDU from AP.
2237 // PPDU UID should be incremented since this is a new PPDU.
2240
2241 // Send HE TB PPDU from STAs to AP.
2242 // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2243 // preceding correctly received PPDU (which normally contains the trigger frame).
2247
2248 // Send HE SU PPDU from STA1.
2249 // PPDU UID should be incremented since this is a new PPDU.
2252
2255}
2256
2257/**
2258 * @ingroup wifi-test
2259 * @ingroup tests
2260 *
2261 * @brief UL-OFDMA multiple RX events test
2262 */
2264{
2265 public:
2267 ~TestMultipleHeTbPreambles() override;
2268
2269 private:
2270 void DoSetup() override;
2271 void DoTeardown() override;
2272 void DoRun() override;
2273
2274 /**
2275 * Receive HE TB PPDU function.
2276 *
2277 * @param uid the UID used to identify a set of HE TB PPDUs belonging to the same UL-MU
2278 * transmission
2279 * @param staId the STA ID
2280 * @param txPower the TX power
2281 * @param payloadSize the size of the payload in bytes
2282 */
2283 void RxHeTbPpdu(uint64_t uid, uint16_t staId, Watt_u txPower, size_t payloadSize);
2284
2285 /**
2286 * Receive OFDMA part of HE TB PPDU function.
2287 * Immediately schedules DoRxHeTbPpduOfdmaPart.
2288 *
2289 * @param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2290 */
2292 /**
2293 * Receive OFDMA part of HE TB PPDU function.
2294 * Actual reception call.
2295 *
2296 * @param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2297 */
2299
2300 /**
2301 * RX dropped function
2302 * @param p the packet
2303 * @param reason the reason
2304 */
2306
2307 /**
2308 * Reset function
2309 */
2310 void Reset();
2311
2312 /**
2313 * Check the received HE TB preambles
2314 * @param nEvents the number of events created by the PHY
2315 * @param uids the vector of expected UIDs
2316 */
2317 void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2318
2319 /**
2320 * Check the number of bytes dropped
2321 * @param expectedBytesDropped the expected number of bytes dropped
2322 */
2323 void CheckBytesDropped(size_t expectedBytesDropped);
2324
2326
2327 uint64_t m_totalBytesDropped; ///< total number of dropped bytes
2329};
2330
2332 : TestCase("UL-OFDMA multiple RX events test"),
2333 m_totalBytesDropped(0),
2334 m_trigVector(HePhy::GetHeMcs7(),
2335 0,
2337 NanoSeconds(1600),
2338 1,
2339 1,
2340 0,
2342 false,
2343 false)
2344{
2345}
2346
2350
2351void
2353{
2354 NS_LOG_FUNCTION(this);
2356 // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2357 m_phy->Reset();
2359}
2360
2361void
2363{
2364 NS_LOG_FUNCTION(this << p << reason);
2365 m_totalBytesDropped += (p->GetSize() - 30);
2366}
2367
2368void
2369TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2370{
2371 auto events = m_phy->GetCurrentPreambleEvents();
2372 NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2373 for (const auto& uid : uids)
2374 {
2375 auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2376 auto it = events.find(pair);
2377 bool found = (it != events.end());
2379 true,
2380 "HE TB PPDU with UID " << uid << " has not been received!");
2381 }
2382}
2383
2384void
2386{
2388 expectedBytesDropped,
2389 "The number of dropped bytes is not correct!");
2390}
2391
2392void
2394 uint16_t staId,
2395 Watt_u txPower,
2396 size_t payloadSize)
2397{
2398 WifiConstPsduMap psdus;
2399 WifiTxVector txVector{HePhy::GetHeMcs7(),
2400 0,
2402 NanoSeconds(1600),
2403 1,
2404 1,
2405 0,
2407 false,
2408 false};
2409
2410 HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2411 txVector.SetRu(ru, staId);
2412 txVector.SetMode(HePhy::GetHeMcs7(), staId);
2413 txVector.SetNss(1, staId);
2414
2415 m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2416
2417 auto pkt = Create<Packet>(payloadSize);
2418 WifiMacHeader hdr;
2420 hdr.SetQosTid(0);
2421 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2422 hdr.SetSequenceNumber(1);
2423 auto psdu = Create<WifiPsdu>(pkt, hdr);
2424 psdus.insert(std::make_pair(staId, psdu));
2425
2426 auto ppduDuration = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu->GetSize(),
2427 txVector,
2428 m_phy->GetPhyBand(),
2429 staId);
2430 auto ppdu = Create<HePpdu>(psdus,
2431 txVector,
2433 ppduDuration,
2434 uid,
2436
2437 // Send non-OFDMA part
2438 const auto nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonHeDurationForHeTb(txVector);
2439 const auto centerFrequency =
2440 m_phy->GetHePhy()->GetCenterFrequenciesForNonHePart(ppdu, staId).front();
2441 MHz_u ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2442 MHz_u channelWidth = ruWidth < MHz_u{20} ? MHz_u{20} : ruWidth;
2444 centerFrequency,
2445 channelWidth,
2446 txPower,
2447 m_phy->GetGuardBandwidth(channelWidth));
2448 auto rxParams = Create<WifiSpectrumSignalParameters>();
2449 rxParams->psd = rxPsd;
2450 rxParams->txPhy = nullptr;
2451 rxParams->duration = nonOfdmaDuration;
2452 rxParams->ppdu = ppdu;
2453
2454 uint16_t length;
2455 std::tie(length, ppduDuration) =
2457 txVector.SetLength(length);
2458 m_trigVector.SetLength(length);
2460 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2461 ppdu->ResetTxVector();
2462 m_phy->StartRx(rxParams, nullptr);
2463
2464 // Schedule OFDMA part
2465 auto ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2466 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2467 const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2468 auto rxPsdOfdma =
2471 txPower,
2473 band.indices);
2474 auto rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2475 rxParamsOfdma->psd = rxPsd;
2476 rxParamsOfdma->txPhy = nullptr;
2477 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2478 rxParamsOfdma->ppdu = ppduOfdma;
2479 Simulator::Schedule(nonOfdmaDuration,
2481 this,
2482 rxParamsOfdma);
2483}
2484
2485void
2490
2491void
2493{
2494 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2495 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2496 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2497 m_phy->StartRx(rxParamsOfdma, nullptr);
2498}
2499
2500void
2502{
2506 dev->SetStandard(WIFI_STANDARD_80211ax);
2511 "Txop",
2512 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
2513 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2514 dev->SetMac(mac);
2515 m_phy->SetInterferenceHelper(interferenceHelper);
2516 m_phy->SetErrorRateModel(error);
2517 m_phy->AddChannel(spectrumChannel);
2522 0});
2523 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2525 m_phy->SetDevice(dev);
2526 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2528 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2529 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2530 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2532 heConfiguration->m_maxTbPpduDelay = NanoSeconds(400);
2533 dev->SetHeConfiguration(heConfiguration);
2534 dev->SetPhy(m_phy);
2535 node->AddDevice(dev);
2536}
2537
2538void
2540{
2541 m_phy->Dispose();
2542 m_phy = nullptr;
2543}
2544
2545void
2547{
2550 int64_t streamNumber = 0;
2551 m_phy->AssignStreams(streamNumber);
2552
2553 Watt_u txPower{0.01};
2554
2555 {
2556 // Verify a single UL MU transmission with two stations belonging to the same BSS
2557 std::vector<uint64_t> uids{0};
2560 this,
2561 uids[0],
2562 1,
2563 txPower,
2564 1001);
2567 this,
2568 uids[0],
2569 2,
2570 txPower,
2571 1002);
2572 // Check that we received a single UL MU transmission with the corresponding UID
2575 this,
2576 1,
2577 uids);
2579 }
2580
2581 {
2582 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2583 // the second transmission arrives during the preamble detection window and with half the
2584 // power of the first transmission.
2585 std::vector<uint64_t> uids{1, 2};
2588 this,
2589 uids[0],
2590 1,
2591 txPower,
2592 1001);
2595 this,
2596 uids[0],
2597 2,
2598 txPower,
2599 1002);
2602 this,
2603 uids[1],
2604 1,
2605 txPower / 2,
2606 1003);
2609 this,
2610 uids[1],
2611 2,
2612 txPower / 2,
2613 1004);
2614 // Check that we received the correct reception of 2 UL MU transmissions with the
2615 // corresponding UIDs
2618 this,
2619 2,
2620 uids);
2622 // TODO: verify PPDUs from second UL MU transmission are dropped
2623 }
2624
2625 {
2626 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2627 // the second transmission arrives during the preamble detection window and with twice the
2628 // power of the first transmission.
2629 std::vector<uint64_t> uids{3, 4};
2632 this,
2633 uids[0],
2634 1,
2635 txPower / 2,
2636 1001);
2639 this,
2640 uids[0],
2641 2,
2642 txPower / 2,
2643 1002);
2646 this,
2647 uids[1],
2648 1,
2649 txPower,
2650 1003);
2653 this,
2654 uids[1],
2655 2,
2656 txPower,
2657 1004);
2658 // Check that we received the correct reception of 2 UL MU transmissions with the
2659 // corresponding UIDs
2662 this,
2663 2,
2664 uids);
2666 // TODO: verify PPDUs from first UL MU transmission are dropped
2667 }
2668
2669 {
2670 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2671 // the second transmission arrives during PHY header reception and with the same power as
2672 // the first transmission.
2673 std::vector<uint64_t> uids{5, 6};
2676 this,
2677 uids[0],
2678 1,
2679 txPower,
2680 1001);
2683 this,
2684 uids[0],
2685 2,
2686 txPower,
2687 1002);
2690 this,
2691 uids[1],
2692 1,
2693 txPower,
2694 1003);
2697 this,
2698 uids[1],
2699 2,
2700 txPower,
2701 1004);
2702 // Check that we received the correct reception of the first UL MU transmission with the
2703 // corresponding UID (second one dropped)
2706 this,
2707 1,
2708 std::vector<uint64_t>{uids[0]});
2709 // The packets of the second UL MU transmission should have been dropped
2712 this,
2713 1003 + 1004);
2715 }
2716
2717 {
2718 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2719 // BSS, where the second transmission arrives during payload reception and with the same
2720 // power as the first transmission.
2721 std::vector<uint64_t> uids{7, 8};
2724 this,
2725 uids[0],
2726 1,
2727 txPower,
2728 1001);
2731 this,
2732 uids[0],
2733 2,
2734 txPower,
2735 1002);
2738 this,
2739 uids[1],
2740 1,
2741 txPower,
2742 1003);
2745 this,
2746 uids[1],
2747 2,
2748 txPower,
2749 1004);
2750 // Check that we received the correct reception of the first UL MU transmission with the
2751 // corresponding UID (second one dropped)
2754 this,
2755 1,
2756 std::vector<uint64_t>{uids[0]});
2757 // The packets of the second UL MU transmission should have been dropped
2760 this,
2761 1003 + 1004);
2763 }
2764
2765 {
2766 // Verify the correct reception of a single UL MU transmission with two stations belonging
2767 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2768 // the configured delay spread of 400ns
2769 std::vector<uint64_t> uids{9};
2772 this,
2773 uids[0],
2774 1,
2775 txPower,
2776 1001);
2779 this,
2780 uids[0],
2781 2,
2782 txPower,
2783 1002);
2784 // Check that we received a single UL MU transmission with the corresponding UID
2787 this,
2788 1,
2789 uids);
2790 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2791 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2792 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2793 // second packet of 1002 bytes is dropped as well.
2796 this,
2797 1001 + 1002);
2799 }
2800
2803}
2804
2805/**
2806 * @ingroup wifi-test
2807 * @ingroup tests
2808 *
2809 * @brief PHY listener for OFDMA tests
2810 */
2812{
2813 public:
2815
2816 void NotifyRxStart(Time duration) override
2817 {
2818 NS_LOG_FUNCTION(this << duration);
2821 m_lastRxSuccess = false;
2822 }
2823
2824 void NotifyRxEndOk() override
2825 {
2826 NS_LOG_FUNCTION(this);
2828 ++m_notifyRxEnd;
2829 m_lastRxSuccess = true;
2830 }
2831
2832 void NotifyRxEndError() override
2833 {
2834 NS_LOG_FUNCTION(this);
2836 ++m_notifyRxEnd;
2837 m_lastRxSuccess = false;
2838 }
2839
2840 void NotifyTxStart(Time duration, dBm_u txPower) override
2841 {
2842 NS_LOG_FUNCTION(this << duration << txPower);
2843 }
2844
2846 WifiChannelListType channelType,
2847 const std::vector<Time>& /*per20MhzDurations*/) override
2848 {
2849 NS_LOG_FUNCTION(this << duration << channelType);
2850 }
2851
2852 void NotifySwitchingStart(Time duration) override
2853 {
2854 }
2855
2856 void NotifySleep() override
2857 {
2858 }
2859
2860 void NotifyOff() override
2861 {
2862 }
2863
2864 void NotifyWakeup() override
2865 {
2866 }
2867
2868 void NotifyOn() override
2869 {
2870 }
2871
2872 /**
2873 * Reset function.
2874 */
2875 void Reset()
2876 {
2877 m_notifyRxStart = 0;
2878 m_notifyRxEnd = 0;
2880 m_lastRxEnd = Seconds(0);
2881 m_lastRxSuccess = false;
2882 }
2883
2884 /**
2885 * Return the number of RX start notifications that has been received since the last reset.
2886 * @return the number of RX start notifications that has been received
2887 */
2889 {
2890 return m_notifyRxStart;
2891 }
2892
2893 /**
2894 * Return the number of RX end notifications that has been received since the last reset.
2895 * @return the number of RX end notifications that has been received
2896 */
2898 {
2899 return m_notifyRxEnd;
2900 }
2901
2902 /**
2903 * Return the time at which the last RX start notification has been received.
2904 * @return the time at which the last RX start notification has been received
2905 */
2907 {
2908 return m_lastRxStart;
2909 }
2910
2911 /**
2912 * Return the time at which the last RX end notification has been received.
2913 * @return the time at which the last RX end notification has been received
2914 */
2916 {
2917 return m_lastRxEnd;
2918 }
2919
2920 /**
2921 * Return whether last RX has been successful.
2922 * @return true if last RX has been successful, false otherwise
2923 */
2924 bool IsLastRxSuccess() const
2925 {
2926 return m_lastRxSuccess;
2927 }
2928
2929 private:
2930 uint32_t m_notifyRxStart{0}; ///< count number of RX start notifications
2931 uint32_t m_notifyRxEnd{0}; ///< count number of RX end notifications
2932 Time m_lastRxStart{Seconds(0)}; ///< last time a RX start notification has been received
2933 Time m_lastRxEnd{Seconds(0)}; ///< last time a RX end notification has been received
2934 bool m_lastRxSuccess{false}; ///< flag whether last RX has been successful
2935};
2936
2937/**
2938 * @ingroup wifi-test
2939 * @ingroup tests
2940 *
2941 * @brief UL-OFDMA PHY test
2942 */
2944{
2945 public:
2946 /**
2947 * Erroneous info included in a TRIGVECTOR
2948 */
2956
2958 ~TestUlOfdmaPhyTransmission() override;
2959
2960 private:
2961 void DoSetup() override;
2962 void DoTeardown() override;
2963 void DoRun() override;
2964
2965 /**
2966 * Get TXVECTOR for HE TB PPDU.
2967 * @param txStaId the ID of the TX STA
2968 * @param index the RU index used for the transmission
2969 * @param bssColor the BSS color of the TX STA
2970 * @return the TXVECTOR for HE TB PPDU
2971 */
2972 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2973 std::size_t index,
2974 uint8_t bssColor) const;
2975 /**
2976 * Set TRIGVECTOR for HE TB PPDU
2977 *
2978 * @param bssColor the BSS color of the TX STA
2979 * @param error the erroneous info (if any) in the TRIGVECTOR to set
2980 */
2981 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2982 /**
2983 * Send HE TB PPDU function
2984 * @param txStaId the ID of the TX STA
2985 * @param index the RU index used for the transmission
2986 * @param payloadSize the size of the payload in bytes
2987 * @param uid the UID of the trigger frame that is initiating this transmission
2988 * @param bssColor the BSS color of the TX STA
2989 * @param incrementUid whether UID shall be incremented
2990 */
2991 void SendHeTbPpdu(uint16_t txStaId,
2992 std::size_t index,
2993 std::size_t payloadSize,
2994 uint64_t uid,
2995 uint8_t bssColor,
2996 bool incrementUid);
2997
2998 /**
2999 * Send HE SU PPDU function
3000 * @param txStaId the ID of the TX STA
3001 * @param payloadSize the size of the payload in bytes
3002 * @param uid the UID of the trigger frame that is initiating this transmission
3003 * @param bssColor the BSS color of the TX STA
3004 */
3005 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
3006
3007 /**
3008 * Set the BSS color
3009 * @param phy the PHY
3010 * @param bssColor the BSS color
3011 */
3012 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3013
3014 /**
3015 * Set the PSD limit
3016 * @param phy the PHY
3017 * @param psdLimit the PSD limit
3018 */
3019 void SetPsdLimit(Ptr<WifiPhy> phy, dBm_per_MHz_u psdLimit);
3020
3021 /**
3022 * Generate interference function
3023 * @param interferencePsd the PSD of the interference to be generated
3024 * @param duration the duration of the interference
3025 */
3026 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3027 /**
3028 * Stop interference function
3029 */
3030 void StopInterference();
3031
3032 /**
3033 * Run one function
3034 */
3035 void RunOne();
3036
3037 /**
3038 * Check the received PSDUs from STA1
3039 * @param expectedSuccess the expected number of success
3040 * @param expectedFailures the expected number of failures
3041 * @param expectedBytes the expected number of bytes
3042 */
3043 void CheckRxFromSta1(uint32_t expectedSuccess,
3044 uint32_t expectedFailures,
3045 uint32_t expectedBytes);
3046
3047 /**
3048 * Check the received PSDUs from STA2
3049 * @param expectedSuccess the expected number of success
3050 * @param expectedFailures the expected number of failures
3051 * @param expectedBytes the expected number of bytes
3052 */
3053 void CheckRxFromSta2(uint32_t expectedSuccess,
3054 uint32_t expectedFailures,
3055 uint32_t expectedBytes);
3056
3057 /**
3058 * Check the received power for the non-OFDMA of the HE TB PPDUs over the given band
3059 * @param phy the PHY
3060 * @param band the indices of the band over which the power is measured
3061 * @param expectedRxPower the expected received power
3062 */
3065 Watt_u expectedRxPower);
3066 /**
3067 * Check the received power for the OFDMA part of the HE TB PPDUs over the given band
3068 * @param phy the PHY
3069 * @param band the indices of the band over which the power is measured
3070 * @param expectedRxPower the expected received power
3071 */
3074 Watt_u expectedRxPower);
3075
3076 /**
3077 * Verify all events are cleared at end of TX or RX
3078 */
3079 void VerifyEventsCleared();
3080
3081 /**
3082 * Check the PHY state
3083 * @param phy the PHY
3084 * @param expectedState the expected state of the PHY
3085 */
3086 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
3087 /// @copydoc CheckPhyState
3089
3090 /**
3091 * Check the the number of RX start notifications at the AP as well as the last time a RX start
3092 * has been notified
3093 * @param expectedNotifications the expected number of RX start notifications at the AP
3094 * @param expectedLastNotification the expected time of the last RX start notification at the AP
3095 */
3096 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3097 /**
3098 * Check the the number of RX end notifications at the AP as well as the last time a RX end has
3099 * been notified
3100 * @param expectedNotifications the expected number of RX end notifications at the AP
3101 * @param expectedLastNotification the expected time of the last RX end notification at the AP
3102 * @param expectedSuccess true if the last RX notification indicates a success, false otherwise
3103 */
3104 void CheckApRxEnd(uint32_t expectedNotifications,
3105 Time expectedLastNotification,
3106 bool expectedSuccess);
3107
3108 /**
3109 * Reset function
3110 */
3111 void Reset();
3112
3113 /**
3114 * Receive success function
3115 * @param psdu the PSDU
3116 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
3117 * @param txVector the transmit vector
3118 * @param statusPerMpdu reception status per MPDU
3119 */
3121 RxSignalInfo rxSignalInfo,
3122 const WifiTxVector& txVector,
3123 const std::vector<bool>& statusPerMpdu);
3124
3125 /**
3126 * Receive failure function
3127 * @param psdu the PSDU
3128 */
3129 void RxFailure(Ptr<const WifiPsdu> psdu);
3130
3131 /**
3132 * Schedule test to perform.
3133 * The interference generation should be scheduled apart.
3134 *
3135 * @param delay the reference delay to schedule the events
3136 * @param solicited flag indicating if HE TB PPDUs were solicited by the AP
3137 * @param expectedStateAtEnd the expected state of the PHY at the end of the reception
3138 * @param expectedSuccessFromSta1 the expected number of success from STA 1
3139 * @param expectedFailuresFromSta1 the expected number of failures from STA 1
3140 * @param expectedBytesFromSta1 the expected number of bytes from STA 1
3141 * @param expectedSuccessFromSta2 the expected number of success from STA 2
3142 * @param expectedFailuresFromSta2 the expected number of failures from STA 2
3143 * @param expectedBytesFromSta2 the expected number of bytes from STA 2
3144 * @param scheduleTxSta1 flag indicating to schedule a HE TB PPDU from STA 1
3145 * @param ulTimeDifference delay between HE TB PPDU from STA 1 and HE TB PPDU from STA 2
3146 * are received
3147 * @param expectedStateBeforeEnd the expected state of the PHY before the end of the
3148 * transmission
3149 * @param error the erroneous info (if any) in the TRIGVECTOR to set
3150 */
3151 void ScheduleTest(Time delay,
3152 bool solicited,
3153 WifiPhyState expectedStateAtEnd,
3154 uint32_t expectedSuccessFromSta1,
3155 uint32_t expectedFailuresFromSta1,
3156 uint32_t expectedBytesFromSta1,
3157 uint32_t expectedSuccessFromSta2,
3158 uint32_t expectedFailuresFromSta2,
3159 uint32_t expectedBytesFromSta2,
3160 bool scheduleTxSta1 = true,
3161 Time ulTimeDifference = Seconds(0),
3162 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3163 TrigVectorInfo error = NONE);
3164
3165 /**
3166 * Schedule power measurement related checks.
3167 *
3168 * @param delay the reference delay used to schedule the events
3169 * @param rxPowerNonOfdmaRu1 the received power on the non-OFDMA part of RU1
3170 * @param rxPowerNonOfdmaRu2 the received power on the non-OFDMA part of RU2
3171 * @param rxPowerOfdmaRu1 the received power on RU1
3172 * @param rxPowerOfdmaRu2 the received power on RU2
3173 */
3175 Watt_u rxPowerNonOfdmaRu1,
3176 Watt_u rxPowerNonOfdmaRu2,
3177 Watt_u rxPowerOfdmaRu1,
3178 Watt_u rxPowerOfdmaRu2);
3179 /**
3180 * Log scenario description
3181 *
3182 * @param log the scenario description to add to log
3183 */
3184 void LogScenario(std::string log) const;
3185
3190
3191 std::shared_ptr<OfdmaTestPhyListener>
3192 m_apPhyStateListener; ///< listener for AP PHY state transitions
3193
3195
3196 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
3197 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
3198 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
3199 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
3200 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
3201 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
3202
3203 MHz_u m_frequency; ///< frequency
3204 MHz_u m_channelWidth; ///< channel width
3205 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
3206};
3207
3209 : TestCase("UL-OFDMA PHY test"),
3210 m_countRxSuccessFromSta1(0),
3211 m_countRxSuccessFromSta2(0),
3212 m_countRxFailureFromSta1(0),
3213 m_countRxFailureFromSta2(0),
3214 m_countRxBytesFromSta1(0),
3215 m_countRxBytesFromSta2(0),
3216 m_frequency(DEFAULT_FREQUENCY),
3217 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3218 m_expectedPpduDuration(NanoSeconds(271200))
3219{
3220}
3221
3222void
3224 std::size_t payloadSize,
3225 uint64_t uid,
3226 uint8_t bssColor)
3227{
3228 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3229 WifiConstPsduMap psdus;
3230
3231 WifiTxVector txVector{HePhy::GetHeMcs7(),
3232 0,
3234 NanoSeconds(800),
3235 1,
3236 1,
3237 0,
3239 false,
3240 false,
3241 false,
3242 bssColor};
3243
3244 auto pkt = Create<Packet>(payloadSize);
3245 WifiMacHeader hdr;
3247 hdr.SetQosTid(0);
3248 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3249 std::ostringstream addr;
3250 addr << "00:00:00:00:00:0" << txStaId;
3251 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3252 hdr.SetSequenceNumber(1);
3253 auto psdu = Create<WifiPsdu>(pkt, hdr);
3254 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3255
3257 if (txStaId == 1)
3258 {
3259 phy = m_phySta1;
3260 }
3261 else if (txStaId == 2)
3262 {
3263 phy = m_phySta2;
3264 }
3265 else if (txStaId == 3)
3266 {
3267 phy = m_phySta3;
3268 }
3269 else if (txStaId == 0)
3270 {
3271 phy = m_phyAp;
3272 }
3273 phy->SetPpduUid(uid);
3274 phy->Send(psdus, txVector);
3275}
3276
3279 std::size_t index,
3280 uint8_t bssColor) const
3281{
3282 WifiTxVector txVector{HePhy::GetHeMcs7(),
3283 0,
3285 NanoSeconds(1600),
3286 1,
3287 1,
3288 0,
3290 false,
3291 false,
3292 false,
3293 bssColor};
3294
3295 auto ruType = HeRu::RU_106_TONE;
3296 if (m_channelWidth == MHz_u{20})
3297 {
3298 ruType = HeRu::RU_106_TONE;
3299 }
3300 else if (m_channelWidth == MHz_u{40})
3301 {
3302 ruType = HeRu::RU_242_TONE;
3303 }
3304 else if (m_channelWidth == MHz_u{80})
3305 {
3306 ruType = HeRu::RU_484_TONE;
3307 }
3308 else if (m_channelWidth == MHz_u{160})
3309 {
3310 ruType = HeRu::RU_996_TONE;
3311 }
3312 else
3313 {
3314 NS_ASSERT_MSG(false, "Unsupported channel width");
3315 }
3316
3317 auto primary80MHz = true;
3318 if (m_channelWidth == MHz_u{160} && index == 2)
3319 {
3320 primary80MHz = false;
3321 index = 1;
3322 }
3323 HeRu::RuSpec ru(ruType, index, primary80MHz);
3324 txVector.SetRu(ru, txStaId);
3325 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3326 txVector.SetNss(1, txStaId);
3327 return txVector;
3328}
3329
3330void
3332{
3333 auto channelWidth = m_channelWidth;
3334 if (error == CHANNEL_WIDTH)
3335 {
3336 channelWidth = (channelWidth == MHz_u{160} ? MHz_u{20} : channelWidth * 2);
3337 }
3338
3339 WifiTxVector txVector(HePhy::GetHeMcs7(),
3340 0,
3342 NanoSeconds(1600),
3343 1,
3344 1,
3345 0,
3346 channelWidth,
3347 false,
3348 false,
3349 false,
3350 bssColor);
3351
3353 if (channelWidth == MHz_u{20})
3354 {
3355 ruType = HeRu::RU_106_TONE;
3356 }
3357 else if (channelWidth == MHz_u{40})
3358 {
3359 ruType = HeRu::RU_242_TONE;
3360 }
3361 else if (channelWidth == MHz_u{80})
3362 {
3363 ruType = HeRu::RU_484_TONE;
3364 }
3365 else if (channelWidth == MHz_u{160})
3366 {
3367 ruType = HeRu::RU_996_TONE;
3368 }
3369 else
3370 {
3371 NS_ASSERT_MSG(false, "Unsupported channel width");
3372 }
3373
3374 uint16_t aid1 = (error == AID ? 3 : 1);
3375 uint16_t aid2 = (error == AID ? 4 : 2);
3376
3377 HeRu::RuSpec ru1(ruType, 1, true);
3378 txVector.SetRu(ru1, aid1);
3379 txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3380 txVector.SetNss(1, aid1);
3381
3382 HeRu::RuSpec ru2(ruType, (channelWidth == MHz_u{160} ? 1 : 2), (channelWidth != MHz_u{160}));
3383 txVector.SetRu(ru2, aid2);
3384 txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3385 txVector.SetNss(1, aid2);
3386
3387 uint16_t length;
3388 std::tie(length, m_expectedPpduDuration) =
3390 txVector,
3391 m_phyAp->GetPhyBand());
3392 if (error == UL_LENGTH)
3393 {
3394 ++length;
3395 }
3396 txVector.SetLength(length);
3398 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3399}
3400
3401void
3403 std::size_t index,
3404 std::size_t payloadSize,
3405 uint64_t uid,
3406 uint8_t bssColor,
3407 bool incrementUid)
3408{
3409 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3410 WifiConstPsduMap psdus;
3411
3412 if (incrementUid)
3413 {
3414 ++uid;
3415 }
3416
3417 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3418 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3419 WifiMacHeader hdr;
3421 hdr.SetQosTid(0);
3422 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3423 std::ostringstream addr;
3424 addr << "00:00:00:00:00:0" << txStaId;
3425 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3426 hdr.SetSequenceNumber(1);
3427 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3428 psdus.insert(std::make_pair(txStaId, psdu));
3429
3431 if (txStaId == 1)
3432 {
3433 phy = m_phySta1;
3434 }
3435 else if (txStaId == 2)
3436 {
3437 phy = m_phySta2;
3438 }
3439 else if (txStaId == 3)
3440 {
3441 phy = m_phySta3;
3442 }
3443
3444 Time txDuration = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu->GetSize(),
3445 txVector,
3446 phy->GetPhyBand(),
3447 txStaId);
3448 txVector.SetLength(
3449 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3450
3451 phy->SetPpduUid(uid);
3452 phy->Send(psdus, txVector);
3453}
3454
3455void
3457{
3458 NS_LOG_FUNCTION(this << duration);
3459 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
3460 m_phyInterferer->SetPeriod(duration);
3461 m_phyInterferer->Start();
3463}
3464
3465void
3470
3474
3475void
3477 RxSignalInfo rxSignalInfo,
3478 const WifiTxVector& txVector,
3479 const std::vector<bool>& /*statusPerMpdu*/)
3480{
3481 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3482 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3483 {
3485 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3486 }
3487 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3488 {
3490 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3491 }
3492}
3493
3494void
3496{
3497 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3498 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3499 {
3501 }
3502 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3503 {
3505 }
3506}
3507
3508void
3510 uint32_t expectedFailures,
3511 uint32_t expectedBytes)
3512{
3514 expectedSuccess,
3515 "The number of successfully received packets from STA 1 is not correct!");
3518 expectedFailures,
3519 "The number of unsuccessfuly received packets from STA 1 is not correct!");
3521 expectedBytes,
3522 "The number of bytes received from STA 1 is not correct!");
3523}
3524
3525void
3527 uint32_t expectedFailures,
3528 uint32_t expectedBytes)
3529{
3531 expectedSuccess,
3532 "The number of successfully received packets from STA 2 is not correct!");
3535 expectedFailures,
3536 "The number of unsuccessfuly received packets from STA 2 is not correct!");
3538 expectedBytes,
3539 "The number of bytes received from STA 2 is not correct!");
3540}
3541
3542void
3545 Watt_u expectedRxPower)
3546{
3547 auto event = phy->GetCurrentEvent();
3548 NS_ASSERT(event);
3549 auto rxPower = event->GetRxPower(band);
3550 NS_LOG_FUNCTION(this << band << expectedRxPower << rxPower);
3551 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3553 expectedRxPower,
3554 Watt_u{5e-3},
3555 "RX power " << rxPower << " over (" << band
3556 << ") does not match expected power " << expectedRxPower
3557 << " at " << Simulator::Now());
3558}
3559
3560void
3563 Watt_u expectedRxPower)
3564{
3565 /**
3566 * The current event cannot be used since it points to the preamble part of the HE TB PPDU.
3567 * We will have to check if the expected power is indeed the max power returning a positive
3568 * duration when calling GetEnergyDuration.
3569 */
3570 NS_LOG_FUNCTION(this << band << expectedRxPower);
3571 Watt_u step{5e-3};
3572 if (expectedRxPower > Watt_u{0.0})
3573 {
3575 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3576 true,
3577 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3578 << Simulator::Now());
3580 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3581 false,
3582 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3583 << Simulator::Now());
3584 }
3585 else
3586 {
3588 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3589 false,
3590 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3591 << Simulator::Now());
3592 }
3593}
3594
3595void
3597{
3599 nullptr,
3600 "m_currentEvent for AP was not cleared");
3602 nullptr,
3603 "m_currentEvent for STA 1 was not cleared");
3605 nullptr,
3606 "m_currentEvent for STA 2 was not cleared");
3607}
3608
3609void
3611{
3612 // This is needed to make sure PHY state will be checked as the last event if a state change
3613 // occurred at the exact same time as the check
3615}
3616
3617void
3619 WifiPhyState expectedState)
3620{
3621 WifiPhyState currentState;
3622 PointerValue ptr;
3623 phy->GetAttribute("State", ptr);
3625 currentState = state->GetState();
3626 NS_LOG_FUNCTION(this << currentState);
3627 NS_TEST_ASSERT_MSG_EQ(currentState,
3628 expectedState,
3629 "PHY State " << currentState << " does not match expected state "
3630 << expectedState << " at " << Simulator::Now());
3631}
3632
3633void
3635 Time expectedLastNotification)
3636{
3638 expectedNotifications,
3639 "Number of RX start notifications "
3641 << " does not match expected count " << expectedNotifications
3642 << " for AP at " << Simulator::Now());
3644 expectedLastNotification,
3645 "Last time RX start notification has been received "
3647 << " does not match expected time " << expectedLastNotification
3648 << " for AP at " << Simulator::Now());
3649}
3650
3651void
3653 Time expectedLastNotification,
3654 bool expectedSuccess)
3655{
3657 expectedNotifications,
3658 "Number of RX end notifications "
3660 << " does not match expected count " << expectedNotifications
3661 << " for AP at " << Simulator::Now());
3663 expectedLastNotification,
3664 "Last time RX end notification has been received "
3666 << " does not match expected time " << expectedLastNotification
3667 << " for AP at " << Simulator::Now());
3669 expectedSuccess,
3670 "Last time RX end notification indicated a "
3671 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3672 << " but expected a " << (expectedSuccess ? "success" : "failure")
3673 << " for AP at " << Simulator::Now());
3674}
3675
3676void
3691
3692void
3694{
3695 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3696 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3697 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3698}
3699
3700void
3702{
3703 NS_LOG_FUNCTION(this << phy << psdLimit);
3704 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3705}
3706
3707void
3709{
3712 lossModel->SetFrequency(m_frequency);
3713 spectrumChannel->AddPropagationLossModel(lossModel);
3716 spectrumChannel->SetPropagationDelayModel(delayModel);
3717
3718 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3720 preambleDetectionModel->SetAttribute(
3721 "MinimumRssi",
3723 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3724 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3725
3726 Ptr<Node> apNode = CreateObject<Node>();
3728 apDev->SetStandard(WIFI_STANDARD_80211ax);
3730 "Txop",
3731 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
3732 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3733 apDev->SetMac(apMac);
3736 apDev->SetHeConfiguration(heConfiguration);
3738 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3740 m_phyAp->SetErrorRateModel(apErrorModel);
3741 m_phyAp->SetDevice(apDev);
3742 m_phyAp->AddChannel(spectrumChannel);
3746 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3748 m_phyAp->SetMobility(apMobility);
3749 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3751 apDev->SetPhy(m_phyAp);
3752 apMac->SetWifiPhys({m_phyAp});
3753 apNode->AggregateObject(apMobility);
3754 apNode->AddDevice(apDev);
3755
3756 Ptr<Node> sta1Node = CreateObject<Node>();
3758 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
3759 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3762 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3764 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3765 m_phySta1->SetDevice(sta1Dev);
3766 m_phySta1->AddChannel(spectrumChannel);
3768 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3770 m_phySta1->SetMobility(sta1Mobility);
3771 sta1Dev->SetPhy(m_phySta1);
3772 sta1Node->AggregateObject(sta1Mobility);
3773 sta1Node->AddDevice(sta1Dev);
3774
3775 Ptr<Node> sta2Node = CreateObject<Node>();
3777 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
3778 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3781 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3783 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3784 m_phySta2->SetDevice(sta2Dev);
3785 m_phySta2->AddChannel(spectrumChannel);
3787 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3789 m_phySta2->SetMobility(sta2Mobility);
3790 sta2Dev->SetPhy(m_phySta2);
3791 sta2Node->AggregateObject(sta2Mobility);
3792 sta2Node->AddDevice(sta2Dev);
3793
3794 Ptr<Node> sta3Node = CreateObject<Node>();
3796 sta3Dev->SetStandard(WIFI_STANDARD_80211ax);
3797 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3800 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3802 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3803 m_phySta3->SetDevice(sta3Dev);
3804 m_phySta3->AddChannel(spectrumChannel);
3806 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3808 m_phySta3->SetMobility(sta3Mobility);
3809 sta3Dev->SetPhy(m_phySta3);
3810 sta3Node->AggregateObject(sta3Mobility);
3811 sta3Node->AddDevice(sta3Dev);
3812
3813 Ptr<Node> interfererNode = CreateObject<Node>();
3816 m_phyInterferer->SetDevice(interfererDev);
3817 m_phyInterferer->SetChannel(spectrumChannel);
3818 m_phyInterferer->SetDutyCycle(1);
3819 interfererNode->AddDevice(interfererDev);
3820
3821 // Configure power attributes of all wifi devices
3822 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3823 for (auto& phy : phys)
3824 {
3825 phy->SetAttribute("TxGain", DoubleValue(1.0));
3826 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3827 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3828 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3829 phy->SetAttribute("RxGain", DoubleValue(2.0));
3830 // test assumes no rejection power for simplicity
3831 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3832 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3833 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3834 }
3835}
3836
3837void
3839{
3840 m_phyAp->Dispose();
3841 m_phyAp = nullptr;
3842 m_phySta1->Dispose();
3843 m_phySta1 = nullptr;
3844 m_phySta2->Dispose();
3845 m_phySta2 = nullptr;
3846 m_phySta3->Dispose();
3847 m_phySta3 = nullptr;
3849 m_phyInterferer = nullptr;
3850}
3851
3852void
3854{
3855 NS_LOG_INFO(log);
3856}
3857
3858void
3860 bool solicited,
3861 WifiPhyState expectedStateAtEnd,
3862 uint32_t expectedSuccessFromSta1,
3863 uint32_t expectedFailuresFromSta1,
3864 uint32_t expectedBytesFromSta1,
3865 uint32_t expectedSuccessFromSta2,
3866 uint32_t expectedFailuresFromSta2,
3867 uint32_t expectedBytesFromSta2,
3868 bool scheduleTxSta1,
3869 Time ulTimeDifference,
3870 WifiPhyState expectedStateBeforeEnd,
3871 TrigVectorInfo error)
3872{
3873 static uint64_t uid = 0;
3874
3875 // AP sends an SU packet preceding HE TB PPDUs
3878 this,
3879 0,
3880 50,
3881 ++uid,
3882 0);
3883 if (!solicited)
3884 {
3885 // UID of TB PPDUs will be different than the one of the preceding frame
3886 ++uid;
3887 }
3888 else
3889 {
3891 }
3892 // STA1 and STA2 send MU UL PPDUs addressed to AP
3895 m_apPhyStateListener.get());
3896 if (scheduleTxSta1)
3897 {
3898 Simulator::Schedule(delay,
3900 this,
3901 1,
3902 1,
3903 1000,
3904 uid,
3905 0,
3906 false);
3907 }
3908 Simulator::Schedule(delay + ulTimeDifference,
3910 this,
3911 2,
3912 2,
3913 1001,
3914 uid,
3915 0,
3916 false);
3917
3918 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3921 this,
3922 m_phyAp,
3923 expectedStateBeforeEnd);
3924 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3926 this,
3927 m_phyAp,
3928 expectedStateAtEnd);
3929 // TODO: add checks on TX stop for STAs
3930
3931 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3932 expectedFailuresFromSta2 >
3933 0)
3934 {
3935 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3936 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3937 // The expected time at which the reception is started corresponds to the time at which the
3938 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3939 const Time expectedPayloadStart = delay + MicroSeconds(48);
3940 // The expected time at which the reception is terminated corresponds to the time at which
3941 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3942 // received HE TB PPDU and the last received HE TB PPDU.
3943 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3944 // At the end of the transmission, verify that a single RX start notification shall have
3945 // been notified when the reception of the first HE RB PPDU starts.
3946 Simulator::Schedule(expectedPayloadEnd,
3948 this,
3949 1,
3950 Simulator::Now() + expectedPayloadStart);
3951 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3952 // notification shall have been notified when the reception of the last HE RB PPDU ends
3953 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3955 this,
3956 1,
3957 Simulator::Now() + expectedPayloadEnd,
3958 isSuccess);
3959 }
3960
3961 delay += MilliSeconds(100);
3962 // Check reception state from STA 1
3963 Simulator::Schedule(delay,
3965 this,
3966 expectedSuccessFromSta1,
3967 expectedFailuresFromSta1,
3968 expectedBytesFromSta1);
3969 // Check reception state from STA 2
3970 Simulator::Schedule(delay,
3972 this,
3973 expectedSuccessFromSta2,
3974 expectedFailuresFromSta2,
3975 expectedBytesFromSta2);
3976 // Verify events data have been cleared
3978
3979 delay += MilliSeconds(100);
3981}
3982
3983void
3985 Watt_u rxPowerNonOfdmaRu1,
3986 Watt_u rxPowerNonOfdmaRu2,
3987 Watt_u rxPowerOfdmaRu1,
3988 Watt_u rxPowerOfdmaRu2)
3989{
3990 const auto detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3991 const auto txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3992 const auto txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3993 const auto hePhy = m_phyAp->GetHePhy();
3994 const auto nonOfdmaDuration = hePhy->CalculateNonHeDurationForHeTb(txVectorSta2);
3995 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonHeDurationForHeTb(txVectorSta1));
3996
3997 std::vector<Watt_u> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3998 std::vector<WifiSpectrumBandInfo> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3999 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
4000 std::vector<Watt_u> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
4001 std::vector<WifiSpectrumBandInfo> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
4002 hePhy->GetRuBandForRx(txVectorSta2, 2)};
4003
4004 for (uint8_t i = 0; i < 2; ++i)
4005 {
4006 /**
4007 * Perform checks at AP
4008 */
4009 // Check received power on non-OFDMA portion
4011 delay + detectionDuration +
4012 NanoSeconds(1), // just after beginning of portion (once event is stored)
4014 this,
4015 m_phyAp,
4016 nonOfdmaBand[i],
4017 rxPowerNonOfdma[i]);
4018 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4020 this,
4021 m_phyAp,
4022 nonOfdmaBand[i],
4023 rxPowerNonOfdma[i]);
4024 // Check received power on OFDMA portion
4025 Simulator::Schedule(delay + nonOfdmaDuration +
4026 NanoSeconds(1), // just after beginning of portion
4028 this,
4029 m_phyAp,
4030 ofdmaBand[i],
4031 rxPowerOfdma[i]);
4033 NanoSeconds(1), // just before end of portion
4035 this,
4036 m_phyAp,
4037 ofdmaBand[i],
4038 rxPowerOfdma[i]);
4039
4040 /**
4041 * Perform checks for non-transmitting STA (STA 3).
4042 * Cannot use CheckNonOfdmaRxPower method since current event may be reset if
4043 * preamble not detected (e.g. not on primary).
4044 */
4045 // Check received power on non-OFDMA portion
4047 delay + detectionDuration +
4048 NanoSeconds(1), // just after beginning of portion (once event is stored)
4050 this,
4051 m_phySta3,
4052 nonOfdmaBand[i],
4053 rxPowerNonOfdma[i]);
4054 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4056 this,
4057 m_phySta3,
4058 nonOfdmaBand[i],
4059 rxPowerNonOfdma[i]);
4060 // Check received power on OFDMA portion
4061 Simulator::Schedule(delay + nonOfdmaDuration +
4062 NanoSeconds(1), // just after beginning of portion
4064 this,
4065 m_phySta3,
4066 ofdmaBand[i],
4067 rxPowerOfdma[i]);
4069 NanoSeconds(1), // just before end of portion
4071 this,
4072 m_phySta3,
4073 ofdmaBand[i],
4074 rxPowerOfdma[i]);
4075 }
4076
4077 if (rxPowerOfdmaRu1 != Watt_u{0.0})
4078 {
4079 /**
4080 * Perform checks for transmitting STA (STA 2) to ensure it has correctly logged
4081 * power received from other transmitting STA (STA 1).
4082 * Cannot use CheckNonOfdmaRxPower method since current event not set.
4083 */
4084 const auto rxPowerNonOfdmaSta1Only =
4085 (m_channelWidth >= MHz_u{40})
4086 ? rxPowerNonOfdma[0]
4087 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4088 // Check received power on non-OFDMA portion
4090 delay + detectionDuration +
4091 NanoSeconds(1), // just after beginning of portion (once event is stored)
4093 this,
4094 m_phySta2,
4095 nonOfdmaBand[0],
4096 rxPowerNonOfdmaSta1Only);
4097 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4099 this,
4100 m_phySta2,
4101 nonOfdmaBand[0],
4102 rxPowerNonOfdmaSta1Only);
4103 // Check received power on OFDMA portion
4104 Simulator::Schedule(delay + nonOfdmaDuration +
4105 NanoSeconds(1), // just after beginning of portion
4107 this,
4108 m_phySta2,
4109 ofdmaBand[0],
4110 rxPowerOfdma[0]);
4112 NanoSeconds(1), // just before end of portion
4114 this,
4115 m_phySta2,
4116 ofdmaBand[0],
4117 rxPowerOfdma[0]);
4118 }
4119}
4120
4121void
4123{
4126 int64_t streamNumber = 0;
4127 m_phyAp->AssignStreams(streamNumber);
4128 m_phySta1->AssignStreams(streamNumber);
4129 m_phySta2->AssignStreams(streamNumber);
4130 m_phySta3->AssignStreams(streamNumber);
4131
4132 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
4137 ->number;
4138
4147
4148 Time delay;
4150 delay += Seconds(1);
4151
4152 /**
4153 * In all the following tests, 2 HE TB PPDUs of the same UL MU transmission
4154 * are sent on RU 1 for STA 1 and RU 2 for STA 2.
4155 * The difference between solicited and unsolicited lies in that their PPDU
4156 * ID correspond to the one of the immediately preceding HE SU PPDU (thus
4157 * mimicking trigger frame reception).
4158 */
4159
4160 //---------------------------------------------------------------------------
4161 // Verify that both solicited HE TB PPDUs have been corrected received
4162 Simulator::Schedule(delay,
4164 this,
4165 "Reception of solicited HE TB PPDUs");
4166 ScheduleTest(delay,
4167 true,
4168 WifiPhyState::IDLE,
4169 1,
4170 0,
4171 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4172 1,
4173 0,
4174 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4175 delay += Seconds(1);
4176
4177 //---------------------------------------------------------------------------
4178 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4179 // corrected received
4181 delay,
4183 this,
4184 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4185 ScheduleTest(delay,
4186 true,
4187 WifiPhyState::IDLE,
4188 1,
4189 0,
4190 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4191 1,
4192 0,
4193 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4194 true,
4195 NanoSeconds(100));
4196 delay += Seconds(1);
4197
4198 //---------------------------------------------------------------------------
4199 // Verify that no unsolicited HE TB PPDU is received
4200 Simulator::Schedule(delay,
4202 this,
4203 "Dropping of unsolicited HE TB PPDUs");
4204 ScheduleTest(delay,
4205 false,
4206 WifiPhyState::IDLE,
4207 0,
4208 0,
4209 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4210 0,
4211 0,
4212 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4213 true,
4214 Seconds(0),
4215 WifiPhyState::CCA_BUSY);
4216 delay += Seconds(1);
4217
4218 //---------------------------------------------------------------------------
4219 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4220 Simulator::Schedule(delay,
4222 this,
4223 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4224 ScheduleTest(delay,
4225 true,
4226 WifiPhyState::IDLE,
4227 0,
4228 0,
4229 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4230 0,
4231 0,
4232 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4233 true,
4234 Seconds(0),
4235 WifiPhyState::CCA_BUSY,
4237 delay += Seconds(1);
4238
4239 //---------------------------------------------------------------------------
4240 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4241 Simulator::Schedule(delay,
4243 this,
4244 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4245 ScheduleTest(delay,
4246 true,
4247 WifiPhyState::IDLE,
4248 0,
4249 0,
4250 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4251 0,
4252 0,
4253 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4254 true,
4255 Seconds(0),
4256 WifiPhyState::CCA_BUSY,
4257 UL_LENGTH);
4258 delay += Seconds(1);
4259
4260 //---------------------------------------------------------------------------
4261 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4262 Simulator::Schedule(delay,
4264 this,
4265 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4266 ScheduleTest(delay,
4267 true,
4268 WifiPhyState::IDLE,
4269 0,
4270 0,
4271 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4272 0,
4273 0,
4274 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4275 true,
4276 Seconds(0),
4277 WifiPhyState::CCA_BUSY,
4278 AID);
4279 delay += Seconds(1);
4280
4281 //---------------------------------------------------------------------------
4282 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4283 // impacted
4285 delay,
4287 this,
4288 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4289 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4290 BandInfo bandInfo;
4291 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 4));
4292 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
4293 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
4294 Bands bands;
4295 bands.push_back(bandInfo);
4296
4297 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4298 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4299 Watt_u interferencePower{0.1};
4300 *interferencePsdRu1 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
4301
4304 this,
4305 interferencePsdRu1,
4306 MilliSeconds(100));
4308 delay,
4309 true,
4310 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4311 // interference
4312 0,
4313 1,
4314 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4315 1,
4316 0,
4317 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4318 delay += Seconds(1);
4319
4320 //---------------------------------------------------------------------------
4321 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4322 // impacted
4324 delay,
4326 this,
4327 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4328 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4329 bandInfo.fc = MHzToHz(m_frequency + (m_channelWidth / 4));
4330 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
4331 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
4332 bands.clear();
4333 bands.push_back(bandInfo);
4334
4335 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4336 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4337 *interferencePsdRu2 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
4338
4341 this,
4342 interferencePsdRu2,
4343 MilliSeconds(100));
4344 ScheduleTest(delay,
4345 true,
4346 (m_channelWidth >= MHz_u{40})
4347 ? WifiPhyState::IDLE
4348 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4349 // generated in its primary channel
4350 1,
4351 0,
4352 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4353 0,
4354 1,
4355 0); // Reception of the PSDU from STA 2 should have failed (since interference
4356 // occupies RU 2)
4357 delay += Seconds(1);
4358
4359 //---------------------------------------------------------------------------
4360 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4361 // been impacted
4362 Simulator::Schedule(delay,
4364 this,
4365 "Reception of solicited HE TB PPDUs with interference on the full band "
4366 "during PSDU reception");
4367 // A strong non-wifi interference is generated on the full band during PSDU reception
4368 bandInfo.fc = MHzToHz(m_frequency);
4369 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 2);
4370 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 2);
4371 bands.clear();
4372 bands.push_back(bandInfo);
4373
4374 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4375 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4376 *interferencePsdAll = interferencePower / (MHzToHz(m_channelWidth) * 20);
4377
4380 this,
4381 interferencePsdAll,
4382 MilliSeconds(100));
4384 delay,
4385 true,
4386 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4387 // interference
4388 0,
4389 1,
4390 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4391 0,
4392 1,
4393 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4394 // 2)
4395 delay += Seconds(1);
4396
4397 //---------------------------------------------------------------------------
4398 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4399 // solicited HE TB PPDUs have been impacted if they are on the same
4400 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4401 Simulator::Schedule(delay,
4403 this,
4404 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4405 "1 during PSDU reception");
4406 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4409 this,
4410 3,
4411 1,
4412 1002,
4413 1,
4414 0,
4415 false);
4416 // Expected figures from STA 2
4417 uint32_t succ;
4418 uint32_t fail;
4419 uint32_t bytes;
4420 if (m_channelWidth > MHz_u{20})
4421 {
4422 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4423 // interference from STA 3 on distinct 20 MHz channel)
4424 succ = 1;
4425 fail = 0;
4426 bytes = 1001;
4427 }
4428 else
4429 {
4430 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4431 // same 20 MHz channel)
4432 succ = 0;
4433 fail = 1;
4434 bytes = 0;
4435 }
4436 ScheduleTest(delay,
4437 true,
4438 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4439 // interference on measurement channel width
4440 0,
4441 1,
4442 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4443 // STA 3 on same 20 MHz channel)
4444 succ,
4445 fail,
4446 bytes);
4447 delay += Seconds(1);
4448
4449 //---------------------------------------------------------------------------
4450 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4451 // solicited HE TB PPDUs have been impacted if they are on the same
4452 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4453 Simulator::Schedule(delay,
4455 this,
4456 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4457 "2 during PSDU reception");
4458 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4461 this,
4462 3,
4463 2,
4464 1002,
4465 1,
4466 0,
4467 false);
4468 // Expected figures from STA 1
4469 if (m_channelWidth > MHz_u{20})
4470 {
4471 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4472 // interference from STA 3 on distinct 20 MHz channel)
4473 succ = 1;
4474 fail = 0;
4475 bytes = 1000;
4476 }
4477 else
4478 {
4479 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4480 // same 20 MHz channel)
4481 succ = 0;
4482 fail = 1;
4483 bytes = 0;
4484 }
4485 ScheduleTest(delay,
4486 true,
4487 (m_channelWidth >= MHz_u{40})
4488 ? WifiPhyState::IDLE
4489 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4490 // TB PPDU on primary channel
4491 succ,
4492 fail,
4493 bytes,
4494 0,
4495 1,
4496 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4497 // STA 3 on same 20 MHz channel)
4498 delay += Seconds(1);
4499
4500 //---------------------------------------------------------------------------
4501 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4502 // impacted
4504 delay,
4506 this,
4507 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4508 // One HE SU arrives at AP during the 400ns window
4509 Simulator::Schedule(delay + NanoSeconds(300),
4511 this,
4512 3,
4513 1002,
4514 1,
4515 0);
4517 delay,
4518 true,
4519 WifiPhyState::IDLE,
4520 0,
4521 1,
4522 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4523 0,
4524 1,
4525 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4526 delay += Seconds(1);
4527
4528 //---------------------------------------------------------------------------
4529 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4530 // received
4531 Simulator::Schedule(delay,
4533 this,
4534 "Reception of solicited HE TB PPDU only on RU 2");
4535 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4536 // otherwise
4539 this,
4540 m_phySta3,
4541 (m_channelWidth >= MHz_u{40})
4542 ? WifiPhyState::IDLE
4543 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4544 // IDLE if HE TB PPDU on primary channel
4545 ScheduleTest(delay,
4546 true,
4547 WifiPhyState::IDLE,
4548 0,
4549 0,
4550 0, // No transmission scheduled for STA 1
4551 1,
4552 0,
4553 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4554 false,
4555 Seconds(0),
4556 WifiPhyState::RX); // Measurement channel is total channel width
4557 delay += Seconds(1);
4558
4559 //---------------------------------------------------------------------------
4560 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4561 Simulator::Schedule(delay,
4563 this,
4564 "Measure power for reception of HE TB PPDU only on RU 2");
4565 auto rxPower = DbmToW(
4566 dBm_u{19}); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4568 (m_channelWidth >= MHz_u{40}) ? Watt_u{0.0} : rxPower,
4569 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4570 Watt_u{0.0},
4571 rxPower);
4572 ScheduleTest(delay,
4573 true,
4574 WifiPhyState::IDLE,
4575 0,
4576 0,
4577 0, // No transmission scheduled for STA 1
4578 1,
4579 0,
4580 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4581 false,
4582 Seconds(0),
4583 WifiPhyState::RX); // Measurement channel is total channel width
4584 delay += Seconds(1);
4585
4586 //---------------------------------------------------------------------------
4587 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4588 // limitation enforced
4590 delay,
4592 this,
4593 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4594 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4595 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4596 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4598 this,
4599 m_phySta2,
4600 dBm_per_MHz_u{3});
4601
4602 rxPower = (m_channelWidth > MHz_u{40})
4603 ? DbmToW(dBm_u{19})
4604 : DbmToW(dBm_u{18.0103}); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4605 // transmitted only on one 20 MHz channel
4606 auto rxPowerOfdma = rxPower;
4607 if (m_channelWidth <= MHz_u{40})
4608 {
4609 rxPowerOfdma =
4610 (m_channelWidth == MHz_u{20})
4611 ? DbmToW(dBm_u{14.0309}) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4612 : DbmToW(dBm_u{18.0103}); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4613 }
4615 (m_channelWidth >= MHz_u{40}) ? Watt_u{0.0} : rxPower,
4616 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4617 Watt_u{0.0},
4618 rxPowerOfdma);
4619
4620 // Reset PSD limitation once HE TB has been sent
4623 this,
4624 m_phySta2,
4625 dBm_per_MHz_u{100});
4626 ScheduleTest(delay,
4627 true,
4628 WifiPhyState::IDLE,
4629 0,
4630 0,
4631 0, // No transmission scheduled for STA 1
4632 1,
4633 0,
4634 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4635 false,
4636 Seconds(0),
4637 WifiPhyState::RX); // Measurement channel is total channel width
4638 delay += Seconds(1);
4639
4640 //---------------------------------------------------------------------------
4641 // Measure the power of 2 solicited HE TB PPDU from both STAs
4642 Simulator::Schedule(delay,
4644 this,
4645 "Measure power for reception of HE TB PPDU on both RUs");
4646 rxPower = DbmToW(
4647 dBm_u{19}); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4648 const auto rxPowerNonOfdma =
4649 (m_channelWidth >= MHz_u{40})
4650 ? rxPower
4651 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4652 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4653 ScheduleTest(delay,
4654 true,
4655 WifiPhyState::IDLE,
4656 1,
4657 0,
4658 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4659 1,
4660 0,
4661 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4662 delay += Seconds(1);
4663
4664 //---------------------------------------------------------------------------
4665 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4666 // ongoing)
4667 Simulator::Schedule(delay,
4669 this,
4670 "Reception of an HE TB PPDU from another BSS");
4671 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4673 Simulator::Schedule(delay + MilliSeconds(100),
4675 this,
4676 3,
4677 1,
4678 1002,
4679 1,
4680 2,
4681 false);
4682
4683 // Verify events data have been cleared
4684 Simulator::Schedule(delay + MilliSeconds(200),
4686 this);
4687
4689 delay += Seconds(1);
4690
4691 //---------------------------------------------------------------------------
4692 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4693 // corrected received
4695 delay,
4697 this,
4698 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4699 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4703 this,
4704 3,
4705 1,
4706 1002,
4707 1,
4708 2,
4709 true);
4710 ScheduleTest(delay,
4711 true,
4712 WifiPhyState::CCA_BUSY,
4713 1,
4714 0,
4715 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4716 1,
4717 0,
4718 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4719 true,
4720 NanoSeconds(200));
4721 delay += Seconds(1);
4722
4724}
4725
4726void
4728{
4729 m_frequency = MHz_u{5180};
4730 m_channelWidth = MHz_u{20};
4732 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4733 RunOne();
4734
4735 m_frequency = MHz_u{5190};
4736 m_channelWidth = MHz_u{40};
4738 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4739 RunOne();
4740
4741 m_frequency = MHz_u{5210};
4742 m_channelWidth = MHz_u{80};
4744 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4745 RunOne();
4746
4747 m_frequency = MHz_u{5250};
4748 m_channelWidth = MHz_u{160};
4750 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4751 RunOne();
4752
4754}
4755
4756/**
4757 * @ingroup wifi-test
4758 * @ingroup tests
4759 *
4760 * @brief PHY padding exclusion test
4761 */
4763{
4764 public:
4766 ~TestPhyPaddingExclusion() override;
4767
4768 private:
4769 void DoSetup() override;
4770 void DoTeardown() override;
4771 void DoRun() override;
4772
4773 /**
4774 * Send HE TB PPDU function
4775 * @param txStaId the ID of the TX STA
4776 * @param index the RU index used for the transmission
4777 * @param payloadSize the size of the payload in bytes
4778 * @param txDuration the duration of the PPDU
4779 */
4780 void SendHeTbPpdu(uint16_t txStaId,
4781 std::size_t index,
4782 std::size_t payloadSize,
4783 Time txDuration);
4784 /**
4785 * Set TRIGVECTOR for HE TB PPDU
4786 *
4787 * @param ppduDuration the duration of the HE TB PPDU
4788 */
4789 void SetTrigVector(Time ppduDuration);
4790
4791 /**
4792 * Generate interference function
4793 * @param interferencePsd the PSD of the interference to be generated
4794 * @param duration the duration of the interference
4795 */
4796 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4797 /**
4798 * Stop interference function
4799 */
4800 void StopInterference();
4801
4802 /**
4803 * Run one function
4804 */
4805 void RunOne();
4806
4807 /**
4808 * Check the received PSDUs from STA1
4809 * @param expectedSuccess the expected number of success
4810 * @param expectedFailures the expected number of failures
4811 * @param expectedBytes the expected number of bytes
4812 */
4813 void CheckRxFromSta1(uint32_t expectedSuccess,
4814 uint32_t expectedFailures,
4815 uint32_t expectedBytes);
4816
4817 /**
4818 * Check the received PSDUs from STA2
4819 * @param expectedSuccess the expected number of success
4820 * @param expectedFailures the expected number of failures
4821 * @param expectedBytes the expected number of bytes
4822 */
4823 void CheckRxFromSta2(uint32_t expectedSuccess,
4824 uint32_t expectedFailures,
4825 uint32_t expectedBytes);
4826
4827 /**
4828 * Verify all events are cleared at end of TX or RX
4829 */
4830 void VerifyEventsCleared();
4831
4832 /**
4833 * Check the PHY state
4834 * @param phy the PHY
4835 * @param expectedState the expected state of the PHY
4836 */
4837 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
4838 /// @copydoc CheckPhyState
4840
4841 /**
4842 * Reset function
4843 */
4844 void Reset();
4845
4846 /**
4847 * Receive success function
4848 * @param psdu the PSDU
4849 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
4850 * @param txVector the transmit vector
4851 * @param statusPerMpdu reception status per MPDU
4852 */
4854 RxSignalInfo rxSignalInfo,
4855 const WifiTxVector& txVector,
4856 const std::vector<bool>& statusPerMpdu);
4857
4858 /**
4859 * Receive failure function
4860 * @param psdu the PSDU
4861 */
4862 void RxFailure(Ptr<const WifiPsdu> psdu);
4863
4867
4869
4870 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
4871 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
4872 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
4873 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
4874 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
4875 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
4876};
4877
4879 : TestCase("PHY padding exclusion test"),
4880 m_countRxSuccessFromSta1(0),
4881 m_countRxSuccessFromSta2(0),
4882 m_countRxFailureFromSta1(0),
4883 m_countRxFailureFromSta2(0),
4884 m_countRxBytesFromSta1(0),
4885 m_countRxBytesFromSta2(0)
4886{
4887}
4888
4889void
4891 std::size_t index,
4892 std::size_t payloadSize,
4893 Time txDuration)
4894{
4895 WifiConstPsduMap psdus;
4896
4897 WifiTxVector txVector{HePhy::GetHeMcs7(),
4898 0,
4900 NanoSeconds(1600),
4901 1,
4902 1,
4903 0,
4905 false,
4906 false,
4907 true};
4908
4909 HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4910 txVector.SetRu(ru, txStaId);
4911 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4912 txVector.SetNss(1, txStaId);
4913
4914 auto pkt = Create<Packet>(payloadSize);
4915 WifiMacHeader hdr;
4917 hdr.SetQosTid(0);
4918 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4919 std::ostringstream addr;
4920 addr << "00:00:00:00:00:0" << txStaId;
4921 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4922 hdr.SetSequenceNumber(1);
4923 auto psdu = Create<WifiPsdu>(pkt, hdr);
4924 psdus.insert(std::make_pair(txStaId, psdu));
4925
4927 if (txStaId == 1)
4928 {
4929 phy = m_phySta1;
4930 }
4931 else if (txStaId == 2)
4932 {
4933 phy = m_phySta2;
4934 }
4935
4936 txVector.SetLength(
4937 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4938
4939 phy->SetPpduUid(0);
4940 phy->Send(psdus, txVector);
4941}
4942
4943void
4945{
4946 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
4947 m_phyInterferer->SetPeriod(duration);
4948 m_phyInterferer->Start();
4950}
4951
4952void
4957
4961
4962void
4964 RxSignalInfo rxSignalInfo,
4965 const WifiTxVector& txVector,
4966 const std::vector<bool>& /*statusPerMpdu*/)
4967{
4968 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
4969 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4970 {
4972 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
4973 }
4974 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4975 {
4977 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
4978 }
4979}
4980
4981void
4983{
4984 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
4985 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4986 {
4988 }
4989 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4990 {
4992 }
4993}
4994
4995void
4997 uint32_t expectedFailures,
4998 uint32_t expectedBytes)
4999{
5001 expectedSuccess,
5002 "The number of successfully received packets from STA 1 is not correct!");
5005 expectedFailures,
5006 "The number of unsuccessfuly received packets from STA 1 is not correct!");
5008 expectedBytes,
5009 "The number of bytes received from STA 1 is not correct!");
5010}
5011
5012void
5014 uint32_t expectedFailures,
5015 uint32_t expectedBytes)
5016{
5018 expectedSuccess,
5019 "The number of successfully received packets from STA 2 is not correct!");
5022 expectedFailures,
5023 "The number of unsuccessfuly received packets from STA 2 is not correct!");
5025 expectedBytes,
5026 "The number of bytes received from STA 2 is not correct!");
5027}
5028
5029void
5031{
5033 nullptr,
5034 "m_currentEvent for AP was not cleared");
5036 nullptr,
5037 "m_currentEvent for STA 1 was not cleared");
5039 nullptr,
5040 "m_currentEvent for STA 2 was not cleared");
5041}
5042
5043void
5045{
5046 // This is needed to make sure PHY state will be checked as the last event if a state change
5047 // occurred at the exact same time as the check
5049}
5050
5051void
5053{
5054 WifiPhyState currentState = phy->GetState()->GetState();
5055 NS_LOG_FUNCTION(this << currentState);
5056 NS_TEST_ASSERT_MSG_EQ(currentState,
5057 expectedState,
5058 "PHY State " << currentState << " does not match expected state "
5059 << expectedState << " at " << Simulator::Now());
5060}
5061
5062void
5075
5076void
5078{
5081 int64_t streamNumber = 0;
5082
5085 lossModel->SetFrequency(MHzToHz(DEFAULT_FREQUENCY));
5086 spectrumChannel->AddPropagationLossModel(lossModel);
5089 spectrumChannel->SetPropagationDelayModel(delayModel);
5090
5091 Ptr<Node> apNode = CreateObject<Node>();
5094 "Txop",
5095 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
5096 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5097 apDev->SetMac(apMac);
5100 apDev->SetHeConfiguration(heConfiguration);
5102 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5104 m_phyAp->SetErrorRateModel(apErrorModel);
5105 m_phyAp->SetDevice(apDev);
5106 m_phyAp->AddChannel(spectrumChannel);
5108 m_phyAp->AssignStreams(streamNumber);
5109 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
5114 ->number;
5115
5121 m_phyAp->SetMobility(apMobility);
5122 apDev->SetPhy(m_phyAp);
5123 apDev->SetStandard(WIFI_STANDARD_80211ax);
5124 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5125 apMac->SetWifiPhys({m_phyAp});
5126 apNode->AggregateObject(apMobility);
5127 apNode->AddDevice(apDev);
5128
5129 Ptr<Node> sta1Node = CreateObject<Node>();
5133 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5135 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5136 m_phySta1->SetDevice(sta1Dev);
5137 m_phySta1->AddChannel(spectrumChannel);
5139 m_phySta1->AssignStreams(streamNumber);
5143 m_phySta1->SetMobility(sta1Mobility);
5144 sta1Dev->SetPhy(m_phySta1);
5145 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
5146 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5147 sta1Node->AggregateObject(sta1Mobility);
5148 sta1Node->AddDevice(sta1Dev);
5149
5150 Ptr<Node> sta2Node = CreateObject<Node>();
5154 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5156 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5157 m_phySta2->SetDevice(sta2Dev);
5158 m_phySta2->AddChannel(spectrumChannel);
5160 m_phySta2->AssignStreams(streamNumber);
5164 m_phySta2->SetMobility(sta2Mobility);
5165 sta2Dev->SetPhy(m_phySta2);
5166 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
5167 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5168 sta2Node->AggregateObject(sta2Mobility);
5169 sta2Node->AddDevice(sta2Dev);
5170
5171 Ptr<Node> interfererNode = CreateObject<Node>();
5174 m_phyInterferer->SetDevice(interfererDev);
5175 m_phyInterferer->SetChannel(spectrumChannel);
5176 m_phyInterferer->SetDutyCycle(1);
5177 interfererNode->AddDevice(interfererDev);
5178}
5179
5180void
5182{
5183 m_phyAp->Dispose();
5184 m_phyAp = nullptr;
5185 m_phySta1->Dispose();
5186 m_phySta1 = nullptr;
5187 m_phySta2->Dispose();
5188 m_phySta2 = nullptr;
5190 m_phyInterferer = nullptr;
5191}
5192
5193void
5195{
5196 WifiTxVector trigVector{HePhy::GetHeMcs7(),
5197 0,
5199 NanoSeconds(1600),
5200 1,
5201 1,
5202 0,
5204 false,
5205 false,
5206 true};
5207 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5208 trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5209 trigVector.SetNss(1, 1);
5210 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5211 trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5212 trigVector.SetNss(1, 2);
5213 uint16_t length;
5214 std::tie(length, ppduDuration) =
5216 trigVector.SetLength(length);
5218 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5219}
5220
5221void
5223{
5224 Time expectedPpduDuration = NanoSeconds(292800);
5225 Time ppduWithPaddingDuration =
5226 expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5227
5229
5230 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5233 this,
5234 1,
5235 1,
5236 1000,
5237 ppduWithPaddingDuration);
5240 this,
5241 2,
5242 2,
5243 1001,
5244 ppduWithPaddingDuration);
5245
5246 // Set TRIGVECTOR on AP
5249 this,
5250 ppduWithPaddingDuration);
5251
5252 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5253 Simulator::Schedule(Seconds(1) + ppduWithPaddingDuration - NanoSeconds(1),
5255 this,
5256 m_phyAp,
5257 WifiPhyState::RX);
5258 Simulator::Schedule(Seconds(1) + ppduWithPaddingDuration,
5260 this,
5261 m_phyAp,
5262 WifiPhyState::IDLE);
5263
5264 // One PSDU of 1000 bytes should have been successfully received from STA 1
5266 // One PSDU of 1001 bytes should have been successfully received from STA 2
5268 // Verify events data have been cleared
5270
5272
5273 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5276 this,
5277 1,
5278 1,
5279 1000,
5280 ppduWithPaddingDuration);
5283 this,
5284 2,
5285 2,
5286 1001,
5287 ppduWithPaddingDuration);
5288
5289 // Set TRIGVECTOR on AP
5292 this,
5293 ppduWithPaddingDuration);
5294
5295 // A strong non-wifi interference is generated on RU 1 during padding reception
5296 BandInfo bandInfo;
5298 bandInfo.fl = bandInfo.fc - MHzToHz(DEFAULT_CHANNEL_WIDTH / 4);
5299 bandInfo.fh = bandInfo.fc + MHzToHz(DEFAULT_CHANNEL_WIDTH / 4);
5300 Bands bands;
5301 bands.push_back(bandInfo);
5302
5303 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5304 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5305 Watt_u interferencePower{0.1};
5306 *interferencePsdRu1 = interferencePower / (MHzToHz(DEFAULT_CHANNEL_WIDTH / 2) * 20);
5307
5308 Simulator::Schedule(Seconds(2) + MicroSeconds(50) + expectedPpduDuration,
5310 this,
5311 interferencePsdRu1,
5312 MilliSeconds(100));
5313
5314 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5315 // CCA_BUSY instead of IDLE due to the interference)
5316 Simulator::Schedule(Seconds(2) + ppduWithPaddingDuration - NanoSeconds(1),
5318 this,
5319 m_phyAp,
5320 WifiPhyState::RX);
5321 Simulator::Schedule(Seconds(2) + ppduWithPaddingDuration,
5323 this,
5324 m_phyAp,
5325 WifiPhyState::CCA_BUSY);
5326
5327 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5328 // occupies RU 1 after payload, during PHY padding)
5330 // One PSDU of 1001 bytes should have been successfully received from STA 2
5332 // Verify events data have been cleared
5334
5336
5338
5340}
5341
5342/**
5343 * @ingroup wifi-test
5344 * @ingroup tests
5345 *
5346 * @brief UL-OFDMA power control test
5347 */
5349{
5350 public:
5352 ~TestUlOfdmaPowerControl() override;
5353
5354 private:
5355 void DoSetup() override;
5356 void DoTeardown() override;
5357 void DoRun() override;
5358
5359 /**
5360 * Send a MU BAR through the AP to the STAs listed in the provided vector.
5361 *
5362 * @param staIds the vector of STA-IDs of STAs to address the MU-BAR to
5363 */
5364 void SendMuBar(std::vector<uint16_t> staIds);
5365
5366 /**
5367 * Send a QoS Data packet to the destination station in order
5368 * to set up a block Ack session (so that the MU-BAR may have a reply).
5369 *
5370 * @param destination the address of the destination station
5371 */
5372 void SetupBa(Address destination);
5373
5374 /**
5375 * Run one simulation with an optional BA session set up phase.
5376 *
5377 * @param setupBa true if BA session should be set up (i.e. upon first run),
5378 * false otherwise
5379 */
5380 void RunOne(bool setupBa);
5381
5382 /**
5383 * Replace the AP's callback on its PHY's ReceiveOkCallback
5384 * by the ReceiveOkCallbackAtAp method.
5385 */
5387
5388 /**
5389 * Receive OK callback function at AP.
5390 * This method will be plugged into the AP PHY's ReceiveOkCallback once the
5391 * block Ack session has been set up. This is done in the Reset function.
5392 * @param psdu the PSDU
5393 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
5394 * @param txVector the TXVECTOR used for the packet
5395 * @param statusPerMpdu reception status per MPDU
5396 */
5398 RxSignalInfo rxSignalInfo,
5399 const WifiTxVector& txVector,
5400 const std::vector<bool>& statusPerMpdu);
5401
5402 uint8_t m_bssColor; ///< BSS color
5403
5404 Ptr<WifiNetDevice> m_apDev; ///< network device of AP
5405 Ptr<WifiNetDevice> m_sta1Dev; ///< network device of STA 1
5406 Ptr<WifiNetDevice> m_sta2Dev; ///< network device of STA 2
5407
5409
5410 dBm_u m_txPowerAp; ///< transmit power of AP
5411 dBm_u m_txPowerStart; ///< minimum transmission power for STAs
5412 dBm_u m_txPowerEnd; ///< maximum transmission power for STAs
5413 uint8_t m_txPowerLevels; ///< number of transmission power levels for STAs
5414
5415 dBm_u m_requestedRssiSta1; ///< requested RSSI from STA 1 at AP for HE TB PPDUs
5416 dBm_u m_requestedRssiSta2; ///< requested RSSI from STA 2 at AP for HE TB PPDUs
5417
5418 dBm_u m_rssiSta1; ///< expected RSSI from STA 1 at AP for HE TB PPDUs
5419 dBm_u m_rssiSta2; ///< expected RSSI from STA 2 at AP for HE TB PPDUs
5420
5421 dB_u m_tol; ///< tolerance between received and expected RSSIs
5422};
5423
5425 : TestCase("UL-OFDMA power control test"),
5426 m_bssColor(1),
5427 m_txPowerAp(dBm_u{0}),
5428 m_txPowerStart(dBm_u{0}),
5429 m_txPowerEnd(dBm_u{0}),
5430 m_txPowerLevels(0),
5431 m_requestedRssiSta1(dBm_u{0}),
5432 m_requestedRssiSta2(dBm_u{0}),
5433 m_rssiSta1(dBm_u{0}),
5434 m_rssiSta2(dBm_u{0}),
5435 m_tol(dB_u{0.1})
5436{
5437}
5438
5440{
5441 m_phyAp = nullptr;
5442 m_apDev = nullptr;
5443 m_sta1Dev = nullptr;
5444 m_sta2Dev = nullptr;
5445}
5446
5447void
5449{
5450 // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5451 Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5452 m_apDev->Send(pkt, destination, 0);
5453}
5454
5455void
5456TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5457{
5458 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5459
5460 // Build MU-BAR trigger frame
5461 CtrlTriggerHeader muBar;
5462 muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5463 muBar.SetMoreTF(true);
5464 muBar.SetCsRequired(true);
5466 muBar.SetGiAndLtfType(NanoSeconds(1600), 2);
5467 muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5468 muBar.SetUlSpatialReuse(60500);
5469
5470 HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5471 std::size_t index = 1;
5472 int8_t ulTargetRssi = -40; // will be overwritten
5473 for (const auto& staId : staIds)
5474 {
5476 ui.SetAid12(staId);
5477 ui.SetRuAllocation({ru, index, true});
5478 ui.SetUlFecCodingType(true);
5479 ui.SetUlMcs(7);
5480 ui.SetUlDcm(false);
5481 ui.SetSsAllocation(1, 1);
5482 if (staId == 1)
5483 {
5484 ulTargetRssi = m_requestedRssiSta1;
5485 }
5486 else if (staId == 2)
5487 {
5488 ulTargetRssi = m_requestedRssiSta2;
5489 }
5490 else
5491 {
5492 NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5493 }
5494 ui.SetUlTargetRssi(ulTargetRssi);
5495
5498 bar.SetTidInfo(0);
5499 bar.SetStartingSequence(4095);
5501
5502 ++index;
5503 }
5504
5505 WifiTxVector tbTxVector{muBar.GetHeTbTxVector(staIds.front())};
5507 tbTxVector,
5509 .first);
5510
5511 WifiConstPsduMap psdus;
5512 WifiTxVector txVector{HePhy::GetHeMcs7(),
5513 0,
5515 NanoSeconds(800),
5516 1,
5517 1,
5518 0,
5520 false,
5521 false,
5522 false,
5523 m_bssColor};
5524
5525 auto bar = Create<Packet>();
5526 bar->AddHeader(muBar);
5527
5528 auto receiver = Mac48Address::GetBroadcast();
5529 if (staIds.size() == 1)
5530 {
5531 const auto aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5532 if (staIds.front() == aidSta1)
5533 {
5534 receiver = Mac48Address::ConvertFrom(m_sta1Dev->GetAddress());
5535 }
5536 else
5537 {
5538 NS_ASSERT(staIds.front() ==
5539 DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5540 receiver = Mac48Address::ConvertFrom(m_sta2Dev->GetAddress());
5541 }
5542 }
5543
5544 WifiMacHeader hdr;
5546 hdr.SetAddr1(receiver);
5547 hdr.SetAddr2(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5548 hdr.SetAddr3(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5549 hdr.SetDsNotTo();
5550 hdr.SetDsFrom();
5551 hdr.SetNoRetry();
5552 hdr.SetNoMoreFragments();
5553 auto psdu = Create<WifiPsdu>(bar, hdr);
5554
5555 auto nav = m_apDev->GetPhy()->GetSifs();
5556 const auto staId = staIds.front(); // either will do
5557 nav += SpectrumWifiPhy::CalculateTxDuration(GetBlockAckSize(BlockAckType::COMPRESSED),
5558 tbTxVector,
5560 staId);
5561 psdu->SetDuration(nav);
5562 psdus.insert(std::make_pair(SU_STA_ID, psdu));
5563
5564 m_phyAp->Send(psdus, txVector);
5565}
5566
5567void
5569 RxSignalInfo rxSignalInfo,
5570 const WifiTxVector& txVector,
5571 const std::vector<bool>& /*statusPerMpdu*/)
5572{
5573 NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5574 const auto rssi = rxSignalInfo.rssi;
5575 NS_ASSERT(psdu->GetNMpdus() == 1);
5576 const auto& hdr = psdu->GetHeader(0);
5577 NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5578 if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5579 {
5581 rssi,
5582 m_rssiSta1,
5583 m_tol,
5584 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5585 << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5586 }
5587 else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5588 {
5590 rssi,
5591 m_rssiSta2,
5592 m_tol,
5593 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5594 << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5595 }
5596 else
5597 {
5598 NS_ABORT_MSG("The receiver address is unknown");
5599 }
5600}
5601
5602void
5604{
5605 // Now that BA session has been established we can plug our method
5606 m_phyAp->SetReceiveOkCallback(
5608}
5609
5610void
5612{
5613 auto apNode = CreateObject<Node>();
5614 NodeContainer staNodes;
5615 staNodes.Create(2);
5616
5617 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5619 spectrumChannel->AddPropagationLossModel(lossModel);
5621 spectrumChannel->SetPropagationDelayModel(delayModel);
5622
5623 SpectrumWifiPhyHelper spectrumPhy;
5624 spectrumPhy.SetChannel(spectrumChannel);
5625 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5626 spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5627
5628 WifiHelper wifi;
5629 wifi.SetStandard(WIFI_STANDARD_80211ax);
5630 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5631 "DataMode",
5632 StringValue("HeMcs7"),
5633 "ControlMode",
5634 StringValue("HeMcs7"));
5635
5636 WifiMacHelper mac;
5637 mac.SetType("ns3::StaWifiMac");
5638 auto staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5639 WifiHelper::AssignStreams(staDevs, 0);
5640 m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5642 m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5644
5645 // Set the beacon interval long enough so that associated STAs may not consider link lost when
5646 // beacon generation is disabled during the actual tests. Having such a long interval also
5647 // avoids bloating logs with beacons during the set up phase.
5648 mac.SetType("ns3::ApWifiMac",
5649 "BeaconGeneration",
5650 BooleanValue(true),
5651 "BeaconInterval",
5652 TimeValue(MicroSeconds(1024 * 600)));
5653 m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5655 m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5658 // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5659 // set up for both STAs
5660
5661 MobilityHelper mobility;
5662 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5663 auto positionAlloc = CreateObject<ListPositionAllocator>();
5664 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5665 positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5666 positionAlloc->Add(
5667 Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5668 mobility.SetPositionAllocator(positionAlloc);
5669
5670 mobility.Install(apNode);
5671 mobility.Install(staNodes);
5672
5673 lossModel->SetDefaultLoss(50.0);
5674 lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5675 staNodes.Get(1)->GetObject<MobilityModel>(),
5676 56.0,
5677 true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5678}
5679
5680void
5682{
5683 m_phyAp->Dispose();
5684 m_phyAp = nullptr;
5685 m_apDev->Dispose();
5686 m_apDev = nullptr;
5687 m_sta1Dev->Dispose();
5688 m_sta1Dev = nullptr;
5689 m_sta2Dev->Dispose();
5690 m_sta2Dev = nullptr;
5691}
5692
5693void
5695{
5698 int64_t streamNumber = 0;
5699
5700 auto phySta1 = m_sta1Dev->GetPhy();
5701 auto phySta2 = m_sta2Dev->GetPhy();
5702
5703 m_phyAp->AssignStreams(streamNumber);
5704 phySta1->AssignStreams(streamNumber);
5705 phySta2->AssignStreams(streamNumber);
5706
5707 m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5708 m_phyAp->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerAp));
5709 m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5710
5711 phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5712 phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5713 phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5714
5715 phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5716 phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5717 phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5718
5719 Time relativeStart{};
5720 if (setupBa)
5721 {
5722 // Set up BA for each station once the association phase has ended
5723 // so that a BA session is established when the MU-BAR is received.
5726 this,
5727 m_sta1Dev->GetAddress());
5730 this,
5731 m_sta2Dev->GetAddress());
5732 relativeStart = MilliSeconds(1000);
5733 }
5734 else
5735 {
5736 auto apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5737 NS_ASSERT(apMac);
5738 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5739 }
5740
5741 Simulator::Schedule(relativeStart,
5743 this);
5744
5745 {
5746 // Verify that the RSSI from STA 1 is consistent with what was requested
5747 std::vector<uint16_t> staIds{1};
5748 Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5749 }
5750
5751 {
5752 // Verify that the RSSI from STA 2 is consistent with what was requested
5753 std::vector<uint16_t> staIds{2};
5754 Simulator::Schedule(relativeStart + MilliSeconds(20),
5756 this,
5757 staIds);
5758 }
5759
5760 {
5761 // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5762 std::vector<uint16_t> staIds{1, 2};
5763 Simulator::Schedule(relativeStart + MilliSeconds(40),
5765 this,
5766 staIds);
5767 }
5768
5769 Simulator::Stop(relativeStart + MilliSeconds(100));
5771}
5772
5773void
5775{
5776 // Power configurations
5777 m_txPowerAp = dBm_u{20}; // so as to have -30 and -36 dBm at STA 1 and STA 2 resp., since path
5778 // loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5779 m_txPowerStart = dBm_u{15};
5780
5781 // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5784
5785 // Test single power level
5786 {
5787 // STA power configurations: 15 dBm only
5788 m_txPowerEnd = dBm_u{15};
5789 m_txPowerLevels = 1;
5790
5791 // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5792 // regardless of the estimated path loss.
5793 m_rssiSta1 = dBm_u{-35}; // 15 dBm - 50 dB
5794 m_rssiSta2 = dBm_u{-41}; // 15 dBm - 56 dB
5795
5796 RunOne(true);
5797 }
5798
5799 // Test 2 dBm granularity
5800 {
5801 // STA power configurations: [15:2:25] dBm
5802 m_txPowerEnd = dBm_u{25};
5803 m_txPowerLevels = 6;
5804
5805 // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5806 // requested
5807 m_rssiSta1 = dBm_u{-29}; // 21 dBm - 50 dB
5808 m_rssiSta2 = dBm_u{-35}; // 21 dBm - 50 dB
5809
5810 RunOne(false);
5811 }
5812
5813 // Test 1 dBm granularity
5814 {
5815 // STA power configurations: [15:1:25] dBm
5816 m_txPowerEnd = dBm_u{25};
5817 m_txPowerLevels = 11;
5818
5819 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5820 m_rssiSta1 = dBm_u{-30}; // 20 dBm - 50 dB
5821 m_rssiSta2 = dBm_u{-36}; // 20 dBm - 56 dB
5822
5823 RunOne(false);
5824 }
5825
5826 // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5827 {
5828 // STA power configurations: [15:1:25] dBm
5829 m_txPowerEnd = dBm_u{25};
5830 m_txPowerLevels = 11;
5831
5832 // Requested UL RSSIs
5834 dBm_u{-28}; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5835 m_requestedRssiSta2 = dBm_u{-37}; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5836
5837 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5838 m_rssiSta1 = dBm_u{-28}; // 22 dBm - 50 dB
5839 m_rssiSta2 = dBm_u{-37}; // 19 dBm - 56 dB
5840
5841 RunOne(false);
5842 }
5843
5845}
5846
5847/**
5848 * @ingroup wifi-test
5849 * @ingroup tests
5850 *
5851 * @brief wifi PHY OFDMA Test Suite
5852 */
5854{
5855 public:
5857};
5858
5860 : TestSuite("wifi-phy-ofdma", Type::UNIT)
5861{
5862 AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5863 AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::Duration::QUICK);
5864 AddTestCase(new TestUlOfdmaPpduUid, TestCase::Duration::QUICK);
5865 AddTestCase(new TestMultipleHeTbPreambles, TestCase::Duration::QUICK);
5866 AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5867 AddTestCase(new TestPhyPaddingExclusion, TestCase::Duration::QUICK);
5868 AddTestCase(new TestUlOfdmaPowerControl, TestCase::Duration::QUICK);
5869}
5870
SpectrumWifiPhy used for testing OFDMA.
void SetTriggerFrameUid(uint64_t uid)
Since we assume trigger frame was previously received from AP, this is used to set its UID.
Ptr< const HePhy > GetHePhy() const
void(* TxPpduUidCallback)(uint64_t uid)
TracedCallback signature for UID of transmitted PPDU.
void SetPpduUid(uint64_t uid)
Set the global PPDU UID counter.
static TypeId GetTypeId()
Get the type ID.
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents()
Ptr< OfdmaTestHePhy > m_ofdmTestHePhy
Pointer to HE PHY instance used for OFDMA test.
void StartTx(Ptr< const WifiPpdu > ppdu) override
void DoDispose() override
Destructor implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
void Reset()
Reset data upon end of TX or RX.
Definition wifi-phy.cc:1967
TracedCallback< uint64_t > m_phyTxPpduUidTrace
Callback providing UID of the PPDU that is about to be transmitted.
void DoInitialize() override
Initialize() implementation.
Time GetEnergyDuration(Watt_u energy, WifiSpectrumBandInfo band)
Wrapper to InterferenceHelper method.
HE PHY slightly modified so as to return a given STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
OfdmaTestHePhy(uint16_t staId)
Constructor.
void SetGlobalPpduUid(uint64_t uid)
Set the global PPDU UID counter.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
uint16_t m_staId
ID of the STA to which this PHY belongs to.
PHY listener for OFDMA tests.
OfdmaTestPhyListener()=default
void NotifyRxEndError() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
bool m_lastRxSuccess
flag whether last RX has been successful
void NotifyRxStart(Time duration) override
Time GetLastRxStartNotification() const
Return the time at which the last RX start notification has been received.
void NotifySwitchingStart(Time duration) override
void NotifyWakeup() override
Notify listeners that we woke up.
uint32_t m_notifyRxStart
count number of RX start notifications
void Reset()
Reset function.
Time m_lastRxEnd
last time a RX end notification has been received
Time m_lastRxStart
last time a RX start notification has been received
Time GetLastRxEndNotification() const
Return the time at which the last RX end notification has been received.
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &) override
uint32_t m_notifyRxEnd
count number of RX end notifications
bool IsLastRxSuccess() const
Return whether last RX has been successful.
void NotifySleep() override
Notify listeners that we went to sleep.
uint32_t GetNumRxEndNotifications() const
Return the number of RX end notifications that has been received since the last reset.
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyTxStart(Time duration, dBm_u txPower) override
uint32_t GetNumRxStartNotifications() const
Return the number of RX start notifications that has been received since the last reset.
void NotifyOff() override
Notify listeners that we went to switch off.
void NotifyOn() override
Notify listeners that we went to switch on.
DL-OFDMA PHY puncturing test.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void DoRun() override
Implementation to actually run this TestCase.
Time m_expectedPpduDuration20Mhz
expected duration to send MU PPDU on 20 MHz RU
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
void ResetResults()
Reset the results.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
void RunOne()
Run one function.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2, const std::vector< bool > &puncturedSubchannels)
Send MU-PPDU function.
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 2.
Time m_expectedPpduDuration40Mhz
expected duration to send MU PPDU on 40 MHz RU
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void StopInterference()
Stop interference function.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 1.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint8_t m_indexSubchannel
Index of the subchannel (starting from 0) that should contain an interference and be punctured during...
uint32_t m_countRxSuccessSta1
count RX success for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 2.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
void RunOne()
Run one function.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 1.
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Time m_expectedPpduDuration
expected duration to send MU PPDU
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void RxSuccessSta3(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 3.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
uint32_t m_countRxSuccessSta3
count RX success for STA 3
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
uint32_t m_countRxBytesSta3
count RX bytes for STA 3
void RxFailureSta3(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 3.
void StopInterference()
Stop interference function.
void ResetResults()
Reset the results.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxSuccessSta1
count RX success for STA 1
void CheckResultsSta3(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 3.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
Send MU-PPDU function.
UL-OFDMA multiple RX events test.
WifiTxVector m_trigVector
TRIGVECTOR.
void RxHeTbPpdu(uint64_t uid, uint16_t staId, Watt_u txPower, size_t payloadSize)
Receive HE TB PPDU function.
Ptr< OfdmaSpectrumWifiPhy > m_phy
Phy.
void RxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void CheckHeTbPreambles(size_t nEvents, std::vector< uint64_t > uids)
Check the received HE TB preambles.
uint64_t m_totalBytesDropped
total number of dropped bytes
void CheckBytesDropped(size_t expectedBytesDropped)
Check the number of bytes dropped.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
PHY padding exclusion test.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
void DoRun() override
Implementation to actually run this TestCase.
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
void SetTrigVector(Time ppduDuration)
Set TRIGVECTOR for HE TB PPDU.
void Reset()
Reset function.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
void StopInterference()
Stop interference function.
void RunOne()
Run one function.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void ScheduleTest(Time delay, bool solicited, WifiPhyState expectedStateAtEnd, uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1, uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2, bool scheduleTxSta1=true, Time ulTimeDifference=Seconds(0), WifiPhyState expectedStateBeforeEnd=WifiPhyState::RX, TrigVectorInfo error=NONE)
Schedule test to perform.
std::shared_ptr< OfdmaTestPhyListener > m_apPhyStateListener
listener for AP PHY state transitions
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId, std::size_t index, uint8_t bssColor) const
Get TXVECTOR for HE TB PPDU.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification)
Check the the number of RX start notifications at the AP as well as the last time a RX start has been...
TrigVectorInfo
Erroneous info included in a TRIGVECTOR.
void SetBssColor(Ptr< WifiPhy > phy, uint8_t bssColor)
Set the BSS color.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void LogScenario(std::string log) const
Log scenario description.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor, bool incrementUid)
Send HE TB PPDU function.
void DoRun() override
Implementation to actually run this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void StopInterference()
Stop interference function.
void CheckOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, Watt_u expectedRxPower)
Check the received power for the OFDMA part of the HE TB PPDUs over the given band.
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void SetPsdLimit(Ptr< WifiPhy > phy, dBm_per_MHz_u psdLimit)
Set the PSD limit.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
void RunOne()
Run one function.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void CheckApRxEnd(uint32_t expectedNotifications, Time expectedLastNotification, bool expectedSuccess)
Check the the number of RX end notifications at the AP as well as the last time a RX end has been not...
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
void CheckNonOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, Watt_u expectedRxPower)
Check the received power for the non-OFDMA of the HE TB PPDUs over the given band.
void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE SU PPDU function.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void SetTrigVector(uint8_t bssColor, TrigVectorInfo error)
Set TRIGVECTOR for HE TB PPDU.
void SchedulePowerMeasurementChecks(Time delay, Watt_u rxPowerNonOfdmaRu1, Watt_u rxPowerNonOfdmaRu2, Watt_u rxPowerOfdmaRu1, Watt_u rxPowerOfdmaRu2)
Schedule power measurement related checks.
Time m_expectedPpduDuration
expected duration to send MU PPDU
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
UL-OFDMA power control test.
dBm_u m_requestedRssiSta2
requested RSSI from STA 2 at AP for HE TB PPDUs
void DoRun() override
Implementation to actually run this TestCase.
Ptr< WifiNetDevice > m_sta2Dev
network device of STA 2
dBm_u m_rssiSta2
expected RSSI from STA 2 at AP for HE TB PPDUs
dBm_u m_txPowerEnd
maximum transmission power for STAs
dBm_u m_txPowerStart
minimum transmission power for STAs
void SetupBa(Address destination)
Send a QoS Data packet to the destination station in order to set up a block Ack session (so that the...
Ptr< WifiNetDevice > m_sta1Dev
network device of STA 1
dBm_u m_rssiSta1
expected RSSI from STA 1 at AP for HE TB PPDUs
Ptr< WifiNetDevice > m_apDev
network device of AP
dBm_u m_requestedRssiSta1
requested RSSI from STA 1 at AP for HE TB PPDUs
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void ReplaceReceiveOkCallbackOfAp()
Replace the AP's callback on its PHY's ReceiveOkCallback by the ReceiveOkCallbackAtAp method.
dBm_u m_txPowerAp
transmit power of AP
uint8_t m_txPowerLevels
number of transmission power levels for STAs
dB_u m_tol
tolerance between received and expected RSSIs
void RunOne(bool setupBa)
Run one simulation with an optional BA session set up phase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void ReceiveOkCallbackAtAp(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive OK callback function at AP.
void SendMuBar(std::vector< uint16_t > staIds)
Send a MU BAR through the AP to the STAs listed in the provided vector.
UL-OFDMA PPDU UID attribution test.
void TxPpduSta1(uint64_t uid)
Transmitted PPDU information function for STA 1.
void ResetPpduUid()
Reset the global PPDU UID counter in WifiPhy.
void CheckUid(uint16_t staId, uint64_t expectedUid)
Check the UID of the transmitted PPDU.
void TxPpduAp(uint64_t uid)
Transmitted PPDU information function for AP.
void TxPpduSta2(uint64_t uid)
Transmitted PPDU information function for STA 2.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
uint64_t m_ppduUidAp
UID of PPDU transmitted by AP.
uint64_t m_ppduUidSta1
UID of PPDU transmitted by STA1.
uint64_t m_ppduUidSta2
UID of PPDU transmitted by STA2.
void DoRun() override
Implementation to actually run this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu()
Send MU-PPDU toward both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendTbPpdu()
Send TB-PPDU from both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
void SendSuPpdu(uint16_t txStaId)
Send SU-PPDU function.
wifi PHY OFDMA Test Suite
a polymophic address class
Definition address.h:90
AttributeValue implementation for Boolean.
Definition boolean.h:26
Headers for BlockAckRequest.
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
Headers for Trigger frames.
CtrlTriggerUserInfoField & AddUserInfoField()
Append a new User Info field to this Trigger frame and return a non-const reference to it.
void SetApTxPower(int8_t power)
Set the AP TX Power subfield of the Common Info field.
WifiTxVector GetHeTbTxVector(uint16_t staId) const
Get the TX vector that the station with the given STA-ID will use to send the HE TB PPDU solicited by...
void SetType(TriggerFrameType type)
Set the Trigger frame type.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse subfield of the Common Info field.
void SetGiAndLtfType(Time guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
void SetMoreTF(bool more)
Set the More TF subfield of the Common Info field.
void SetUlBandwidth(MHz_u bw)
Set the bandwidth of the solicited HE TB PPDU.
User Info field of Trigger frames.
void SetAid12(uint16_t aid)
Set the AID12 subfield, which carries the 12 LSBs of the AID of the station for which this User Info ...
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
void SetUlMcs(uint8_t mcs)
Set the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
void SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader &bar)
Set the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlDcm(bool dcm)
Set the UL DCM subfield, which indicates whether or not DCM is used.
void SetSsAllocation(uint8_t startingSs, uint8_t nSs)
Set the SS Allocation subfield, which is present when the AID12 subfield is neither 0 nor 2045.
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
void SetRuAllocation(HeRu::RuSpec ru)
Set the RU Allocation subfield according to the specified RU.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
PHY entity for HE (11ax)
Definition he-phy.h:58
static WifiMode GetHeMcs9()
Return MCS 9 from HE MCS values.
static WifiMode GetHeMcs7()
Return MCS 7 from HE MCS values.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
Definition he-phy.cc:565
static std::pair< uint16_t, Time > ConvertHeTbPpduDurationToLSigLength(Time ppduDuration, const WifiTxVector &txVector, WifiPhyBand band)
Compute the L-SIG length value corresponding to the given HE TB PPDU duration.
Definition he-phy.cc:261
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Definition he-ppdu.h:106
@ PSD_NON_HE_PORTION
Non-HE portion of an HE PPDU.
Definition he-ppdu.h:105
RU Specification.
Definition he-ru.h:57
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition he-ru.cc:756
RuType
The different HE Resource Unit (RU) types.
Definition he-ru.h:32
@ RU_484_TONE
Definition he-ru.h:37
@ RU_996_TONE
Definition he-ru.h:38
@ RU_106_TONE
Definition he-ru.h:35
@ RU_242_TONE
Definition he-ru.h:36
an EUI-48 address
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
void Dispose()
Dispose of this Object.
Definition object.cc:247
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition phy-entity.cc:82
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition phy-entity.h:974
AttributeValue implementation for Pointer.
Ptr< T > Get() const
Definition pointer.h:223
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
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:595
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
AttributeValue implementation for Time.
Definition nstime.h:1432
Forward calls to a chain of Callback.
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
Implements the IEEE 802.11 MAC header.
void SetNoMoreFragments()
Un-set the More Fragment bit in the Frame Control Field.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetDsFrom()
Set the From DS bit in the Frame Control field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetNoRetry()
Un-set the Retry bit in the Frame Control field.
create MAC layers for a ns3::WifiNetDevice.
void Set(std::string name, const AttributeValue &v)
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition wifi-phy.cc:678
void Send(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
This function is a wrapper for the Send variant that accepts a WifiConstPsduMap as first argument.
Definition wifi-phy.cc:1820
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition wifi-phy.cc:687
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > m_currentPreambleEvents
store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is be...
Definition wifi-phy.h:1361
std::tuple< uint8_t, MHz_u, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying a segment of an operating channel.
Definition wifi-phy.h:940
static Time GetPreambleDetectionDuration()
Definition wifi-phy.cc:1528
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition wifi-phy.cc:484
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition wifi-phy.cc:1009
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1587
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition wifi-phy.h:1384
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition wifi-phy.cc:490
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition wifi-phy.cc:1069
Ptr< Event > m_currentEvent
Hold the current event.
Definition wifi-phy.h:1359
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:760
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition wifi-phy.h:1364
void SetOperatingChannel(const WifiPhyOperatingChannel &channel)
If the standard for this object has not been set yet, store the channel settings corresponding to the...
Definition wifi-phy.cc:1135
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition wifi-phy.cc:708
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition wifi-phy.cc:653
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition wifi-phy.h:1346
void SetReceiveOkCallback(RxOkCallback callback)
Definition wifi-phy.cc:478
void Reset()
Reset data upon end of TX or RX.
Definition wifi-phy.cc:1967
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition wifi-phy.cc:1081
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition wifi-phy.cc:775
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition wifi-phy.cc:2363
receive notifications about PHY events.
static ConstIterator FindFirst(uint8_t number, MHz_u frequency, MHz_u width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first frequency segment matching the specified parameters.
This objects implements the PHY state machine of the Wifi device.
static Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(const std::vector< MHz_u > &centerFrequencies, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, const std::vector< WifiSpectrumBandIndices > &ru)
Create a transmit power spectral density corresponding to the OFDMA part of HE TB PPDUs for a given R...
static Ptr< SpectrumValue > CreateHeOfdmTxPowerSpectralDensity(MHz_u centerFrequency, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, dBr_u minInnerBand=dBr_u{-20}, dBr_u minOuterband=dBr_u{-28}, dBr_u lowestPoint=dBr_u{-40}, const std::vector< bool > &puncturedSubchannels={})
Create a transmit power spectral density corresponding to OFDM High Efficiency (HE) (802....
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetRu(HeRu::RuSpec ru, uint16_t staId)
Set the RU specification for the STA-ID.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition test.h:327
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPhyBand
Identifies the PHY band.
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Definition first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
WifiPhyState
The state of the PHY layer.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
std::vector< BandInfo > Bands
Container of BandInfo.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
Definition wifi-utils.h:135
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_CTL_BACKRESP
@ WIFI_MAC_QOSDATA
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
Definition wifi-utils.cc:33
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
Definition wifi-utils.cc:60
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
Definition wifi-utils.h:110
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
std::vector< uint16_t > RuAllocation
9 bits RU_ALLOCATION per 20 MHz
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:72
dBm_u rssi
RSSI.
Definition wifi-types.h:74
WifiSpectrumBandInfo structure containing info about a spectrum band.
static const MHz_u DEFAULT_FREQUENCY
static WifiPhyOfdmaTestSuite wifiPhyOfdmaTestSuite
the test suite
static const uint8_t DEFAULT_CHANNEL_NUMBER
static const WifiPhyBand DEFAULT_WIFI_BAND
static const MHz_u DEFAULT_CHANNEL_WIDTH
static const MHz_u DEFAULT_GUARD_WIDTH