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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
18 */
19
20#include "ns3/ap-wifi-mac.h"
21#include "ns3/boolean.h"
22#include "ns3/constant-position-mobility-model.h"
23#include "ns3/ctrl-headers.h"
24#include "ns3/double.h"
25#include "ns3/he-configuration.h"
26#include "ns3/he-phy.h"
27#include "ns3/he-ppdu.h"
28#include "ns3/interference-helper.h"
29#include "ns3/log.h"
30#include "ns3/mobility-helper.h"
31#include "ns3/multi-model-spectrum-channel.h"
32#include "ns3/nist-error-rate-model.h"
33#include "ns3/node.h"
34#include "ns3/non-communicating-net-device.h"
35#include "ns3/pointer.h"
36#include "ns3/rng-seed-manager.h"
37#include "ns3/simulator.h"
38#include "ns3/spectrum-wifi-helper.h"
39#include "ns3/spectrum-wifi-phy.h"
40#include "ns3/sta-wifi-mac.h"
41#include "ns3/string.h"
42#include "ns3/test.h"
43#include "ns3/threshold-preamble-detection-model.h"
44#include "ns3/waveform-generator.h"
45#include "ns3/wifi-mac-header.h"
46#include "ns3/wifi-net-device.h"
47#include "ns3/wifi-phy-listener.h"
48#include "ns3/wifi-psdu.h"
49#include "ns3/wifi-spectrum-phy-interface.h"
50#include "ns3/wifi-spectrum-signal-parameters.h"
51#include "ns3/wifi-spectrum-value-helper.h"
52#include "ns3/wifi-utils.h"
53
54#include <algorithm>
55#include <iterator>
56#include <memory>
57
58using namespace ns3;
59
60NS_LOG_COMPONENT_DEFINE("WifiPhyOfdmaTest");
61
62static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
63static const uint32_t DEFAULT_FREQUENCY = 5180; // MHz
65static const uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
66static const uint16_t DEFAULT_GUARD_WIDTH =
67 DEFAULT_CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
68
69/**
70 * HE PHY slightly modified so as to return a given
71 * STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
72 */
73class OfdmaTestHePhy : public HePhy
74{
75 public:
76 /**
77 * Constructor
78 *
79 * \param staId the ID of the STA to which this PHY belongs to
80 */
81 OfdmaTestHePhy(uint16_t staId);
82 ~OfdmaTestHePhy() override;
83
84 /**
85 * Return the STA ID that has been assigned to the station this PHY belongs to.
86 * This is typically called for MU PPDUs, in order to pick the correct PSDU.
87 *
88 * \param ppdu the PPDU for which the STA ID is requested
89 * \return the STA ID
90 */
91 uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
92
93 /**
94 * Set the global PPDU UID counter.
95 *
96 * \param uid the value to which the global PPDU UID counter should be set
97 */
98 void SetGlobalPpduUid(uint64_t uid);
99
100 private:
101 uint16_t m_staId; ///< ID of the STA to which this PHY belongs to
102}; // class OfdmaTestHePhy
103
105 : HePhy(),
106 m_staId(staId)
107{
108}
109
111{
112}
113
114uint16_t
116{
117 if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
118 {
119 return m_staId;
120 }
121 return HePhy::GetStaId(ppdu);
122}
123
124void
126{
127 m_globalPpduUid = uid;
128}
129
130/**
131 * SpectrumWifiPhy used for testing OFDMA.
132 */
134{
135 public:
136 /**
137 * \brief Get the type ID.
138 * \return the object TypeId
139 */
140 static TypeId GetTypeId();
141 /**
142 * Constructor
143 *
144 * \param staId the ID of the STA to which this PHY belongs to
145 */
146 OfdmaSpectrumWifiPhy(uint16_t staId);
147 ~OfdmaSpectrumWifiPhy() override;
148
149 void DoInitialize() override;
150 void DoDispose() override;
151
152 using WifiPhy::Reset;
153 void StartTx(Ptr<const WifiPpdu> ppdu) override;
154
155 /**
156 * TracedCallback signature for UID of transmitted PPDU.
157 *
158 * \param uid the UID of the transmitted PPDU
159 */
160 typedef void (*TxPpduUidCallback)(uint64_t uid);
161
162 /**
163 * Set the global PPDU UID counter.
164 *
165 * \param uid the value to which the global PPDU UID counter should be set
166 */
167 void SetPpduUid(uint64_t uid);
168
169 /**
170 * Since we assume trigger frame was previously received from AP, this is used to set its UID
171 *
172 * \param uid the PPDU UID of the trigger frame
173 */
174 void SetTriggerFrameUid(uint64_t uid);
175
176 /**
177 * \return the current preamble events map
178 */
179 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
180 /**
181 * \return the current event
182 */
184
185 /**
186 * Wrapper to InterferenceHelper method.
187 *
188 * \param energyW the minimum energy (W) requested
189 * \param band identify the requested band
190 *
191 * \returns the expected amount of time the observed
192 * energy on the medium for a given band will
193 * be higher than the requested threshold.
194 */
195 Time GetEnergyDuration(double energyW, WifiSpectrumBandInfo band);
196
197 /**
198 * \return a const pointer to the HE PHY instance
199 */
201
202 private:
203 Ptr<OfdmaTestHePhy> m_ofdmTestHePhy; ///< Pointer to HE PHY instance used for OFDMA test
205 m_phyTxPpduUidTrace; //!< Callback providing UID of the PPDU that is about to be transmitted
206}; // class OfdmaSpectrumWifiPhy
207
208TypeId
210{
211 static TypeId tid =
212 TypeId("ns3::OfdmaSpectrumWifiPhy")
214 .SetGroupName("Wifi")
215 .AddTraceSource("TxPpduUid",
216 "UID of the PPDU to be transmitted",
218 "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
219 return tid;
220}
221
224{
225 m_ofdmTestHePhy = Create<OfdmaTestHePhy>(staId);
227}
228
230{
231}
232
233void
235{
236 // Replace HE PHY instance with test instance
239}
240
241void
243{
244 m_ofdmTestHePhy = nullptr;
246}
247
248void
250{
253}
254
255void
257{
259}
260
261void
263{
264 m_phyTxPpduUidTrace(ppdu->GetUid());
266}
267
268std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
270{
272}
273
276{
277 return m_currentEvent;
278}
279
280Time
282{
283 return m_interference->GetEnergyDuration(energyW, band);
284}
285
288{
289 return DynamicCast<const HePhy>(GetLatestPhyEntity());
290}
291
292/**
293 * \ingroup wifi-test
294 * \ingroup tests
295 *
296 * \brief DL-OFDMA PHY test
297 */
299{
300 public:
303
304 private:
305 void DoSetup() override;
306 void DoTeardown() override;
307 void DoRun() override;
308
309 /**
310 * Receive success function for STA 1
311 * \param psdu the PSDU
312 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
313 * \param txVector the transmit vector
314 * \param statusPerMpdu reception status per MPDU
315 */
317 RxSignalInfo rxSignalInfo,
318 WifiTxVector txVector,
319 std::vector<bool> statusPerMpdu);
320 /**
321 * Receive success function for STA 2
322 * \param psdu the PSDU
323 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
324 * \param txVector the transmit vector
325 * \param statusPerMpdu reception status per MPDU
326 */
328 RxSignalInfo rxSignalInfo,
329 WifiTxVector txVector,
330 std::vector<bool> statusPerMpdu);
331 /**
332 * Receive success function for STA 3
333 * \param psdu the PSDU
334 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
335 * \param txVector the transmit vector
336 * \param statusPerMpdu reception status per MPDU
337 */
339 RxSignalInfo rxSignalInfo,
340 WifiTxVector txVector,
341 std::vector<bool> statusPerMpdu);
342
343 /**
344 * Receive failure function for STA 1
345 * \param psdu the PSDU
346 */
348 /**
349 * Receive failure function for STA 2
350 * \param psdu the PSDU
351 */
353 /**
354 * Receive failure function for STA 3
355 * \param psdu the PSDU
356 */
358
359 /**
360 * Check the results for STA 1
361 * \param expectedRxSuccess the expected number of RX success
362 * \param expectedRxFailure the expected number of RX failures
363 * \param expectedRxBytes the expected number of RX bytes
364 */
365 void CheckResultsSta1(uint32_t expectedRxSuccess,
366 uint32_t expectedRxFailure,
367 uint32_t expectedRxBytes);
368 /**
369 * Check the results for STA 2
370 * \param expectedRxSuccess the expected number of RX success
371 * \param expectedRxFailure the expected number of RX failures
372 * \param expectedRxBytes the expected number of RX bytes
373 */
374 void CheckResultsSta2(uint32_t expectedRxSuccess,
375 uint32_t expectedRxFailure,
376 uint32_t expectedRxBytes);
377 /**
378 * Check the results for STA 3
379 * \param expectedRxSuccess the expected number of RX success
380 * \param expectedRxFailure the expected number of RX failures
381 * \param expectedRxBytes the expected number of RX bytes
382 */
383 void CheckResultsSta3(uint32_t expectedRxSuccess,
384 uint32_t expectedRxFailure,
385 uint32_t expectedRxBytes);
386
387 /**
388 * Reset the results
389 */
390 void ResetResults();
391
392 /**
393 * Send MU-PPDU function
394 * \param rxStaId1 the ID of the recipient STA for the first PSDU
395 * \param rxStaId2 the ID of the recipient STA for the second PSDU
396 */
397 void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
398
399 /**
400 * Generate interference function
401 * \param interferencePsd the PSD of the interference to be generated
402 * \param duration the duration of the interference
403 */
404 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
405 /**
406 * Stop interference function
407 */
408 void StopInterference();
409
410 /**
411 * Run one function
412 */
413 void RunOne();
414
415 /**
416 * Schedule now to check the PHY state
417 * \param phy the PHY
418 * \param expectedState the expected state of the PHY
419 */
421 /**
422 * Check the PHY state now
423 * \param phy the PHY
424 * \param expectedState the expected state of the PHY
425 */
427
428 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
429 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
430 uint32_t m_countRxSuccessSta3; ///< count RX success for STA 3
431 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
432 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
433 uint32_t m_countRxFailureSta3; ///< count RX failure for STA 3
434 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
435 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
436 uint32_t m_countRxBytesSta3; ///< count RX bytes for STA 3
437
443
444 uint16_t m_frequency; ///< frequency in MHz
445 uint16_t m_channelWidth; ///< channel width in MHz
446 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
447};
448
450 : TestCase("DL-OFDMA PHY test"),
451 m_countRxSuccessSta1(0),
452 m_countRxSuccessSta2(0),
453 m_countRxSuccessSta3(0),
454 m_countRxFailureSta1(0),
455 m_countRxFailureSta2(0),
456 m_countRxFailureSta3(0),
457 m_countRxBytesSta1(0),
458 m_countRxBytesSta2(0),
459 m_countRxBytesSta3(0),
460 m_frequency(DEFAULT_FREQUENCY),
461 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
462 m_expectedPpduDuration(NanoSeconds(306400))
463{
464}
465
466void
468{
478}
479
480void
481TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
482{
483 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
484 WifiConstPsduMap psdus;
486 0,
488 800,
489 1,
490 1,
491 0,
493 false,
494 false);
496 if (m_channelWidth == 20)
497 {
498 ruType = HeRu::RU_106_TONE;
499 txVector.SetRuAllocation({96}, 0);
500 }
501 else if (m_channelWidth == 40)
502 {
503 ruType = HeRu::RU_242_TONE;
504 txVector.SetRuAllocation({192, 192}, 0);
505 }
506 else if (m_channelWidth == 80)
507 {
508 ruType = HeRu::RU_484_TONE;
509 txVector.SetRuAllocation({200, 200, 200, 200}, 0);
510 }
511 else if (m_channelWidth == 160)
512 {
513 ruType = HeRu::RU_996_TONE;
514 txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208}, 0);
515 }
516 else
517 {
518 NS_ASSERT_MSG(false, "Unsupported channel width");
519 }
520
522
523 HeRu::RuSpec ru1(ruType, 1, true);
524 txVector.SetRu(ru1, rxStaId1);
525 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
526 txVector.SetNss(1, rxStaId1);
527
528 HeRu::RuSpec ru2(ruType, (m_channelWidth == 160 ? 1 : 2), m_channelWidth != 160);
529 txVector.SetRu(ru2, rxStaId2);
530 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
531 txVector.SetNss(1, rxStaId2);
532
533 Ptr<Packet> pkt1 = Create<Packet>(1000);
534 WifiMacHeader hdr1;
536 hdr1.SetQosTid(0);
537 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
538 hdr1.SetSequenceNumber(1);
539 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
540 psdus.insert(std::make_pair(rxStaId1, psdu1));
541
542 Ptr<Packet> pkt2 = Create<Packet>(1500);
543 WifiMacHeader hdr2;
545 hdr2.SetQosTid(0);
546 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
547 hdr2.SetSequenceNumber(2);
548 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
549 psdus.insert(std::make_pair(rxStaId2, psdu2));
550
551 m_phyAp->Send(psdus, txVector);
552}
553
554void
556{
558 m_phyInterferer->SetPeriod(duration);
561}
562
563void
565{
567}
568
570{
571}
572
573void
575 RxSignalInfo rxSignalInfo,
576 WifiTxVector txVector,
577 std::vector<bool> /*statusPerMpdu*/)
578{
579 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
581 m_countRxBytesSta1 += (psdu->GetSize() - 30);
582}
583
584void
586 RxSignalInfo rxSignalInfo,
587 WifiTxVector txVector,
588 std::vector<bool> /*statusPerMpdu*/)
589{
590 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
592 m_countRxBytesSta2 += (psdu->GetSize() - 30);
593}
594
595void
597 RxSignalInfo rxSignalInfo,
598 WifiTxVector txVector,
599 std::vector<bool> /*statusPerMpdu*/)
600{
601 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
603 m_countRxBytesSta3 += (psdu->GetSize() - 30);
604}
605
606void
608{
609 NS_LOG_FUNCTION(this << *psdu);
611}
612
613void
615{
616 NS_LOG_FUNCTION(this << *psdu);
618}
619
620void
622{
623 NS_LOG_FUNCTION(this << *psdu);
625}
626
627void
629 uint32_t expectedRxFailure,
630 uint32_t expectedRxBytes)
631{
633 expectedRxSuccess,
634 "The number of successfully received packets by STA 1 is not correct!");
636 expectedRxFailure,
637 "The number of unsuccessfuly received packets by STA 1 is not correct!");
639 expectedRxBytes,
640 "The number of bytes received by STA 1 is not correct!");
641}
642
643void
645 uint32_t expectedRxFailure,
646 uint32_t expectedRxBytes)
647{
649 expectedRxSuccess,
650 "The number of successfully received packets by STA 2 is not correct!");
652 expectedRxFailure,
653 "The number of unsuccessfuly received packets by STA 2 is not correct!");
655 expectedRxBytes,
656 "The number of bytes received by STA 2 is not correct!");
657}
658
659void
661 uint32_t expectedRxFailure,
662 uint32_t expectedRxBytes)
663{
665 expectedRxSuccess,
666 "The number of successfully received packets by STA 3 is not correct!");
668 expectedRxFailure,
669 "The number of unsuccessfuly received packets by STA 3 is not correct!");
671 expectedRxBytes,
672 "The number of bytes received by STA 3 is not correct!");
673}
674
675void
677{
678 // This is needed to make sure PHY state will be checked as the last event if a state change
679 // occurred at the exact same time as the check
681}
682
683void
685 WifiPhyState expectedState)
686{
687 WifiPhyState currentState;
688 PointerValue ptr;
689 phy->GetAttribute("State", ptr);
690 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
691 currentState = state->GetState();
692 NS_LOG_FUNCTION(this << currentState);
693 NS_TEST_ASSERT_MSG_EQ(currentState,
694 expectedState,
695 "PHY State " << currentState << " does not match expected state "
696 << expectedState << " at " << Simulator::Now());
697}
698
699void
701{
702 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
703 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
704 lossModel->SetFrequency(m_frequency * 1e6);
705 spectrumChannel->AddPropagationLossModel(lossModel);
707 CreateObject<ConstantSpeedPropagationDelayModel>();
708 spectrumChannel->SetPropagationDelayModel(delayModel);
709
710 Ptr<Node> apNode = CreateObject<Node>();
711 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
712 m_phyAp = CreateObject<SpectrumWifiPhy>();
713 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
714 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
715 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
716 m_phyAp->SetErrorRateModel(apErrorModel);
717 m_phyAp->SetDevice(apDev);
718 m_phyAp->AddChannel(spectrumChannel);
720 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
721 m_phyAp->SetMobility(apMobility);
722 apDev->SetPhy(m_phyAp);
723 apNode->AggregateObject(apMobility);
724 apNode->AddDevice(apDev);
725
726 Ptr<Node> sta1Node = CreateObject<Node>();
727 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
728 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
729 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
730 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
731 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
732 m_phySta1->SetErrorRateModel(sta1ErrorModel);
733 m_phySta1->SetDevice(sta1Dev);
734 m_phySta1->AddChannel(spectrumChannel);
739 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
740 m_phySta1->SetMobility(sta1Mobility);
741 sta1Dev->SetPhy(m_phySta1);
742 sta1Node->AggregateObject(sta1Mobility);
743 sta1Node->AddDevice(sta1Dev);
744
745 Ptr<Node> sta2Node = CreateObject<Node>();
746 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
747 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
748 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
749 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
750 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
751 m_phySta2->SetErrorRateModel(sta2ErrorModel);
752 m_phySta2->SetDevice(sta2Dev);
753 m_phySta2->AddChannel(spectrumChannel);
758 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
759 m_phySta2->SetMobility(sta2Mobility);
760 sta2Dev->SetPhy(m_phySta2);
761 sta2Node->AggregateObject(sta2Mobility);
762 sta2Node->AddDevice(sta2Dev);
763
764 Ptr<Node> sta3Node = CreateObject<Node>();
765 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
766 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
767 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
768 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
769 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
770 m_phySta3->SetErrorRateModel(sta3ErrorModel);
771 m_phySta3->SetDevice(sta3Dev);
772 m_phySta3->AddChannel(spectrumChannel);
777 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
778 m_phySta3->SetMobility(sta3Mobility);
779 sta3Dev->SetPhy(m_phySta3);
780 sta3Node->AggregateObject(sta3Mobility);
781 sta3Node->AddDevice(sta3Dev);
782
783 Ptr<Node> interfererNode = CreateObject<Node>();
784 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
785 m_phyInterferer = CreateObject<WaveformGenerator>();
786 m_phyInterferer->SetDevice(interfererDev);
787 m_phyInterferer->SetChannel(spectrumChannel);
789 interfererNode->AddDevice(interfererDev);
790}
791
792void
794{
795 m_phyAp->Dispose();
796 m_phyAp = nullptr;
798 m_phySta1 = nullptr;
800 m_phySta2 = nullptr;
802 m_phySta3 = nullptr;
804 m_phyInterferer = nullptr;
805}
806
807void
809{
812 int64_t streamNumber = 0;
813 m_phyAp->AssignStreams(streamNumber);
814 m_phySta1->AssignStreams(streamNumber);
815 m_phySta2->AssignStreams(streamNumber);
816 m_phySta3->AssignStreams(streamNumber);
817
818 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
823
832
834
835 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
836 // Each STA should receive its PSDU.
838
839 // Since it takes m_expectedPpduDuration to transmit the PPDU,
840 // all 3 PHYs should be back to IDLE at the same time,
841 // even the PHY that has no PSDU addressed to it.
844 this,
845 m_phySta1,
846 WifiPhyState::RX);
849 this,
850 m_phySta2,
851 WifiPhyState::RX);
854 this,
855 m_phySta3,
856 WifiPhyState::CCA_BUSY);
859 this,
860 m_phySta1,
861 WifiPhyState::IDLE);
864 this,
865 m_phySta2,
866 WifiPhyState::IDLE);
869 this,
870 m_phySta3,
871 WifiPhyState::IDLE);
872
873 // One PSDU of 1000 bytes should have been successfully received by STA 1
876 this,
877 1,
878 0,
879 1000);
880 // One PSDU of 1500 bytes should have been successfully received by STA 2
883 this,
884 1,
885 0,
886 1500);
887 // No PSDU should have been received by STA 3
889
891
892 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
893 // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
894 // but should keep its PHY busy during all PPDU duration.
896
897 // Since it takes m_expectedPpduDuration to transmit the PPDU,
898 // all 3 PHYs should be back to IDLE at the same time,
899 // even the PHY that has no PSDU addressed to it.
902 this,
903 m_phySta1,
904 WifiPhyState::RX);
907 this,
908 m_phySta2,
909 WifiPhyState::CCA_BUSY);
912 this,
913 m_phySta3,
914 WifiPhyState::RX);
917 this,
918 m_phySta1,
919 WifiPhyState::IDLE);
922 this,
923 m_phySta2,
924 WifiPhyState::IDLE);
927 this,
928 m_phySta3,
929 WifiPhyState::IDLE);
930
931 // One PSDU of 1000 bytes should have been successfully received by STA 1
934 this,
935 1,
936 0,
937 1000);
938 // No PSDU should have been received by STA 2
940 // One PSDU of 1500 bytes should have been successfully received by STA 3
943 this,
944 1,
945 0,
946 1500);
947
949
950 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
952
953 // A strong non-wifi interference is generated on RU 1 during PSDU reception
954 BandInfo bandInfo;
955 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
956 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
957 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
958 Bands bands;
959 bands.push_back(bandInfo);
960
961 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
962 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
963 double interferencePower = 0.1; // watts
964 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
965
968 this,
969 interferencePsdRu1,
970 MilliSeconds(100));
971
972 // Since it takes m_expectedPpduDuration to transmit the PPDU,
973 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
974 // even the PHY that has no PSDU addressed to it.
977 this,
978 m_phySta1,
979 WifiPhyState::RX);
982 this,
983 m_phySta2,
984 WifiPhyState::RX);
987 this,
988 m_phySta3,
989 WifiPhyState::CCA_BUSY);
992 this,
993 m_phySta1,
994 WifiPhyState::CCA_BUSY);
997 this,
998 m_phySta2,
999 WifiPhyState::CCA_BUSY);
1002 this,
1003 m_phySta3,
1004 WifiPhyState::CCA_BUSY);
1005
1006 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1007 // occupies RU 1)
1009 // One PSDU of 1500 bytes should have been successfully received by STA 2
1012 this,
1013 1,
1014 0,
1015 1500);
1016 // No PSDU should have been received by STA3
1018
1020
1021 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1023
1024 // A strong non-wifi interference is generated on RU 2 during PSDU reception
1025 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
1026 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
1027 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
1028 bands.clear();
1029 bands.push_back(bandInfo);
1030
1031 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1032 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1033 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
1034
1037 this,
1038 interferencePsdRu2,
1039 MilliSeconds(100));
1040
1041 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1042 // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1043 // same time, even the PHY that has no PSDU addressed to it.
1046 this,
1047 m_phySta1,
1048 WifiPhyState::RX);
1051 this,
1052 m_phySta2,
1053 WifiPhyState::RX);
1056 this,
1057 m_phySta3,
1058 WifiPhyState::CCA_BUSY);
1061 this,
1062 m_phySta1,
1063 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1066 this,
1067 m_phySta2,
1068 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1071 this,
1072 m_phySta3,
1073 (m_channelWidth >= 40) ? WifiPhyState::IDLE : 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 = m_frequency * 1e6;
1095 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
1096 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
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 / (m_channelWidth * 20e6);
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 = 5180;
1162 m_channelWidth = 20;
1164 RunOne();
1165
1166 m_frequency = 5190;
1167 m_channelWidth = 40;
1169 RunOne();
1170
1171 m_frequency = 5210;
1172 m_channelWidth = 80;
1174 RunOne();
1175
1176 m_frequency = 5250;
1177 m_channelWidth = 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 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 WifiTxVector txVector,
1222 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 uint16_t m_frequency; ///< frequency in MHz
1316 uint16_t m_channelWidth; ///< channel width in MHz
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(5210),
1334 m_channelWidth(80),
1335 m_indexSubchannel(0),
1336 m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1337 m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1338{
1339}
1340
1341void
1343{
1350}
1351
1352void
1354 uint16_t rxStaId2,
1355 const std::vector<bool>& puncturedSubchannels)
1356{
1357 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1358 WifiConstPsduMap psdus;
1360 0,
1362 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 std::vector<uint8_t> 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);
1438 m_phyInterferer->SetPeriod(duration);
1441}
1442
1443void
1445{
1446 NS_LOG_FUNCTION(this);
1448}
1449
1450void
1452 RxSignalInfo rxSignalInfo,
1453 WifiTxVector txVector,
1454 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 WifiTxVector txVector,
1465 std::vector<bool> /*statusPerMpdu*/)
1466{
1467 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1469 m_countRxBytesSta2 += (psdu->GetSize() - 30);
1470}
1471
1472void
1474{
1475 NS_LOG_FUNCTION(this << *psdu);
1477}
1478
1479void
1481{
1482 NS_LOG_FUNCTION(this << *psdu);
1484}
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);
1532 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
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{
1544 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1545 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1546 lossModel->SetFrequency(m_frequency * 1e6);
1547 spectrumChannel->AddPropagationLossModel(lossModel);
1549 CreateObject<ConstantSpeedPropagationDelayModel>();
1550 spectrumChannel->SetPropagationDelayModel(delayModel);
1551
1552 Ptr<Node> apNode = CreateObject<Node>();
1553 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1554 m_phyAp = CreateObject<SpectrumWifiPhy>();
1555 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1556 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1557 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1558 m_phyAp->SetErrorRateModel(apErrorModel);
1559 m_phyAp->SetDevice(apDev);
1560 m_phyAp->AddChannel(spectrumChannel);
1562 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
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>();
1569 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1570 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1571 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1572 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1573 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1574 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1575 m_phySta1->SetDevice(sta1Dev);
1576 m_phySta1->AddChannel(spectrumChannel);
1581 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
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>();
1588 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1589 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1590 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1591 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1592 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1593 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1594 m_phySta2->SetDevice(sta2Dev);
1595 m_phySta2->AddChannel(spectrumChannel);
1600 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
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>();
1607 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
1608 m_phyInterferer = CreateObject<WaveformGenerator>();
1609 m_phyInterferer->SetDevice(interfererDev);
1610 m_phyInterferer->SetChannel(spectrumChannel);
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 = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1643
1650
1651 // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1652 // duration of the test run
1653 BandInfo bandInfo;
1654 bandInfo.fc = (m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20)) * 1e6;
1655 // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1656 // the border of another RU
1657 bandInfo.fl = bandInfo.fc - (5 * 1e6);
1658 bandInfo.fh = bandInfo.fc + (5 * 1e6);
1659 Bands bands;
1660 bands.push_back(bandInfo);
1661
1662 Ptr<SpectrumModel> spectrumInterference = Create<SpectrumModel>(bands);
1663 Ptr<SpectrumValue> interferencePsd = Create<SpectrumValue>(spectrumInterference);
1664 double interferencePower = 0.1; // watts
1665 *interferencePsd = interferencePower / 10e6;
1666
1669 this,
1670 interferencePsd,
1671 Seconds(3));
1672
1673 //---------------------------------------------------------------------------
1674 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1677 this,
1678 1,
1679 2,
1680 std::vector<bool>{});
1681
1682 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1683 // both PHYs should be back to IDLE at the same time.
1686 this,
1687 m_phySta1,
1688 WifiPhyState::RX);
1691 this,
1692 m_phySta2,
1693 WifiPhyState::RX);
1696 this,
1697 m_phySta1,
1698 WifiPhyState::IDLE);
1701 this,
1702 m_phySta2,
1703 WifiPhyState::IDLE);
1704
1705 if (m_indexSubchannel < 2) // interference in RU 1
1706 {
1707 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1710 this,
1711 0,
1712 1,
1713 0);
1714 // One PSDU of 1500 bytes should have been successfully received by STA 2
1717 this,
1718 1,
1719 0,
1720 1500);
1721 }
1722 else // interference in RU 2
1723 {
1724 // One PSDU of 1000 bytes should have been successfully received by STA 1
1727 this,
1728 1,
1729 0,
1730 1000);
1731 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1734 this,
1735 0,
1736 1,
1737 0);
1738 }
1739
1741
1742 //---------------------------------------------------------------------------
1743 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1744 // the punctured 20 MHz subchannel is the one that has interference
1745 std::vector<bool> puncturedSubchannels;
1746 for (std::size_t i = 0; i < (m_channelWidth / 20); ++i)
1747 {
1748 if (i == m_indexSubchannel)
1749 {
1750 puncturedSubchannels.push_back(true);
1751 }
1752 else
1753 {
1754 puncturedSubchannels.push_back(false);
1755 }
1756 }
1759 this,
1760 1,
1761 2,
1762 puncturedSubchannels);
1763
1764 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1765 // both PHYs should be back to IDLE at the same time.
1768 this,
1769 m_phySta1,
1770 WifiPhyState::RX);
1773 this,
1774 m_phySta2,
1775 WifiPhyState::RX);
1778 this,
1779 m_phySta1,
1780 WifiPhyState::IDLE);
1783 this,
1784 m_phySta2,
1785 WifiPhyState::IDLE);
1786
1787 // One PSDU of 1000 bytes should have been successfully received by STA 1
1790 this,
1791 1,
1792 0,
1793 1000);
1794 // One PSDU of 1500 bytes should have been successfully received by STA 2
1797 this,
1798 1,
1799 0,
1800 1500);
1801
1803
1805}
1806
1807void
1809{
1810 // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1811 // cannot be punctured
1812 for (auto index : {1, 2, 3})
1813 {
1814 m_indexSubchannel = index;
1815 RunOne();
1816 }
1818}
1819
1820/**
1821 * \ingroup wifi-test
1822 * \ingroup tests
1823 *
1824 * \brief UL-OFDMA PPDU UID attribution test
1825 */
1827{
1828 public:
1830 ~TestUlOfdmaPpduUid() override;
1831
1832 private:
1833 void DoSetup() override;
1834 void DoTeardown() override;
1835 void DoRun() override;
1836
1837 /**
1838 * Transmitted PPDU information function for AP
1839 * \param uid the UID of the transmitted PPDU
1840 */
1841 void TxPpduAp(uint64_t uid);
1842 /**
1843 * Transmitted PPDU information function for STA 1
1844 * \param uid the UID of the transmitted PPDU
1845 */
1846 void TxPpduSta1(uint64_t uid);
1847 /**
1848 * Transmitted PPDU information function for STA 2
1849 * \param uid the UID of the transmitted PPDU
1850 */
1851 void TxPpduSta2(uint64_t uid);
1852 /**
1853 * Reset the global PPDU UID counter in WifiPhy
1854 */
1855 void ResetPpduUid();
1856
1857 /**
1858 * Send MU-PPDU toward both STAs.
1859 */
1860 void SendMuPpdu();
1861 /**
1862 * Send TB-PPDU from both STAs.
1863 */
1864 void SendTbPpdu();
1865 /**
1866 * Send SU-PPDU function
1867 * \param txStaId the ID of the sending STA
1868 */
1869 void SendSuPpdu(uint16_t txStaId);
1870
1871 /**
1872 * Check the UID of the transmitted PPDU
1873 * \param staId the STA-ID of the PHY (0 for AP)
1874 * \param expectedUid the expected UID
1875 */
1876 void CheckUid(uint16_t staId, uint64_t expectedUid);
1877
1881
1882 uint64_t m_ppduUidAp; ///< UID of PPDU transmitted by AP
1883 uint64_t m_ppduUidSta1; ///< UID of PPDU transmitted by STA1
1884 uint64_t m_ppduUidSta2; ///< UID of PPDU transmitted by STA2
1885};
1886
1888 : TestCase("UL-OFDMA PPDU UID attribution test"),
1889 m_ppduUidAp(UINT64_MAX),
1890 m_ppduUidSta1(UINT64_MAX),
1891 m_ppduUidSta2(UINT64_MAX)
1892{
1893}
1894
1896{
1897}
1898
1899void
1901{
1902 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1903 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1904 lossModel->SetFrequency(DEFAULT_FREQUENCY);
1905 spectrumChannel->AddPropagationLossModel(lossModel);
1907 CreateObject<ConstantSpeedPropagationDelayModel>();
1908 spectrumChannel->SetPropagationDelayModel(delayModel);
1909
1910 Ptr<Node> apNode = CreateObject<Node>();
1911 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1912 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
1913 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1914 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1915 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1916 m_phyAp->SetErrorRateModel(apErrorModel);
1917 m_phyAp->AddChannel(spectrumChannel);
1919 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1926 m_phyAp->SetDevice(apDev);
1929 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1930 m_phyAp->SetMobility(apMobility);
1931 apDev->SetPhy(m_phyAp);
1932 apNode->AggregateObject(apMobility);
1933 apNode->AddDevice(apDev);
1934 apDev->SetStandard(WIFI_STANDARD_80211ax);
1935 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1936
1937 Ptr<Node> sta1Node = CreateObject<Node>();
1938 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1939 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1940 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1941 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1942 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1943 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1944 m_phySta1->AddChannel(spectrumChannel);
1948 m_phySta1->SetDevice(sta1Dev);
1951 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1952 m_phySta1->SetMobility(sta1Mobility);
1953 sta1Dev->SetPhy(m_phySta1);
1954 sta1Node->AggregateObject(sta1Mobility);
1955 sta1Node->AddDevice(sta1Dev);
1956
1957 Ptr<Node> sta2Node = CreateObject<Node>();
1958 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1959 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1960 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1961 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1962 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1963 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1964 m_phySta2->AddChannel(spectrumChannel);
1968 m_phySta2->SetDevice(sta2Dev);
1971 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1972 m_phySta2->SetMobility(sta2Mobility);
1973 sta2Dev->SetPhy(m_phySta2);
1974 sta2Node->AggregateObject(sta2Mobility);
1975 sta2Node->AddDevice(sta2Dev);
1976}
1977
1978void
1980{
1981 m_phyAp->Dispose();
1982 m_phyAp = nullptr;
1983 m_phySta1->Dispose();
1984 m_phySta1 = nullptr;
1985 m_phySta2->Dispose();
1986 m_phySta2 = nullptr;
1987}
1988
1989void
1990TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
1991{
1992 uint64_t uid;
1993 std::string device;
1994 switch (staId)
1995 {
1996 case 0:
1997 uid = m_ppduUidAp;
1998 device = "AP";
1999 break;
2000 case 1:
2001 uid = m_ppduUidSta1;
2002 device = "STA1";
2003 break;
2004 case 2:
2005 uid = m_ppduUidSta2;
2006 device = "STA2";
2007 break;
2008 default:
2009 NS_ABORT_MSG("Unexpected STA-ID");
2010 }
2012 expectedUid,
2013 "UID " << uid << " does not match expected one " << expectedUid << " for "
2014 << device << " at " << Simulator::Now());
2015}
2016
2017void
2019{
2020 NS_LOG_FUNCTION(this << uid);
2021 m_ppduUidAp = uid;
2022}
2023
2024void
2026{
2027 NS_LOG_FUNCTION(this << uid);
2028 m_ppduUidSta1 = uid;
2029}
2030
2031void
2033{
2034 NS_LOG_FUNCTION(this << uid);
2035 m_ppduUidSta2 = uid;
2036}
2037
2038void
2040{
2041 NS_LOG_FUNCTION(this);
2042 m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2043}
2044
2045void
2047{
2048 WifiConstPsduMap psdus;
2050 0,
2052 800,
2053 1,
2054 1,
2055 0,
2057 false,
2058 false);
2059
2060 uint16_t rxStaId1 = 1;
2061 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2062 txVector.SetRu(ru1, rxStaId1);
2063 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2064 txVector.SetNss(1, rxStaId1);
2065
2066 uint16_t rxStaId2 = 2;
2067 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2068 txVector.SetRu(ru2, rxStaId2);
2069 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2070 txVector.SetNss(1, rxStaId2);
2071 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2072 txVector.SetRuAllocation({96}, 0);
2073
2074 Ptr<Packet> pkt1 = Create<Packet>(1000);
2075 WifiMacHeader hdr1;
2077 hdr1.SetQosTid(0);
2078 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2079 hdr1.SetSequenceNumber(1);
2080 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2081 psdus.insert(std::make_pair(rxStaId1, psdu1));
2082
2083 Ptr<Packet> pkt2 = Create<Packet>(1500);
2084 WifiMacHeader hdr2;
2086 hdr2.SetQosTid(0);
2087 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2088 hdr2.SetSequenceNumber(2);
2089 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2090 psdus.insert(std::make_pair(rxStaId2, psdu2));
2091
2092 m_phyAp->Send(psdus, txVector);
2093}
2094
2095void
2097{
2098 WifiConstPsduMap psdus1;
2099 WifiConstPsduMap psdus2;
2100
2102 0,
2104 1600,
2105 1,
2106 1,
2107 0,
2109 false,
2110 false);
2111 WifiTxVector txVector2 = txVector1;
2112 WifiTxVector trigVector = txVector2;
2113
2114 uint16_t rxStaId1 = 1;
2115 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2116 txVector1.SetRu(ru1, rxStaId1);
2117 txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2118 txVector1.SetNss(1, rxStaId1);
2119 trigVector.SetRu(ru1, rxStaId1);
2120 trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2121 trigVector.SetNss(1, rxStaId1);
2122
2123 Ptr<Packet> pkt1 = Create<Packet>(1000);
2124 WifiMacHeader hdr1;
2126 hdr1.SetQosTid(0);
2127 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2128 hdr1.SetSequenceNumber(1);
2129 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2130 psdus1.insert(std::make_pair(rxStaId1, psdu1));
2131
2132 uint16_t rxStaId2 = 2;
2133 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, false);
2134 txVector2.SetRu(ru2, rxStaId2);
2135 txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2136 txVector2.SetNss(1, rxStaId2);
2137 trigVector.SetRu(ru2, rxStaId2);
2138 trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2139 trigVector.SetNss(1, rxStaId2);
2140
2141 Ptr<Packet> pkt2 = Create<Packet>(1500);
2142 WifiMacHeader hdr2;
2144 hdr2.SetQosTid(0);
2145 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2146 hdr2.SetSequenceNumber(2);
2147 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2148 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2149
2150 Time txDuration1 = m_phySta1->CalculateTxDuration(psdu1->GetSize(),
2151 txVector1,
2153 rxStaId1);
2154 Time txDuration2 = m_phySta2->CalculateTxDuration(psdu2->GetSize(),
2155 txVector2,
2157 rxStaId2);
2158 Time txDuration = std::max(txDuration1, txDuration2);
2159
2160 txVector1.SetLength(
2162 .first);
2163 txVector2.SetLength(
2165 .first);
2166
2167 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
2168 hePhyAp->SetTrigVector(trigVector, txDuration);
2169
2170 m_phySta1->Send(psdus1, txVector1);
2171 m_phySta2->Send(psdus2, txVector2);
2172}
2173
2174void
2176{
2177 WifiConstPsduMap psdus;
2179 0,
2181 800,
2182 1,
2183 1,
2184 0,
2186 false,
2187 false);
2188
2189 Ptr<Packet> pkt = Create<Packet>(1000);
2190 WifiMacHeader hdr;
2192 hdr.SetQosTid(0);
2194 hdr.SetSequenceNumber(1);
2195 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2196 psdus.insert(std::make_pair(SU_STA_ID, psdu));
2197
2198 switch (txStaId)
2199 {
2200 case 0:
2201 m_phyAp->Send(psdus, txVector);
2202 break;
2203 case 1:
2204 m_phySta1->Send(psdus, txVector);
2205 break;
2206 case 2:
2207 m_phySta2->Send(psdus, txVector);
2208 break;
2209 default:
2210 NS_ABORT_MSG("Unexpected STA-ID");
2211 }
2212}
2213
2214void
2216{
2219 int64_t streamNumber = 0;
2220 m_phyAp->AssignStreams(streamNumber);
2221 m_phySta1->AssignStreams(streamNumber);
2222 m_phySta2->AssignStreams(streamNumber);
2223
2224 // Reset PPDU UID so as not to be dependent on previously executed test cases,
2225 // since global attribute will be changed).
2226 ResetPpduUid();
2227
2228 // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2229 // PPDU UID should be equal to 0 (the first counter value).
2232
2233 // Send HE SU PPDU from AP.
2234 // PPDU UID should be incremented since this is a new PPDU.
2237
2238 // Send HE TB PPDU from STAs to AP.
2239 // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2240 // preceding correctly received PPDU (which normally contains the trigger frame).
2244
2245 // Send HE SU PPDU from STA1.
2246 // PPDU UID should be incremented since this is a new PPDU.
2249
2252}
2253
2254/**
2255 * \ingroup wifi-test
2256 * \ingroup tests
2257 *
2258 * \brief UL-OFDMA multiple RX events test
2259 */
2261{
2262 public:
2264 ~TestMultipleHeTbPreambles() override;
2265
2266 private:
2267 void DoSetup() override;
2268 void DoTeardown() override;
2269 void DoRun() override;
2270
2271 /**
2272 * Receive HE TB PPDU function.
2273 *
2274 * \param uid the UID used to identify a set of HE TB PPDUs belonging to the same UL-MU
2275 * transmission
2276 * \param staId the STA ID
2277 * \param txPowerWatts the TX power in watts
2278 * \param payloadSize the size of the payload in bytes
2279 */
2280 void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize);
2281
2282 /**
2283 * Receive OFDMA part of HE TB PPDU function.
2284 * Immediately schedules DoRxHeTbPpduOfdmaPart.
2285 *
2286 * \param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2287 */
2289 /**
2290 * Receive OFDMA part of HE TB PPDU function.
2291 * Actual reception call.
2292 *
2293 * \param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2294 */
2296
2297 /**
2298 * RX dropped function
2299 * \param p the packet
2300 * \param reason the reason
2301 */
2303
2304 /**
2305 * Reset function
2306 */
2307 void Reset();
2308
2309 /**
2310 * Check the received HE TB preambles
2311 * \param nEvents the number of events created by the PHY
2312 * \param uids the vector of expected UIDs
2313 */
2314 void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2315
2316 /**
2317 * Check the number of bytes dropped
2318 * \param expectedBytesDropped the expected number of bytes dropped
2319 */
2320 void CheckBytesDropped(size_t expectedBytesDropped);
2321
2323
2324 uint64_t m_totalBytesDropped; ///< total number of dropped bytes
2326};
2327
2329 : TestCase("UL-OFDMA multiple RX events test"),
2330 m_totalBytesDropped(0),
2331 m_trigVector(HePhy::GetHeMcs7(),
2332 0,
2334 1600,
2335 1,
2336 1,
2337 0,
2339 false,
2340 false)
2341{
2342}
2343
2345{
2346}
2347
2348void
2350{
2351 NS_LOG_FUNCTION(this);
2353 // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2354 m_phy->Reset();
2356}
2357
2358void
2360{
2361 NS_LOG_FUNCTION(this << p << reason);
2362 m_totalBytesDropped += (p->GetSize() - 30);
2363}
2364
2365void
2366TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2367{
2368 auto events = m_phy->GetCurrentPreambleEvents();
2369 NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2370 for (const auto& uid : uids)
2371 {
2372 auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2373 auto it = events.find(pair);
2374 bool found = (it != events.end());
2376 true,
2377 "HE TB PPDU with UID " << uid << " has not been received!");
2378 }
2379}
2380
2381void
2383{
2385 expectedBytesDropped,
2386 "The number of dropped bytes is not correct!");
2387}
2388
2389void
2391 uint16_t staId,
2392 double txPowerWatts,
2393 size_t payloadSize)
2394{
2395 WifiConstPsduMap psdus;
2397 0,
2399 1600,
2400 1,
2401 1,
2402 0,
2404 false,
2405 false);
2406
2407 HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2408 txVector.SetRu(ru, staId);
2409 txVector.SetMode(HePhy::GetHeMcs7(), staId);
2410 txVector.SetNss(1, staId);
2411
2412 m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2413
2414 Ptr<Packet> pkt = Create<Packet>(payloadSize);
2415 WifiMacHeader hdr;
2417 hdr.SetQosTid(0);
2418 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2419 hdr.SetSequenceNumber(1);
2420 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2421 psdus.insert(std::make_pair(staId, psdu));
2422
2423 Time ppduDuration =
2424 m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand(), staId);
2425 Ptr<HePpdu> ppdu = Create<HePpdu>(psdus,
2426 txVector,
2428 ppduDuration,
2429 uid,
2431
2432 // Send non-OFDMA part
2433 Time nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonHeDurationForHeTb(txVector);
2434 uint32_t centerFrequency = m_phy->GetHePhy()->GetCenterFrequencyForNonHePart(txVector, staId);
2435 uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2436 uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
2438 centerFrequency,
2439 channelWidth,
2440 txPowerWatts,
2441 m_phy->GetGuardBandwidth(channelWidth));
2442 Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters>();
2443 rxParams->psd = rxPsd;
2444 rxParams->txPhy = nullptr;
2445 rxParams->duration = nonOfdmaDuration;
2446 rxParams->ppdu = ppdu;
2447
2448 uint16_t length;
2449 std::tie(length, ppduDuration) =
2451 txVector.SetLength(length);
2452 m_trigVector.SetLength(length);
2453 auto hePhy = DynamicCast<HePhy>(m_phy->GetLatestPhyEntity());
2454 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2455 ppdu->ResetTxVector();
2456 m_phy->StartRx(rxParams, nullptr);
2457
2458 // Schedule OFDMA part
2459 Ptr<HePpdu> ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2460 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2461 const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2462 Ptr<SpectrumValue> rxPsdOfdma =
2465 txPowerWatts,
2467 band.indices);
2468 Ptr<WifiSpectrumSignalParameters> rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2469 rxParamsOfdma->psd = rxPsd;
2470 rxParamsOfdma->txPhy = nullptr;
2471 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2472 rxParamsOfdma->ppdu = ppduOfdma;
2473 Simulator::Schedule(nonOfdmaDuration,
2475 this,
2476 rxParamsOfdma);
2477}
2478
2479void
2481{
2483}
2484
2485void
2487{
2488 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2489 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2490 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2491 m_phy->StartRx(rxParamsOfdma, nullptr);
2492}
2493
2494void
2496{
2497 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
2498 Ptr<Node> node = CreateObject<Node>();
2499 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
2500 dev->SetStandard(WIFI_STANDARD_80211ax);
2501 m_phy = CreateObject<OfdmaSpectrumWifiPhy>(0);
2502 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2503 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2504 Ptr<ApWifiMac> mac = CreateObject<ApWifiMac>();
2505 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2506 dev->SetMac(mac);
2507 m_phy->SetInterferenceHelper(interferenceHelper);
2508 m_phy->SetErrorRateModel(error);
2509 m_phy->AddChannel(spectrumChannel);
2514 0});
2515 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2517 m_phy->SetDevice(dev);
2518 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2519 CreateObject<ThresholdPreambleDetectionModel>();
2520 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2521 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2522 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2523 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
2524 heConfiguration->SetMaxTbPpduDelay(NanoSeconds(400));
2525 dev->SetHeConfiguration(heConfiguration);
2526 dev->SetPhy(m_phy);
2527 node->AddDevice(dev);
2528}
2529
2530void
2532{
2533 m_phy->Dispose();
2534 m_phy = nullptr;
2535}
2536
2537void
2539{
2542 int64_t streamNumber = 0;
2543 m_phy->AssignStreams(streamNumber);
2544
2545 double txPowerWatts = 0.01;
2546
2547 {
2548 // Verify a single UL MU transmission with two stations belonging to the same BSS
2549 std::vector<uint64_t> uids{0};
2552 this,
2553 uids[0],
2554 1,
2555 txPowerWatts,
2556 1001);
2559 this,
2560 uids[0],
2561 2,
2562 txPowerWatts,
2563 1002);
2564 // Check that we received a single UL MU transmission with the corresponding UID
2567 this,
2568 1,
2569 uids);
2571 }
2572
2573 {
2574 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2575 // the second transmission arrives during the preamble detection window and with half the
2576 // power of the first transmission.
2577 std::vector<uint64_t> uids{1, 2};
2580 this,
2581 uids[0],
2582 1,
2583 txPowerWatts,
2584 1001);
2587 this,
2588 uids[0],
2589 2,
2590 txPowerWatts,
2591 1002);
2594 this,
2595 uids[1],
2596 1,
2597 txPowerWatts / 2,
2598 1003);
2601 this,
2602 uids[1],
2603 2,
2604 txPowerWatts / 2,
2605 1004);
2606 // Check that we received the correct reception of 2 UL MU transmissions with the
2607 // corresponding UIDs
2610 this,
2611 2,
2612 uids);
2614 // TODO: verify PPDUs from second UL MU transmission are dropped
2615 }
2616
2617 {
2618 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2619 // the second transmission arrives during the preamble detection window and with twice the
2620 // power of the first transmission.
2621 std::vector<uint64_t> uids{3, 4};
2624 this,
2625 uids[0],
2626 1,
2627 txPowerWatts / 2,
2628 1001);
2631 this,
2632 uids[0],
2633 2,
2634 txPowerWatts / 2,
2635 1002);
2638 this,
2639 uids[1],
2640 1,
2641 txPowerWatts,
2642 1003);
2645 this,
2646 uids[1],
2647 2,
2648 txPowerWatts,
2649 1004);
2650 // Check that we received the correct reception of 2 UL MU transmissions with the
2651 // corresponding UIDs
2654 this,
2655 2,
2656 uids);
2658 // TODO: verify PPDUs from first UL MU transmission are dropped
2659 }
2660
2661 {
2662 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2663 // the second transmission arrives during PHY header reception and with the same power as
2664 // the first transmission.
2665 std::vector<uint64_t> uids{5, 6};
2668 this,
2669 uids[0],
2670 1,
2671 txPowerWatts,
2672 1001);
2675 this,
2676 uids[0],
2677 2,
2678 txPowerWatts,
2679 1002);
2682 this,
2683 uids[1],
2684 1,
2685 txPowerWatts,
2686 1003);
2689 this,
2690 uids[1],
2691 2,
2692 txPowerWatts,
2693 1004);
2694 // Check that we received the correct reception of the first UL MU transmission with the
2695 // corresponding UID (second one dropped)
2698 this,
2699 1,
2700 std::vector<uint64_t>{uids[0]});
2701 // The packets of the second UL MU transmission should have been dropped
2704 this,
2705 1003 + 1004);
2707 }
2708
2709 {
2710 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2711 // BSS, where the second transmission arrives during payload reception and with the same
2712 // power as the first transmission.
2713 std::vector<uint64_t> uids{7, 8};
2716 this,
2717 uids[0],
2718 1,
2719 txPowerWatts,
2720 1001);
2723 this,
2724 uids[0],
2725 2,
2726 txPowerWatts,
2727 1002);
2730 this,
2731 uids[1],
2732 1,
2733 txPowerWatts,
2734 1003);
2737 this,
2738 uids[1],
2739 2,
2740 txPowerWatts,
2741 1004);
2742 // Check that we received the correct reception of the first UL MU transmission with the
2743 // corresponding UID (second one dropped)
2746 this,
2747 1,
2748 std::vector<uint64_t>{uids[0]});
2749 // The packets of the second UL MU transmission should have been dropped
2752 this,
2753 1003 + 1004);
2755 }
2756
2757 {
2758 // Verify the correct reception of a single UL MU transmission with two stations belonging
2759 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2760 // the configured delay spread of 400ns
2761 std::vector<uint64_t> uids{9};
2764 this,
2765 uids[0],
2766 1,
2767 txPowerWatts,
2768 1001);
2771 this,
2772 uids[0],
2773 2,
2774 txPowerWatts,
2775 1002);
2776 // Check that we received a single UL MU transmission with the corresponding UID
2779 this,
2780 1,
2781 uids);
2782 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2783 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2784 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2785 // second packet of 1002 bytes is dropped as well.
2788 this,
2789 1001 + 1002);
2791 }
2792
2795}
2796
2797/**
2798 * \ingroup wifi-test
2799 * \ingroup tests
2800 *
2801 * \brief PHY listener for OFDMA tests
2802 */
2804{
2805 public:
2807
2808 void NotifyRxStart(Time duration) override
2809 {
2810 NS_LOG_FUNCTION(this << duration);
2813 m_lastRxSuccess = false;
2814 }
2815
2816 void NotifyRxEndOk() override
2817 {
2818 NS_LOG_FUNCTION(this);
2820 ++m_notifyRxEnd;
2821 m_lastRxSuccess = true;
2822 }
2823
2824 void NotifyRxEndError() override
2825 {
2826 NS_LOG_FUNCTION(this);
2828 ++m_notifyRxEnd;
2829 m_lastRxSuccess = false;
2830 }
2831
2832 void NotifyTxStart(Time duration, double txPowerDbm) override
2833 {
2834 NS_LOG_FUNCTION(this << duration << txPowerDbm);
2835 }
2836
2838 WifiChannelListType channelType,
2839 const std::vector<Time>& /*per20MhzDurations*/) override
2840 {
2841 NS_LOG_FUNCTION(this << duration << channelType);
2842 }
2843
2844 void NotifySwitchingStart(Time duration) override
2845 {
2846 }
2847
2848 void NotifySleep() override
2849 {
2850 }
2851
2852 void NotifyOff() override
2853 {
2854 }
2855
2856 void NotifyWakeup() override
2857 {
2858 }
2859
2860 void NotifyOn() override
2861 {
2862 }
2863
2864 /**
2865 * Reset function.
2866 */
2867 void Reset()
2868 {
2869 m_notifyRxStart = 0;
2870 m_notifyRxEnd = 0;
2872 m_lastRxEnd = Seconds(0);
2873 m_lastRxSuccess = false;
2874 }
2875
2876 /**
2877 * Return the number of RX start notifications that has been received since the last reset.
2878 * \return the number of RX start notifications that has been received
2879 */
2881 {
2882 return m_notifyRxStart;
2883 }
2884
2885 /**
2886 * Return the number of RX end notifications that has been received since the last reset.
2887 * \return the number of RX end notifications that has been received
2888 */
2890 {
2891 return m_notifyRxEnd;
2892 }
2893
2894 /**
2895 * Return the time at which the last RX start notification has been received.
2896 * \return the time at which the last RX start notification has been received
2897 */
2899 {
2900 return m_lastRxStart;
2901 }
2902
2903 /**
2904 * Return the time at which the last RX end notification has been received.
2905 * \return the time at which the last RX end notification has been received
2906 */
2908 {
2909 return m_lastRxEnd;
2910 }
2911
2912 /**
2913 * Return whether last RX has been successful.
2914 * \return true if last RX has been successful, false otherwise
2915 */
2916 bool IsLastRxSuccess() const
2917 {
2918 return m_lastRxSuccess;
2919 }
2920
2921 private:
2922 uint32_t m_notifyRxStart{0}; ///< count number of RX start notifications
2923 uint32_t m_notifyRxEnd{0}; ///< count number of RX end notifications
2924 Time m_lastRxStart{Seconds(0)}; ///< last time a RX start notification has been received
2925 Time m_lastRxEnd{Seconds(0)}; ///< last time a RX end notification has been received
2926 bool m_lastRxSuccess{false}; ///< flag whether last RX has been successful
2927};
2928
2929/**
2930 * \ingroup wifi-test
2931 * \ingroup tests
2932 *
2933 * \brief UL-OFDMA PHY test
2934 */
2936{
2937 public:
2938 /**
2939 * Erroneous info included in a TRIGVECTOR
2940 */
2942 {
2943 NONE = 0,
2947 };
2948
2950 ~TestUlOfdmaPhyTransmission() override;
2951
2952 private:
2953 void DoSetup() override;
2954 void DoTeardown() override;
2955 void DoRun() override;
2956
2957 /**
2958 * Get TXVECTOR for HE TB PPDU.
2959 * \param txStaId the ID of the TX STA
2960 * \param index the RU index used for the transmission
2961 * \param bssColor the BSS color of the TX STA
2962 * \return the TXVECTOR for HE TB PPDU
2963 */
2964 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2965 std::size_t index,
2966 uint8_t bssColor) const;
2967 /**
2968 * Set TRIGVECTOR for HE TB PPDU
2969 *
2970 * \param bssColor the BSS color of the TX STA
2971 * \param error the erroneous info (if any) in the TRIGVECTOR to set
2972 */
2973 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2974 /**
2975 * Send HE TB PPDU function
2976 * \param txStaId the ID of the TX STA
2977 * \param index the RU index used for the transmission
2978 * \param payloadSize the size of the payload in bytes
2979 * \param uid the UID of the trigger frame that is initiating this transmission
2980 * \param bssColor the BSS color of the TX STA
2981 * \param incrementUid whether UID shall be incremented
2982 */
2983 void SendHeTbPpdu(uint16_t txStaId,
2984 std::size_t index,
2985 std::size_t payloadSize,
2986 uint64_t uid,
2987 uint8_t bssColor,
2988 bool incrementUid);
2989
2990 /**
2991 * Send HE SU PPDU function
2992 * \param txStaId the ID of the TX STA
2993 * \param payloadSize the size of the payload in bytes
2994 * \param uid the UID of the trigger frame that is initiating this transmission
2995 * \param bssColor the BSS color of the TX STA
2996 */
2997 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
2998
2999 /**
3000 * Set the BSS color
3001 * \param phy the PHY
3002 * \param bssColor the BSS color
3003 */
3004 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3005
3006 /**
3007 * Set the PSD limit
3008 * \param phy the PHY
3009 * \param psdLimit the PSD limit in dBm/MHz
3010 */
3011 void SetPsdLimit(Ptr<WifiPhy> phy, double psdLimit);
3012
3013 /**
3014 * Generate interference function
3015 * \param interferencePsd the PSD of the interference to be generated
3016 * \param duration the duration of the interference
3017 */
3018 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3019 /**
3020 * Stop interference function
3021 */
3022 void StopInterference();
3023
3024 /**
3025 * Run one function
3026 */
3027 void RunOne();
3028
3029 /**
3030 * Check the received PSDUs from STA1
3031 * \param expectedSuccess the expected number of success
3032 * \param expectedFailures the expected number of failures
3033 * \param expectedBytes the expected number of bytes
3034 */
3035 void CheckRxFromSta1(uint32_t expectedSuccess,
3036 uint32_t expectedFailures,
3037 uint32_t expectedBytes);
3038
3039 /**
3040 * Check the received PSDUs from STA2
3041 * \param expectedSuccess the expected number of success
3042 * \param expectedFailures the expected number of failures
3043 * \param expectedBytes the expected number of bytes
3044 */
3045 void CheckRxFromSta2(uint32_t expectedSuccess,
3046 uint32_t expectedFailures,
3047 uint32_t expectedBytes);
3048
3049 /**
3050 * Check the received power for the non-OFDMA of the HE TB PPDUs over the given band
3051 * \param phy the PHY
3052 * \param band the indices of the band over which the power is measured
3053 * \param expectedRxPower the expected received power in W
3054 */
3057 double expectedRxPower);
3058 /**
3059 * Check the received power for the OFDMA part of the HE TB PPDUs over the given band
3060 * \param phy the PHY
3061 * \param band the indices of the band over which the power is measured
3062 * \param expectedRxPower the expected received power in W
3063 */
3066 double expectedRxPower);
3067
3068 /**
3069 * Verify all events are cleared at end of TX or RX
3070 */
3071 void VerifyEventsCleared();
3072
3073 /**
3074 * Check the PHY state
3075 * \param phy the PHY
3076 * \param expectedState the expected state of the PHY
3077 */
3078 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
3079 /// \copydoc CheckPhyState
3081
3082 /**
3083 * Check the the number of RX start notifications at the AP as well as the last time a RX start
3084 * has been notified
3085 * \param expectedNotifications the expected number of RX start notifications at the AP
3086 * \param expectedLastNotification the expected time of the last RX start notification at the AP
3087 */
3088 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3089 /**
3090 * Check the the number of RX end notifications at the AP as well as the last time a RX end has
3091 * been notified
3092 * \param expectedNotifications the expected number of RX end notifications at the AP
3093 * \param expectedLastNotification the expected time of the last RX end notification at the AP
3094 * \param expectedSuccess true if the last RX notification indicates a success, false otherwise
3095 */
3096 void CheckApRxEnd(uint32_t expectedNotifications,
3097 Time expectedLastNotification,
3098 bool expectedSuccess);
3099
3100 /**
3101 * Reset function
3102 */
3103 void Reset();
3104
3105 /**
3106 * Receive success function
3107 * \param psdu the PSDU
3108 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
3109 * \param txVector the transmit vector
3110 * \param statusPerMpdu reception status per MPDU
3111 */
3113 RxSignalInfo rxSignalInfo,
3114 WifiTxVector txVector,
3115 std::vector<bool> statusPerMpdu);
3116
3117 /**
3118 * Receive failure function
3119 * \param psdu the PSDU
3120 */
3121 void RxFailure(Ptr<const WifiPsdu> psdu);
3122
3123 /**
3124 * Schedule test to perform.
3125 * The interference generation should be scheduled apart.
3126 *
3127 * \param delay the reference delay to schedule the events
3128 * \param solicited flag indicating if HE TB PPDUs were solicited by the AP
3129 * \param expectedStateAtEnd the expected state of the PHY at the end of the reception
3130 * \param expectedSuccessFromSta1 the expected number of success from STA 1
3131 * \param expectedFailuresFromSta1 the expected number of failures from STA 1
3132 * \param expectedBytesFromSta1 the expected number of bytes from STA 1
3133 * \param expectedSuccessFromSta2 the expected number of success from STA 2
3134 * \param expectedFailuresFromSta2 the expected number of failures from STA 2
3135 * \param expectedBytesFromSta2 the expected number of bytes from STA 2
3136 * \param scheduleTxSta1 flag indicating to schedule a HE TB PPDU from STA 1
3137 * \param ulTimeDifference delay between HE TB PPDU from STA 1 and HE TB PPDU from STA 2
3138 * are received
3139 * \param expectedStateBeforeEnd the expected state of the PHY before the end of the
3140 * transmission
3141 * \param error the erroneous info (if any) in the TRIGVECTOR to set
3142 */
3143 void ScheduleTest(Time delay,
3144 bool solicited,
3145 WifiPhyState expectedStateAtEnd,
3146 uint32_t expectedSuccessFromSta1,
3147 uint32_t expectedFailuresFromSta1,
3148 uint32_t expectedBytesFromSta1,
3149 uint32_t expectedSuccessFromSta2,
3150 uint32_t expectedFailuresFromSta2,
3151 uint32_t expectedBytesFromSta2,
3152 bool scheduleTxSta1 = true,
3153 Time ulTimeDifference = Seconds(0),
3154 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3155 TrigVectorInfo error = NONE);
3156
3157 /**
3158 * Schedule power measurement related checks.
3159 *
3160 * \param delay the reference delay used to schedule the events
3161 * \param rxPowerNonOfdmaRu1 the received power (in watts) on the non-OFDMA part of RU1
3162 * \param rxPowerNonOfdmaRu2 the received power (in watts) on the non-OFDMA part of RU2
3163 * \param rxPowerOfdmaRu1 the received power (in watts) on RU1
3164 * \param rxPowerOfdmaRu2 the received power (in watts) on RU2
3165 */
3167 double rxPowerNonOfdmaRu1,
3168 double rxPowerNonOfdmaRu2,
3169 double rxPowerOfdmaRu1,
3170 double rxPowerOfdmaRu2);
3171 /**
3172 * Log scenario description
3173 *
3174 * \param log the scenario description to add to log
3175 */
3176 void LogScenario(std::string log) const;
3177
3182
3183 std::shared_ptr<OfdmaTestPhyListener>
3184 m_apPhyStateListener; ///< listener for AP PHY state transitions
3185
3187
3188 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
3189 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
3190 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
3191 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
3192 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
3193 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
3194
3195 uint16_t m_frequency; ///< frequency in MHz
3196 uint16_t m_channelWidth; ///< channel width in MHz
3197 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
3198};
3199
3201 : TestCase("UL-OFDMA PHY test"),
3202 m_countRxSuccessFromSta1(0),
3203 m_countRxSuccessFromSta2(0),
3204 m_countRxFailureFromSta1(0),
3205 m_countRxFailureFromSta2(0),
3206 m_countRxBytesFromSta1(0),
3207 m_countRxBytesFromSta2(0),
3208 m_frequency(DEFAULT_FREQUENCY),
3209 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3210 m_expectedPpduDuration(NanoSeconds(271200))
3211{
3212}
3213
3214void
3216 std::size_t payloadSize,
3217 uint64_t uid,
3218 uint8_t bssColor)
3219{
3220 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3221 WifiConstPsduMap psdus;
3222
3224 0,
3226 800,
3227 1,
3228 1,
3229 0,
3231 false,
3232 false,
3233 false,
3234 bssColor);
3235
3236 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3237 WifiMacHeader hdr;
3239 hdr.SetQosTid(0);
3240 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3241 std::ostringstream addr;
3242 addr << "00:00:00:00:00:0" << txStaId;
3243 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3244 hdr.SetSequenceNumber(1);
3245 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3246 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3247
3249 if (txStaId == 1)
3250 {
3251 phy = m_phySta1;
3252 }
3253 else if (txStaId == 2)
3254 {
3255 phy = m_phySta2;
3256 }
3257 else if (txStaId == 3)
3258 {
3259 phy = m_phySta3;
3260 }
3261 else if (txStaId == 0)
3262 {
3263 phy = m_phyAp;
3264 }
3265 phy->SetPpduUid(uid);
3266 phy->Send(psdus, txVector);
3267}
3268
3271 std::size_t index,
3272 uint8_t bssColor) const
3273{
3275 0,
3277 1600,
3278 1,
3279 1,
3280 0,
3282 false,
3283 false,
3284 false,
3285 bssColor);
3286
3288 if (m_channelWidth == 20)
3289 {
3290 ruType = HeRu::RU_106_TONE;
3291 }
3292 else if (m_channelWidth == 40)
3293 {
3294 ruType = HeRu::RU_242_TONE;
3295 }
3296 else if (m_channelWidth == 80)
3297 {
3298 ruType = HeRu::RU_484_TONE;
3299 }
3300 else if (m_channelWidth == 160)
3301 {
3302 ruType = HeRu::RU_996_TONE;
3303 }
3304 else
3305 {
3306 NS_ASSERT_MSG(false, "Unsupported channel width");
3307 }
3308
3309 bool primary80MHz = true;
3310 if (m_channelWidth == 160 && index == 2)
3311 {
3312 primary80MHz = false;
3313 index = 1;
3314 }
3315 HeRu::RuSpec ru(ruType, index, primary80MHz);
3316 txVector.SetRu(ru, txStaId);
3317 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3318 txVector.SetNss(1, txStaId);
3319 return txVector;
3320}
3321
3322void
3324{
3325 uint16_t channelWidth = m_channelWidth;
3326 if (error == CHANNEL_WIDTH)
3327 {
3328 channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
3329 }
3330
3331 WifiTxVector txVector(HePhy::GetHeMcs7(),
3332 0,
3334 1600,
3335 1,
3336 1,
3337 0,
3338 channelWidth,
3339 false,
3340 false,
3341 false,
3342 bssColor);
3343
3345 if (channelWidth == 20)
3346 {
3347 ruType = HeRu::RU_106_TONE;
3348 }
3349 else if (channelWidth == 40)
3350 {
3351 ruType = HeRu::RU_242_TONE;
3352 }
3353 else if (channelWidth == 80)
3354 {
3355 ruType = HeRu::RU_484_TONE;
3356 }
3357 else if (channelWidth == 160)
3358 {
3359 ruType = HeRu::RU_996_TONE;
3360 }
3361 else
3362 {
3363 NS_ASSERT_MSG(false, "Unsupported channel width");
3364 }
3365
3366 uint16_t aid1 = (error == AID ? 3 : 1);
3367 uint16_t aid2 = (error == AID ? 4 : 2);
3368
3369 HeRu::RuSpec ru1(ruType, 1, true);
3370 txVector.SetRu(ru1, aid1);
3371 txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3372 txVector.SetNss(1, aid1);
3373
3374 HeRu::RuSpec ru2(ruType, (channelWidth == 160 ? 1 : 2), (channelWidth != 160));
3375 txVector.SetRu(ru2, aid2);
3376 txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3377 txVector.SetNss(1, aid2);
3378
3379 uint16_t length;
3380 std::tie(length, m_expectedPpduDuration) =
3382 txVector,
3383 m_phyAp->GetPhyBand());
3384 if (error == UL_LENGTH)
3385 {
3386 ++length;
3387 }
3388 txVector.SetLength(length);
3389 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
3390 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3391}
3392
3393void
3395 std::size_t index,
3396 std::size_t payloadSize,
3397 uint64_t uid,
3398 uint8_t bssColor,
3399 bool incrementUid)
3400{
3401 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3402 WifiConstPsduMap psdus;
3403
3404 if (incrementUid)
3405 {
3406 ++uid;
3407 }
3408
3409 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3410 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3411 WifiMacHeader hdr;
3413 hdr.SetQosTid(0);
3414 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3415 std::ostringstream addr;
3416 addr << "00:00:00:00:00:0" << txStaId;
3417 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3418 hdr.SetSequenceNumber(1);
3419 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3420 psdus.insert(std::make_pair(txStaId, psdu));
3421
3423 if (txStaId == 1)
3424 {
3425 phy = m_phySta1;
3426 }
3427 else if (txStaId == 2)
3428 {
3429 phy = m_phySta2;
3430 }
3431 else if (txStaId == 3)
3432 {
3433 phy = m_phySta3;
3434 }
3435
3436 Time txDuration =
3437 phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
3438 txVector.SetLength(
3439 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3440
3441 phy->SetPpduUid(uid);
3442 phy->Send(psdus, txVector);
3443}
3444
3445void
3447{
3448 NS_LOG_FUNCTION(this << duration);
3450 m_phyInterferer->SetPeriod(duration);
3453}
3454
3455void
3457{
3459}
3460
3462{
3463}
3464
3465void
3467 RxSignalInfo rxSignalInfo,
3468 WifiTxVector txVector,
3469 std::vector<bool> /*statusPerMpdu*/)
3470{
3471 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3472 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3473 {
3475 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3476 }
3477 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3478 {
3480 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3481 }
3482}
3483
3484void
3486{
3487 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3488 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3489 {
3491 }
3492 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3493 {
3495 }
3496}
3497
3498void
3500 uint32_t expectedFailures,
3501 uint32_t expectedBytes)
3502{
3504 expectedSuccess,
3505 "The number of successfully received packets from STA 1 is not correct!");
3508 expectedFailures,
3509 "The number of unsuccessfuly received packets from STA 1 is not correct!");
3511 expectedBytes,
3512 "The number of bytes received from STA 1 is not correct!");
3513}
3514
3515void
3517 uint32_t expectedFailures,
3518 uint32_t expectedBytes)
3519{
3521 expectedSuccess,
3522 "The number of successfully received packets from STA 2 is not correct!");
3525 expectedFailures,
3526 "The number of unsuccessfuly received packets from STA 2 is not correct!");
3528 expectedBytes,
3529 "The number of bytes received from STA 2 is not correct!");
3530}
3531
3532void
3535 double expectedRxPower)
3536{
3537 Ptr<Event> event = phy->GetCurrentEvent();
3538 NS_ASSERT(event);
3539 auto rxPower = event->GetRxPowerW(band);
3540 NS_LOG_FUNCTION(this << band << expectedRxPower << rxPower);
3541 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3543 expectedRxPower,
3544 5e-3,
3545 "RX power " << rxPower << " over (" << band
3546 << ") does not match expected power " << expectedRxPower
3547 << " at " << Simulator::Now());
3548}
3549
3550void
3553 double expectedRxPower)
3554{
3555 /**
3556 * The current event cannot be used since it points to the preamble part of the HE TB PPDU.
3557 * We will have to check if the expected power is indeed the max power returning a positive
3558 * duration when calling GetEnergyDuration.
3559 */
3560 NS_LOG_FUNCTION(this << band << expectedRxPower);
3561 double step = 5e-3;
3562 if (expectedRxPower > 0.0)
3563 {
3565 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3566 true,
3567 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3568 << Simulator::Now());
3570 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3571 false,
3572 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3573 << Simulator::Now());
3574 }
3575 else
3576 {
3578 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3579 false,
3580 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3581 << Simulator::Now());
3582 }
3583}
3584
3585void
3587{
3589 nullptr,
3590 "m_currentEvent for AP was not cleared");
3592 nullptr,
3593 "m_currentEvent for STA 1 was not cleared");
3595 nullptr,
3596 "m_currentEvent for STA 2 was not cleared");
3597}
3598
3599void
3601{
3602 // This is needed to make sure PHY state will be checked as the last event if a state change
3603 // occurred at the exact same time as the check
3605}
3606
3607void
3609 WifiPhyState expectedState)
3610{
3611 WifiPhyState currentState;
3612 PointerValue ptr;
3613 phy->GetAttribute("State", ptr);
3614 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
3615 currentState = state->GetState();
3616 NS_LOG_FUNCTION(this << currentState);
3617 NS_TEST_ASSERT_MSG_EQ(currentState,
3618 expectedState,
3619 "PHY State " << currentState << " does not match expected state "
3620 << expectedState << " at " << Simulator::Now());
3621}
3622
3623void
3625 Time expectedLastNotification)
3626{
3627 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxStartNotifications(),
3628 expectedNotifications,
3629 "Number of RX start notifications "
3630 << m_apPhyStateListener->GetNumRxStartNotifications()
3631 << " does not match expected count " << expectedNotifications
3632 << " for AP at " << Simulator::Now());
3633 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxStartNotification(),
3634 expectedLastNotification,
3635 "Last time RX start notification has been received "
3636 << m_apPhyStateListener->GetLastRxStartNotification()
3637 << " does not match expected time " << expectedLastNotification
3638 << " for AP at " << Simulator::Now());
3639}
3640
3641void
3643 Time expectedLastNotification,
3644 bool expectedSuccess)
3645{
3646 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxEndNotifications(),
3647 expectedNotifications,
3648 "Number of RX end notifications "
3649 << m_apPhyStateListener->GetNumRxEndNotifications()
3650 << " does not match expected count " << expectedNotifications
3651 << " for AP at " << Simulator::Now());
3652 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxEndNotification(),
3653 expectedLastNotification,
3654 "Last time RX end notification has been received "
3655 << m_apPhyStateListener->GetLastRxEndNotification()
3656 << " does not match expected time " << expectedLastNotification
3657 << " for AP at " << Simulator::Now());
3659 expectedSuccess,
3660 "Last time RX end notification indicated a "
3661 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3662 << " but expected a " << (expectedSuccess ? "success" : "failure")
3663 << " for AP at " << Simulator::Now());
3664}
3665
3666void
3668{
3678 SetBssColor(m_phyAp, 0);
3679 m_apPhyStateListener->Reset();
3680}
3681
3682void
3684{
3685 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3686 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3687 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3688}
3689
3690void
3692{
3693 NS_LOG_FUNCTION(this << phy << psdLimit);
3694 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3695}
3696
3697void
3699{
3700 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
3701 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
3702 lossModel->SetFrequency(m_frequency);
3703 spectrumChannel->AddPropagationLossModel(lossModel);
3705 CreateObject<ConstantSpeedPropagationDelayModel>();
3706 spectrumChannel->SetPropagationDelayModel(delayModel);
3707
3708 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3709 CreateObject<ThresholdPreambleDetectionModel>();
3710 preambleDetectionModel->SetAttribute(
3711 "MinimumRssi",
3713 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3714 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3715
3716 Ptr<Node> apNode = CreateObject<Node>();
3717 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
3718 apDev->SetStandard(WIFI_STANDARD_80211ax);
3719 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
3720 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3721 apDev->SetMac(apMac);
3722 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
3723 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
3724 apDev->SetHeConfiguration(heConfiguration);
3725 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
3726 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3727 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
3728 m_phyAp->SetErrorRateModel(apErrorModel);
3729 m_phyAp->SetDevice(apDev);
3730 m_phyAp->AddChannel(spectrumChannel);
3734 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3735 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
3736 m_phyAp->SetMobility(apMobility);
3737 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3739 apDev->SetPhy(m_phyAp);
3740 apMac->SetWifiPhys({m_phyAp});
3741 apNode->AggregateObject(apMobility);
3742 apNode->AddDevice(apDev);
3743
3744 Ptr<Node> sta1Node = CreateObject<Node>();
3745 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
3746 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
3747 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3748 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
3749 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
3750 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3751 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
3752 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3753 m_phySta1->SetDevice(sta1Dev);
3754 m_phySta1->AddChannel(spectrumChannel);
3756 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3757 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
3758 m_phySta1->SetMobility(sta1Mobility);
3759 sta1Dev->SetPhy(m_phySta1);
3760 sta1Node->AggregateObject(sta1Mobility);
3761 sta1Node->AddDevice(sta1Dev);
3762
3763 Ptr<Node> sta2Node = CreateObject<Node>();
3764 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
3765 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
3766 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3767 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
3768 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
3769 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3770 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
3771 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3772 m_phySta2->SetDevice(sta2Dev);
3773 m_phySta2->AddChannel(spectrumChannel);
3775 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3776 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
3777 m_phySta2->SetMobility(sta2Mobility);
3778 sta2Dev->SetPhy(m_phySta2);
3779 sta2Node->AggregateObject(sta2Mobility);
3780 sta2Node->AddDevice(sta2Dev);
3781
3782 Ptr<Node> sta3Node = CreateObject<Node>();
3783 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
3784 sta3Dev->SetStandard(WIFI_STANDARD_80211ax);
3785 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3786 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
3787 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
3788 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3789 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
3790 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3791 m_phySta3->SetDevice(sta3Dev);
3792 m_phySta3->AddChannel(spectrumChannel);
3794 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3795 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
3796 m_phySta3->SetMobility(sta3Mobility);
3797 sta3Dev->SetPhy(m_phySta3);
3798 sta3Node->AggregateObject(sta3Mobility);
3799 sta3Node->AddDevice(sta3Dev);
3800
3801 Ptr<Node> interfererNode = CreateObject<Node>();
3802 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
3803 m_phyInterferer = CreateObject<WaveformGenerator>();
3804 m_phyInterferer->SetDevice(interfererDev);
3805 m_phyInterferer->SetChannel(spectrumChannel);
3807 interfererNode->AddDevice(interfererDev);
3808
3809 // Configure power attributes of all wifi devices
3810 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3811 for (auto& phy : phys)
3812 {
3813 phy->SetAttribute("TxGain", DoubleValue(1.0));
3814 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3815 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3816 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3817 phy->SetAttribute("RxGain", DoubleValue(2.0));
3818 // test assumes no rejection power for simplicity
3819 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3820 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3821 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3822 }
3823}
3824
3825void
3827{
3828 m_phyAp->Dispose();
3829 m_phyAp = nullptr;
3830 m_phySta1->Dispose();
3831 m_phySta1 = nullptr;
3832 m_phySta2->Dispose();
3833 m_phySta2 = nullptr;
3834 m_phySta3->Dispose();
3835 m_phySta3 = nullptr;
3837 m_phyInterferer = nullptr;
3838}
3839
3840void
3842{
3843 NS_LOG_INFO(log);
3844}
3845
3846void
3848 bool solicited,
3849 WifiPhyState expectedStateAtEnd,
3850 uint32_t expectedSuccessFromSta1,
3851 uint32_t expectedFailuresFromSta1,
3852 uint32_t expectedBytesFromSta1,
3853 uint32_t expectedSuccessFromSta2,
3854 uint32_t expectedFailuresFromSta2,
3855 uint32_t expectedBytesFromSta2,
3856 bool scheduleTxSta1,
3857 Time ulTimeDifference,
3858 WifiPhyState expectedStateBeforeEnd,
3859 TrigVectorInfo error)
3860{
3861 static uint64_t uid = 0;
3862
3863 // AP sends an SU packet preceding HE TB PPDUs
3866 this,
3867 0,
3868 50,
3869 ++uid,
3870 0);
3871 if (!solicited)
3872 {
3873 // UID of TB PPDUs will be different than the one of the preceding frame
3874 ++uid;
3875 }
3876 else
3877 {
3879 }
3880 // STA1 and STA2 send MU UL PPDUs addressed to AP
3883 m_apPhyStateListener.get());
3884 if (scheduleTxSta1)
3885 {
3886 Simulator::Schedule(delay,
3888 this,
3889 1,
3890 1,
3891 1000,
3892 uid,
3893 0,
3894 false);
3895 }
3896 Simulator::Schedule(delay + ulTimeDifference,
3898 this,
3899 2,
3900 2,
3901 1001,
3902 uid,
3903 0,
3904 false);
3905
3906 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3909 this,
3910 m_phyAp,
3911 expectedStateBeforeEnd);
3912 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3914 this,
3915 m_phyAp,
3916 expectedStateAtEnd);
3917 // TODO: add checks on TX stop for STAs
3918
3919 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3920 expectedFailuresFromSta2 >
3921 0)
3922 {
3923 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3924 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3925 // The expected time at which the reception is started corresponds to the time at which the
3926 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3927 const Time expectedPayloadStart = delay + MicroSeconds(48);
3928 // The expected time at which the reception is terminated corresponds to the time at which
3929 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3930 // received HE TB PPDU and the last received HE TB PPDU.
3931 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3932 // At the end of the transmission, verify that a single RX start notification shall have
3933 // been notified when the reception of the first HE RB PPDU starts.
3934 Simulator::Schedule(expectedPayloadEnd,
3936 this,
3937 1,
3938 Simulator::Now() + expectedPayloadStart);
3939 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3940 // notification shall have been notified when the reception of the last HE RB PPDU ends
3941 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3943 this,
3944 1,
3945 Simulator::Now() + expectedPayloadEnd,
3946 isSuccess);
3947 }
3948
3949 delay += MilliSeconds(100);
3950 // Check reception state from STA 1
3951 Simulator::Schedule(delay,
3953 this,
3954 expectedSuccessFromSta1,
3955 expectedFailuresFromSta1,
3956 expectedBytesFromSta1);
3957 // Check reception state from STA 2
3958 Simulator::Schedule(delay,
3960 this,
3961 expectedSuccessFromSta2,
3962 expectedFailuresFromSta2,
3963 expectedBytesFromSta2);
3964 // Verify events data have been cleared
3966
3967 delay += MilliSeconds(100);
3969}
3970
3971void
3973 double rxPowerNonOfdmaRu1,
3974 double rxPowerNonOfdmaRu2,
3975 double rxPowerOfdmaRu1,
3976 double rxPowerOfdmaRu2)
3977{
3978 Time detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3979 WifiTxVector txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3980 WifiTxVector txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3982 Time nonOfdmaDuration = hePhy->CalculateNonHeDurationForHeTb(txVectorSta2);
3983 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonHeDurationForHeTb(txVectorSta1));
3984
3985 std::vector<double> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3986 std::vector<WifiSpectrumBandInfo> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3987 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
3988 std::vector<double> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
3989 std::vector<WifiSpectrumBandInfo> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
3990 hePhy->GetRuBandForRx(txVectorSta2, 2)};
3991
3992 for (uint8_t i = 0; i < 2; ++i)
3993 {
3994 /**
3995 * Perform checks at AP
3996 */
3997 // Check received power on non-OFDMA portion
3999 delay + detectionDuration +
4000 NanoSeconds(1), // just after beginning of portion (once event is stored)
4002 this,
4003 m_phyAp,
4004 nonOfdmaBand[i],
4005 rxPowerNonOfdma[i]);
4006 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4008 this,
4009 m_phyAp,
4010 nonOfdmaBand[i],
4011 rxPowerNonOfdma[i]);
4012 // Check received power on OFDMA portion
4013 Simulator::Schedule(delay + nonOfdmaDuration +
4014 NanoSeconds(1), // just after beginning of portion
4016 this,
4017 m_phyAp,
4018 ofdmaBand[i],
4019 rxPowerOfdma[i]);
4021 NanoSeconds(1), // just before end of portion
4023 this,
4024 m_phyAp,
4025 ofdmaBand[i],
4026 rxPowerOfdma[i]);
4027
4028 /**
4029 * Perform checks for non-transmitting STA (STA 3).
4030 * Cannot use CheckNonOfdmaRxPower method since current event may be reset if
4031 * preamble not detected (e.g. not on primary).
4032 */
4033 // Check received power on non-OFDMA portion
4035 delay + detectionDuration +
4036 NanoSeconds(1), // just after beginning of portion (once event is stored)
4038 this,
4039 m_phySta3,
4040 nonOfdmaBand[i],
4041 rxPowerNonOfdma[i]);
4042 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4044 this,
4045 m_phySta3,
4046 nonOfdmaBand[i],
4047 rxPowerNonOfdma[i]);
4048 // Check received power on OFDMA portion
4049 Simulator::Schedule(delay + nonOfdmaDuration +
4050 NanoSeconds(1), // just after beginning of portion
4052 this,
4053 m_phySta3,
4054 ofdmaBand[i],
4055 rxPowerOfdma[i]);
4057 NanoSeconds(1), // just before end of portion
4059 this,
4060 m_phySta3,
4061 ofdmaBand[i],
4062 rxPowerOfdma[i]);
4063 }
4064
4065 if (rxPowerOfdmaRu1 != 0.0)
4066 {
4067 /**
4068 * Perform checks for transmitting STA (STA 2) to ensure it has correctly logged
4069 * power received from other transmitting STA (STA 1).
4070 * Cannot use CheckNonOfdmaRxPower method since current event not set.
4071 */
4072 double rxPowerNonOfdmaSta1Only =
4073 (m_channelWidth >= 40)
4074 ? rxPowerNonOfdma[0]
4075 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4076 // Check received power on non-OFDMA portion
4078 delay + detectionDuration +
4079 NanoSeconds(1), // just after beginning of portion (once event is stored)
4081 this,
4082 m_phySta2,
4083 nonOfdmaBand[0],
4084 rxPowerNonOfdmaSta1Only);
4085 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4087 this,
4088 m_phySta2,
4089 nonOfdmaBand[0],
4090 rxPowerNonOfdmaSta1Only);
4091 // Check received power on OFDMA portion
4092 Simulator::Schedule(delay + nonOfdmaDuration +
4093 NanoSeconds(1), // just after beginning of portion
4095 this,
4096 m_phySta2,
4097 ofdmaBand[0],
4098 rxPowerOfdma[0]);
4100 NanoSeconds(1), // just before end of portion
4102 this,
4103 m_phySta2,
4104 ofdmaBand[0],
4105 rxPowerOfdma[0]);
4106 }
4107}
4108
4109void
4111{
4114 int64_t streamNumber = 0;
4115 m_phyAp->AssignStreams(streamNumber);
4116 m_phySta1->AssignStreams(streamNumber);
4117 m_phySta2->AssignStreams(streamNumber);
4118 m_phySta3->AssignStreams(streamNumber);
4119
4120 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
4125
4134
4135 Time delay = Seconds(0.0);
4137 delay += Seconds(1.0);
4138
4139 /**
4140 * In all the following tests, 2 HE TB PPDUs of the same UL MU transmission
4141 * are sent on RU 1 for STA 1 and RU 2 for STA 2.
4142 * The difference between solicited and unsolicited lies in that their PPDU
4143 * ID correspond to the one of the immediately preceding HE SU PPDU (thus
4144 * mimicking trigger frame reception).
4145 */
4146
4147 //---------------------------------------------------------------------------
4148 // Verify that both solicited HE TB PPDUs have been corrected received
4149 Simulator::Schedule(delay,
4151 this,
4152 "Reception of solicited HE TB PPDUs");
4153 ScheduleTest(delay,
4154 true,
4155 WifiPhyState::IDLE,
4156 1,
4157 0,
4158 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4159 1,
4160 0,
4161 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4162 delay += Seconds(1.0);
4163
4164 //---------------------------------------------------------------------------
4165 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4166 // corrected received
4168 delay,
4170 this,
4171 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4172 ScheduleTest(delay,
4173 true,
4174 WifiPhyState::IDLE,
4175 1,
4176 0,
4177 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4178 1,
4179 0,
4180 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4181 true,
4182 NanoSeconds(100));
4183 delay += Seconds(1.0);
4184
4185 //---------------------------------------------------------------------------
4186 // Verify that no unsolicited HE TB PPDU is received
4187 Simulator::Schedule(delay,
4189 this,
4190 "Dropping of unsolicited HE TB PPDUs");
4191 ScheduleTest(delay,
4192 false,
4193 WifiPhyState::IDLE,
4194 0,
4195 0,
4196 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4197 0,
4198 0,
4199 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4200 true,
4201 Seconds(0),
4202 WifiPhyState::CCA_BUSY);
4203 delay += Seconds(1.0);
4204
4205 //---------------------------------------------------------------------------
4206 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4207 Simulator::Schedule(delay,
4209 this,
4210 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4211 ScheduleTest(delay,
4212 true,
4213 WifiPhyState::IDLE,
4214 0,
4215 0,
4216 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4217 0,
4218 0,
4219 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4220 true,
4221 Seconds(0),
4222 WifiPhyState::CCA_BUSY,
4224 delay += Seconds(1.0);
4225
4226 //---------------------------------------------------------------------------
4227 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4228 Simulator::Schedule(delay,
4230 this,
4231 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4232 ScheduleTest(delay,
4233 true,
4234 WifiPhyState::IDLE,
4235 0,
4236 0,
4237 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4238 0,
4239 0,
4240 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4241 true,
4242 Seconds(0),
4243 WifiPhyState::CCA_BUSY,
4244 UL_LENGTH);
4245 delay += Seconds(1.0);
4246
4247 //---------------------------------------------------------------------------
4248 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4249 Simulator::Schedule(delay,
4251 this,
4252 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4253 ScheduleTest(delay,
4254 true,
4255 WifiPhyState::IDLE,
4256 0,
4257 0,
4258 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4259 0,
4260 0,
4261 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4262 true,
4263 Seconds(0),
4264 WifiPhyState::CCA_BUSY,
4265 AID);
4266 delay += Seconds(1.0);
4267
4268 //---------------------------------------------------------------------------
4269 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4270 // impacted
4272 delay,
4274 this,
4275 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4276 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4277 BandInfo bandInfo;
4278 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
4279 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4280 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4281 Bands bands;
4282 bands.push_back(bandInfo);
4283
4284 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4285 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4286 double interferencePower = 0.1; // watts
4287 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
4288
4291 this,
4292 interferencePsdRu1,
4293 MilliSeconds(100));
4295 delay,
4296 true,
4297 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4298 // interference
4299 0,
4300 1,
4301 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4302 1,
4303 0,
4304 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4305 delay += Seconds(1.0);
4306
4307 //---------------------------------------------------------------------------
4308 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4309 // impacted
4311 delay,
4313 this,
4314 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4315 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4316 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
4317 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4318 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4319 bands.clear();
4320 bands.push_back(bandInfo);
4321
4322 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4323 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4324 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
4325
4328 this,
4329 interferencePsdRu2,
4330 MilliSeconds(100));
4331 ScheduleTest(delay,
4332 true,
4333 (m_channelWidth >= 40)
4334 ? WifiPhyState::IDLE
4335 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4336 // generated in its primary channel
4337 1,
4338 0,
4339 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4340 0,
4341 1,
4342 0); // Reception of the PSDU from STA 2 should have failed (since interference
4343 // occupies RU 2)
4344 delay += Seconds(1.0);
4345
4346 //---------------------------------------------------------------------------
4347 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4348 // been impacted
4349 Simulator::Schedule(delay,
4351 this,
4352 "Reception of solicited HE TB PPDUs with interference on the full band "
4353 "during PSDU reception");
4354 // A strong non-wifi interference is generated on the full band during PSDU reception
4355 bandInfo.fc = m_frequency * 1e6;
4356 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
4357 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
4358 bands.clear();
4359 bands.push_back(bandInfo);
4360
4361 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4362 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4363 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
4364
4367 this,
4368 interferencePsdAll,
4369 MilliSeconds(100));
4371 delay,
4372 true,
4373 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4374 // interference
4375 0,
4376 1,
4377 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4378 0,
4379 1,
4380 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4381 // 2)
4382 delay += Seconds(1.0);
4383
4384 //---------------------------------------------------------------------------
4385 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4386 // solicited HE TB PPDUs have been impacted if they are on the same
4387 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4388 Simulator::Schedule(delay,
4390 this,
4391 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4392 "1 during PSDU reception");
4393 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4396 this,
4397 3,
4398 1,
4399 1002,
4400 1,
4401 0,
4402 false);
4403 // Expected figures from STA 2
4404 uint32_t succ;
4405 uint32_t fail;
4406 uint32_t bytes;
4407 if (m_channelWidth > 20)
4408 {
4409 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4410 // interference from STA 3 on distinct 20 MHz channel)
4411 succ = 1;
4412 fail = 0;
4413 bytes = 1001;
4414 }
4415 else
4416 {
4417 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4418 // same 20 MHz channel)
4419 succ = 0;
4420 fail = 1;
4421 bytes = 0;
4422 }
4423 ScheduleTest(delay,
4424 true,
4425 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4426 // interference on measurement channel width
4427 0,
4428 1,
4429 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4430 // STA 3 on same 20 MHz channel)
4431 succ,
4432 fail,
4433 bytes);
4434 delay += Seconds(1.0);
4435
4436 //---------------------------------------------------------------------------
4437 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4438 // solicited HE TB PPDUs have been impacted if they are on the same
4439 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4440 Simulator::Schedule(delay,
4442 this,
4443 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4444 "2 during PSDU reception");
4445 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4448 this,
4449 3,
4450 2,
4451 1002,
4452 1,
4453 0,
4454 false);
4455 // Expected figures from STA 1
4456 if (m_channelWidth > 20)
4457 {
4458 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4459 // interference from STA 3 on distinct 20 MHz channel)
4460 succ = 1;
4461 fail = 0;
4462 bytes = 1000;
4463 }
4464 else
4465 {
4466 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4467 // same 20 MHz channel)
4468 succ = 0;
4469 fail = 1;
4470 bytes = 0;
4471 }
4472 ScheduleTest(delay,
4473 true,
4474 (m_channelWidth >= 40)
4475 ? WifiPhyState::IDLE
4476 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4477 // TB PPDU on primary channel
4478 succ,
4479 fail,
4480 bytes,
4481 0,
4482 1,
4483 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4484 // STA 3 on same 20 MHz channel)
4485 delay += Seconds(1.0);
4486
4487 //---------------------------------------------------------------------------
4488 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4489 // impacted
4491 delay,
4493 this,
4494 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4495 // One HE SU arrives at AP during the 400ns window
4496 Simulator::Schedule(delay + NanoSeconds(300),
4498 this,
4499 3,
4500 1002,
4501 1,
4502 0);
4504 delay,
4505 true,
4506 WifiPhyState::IDLE,
4507 0,
4508 1,
4509 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4510 0,
4511 1,
4512 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4513 delay += Seconds(1.0);
4514
4515 //---------------------------------------------------------------------------
4516 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4517 // received
4518 Simulator::Schedule(delay,
4520 this,
4521 "Reception of solicited HE TB PPDU only on RU 2");
4522 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4523 // otherwise
4526 this,
4527 m_phySta3,
4528 (m_channelWidth >= 40)
4529 ? WifiPhyState::IDLE
4530 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4531 // IDLE if HE TB PPDU on primary channel
4532 ScheduleTest(delay,
4533 true,
4534 WifiPhyState::IDLE,
4535 0,
4536 0,
4537 0, // No transmission scheduled for STA 1
4538 1,
4539 0,
4540 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4541 false,
4542 Seconds(0),
4543 WifiPhyState::RX); // Measurement channel is total channel width
4544 delay += Seconds(1.0);
4545
4546 //---------------------------------------------------------------------------
4547 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4548 Simulator::Schedule(delay,
4550 this,
4551 "Measure power for reception of HE TB PPDU only on RU 2");
4552 double rxPower =
4553 DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4555 (m_channelWidth >= 40) ? 0.0 : rxPower,
4556 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4557 0.0,
4558 rxPower);
4559 ScheduleTest(delay,
4560 true,
4561 WifiPhyState::IDLE,
4562 0,
4563 0,
4564 0, // No transmission scheduled for STA 1
4565 1,
4566 0,
4567 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4568 false,
4569 Seconds(0),
4570 WifiPhyState::RX); // Measurement channel is total channel width
4571 delay += Seconds(1.0);
4572
4573 //---------------------------------------------------------------------------
4574 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4575 // limitation enforced
4577 delay,
4579 this,
4580 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4581 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4582 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4583 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4585 this,
4586 m_phySta2,
4587 3.0);
4588
4589 rxPower = (m_channelWidth > 40)
4590 ? DbmToW(19)
4591 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4592 // transmitted only on one 20 MHz channel
4593 double rxPowerOfdma = rxPower;
4594 if (m_channelWidth <= 40)
4595 {
4596 rxPowerOfdma = (m_channelWidth == 20)
4597 ? DbmToW(14.0309) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4598 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4599 }
4601 (m_channelWidth >= 40) ? 0.0 : rxPower,
4602 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4603 0.0,
4604 rxPowerOfdma);
4605
4606 // Reset PSD limitation once HE TB has been sent
4609 this,
4610 m_phySta2,
4611 100.0);
4612 ScheduleTest(delay,
4613 true,
4614 WifiPhyState::IDLE,
4615 0,
4616 0,
4617 0, // No transmission scheduled for STA 1
4618 1,
4619 0,
4620 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4621 false,
4622 Seconds(0),
4623 WifiPhyState::RX); // Measurement channel is total channel width
4624 delay += Seconds(1.0);
4625
4626 //---------------------------------------------------------------------------
4627 // Measure the power of 2 solicited HE TB PPDU from both STAs
4628 Simulator::Schedule(delay,
4630 this,
4631 "Measure power for reception of HE TB PPDU on both RUs");
4632 rxPower = DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4633 double rxPowerNonOfdma = (m_channelWidth >= 40)
4634 ? rxPower
4635 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4636 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4637 ScheduleTest(delay,
4638 true,
4639 WifiPhyState::IDLE,
4640 1,
4641 0,
4642 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4643 1,
4644 0,
4645 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4646 delay += Seconds(1.0);
4647
4648 //---------------------------------------------------------------------------
4649 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4650 // ongoing)
4651 Simulator::Schedule(delay,
4653 this,
4654 "Reception of an HE TB PPDU from another BSS");
4655 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4657 Simulator::Schedule(delay + MilliSeconds(100),
4659 this,
4660 3,
4661 1,
4662 1002,
4663 1,
4664 2,
4665 false);
4666
4667 // Verify events data have been cleared
4668 Simulator::Schedule(delay + MilliSeconds(200),
4670 this);
4671
4673 delay += Seconds(1.0);
4674
4675 //---------------------------------------------------------------------------
4676 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4677 // corrected received
4679 delay,
4681 this,
4682 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4683 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4687 this,
4688 3,
4689 1,
4690 1002,
4691 1,
4692 2,
4693 true);
4694 ScheduleTest(delay,
4695 true,
4696 WifiPhyState::CCA_BUSY,
4697 1,
4698 0,
4699 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4700 1,
4701 0,
4702 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4703 true,
4704 NanoSeconds(200));
4705 delay += Seconds(1.0);
4706
4708}
4709
4710void
4712{
4713 m_frequency = 5180;
4714 m_channelWidth = 20;
4716 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4717 RunOne();
4718
4719 m_frequency = 5190;
4720 m_channelWidth = 40;
4722 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4723 RunOne();
4724
4725 m_frequency = 5210;
4726 m_channelWidth = 80;
4728 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4729 RunOne();
4730
4731 m_frequency = 5250;
4732 m_channelWidth = 160;
4734 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4735 RunOne();
4736
4738}
4739
4740/**
4741 * \ingroup wifi-test
4742 * \ingroup tests
4743 *
4744 * \brief PHY padding exclusion test
4745 */
4747{
4748 public:
4750 ~TestPhyPaddingExclusion() override;
4751
4752 private:
4753 void DoSetup() override;
4754 void DoTeardown() override;
4755 void DoRun() override;
4756
4757 /**
4758 * Send HE TB PPDU function
4759 * \param txStaId the ID of the TX STA
4760 * \param index the RU index used for the transmission
4761 * \param payloadSize the size of the payload in bytes
4762 * \param txDuration the duration of the PPDU
4763 */
4764 void SendHeTbPpdu(uint16_t txStaId,
4765 std::size_t index,
4766 std::size_t payloadSize,
4767 Time txDuration);
4768 /**
4769 * Set TRIGVECTOR for HE TB PPDU
4770 *
4771 * \param ppduDuration the duration of the HE TB PPDU
4772 */
4773 void SetTrigVector(Time ppduDuration);
4774
4775 /**
4776 * Generate interference function
4777 * \param interferencePsd the PSD of the interference to be generated
4778 * \param duration the duration of the interference
4779 */
4780 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4781 /**
4782 * Stop interference function
4783 */
4784 void StopInterference();
4785
4786 /**
4787 * Run one function
4788 */
4789 void RunOne();
4790
4791 /**
4792 * Check the received PSDUs from STA1
4793 * \param expectedSuccess the expected number of success
4794 * \param expectedFailures the expected number of failures
4795 * \param expectedBytes the expected number of bytes
4796 */
4797 void CheckRxFromSta1(uint32_t expectedSuccess,
4798 uint32_t expectedFailures,
4799 uint32_t expectedBytes);
4800
4801 /**
4802 * Check the received PSDUs from STA2
4803 * \param expectedSuccess the expected number of success
4804 * \param expectedFailures the expected number of failures
4805 * \param expectedBytes the expected number of bytes
4806 */
4807 void CheckRxFromSta2(uint32_t expectedSuccess,
4808 uint32_t expectedFailures,
4809 uint32_t expectedBytes);
4810
4811 /**
4812 * Verify all events are cleared at end of TX or RX
4813 */
4814 void VerifyEventsCleared();
4815
4816 /**
4817 * Check the PHY state
4818 * \param phy the PHY
4819 * \param expectedState the expected state of the PHY
4820 */
4821 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
4822 /// \copydoc CheckPhyState
4824
4825 /**
4826 * Reset function
4827 */
4828 void Reset();
4829
4830 /**
4831 * Receive success function
4832 * \param psdu the PSDU
4833 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
4834 * \param txVector the transmit vector
4835 * \param statusPerMpdu reception status per MPDU
4836 */
4838 RxSignalInfo rxSignalInfo,
4839 WifiTxVector txVector,
4840 std::vector<bool> statusPerMpdu);
4841
4842 /**
4843 * Receive failure function
4844 * \param psdu the PSDU
4845 */
4846 void RxFailure(Ptr<const WifiPsdu> psdu);
4847
4851
4853
4854 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
4855 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
4856 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
4857 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
4858 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
4859 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
4860};
4861
4863 : TestCase("PHY padding exclusion test"),
4864 m_countRxSuccessFromSta1(0),
4865 m_countRxSuccessFromSta2(0),
4866 m_countRxFailureFromSta1(0),
4867 m_countRxFailureFromSta2(0),
4868 m_countRxBytesFromSta1(0),
4869 m_countRxBytesFromSta2(0)
4870{
4871}
4872
4873void
4875 std::size_t index,
4876 std::size_t payloadSize,
4877 Time txDuration)
4878{
4879 WifiConstPsduMap psdus;
4880
4882 0,
4884 1600,
4885 1,
4886 1,
4887 0,
4889 false,
4890 false,
4891 true);
4892
4893 HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4894 txVector.SetRu(ru, txStaId);
4895 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4896 txVector.SetNss(1, txStaId);
4897
4898 Ptr<Packet> pkt = Create<Packet>(payloadSize);
4899 WifiMacHeader hdr;
4901 hdr.SetQosTid(0);
4902 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4903 std::ostringstream addr;
4904 addr << "00:00:00:00:00:0" << txStaId;
4905 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4906 hdr.SetSequenceNumber(1);
4907 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4908 psdus.insert(std::make_pair(txStaId, psdu));
4909
4911 if (txStaId == 1)
4912 {
4913 phy = m_phySta1;
4914 }
4915 else if (txStaId == 2)
4916 {
4917 phy = m_phySta2;
4918 }
4919
4920 txVector.SetLength(
4921 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4922
4923 phy->SetPpduUid(0);
4924 phy->Send(psdus, txVector);
4925}
4926
4927void
4929{
4931 m_phyInterferer->SetPeriod(duration);
4934}
4935
4936void
4938{
4940}
4941
4943{
4944}
4945
4946void
4948 RxSignalInfo rxSignalInfo,
4949 WifiTxVector txVector,
4950 std::vector<bool> /*statusPerMpdu*/)
4951{
4952 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
4953 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4954 {
4956 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
4957 }
4958 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4959 {
4961 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
4962 }
4963}
4964
4965void
4967{
4968 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
4969 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4970 {
4972 }
4973 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4974 {
4976 }
4977}
4978
4979void
4981 uint32_t expectedFailures,
4982 uint32_t expectedBytes)
4983{
4985 expectedSuccess,
4986 "The number of successfully received packets from STA 1 is not correct!");
4989 expectedFailures,
4990 "The number of unsuccessfuly received packets from STA 1 is not correct!");
4992 expectedBytes,
4993 "The number of bytes received from STA 1 is not correct!");
4994}
4995
4996void
4998 uint32_t expectedFailures,
4999 uint32_t expectedBytes)
5000{
5002 expectedSuccess,
5003 "The number of successfully received packets from STA 2 is not correct!");
5006 expectedFailures,
5007 "The number of unsuccessfuly received packets from STA 2 is not correct!");
5009 expectedBytes,
5010 "The number of bytes received from STA 2 is not correct!");
5011}
5012
5013void
5015{
5017 nullptr,
5018 "m_currentEvent for AP was not cleared");
5020 nullptr,
5021 "m_currentEvent for STA 1 was not cleared");
5023 nullptr,
5024 "m_currentEvent for STA 2 was not cleared");
5025}
5026
5027void
5029{
5030 // This is needed to make sure PHY state will be checked as the last event if a state change
5031 // occurred at the exact same time as the check
5033}
5034
5035void
5037{
5038 WifiPhyState currentState = phy->GetState()->GetState();
5039 NS_LOG_FUNCTION(this << currentState);
5040 NS_TEST_ASSERT_MSG_EQ(currentState,
5041 expectedState,
5042 "PHY State " << currentState << " does not match expected state "
5043 << expectedState << " at " << Simulator::Now());
5044}
5045
5046void
5048{
5058}
5059
5060void
5062{
5065 int64_t streamNumber = 0;
5066
5067 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5068 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
5069 lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
5070 spectrumChannel->AddPropagationLossModel(lossModel);
5072 CreateObject<ConstantSpeedPropagationDelayModel>();
5073 spectrumChannel->SetPropagationDelayModel(delayModel);
5074
5075 Ptr<Node> apNode = CreateObject<Node>();
5076 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
5077 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
5078 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5079 apDev->SetMac(apMac);
5080 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
5081 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
5082 apDev->SetHeConfiguration(heConfiguration);
5083 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
5084 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5085 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
5086 m_phyAp->SetErrorRateModel(apErrorModel);
5087 m_phyAp->SetDevice(apDev);
5088 m_phyAp->AddChannel(spectrumChannel);
5090 m_phyAp->AssignStreams(streamNumber);
5091 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
5096
5101 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
5102 m_phyAp->SetMobility(apMobility);
5103 apDev->SetPhy(m_phyAp);
5104 apDev->SetStandard(WIFI_STANDARD_80211ax);
5105 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5106 apMac->SetWifiPhys({m_phyAp});
5107 apNode->AggregateObject(apMobility);
5108 apNode->AddDevice(apDev);
5109
5110 Ptr<Node> sta1Node = CreateObject<Node>();
5111 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
5112 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
5113 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
5114 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5115 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
5116 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5117 m_phySta1->SetDevice(sta1Dev);
5118 m_phySta1->AddChannel(spectrumChannel);
5120 m_phySta1->AssignStreams(streamNumber);
5123 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
5124 m_phySta1->SetMobility(sta1Mobility);
5125 sta1Dev->SetPhy(m_phySta1);
5126 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
5127 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5128 sta1Node->AggregateObject(sta1Mobility);
5129 sta1Node->AddDevice(sta1Dev);
5130
5131 Ptr<Node> sta2Node = CreateObject<Node>();
5132 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
5133 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
5134 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
5135 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5136 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
5137 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5138 m_phySta2->SetDevice(sta2Dev);
5139 m_phySta2->AddChannel(spectrumChannel);
5141 m_phySta2->AssignStreams(streamNumber);
5144 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
5145 m_phySta2->SetMobility(sta2Mobility);
5146 sta2Dev->SetPhy(m_phySta2);
5147 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
5148 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5149 sta2Node->AggregateObject(sta2Mobility);
5150 sta2Node->AddDevice(sta2Dev);
5151
5152 Ptr<Node> interfererNode = CreateObject<Node>();
5153 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
5154 m_phyInterferer = CreateObject<WaveformGenerator>();
5155 m_phyInterferer->SetDevice(interfererDev);
5156 m_phyInterferer->SetChannel(spectrumChannel);
5158 interfererNode->AddDevice(interfererDev);
5159}
5160
5161void
5163{
5164 m_phyAp->Dispose();
5165 m_phyAp = nullptr;
5166 m_phySta1->Dispose();
5167 m_phySta1 = nullptr;
5168 m_phySta2->Dispose();
5169 m_phySta2 = nullptr;
5171 m_phyInterferer = nullptr;
5172}
5173
5174void
5176{
5177 WifiTxVector trigVector(HePhy::GetHeMcs7(),
5178 0,
5180 1600,
5181 1,
5182 1,
5183 0,
5185 false,
5186 false,
5187 true);
5188 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5189 trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5190 trigVector.SetNss(1, 1);
5191 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5192 trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5193 trigVector.SetNss(1, 2);
5194 uint16_t length;
5195 std::tie(length, ppduDuration) =
5197 trigVector.SetLength(length);
5198 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
5199 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5200}
5201
5202void
5204{
5205 Time expectedPpduDuration = NanoSeconds(292800);
5206 Time ppduWithPaddingDuration =
5207 expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5208
5210
5211 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5214 this,
5215 1,
5216 1,
5217 1000,
5218 ppduWithPaddingDuration);
5221 this,
5222 2,
5223 2,
5224 1001,
5225 ppduWithPaddingDuration);
5226
5227 // Set TRIGVECTOR on AP
5230 this,
5231 ppduWithPaddingDuration);
5232
5233 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5234 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration - NanoSeconds(1),
5236 this,
5237 m_phyAp,
5238 WifiPhyState::RX);
5239 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration,
5241 this,
5242 m_phyAp,
5243 WifiPhyState::IDLE);
5244
5245 // One PSDU of 1000 bytes should have been successfully received from STA 1
5247 // One PSDU of 1001 bytes should have been successfully received from STA 2
5249 // Verify events data have been cleared
5251
5253
5254 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5257 this,
5258 1,
5259 1,
5260 1000,
5261 ppduWithPaddingDuration);
5264 this,
5265 2,
5266 2,
5267 1001,
5268 ppduWithPaddingDuration);
5269
5270 // Set TRIGVECTOR on AP
5273 this,
5274 ppduWithPaddingDuration);
5275
5276 // A strong non-wifi interference is generated on RU 1 during padding reception
5277 BandInfo bandInfo;
5278 bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
5279 bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5280 bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5281 Bands bands;
5282 bands.push_back(bandInfo);
5283
5284 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5285 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5286 double interferencePower = 0.1; // watts
5287 *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
5288
5289 Simulator::Schedule(Seconds(2.0) + MicroSeconds(50) + expectedPpduDuration,
5291 this,
5292 interferencePsdRu1,
5293 MilliSeconds(100));
5294
5295 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5296 // CCA_BUSY instead of IDLE due to the interference)
5297 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration - NanoSeconds(1),
5299 this,
5300 m_phyAp,
5301 WifiPhyState::RX);
5302 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration,
5304 this,
5305 m_phyAp,
5306 WifiPhyState::CCA_BUSY);
5307
5308 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5309 // occupies RU 1 after payload, during PHY padding)
5311 // One PSDU of 1001 bytes should have been successfully received from STA 2
5313 // Verify events data have been cleared
5315
5317
5319
5321}
5322
5323/**
5324 * \ingroup wifi-test
5325 * \ingroup tests
5326 *
5327 * \brief UL-OFDMA power control test
5328 */
5330{
5331 public:
5333 ~TestUlOfdmaPowerControl() override;
5334
5335 private:
5336 void DoSetup() override;
5337 void DoTeardown() override;
5338 void DoRun() override;
5339
5340 /**
5341 * Send a MU BAR through the AP to the STAs listed in the provided vector.
5342 *
5343 * \param staIds the vector of STA-IDs of STAs to address the MU-BAR to
5344 */
5345 void SendMuBar(std::vector<uint16_t> staIds);
5346
5347 /**
5348 * Send a QoS Data packet to the destination station in order
5349 * to set up a block Ack session (so that the MU-BAR may have a reply).
5350 *
5351 * \param destination the address of the destination station
5352 */
5353 void SetupBa(Address destination);
5354
5355 /**
5356 * Run one simulation with an optional BA session set up phase.
5357 *
5358 * \param setupBa true if BA session should be set up (i.e. upon first run),
5359 * false otherwise
5360 */
5361 void RunOne(bool setupBa);
5362
5363 /**
5364 * Replace the AP's callback on its PHY's ReceiveOkCallback
5365 * by the ReceiveOkCallbackAtAp method.
5366 */
5368
5369 /**
5370 * Receive OK callback function at AP.
5371 * This method will be plugged into the AP PHY's ReceiveOkCallback once the
5372 * block Ack session has been set up. This is done in the Reset function.
5373 * \param psdu the PSDU
5374 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
5375 * \param txVector the TXVECTOR used for the packet
5376 * \param statusPerMpdu reception status per MPDU
5377 */
5379 RxSignalInfo rxSignalInfo,
5380 WifiTxVector txVector,
5381 std::vector<bool> statusPerMpdu);
5382
5383 uint8_t m_bssColor; ///< BSS color
5384
5385 Ptr<WifiNetDevice> m_apDev; ///< network device of AP
5386 Ptr<WifiNetDevice> m_sta1Dev; ///< network device of STA 1
5387 Ptr<WifiNetDevice> m_sta2Dev; ///< network device of STA 2
5388
5390
5391 double m_txPowerAp; ///< transmit power (in dBm) of AP
5392 double m_txPowerStart; ///< minimum transmission power (in dBm) for STAs
5393 double m_txPowerEnd; ///< maximum transmission power (in dBm) for STAs
5394 uint8_t m_txPowerLevels; ///< number of transmission power levels for STAs
5395
5396 double m_requestedRssiSta1; ///< requested RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
5397 double m_requestedRssiSta2; ///< requested RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
5398
5399 double m_rssiSta1; ///< expected RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
5400 double m_rssiSta2; ///< expected RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
5401
5402 double m_tol; ///< tolerance (in dB) between received and expected RSSIs
5403};
5404
5406 : TestCase("UL-OFDMA power control test"),
5407 m_bssColor(1),
5408 m_txPowerAp(0),
5409 m_txPowerStart(0),
5410 m_txPowerEnd(0),
5411 m_txPowerLevels(0),
5412 m_requestedRssiSta1(0),
5413 m_requestedRssiSta2(0),
5414 m_rssiSta1(0),
5415 m_rssiSta2(0),
5416 m_tol(0.1)
5417{
5418}
5419
5421{
5422 m_phyAp = nullptr;
5423 m_apDev = nullptr;
5424 m_sta1Dev = nullptr;
5425 m_sta2Dev = nullptr;
5426}
5427
5428void
5430{
5431 // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5432 Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5433 m_apDev->Send(pkt, destination, 0);
5434}
5435
5436void
5437TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5438{
5439 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5440
5441 // Build MU-BAR trigger frame
5442 CtrlTriggerHeader muBar;
5443 muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5444 muBar.SetMoreTF(true);
5445 muBar.SetCsRequired(true);
5447 muBar.SetGiAndLtfType(1600, 2);
5448 muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5449 muBar.SetUlSpatialReuse(60500);
5450
5451 HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5452 std::size_t index = 1;
5453 int8_t ulTargetRssi = -40; // will be overwritten
5454 for (const auto& staId : staIds)
5455 {
5457 ui.SetAid12(staId);
5458 ui.SetRuAllocation({ru, index, true});
5459 ui.SetUlFecCodingType(true);
5460 ui.SetUlMcs(7);
5461 ui.SetUlDcm(false);
5462 ui.SetSsAllocation(1, 1);
5463 if (staId == 1)
5464 {
5465 ulTargetRssi = m_requestedRssiSta1;
5466 }
5467 else if (staId == 2)
5468 {
5469 ulTargetRssi = m_requestedRssiSta2;
5470 }
5471 else
5472 {
5473 NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5474 }
5475 ui.SetUlTargetRssi(ulTargetRssi);
5476
5479 bar.SetTidInfo(0);
5480 bar.SetStartingSequence(4095);
5482
5483 ++index;
5484 }
5485
5486 WifiTxVector tbTxVector = muBar.GetHeTbTxVector(staIds.front());
5488 tbTxVector,
5490 .first);
5491
5492 WifiConstPsduMap psdus;
5494 0,
5496 800,
5497 1,
5498 1,
5499 0,
5501 false,
5502 false,
5503 false,
5504 m_bssColor);
5505
5506 Ptr<Packet> bar = Create<Packet>();
5507 bar->AddHeader(muBar);
5508
5510 if (staIds.size() == 1)
5511 {
5512 uint16_t aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5513 if (staIds.front() == aidSta1)
5514 {
5516 }
5517 else
5518 {
5519 NS_ASSERT(staIds.front() ==
5520 DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5522 }
5523 }
5524
5525 WifiMacHeader hdr;
5527 hdr.SetAddr1(receiver);
5530 hdr.SetDsNotTo();
5531 hdr.SetDsFrom();
5532 hdr.SetNoRetry();
5533 hdr.SetNoMoreFragments();
5534 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(bar, hdr);
5535
5536 Time nav = m_apDev->GetPhy()->GetSifs();
5537 uint16_t staId = staIds.front(); // either will do
5539 tbTxVector,
5541 staId);
5542 psdu->SetDuration(nav);
5543 psdus.insert(std::make_pair(SU_STA_ID, psdu));
5544
5545 m_phyAp->Send(psdus, txVector);
5546}
5547
5548void
5550 RxSignalInfo rxSignalInfo,
5551 WifiTxVector txVector,
5552 std::vector<bool> /*statusPerMpdu*/)
5553{
5554 NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5555 double rssi = rxSignalInfo.rssi;
5556 NS_ASSERT(psdu->GetNMpdus() == 1);
5557 WifiMacHeader hdr = psdu->GetHeader(0);
5558 NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5559 if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5560 {
5562 rssi,
5563 m_rssiSta1,
5564 m_tol,
5565 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5566 << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5567 }
5568 else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5569 {
5571 rssi,
5572 m_rssiSta2,
5573 m_tol,
5574 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5575 << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5576 }
5577 else
5578 {
5579 NS_ABORT_MSG("The receiver address is unknown");
5580 }
5581}
5582
5583void
5585{
5586 // Now that BA session has been established we can plug our method
5589}
5590
5591void
5593{
5594 Ptr<Node> apNode = CreateObject<Node>();
5595 NodeContainer staNodes;
5596 staNodes.Create(2);
5597
5598 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5599 Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel>();
5600 spectrumChannel->AddPropagationLossModel(lossModel);
5602 CreateObject<ConstantSpeedPropagationDelayModel>();
5603 spectrumChannel->SetPropagationDelayModel(delayModel);
5604
5605 SpectrumWifiPhyHelper spectrumPhy;
5606 spectrumPhy.SetChannel(spectrumChannel);
5607 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5608 spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5609
5610 WifiHelper wifi;
5611 wifi.SetStandard(WIFI_STANDARD_80211ax);
5612 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5613 "DataMode",
5614 StringValue("HeMcs7"),
5615 "ControlMode",
5616 StringValue("HeMcs7"));
5617
5618 WifiMacHelper mac;
5619 mac.SetType("ns3::StaWifiMac");
5620 NetDeviceContainer staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5621 wifi.AssignStreams(staDevs, 0);
5622 m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5624 m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5626
5627 // Set the beacon interval long enough so that associated STAs may not consider link lost when
5628 // beacon generation is disabled during the actual tests. Having such a long interval also
5629 // avoids bloating logs with beacons during the set up phase.
5630 mac.SetType("ns3::ApWifiMac",
5631 "BeaconGeneration",
5632 BooleanValue(true),
5633 "BeaconInterval",
5634 TimeValue(MicroSeconds(1024 * 600)));
5635 m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5637 m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5638 m_phyAp = DynamicCast<SpectrumWifiPhy>(m_apDev->GetPhy());
5640 // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5641 // set up for both STAs
5642
5643 MobilityHelper mobility;
5644 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5645 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
5646 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5647 positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5648 positionAlloc->Add(
5649 Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5650 mobility.SetPositionAllocator(positionAlloc);
5651
5652 mobility.Install(apNode);
5653 mobility.Install(staNodes);
5654
5655 lossModel->SetDefaultLoss(50.0);
5656 lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5657 staNodes.Get(1)->GetObject<MobilityModel>(),
5658 56.0,
5659 true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5660}
5661
5662void
5664{
5665 m_phyAp->Dispose();
5666 m_phyAp = nullptr;
5667 m_apDev->Dispose();
5668 m_apDev = nullptr;
5669 m_sta1Dev->Dispose();
5670 m_sta1Dev = nullptr;
5671 m_sta2Dev->Dispose();
5672 m_sta2Dev = nullptr;
5673}
5674
5675void
5677{
5680 int64_t streamNumber = 0;
5681
5682 Ptr<WifiPhy> phySta1 = m_sta1Dev->GetPhy();
5683 Ptr<WifiPhy> phySta2 = m_sta2Dev->GetPhy();
5684
5685 m_phyAp->AssignStreams(streamNumber);
5686 phySta1->AssignStreams(streamNumber);
5687 phySta2->AssignStreams(streamNumber);
5688
5689 m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5691 m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5692
5693 phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5694 phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5695 phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5696
5697 phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5698 phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5699 phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5700
5701 Time relativeStart = MilliSeconds(0);
5702 if (setupBa)
5703 {
5704 // Set up BA for each station once the association phase has ended
5705 // so that a BA session is established when the MU-BAR is received.
5708 this,
5712 this,
5714 relativeStart = MilliSeconds(1000);
5715 }
5716 else
5717 {
5718 Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5719 NS_ASSERT(apMac);
5720 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5721 }
5722
5723 Simulator::Schedule(relativeStart,
5725 this);
5726
5727 {
5728 // Verify that the RSSI from STA 1 is consistent with what was requested
5729 std::vector<uint16_t> staIds{1};
5730 Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5731 }
5732
5733 {
5734 // Verify that the RSSI from STA 2 is consistent with what was requested
5735 std::vector<uint16_t> staIds{2};
5736 Simulator::Schedule(relativeStart + MilliSeconds(20),
5738 this,
5739 staIds);
5740 }
5741
5742 {
5743 // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5744 std::vector<uint16_t> staIds{1, 2};
5745 Simulator::Schedule(relativeStart + MilliSeconds(40),
5747 this,
5748 staIds);
5749 }
5750
5751 Simulator::Stop(relativeStart + MilliSeconds(100));
5753}
5754
5755void
5757{
5758 // Power configurations
5759 m_txPowerAp = 20; // dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
5760 // since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5761 m_txPowerStart = 15; // dBm
5762
5763 // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5764 m_requestedRssiSta1 = -30.0;
5765 m_requestedRssiSta2 = -36.0;
5766
5767 // Test single power level
5768 {
5769 // STA power configurations: 15 dBm only
5770 m_txPowerEnd = 15;
5771 m_txPowerLevels = 1;
5772
5773 // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5774 // regardless of the estimated path loss.
5775 m_rssiSta1 = -35.0; // 15 dBm - 50 dB
5776 m_rssiSta2 = -41.0; // 15 dBm - 56 dB
5777
5778 RunOne(true);
5779 }
5780
5781 // Test 2 dBm granularity
5782 {
5783 // STA power configurations: [15:2:25] dBm
5784 m_txPowerEnd = 25;
5785 m_txPowerLevels = 6;
5786
5787 // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5788 // requested
5789 m_rssiSta1 = -29.0; // 21 dBm - 50 dB
5790 m_rssiSta2 = -35.0; // 21 dBm - 50 dB
5791
5792 RunOne(false);
5793 }
5794
5795 // Test 1 dBm granularity
5796 {
5797 // STA power configurations: [15:1:25] dBm
5798 m_txPowerEnd = 25;
5799 m_txPowerLevels = 11;
5800
5801 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5802 m_rssiSta1 = -30.0; // 20 dBm - 50 dB
5803 m_rssiSta2 = -36.0; // 20 dBm - 56 dB
5804
5805 RunOne(false);
5806 }
5807
5808 // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5809 {
5810 // STA power configurations: [15:1:25] dBm
5811 m_txPowerEnd = 25;
5812 m_txPowerLevels = 11;
5813
5814 // Requested UL RSSIs
5815 m_requestedRssiSta1 = -28.0; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5816 m_requestedRssiSta2 = -37.0; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5817
5818 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5819 m_rssiSta1 = -28.0; // 22 dBm - 50 dB
5820 m_rssiSta2 = -37.0; // 19 dBm - 56 dB
5821
5822 RunOne(false);
5823 }
5824
5826}
5827
5828/**
5829 * \ingroup wifi-test
5830 * \ingroup tests
5831 *
5832 * \brief wifi PHY OFDMA Test Suite
5833 */
5835{
5836 public:
5838};
5839
5841 : TestSuite("wifi-phy-ofdma", Type::UNIT)
5842{
5843 AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5844 AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::Duration::QUICK);
5845 AddTestCase(new TestUlOfdmaPpduUid, TestCase::Duration::QUICK);
5846 AddTestCase(new TestMultipleHeTbPreambles, TestCase::Duration::QUICK);
5847 AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5848 AddTestCase(new TestPhyPaddingExclusion, TestCase::Duration::QUICK);
5849 AddTestCase(new TestUlOfdmaPowerControl, TestCase::Duration::QUICK);
5850}
5851
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.
Ptr< Event > GetCurrentEvent()
void StartTx(Ptr< const WifiPpdu > ppdu) override
void DoDispose() override
Destructor implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
Time GetEnergyDuration(double energyW, WifiSpectrumBandInfo band)
Wrapper to InterferenceHelper method.
TracedCallback< uint64_t > m_phyTxPpduUidTrace
Callback providing UID of the PPDU that is about to be transmitted.
void DoInitialize() override
Initialize() implementation.
HE PHY slightly modified so as to return a given STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
OfdmaTestHePhy(uint16_t staId)
Constructor.
~OfdmaTestHePhy() override
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,...
void NotifyTxStart(Time duration, double txPowerDbm) override
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,...
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.
uint16_t m_frequency
frequency in MHz
uint16_t m_channelWidth
channel width in MHz
uint32_t m_countRxFailureSta1
count RX failure for STA 1
Time m_expectedPpduDuration40Mhz
expected duration to send MU PPDU on 40 MHz RU
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void StopInterference()
Stop interference function.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint8_t m_indexSubchannel
Index of the subchannel (starting from 0) that should contain an interference and be punctured during...
uint32_t m_countRxSuccessSta1
count RX success for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, const std::vector< bool > statusPerMpdu)
Receive success function for STA 1.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
uint16_t m_frequency
frequency in MHz
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint16_t m_channelWidth
channel width in MHz
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
void RunOne()
Run one function.
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Time m_expectedPpduDuration
expected duration to send MU PPDU
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 1.
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
void RxSuccessSta3(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 3.
uint32_t m_countRxSuccessSta3
count RX success for STA 3
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
uint32_t m_countRxBytesSta3
count RX bytes for STA 3
void RxFailureSta3(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 3.
void StopInterference()
Stop interference function.
void ResetResults()
Reset the results.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxSuccessSta1
count RX success for STA 1
void CheckResultsSta3(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 3.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
Send MU-PPDU function.
UL-OFDMA multiple RX events test.
WifiTxVector m_trigVector
TRIGVECTOR.
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.
void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize)
Receive HE TB PPDU function.
uint64_t m_totalBytesDropped
total number of dropped bytes
void CheckBytesDropped(size_t expectedBytesDropped)
Check the number of bytes dropped.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
PHY padding exclusion test.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
void DoRun() override
Implementation to actually run this TestCase.
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
void SetTrigVector(Time ppduDuration)
Set TRIGVECTOR for HE TB PPDU.
void Reset()
Reset function.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
void StopInterference()
Stop interference function.
void RunOne()
Run one function.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void ScheduleTest(Time delay, bool solicited, WifiPhyState expectedStateAtEnd, uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1, uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2, bool scheduleTxSta1=true, Time ulTimeDifference=Seconds(0), WifiPhyState expectedStateBeforeEnd=WifiPhyState::RX, TrigVectorInfo error=NONE)
Schedule test to perform.
std::shared_ptr< OfdmaTestPhyListener > m_apPhyStateListener
listener for AP PHY state transitions
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId, std::size_t index, uint8_t bssColor) const
Get TXVECTOR for HE TB PPDU.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
uint16_t m_frequency
frequency in MHz
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 SchedulePowerMeasurementChecks(Time delay, double rxPowerNonOfdmaRu1, double rxPowerNonOfdmaRu2, double rxPowerOfdmaRu1, double rxPowerOfdmaRu2)
Schedule power measurement related checks.
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 SetPsdLimit(Ptr< WifiPhy > phy, double psdLimit)
Set the PSD limit.
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.
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void CheckNonOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, double expectedRxPower)
Check the received power for the non-OFDMA of the HE TB PPDUs over the given band.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
void RunOne()
Run one function.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void CheckApRxEnd(uint32_t expectedNotifications, Time expectedLastNotification, bool expectedSuccess)
Check the the number of RX end notifications at the AP as well as the last time a RX end has been not...
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
void CheckOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, double expectedRxPower)
Check the received power for the OFDMA part of the HE TB PPDUs over the given band.
uint16_t m_channelWidth
channel width in MHz
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.
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.
double m_requestedRssiSta1
requested RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
double m_txPowerStart
minimum transmission power (in dBm) for STAs
void DoRun() override
Implementation to actually run this TestCase.
double m_rssiSta2
expected RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
Ptr< WifiNetDevice > m_sta2Dev
network device of STA 2
double m_txPowerEnd
maximum transmission power (in dBm) 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
double m_tol
tolerance (in dB) between received and expected RSSIs
Ptr< WifiNetDevice > m_apDev
network device of AP
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void ReceiveOkCallbackAtAp(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive OK callback function at AP.
void ReplaceReceiveOkCallbackOfAp()
Replace the AP's callback on its PHY's ReceiveOkCallback by the ReceiveOkCallbackAtAp method.
double m_rssiSta1
expected RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
uint8_t m_txPowerLevels
number of transmission power levels for STAs
double m_requestedRssiSta2
requested RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
double m_txPowerAp
transmit power (in dBm) of AP
void RunOne(bool setupBa)
Run one simulation with an optional BA session set up phase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void SendMuBar(std::vector< uint16_t > staIds)
Send a MU BAR through the AP to the STAs listed in the provided vector.
UL-OFDMA PPDU UID attribution test.
void TxPpduSta1(uint64_t uid)
Transmitted PPDU information function for STA 1.
void ResetPpduUid()
Reset the global PPDU UID counter in WifiPhy.
void CheckUid(uint16_t staId, uint64_t expectedUid)
Check the UID of the transmitted PPDU.
void TxPpduAp(uint64_t uid)
Transmitted PPDU information function for AP.
void TxPpduSta2(uint64_t uid)
Transmitted PPDU information function for STA 2.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
uint64_t m_ppduUidAp
UID of PPDU transmitted by AP.
uint64_t m_ppduUidSta1
UID of PPDU transmitted by STA1.
uint64_t m_ppduUidSta2
UID of PPDU transmitted by STA2.
void DoRun() override
Implementation to actually run this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu()
Send MU-PPDU toward both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendTbPpdu()
Send TB-PPDU from both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
void SendSuPpdu(uint16_t txStaId)
Send SU-PPDU function.
wifi PHY OFDMA Test Suite
a polymophic address class
Definition: address.h:101
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAckRequest.
Definition: ctrl-headers.h:52
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.
Definition: ctrl-headers.h:942
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 SetUlBandwidth(uint16_t bw)
Set the bandwidth of the solicited HE TB PPDU.
void SetType(TriggerFrameType type)
Set the Trigger frame type.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
void SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse 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.
User Info field of Trigger frames.
Definition: ctrl-headers.h:590
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:42
PHY entity for HE (11ax)
Definition: he-phy.h:68
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:575
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:272
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Definition: he-ppdu.h:117
@ PSD_NON_HE_PORTION
Non-HE portion of an HE PPDU.
Definition: he-ppdu.h:116
RU Specification.
Definition: he-ru.h:66
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:454
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:763
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
@ RU_484_TONE
Definition: he-ru.h:46
@ RU_996_TONE
Definition: he-ru.h:47
@ RU_106_TONE
Definition: he-ru.h:44
@ RU_242_TONE
Definition: he-ru.h:45
an EUI-48 address
Definition: mac48-address.h:46
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.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
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.
Definition: object-base.cc:322
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:211
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:522
void Dispose()
Dispose of this Object.
Definition: object.cc:258
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:92
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:1005
AttributeValue implementation for Pointer.
Definition: pointer.h:48
Ptr< T > Get() const
Definition: pointer.h:234
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static void Run()
Run the simulation.
Definition: simulator.cc:178
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
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.
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.
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const override
void StartTx(Ptr< const WifiPpdu > ppdu) override
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1413
Forward calls to a chain of Callback.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Hold an unsigned integer type.
Definition: uinteger.h:45
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
void SetDevice(Ptr< NetDevice > d) override
Set the associated NetDevice instance.
void SetChannel(Ptr< SpectrumChannel > c) override
Set the channel attached to this device.
virtual void Start()
Start the waveform generator.
void SetTxPowerSpectralDensity(Ptr< SpectrumValue > txs)
Set the Power Spectral Density used for outgoing waveforms.
void SetDutyCycle(double value)
void SetPeriod(Time period)
Set the period according to which the WaveformGenerator switches on and off.
virtual void Stop()
Stop the waveform generator.
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
Implements the IEEE 802.11 MAC header.
virtual WifiMacType GetType() const
Return the type (WifiMacType)
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.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
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.
Ptr< WifiMac > GetMac() const
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Ptr< HeConfiguration > GetHeConfiguration() const
Ptr< WifiPhy > GetPhy() const
Address GetAddress() const override
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:163
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
Definition: wifi-helper.h:550
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:649
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:1739
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:658
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:1303
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:800
static Time GetPreambleDetectionDuration()
Definition: wifi-phy.cc:1467
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:460
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:980
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1526
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1326
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition: wifi-phy.cc:466
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:1117
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1040
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1301
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:731
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1306
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:679
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:903
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:624
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1288
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:454
void Reset()
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1879
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1052
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition: wifi-phy.cc:746
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:2256
receive notifications about PHY events.
static ConstIterator FindFirst(uint8_t number, uint16_t frequency, uint16_t width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first channel matching the specified parameters.
This objects implements the PHY state machine of the Wifi device.
static Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, const 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(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40, const std::vector< bool > &puncturedSubchannels=std::vector< bool >{})
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 SetRuAllocation(const RuAllocation &ruAlloc, uint8_t p20Index)
Set RU_ALLOCATION field.
void SetInactiveSubchannels(const std::vector< bool > &inactiveSubchannels)
Set the 20 MHz subchannels that are punctured.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
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 SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
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:66
#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:86
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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:275
#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:145
#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:338
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
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.
Definition: wifi-phy-band.h:33
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.
Definition: wifi-phy-band.h:37
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
WifiPhyState
The state of the PHY layer.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
std::vector< BandInfo > Bands
Container of BandInfo.
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_CTL_BACKRESP
@ WIFI_MAC_QOSDATA
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
Definition: wifi-utils.cc:66
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
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: phy-entity.h:69
double rssi
RSSI in dBm.
Definition: phy-entity.h:71
WifiSpectrumBandInfo structure containing info about a spectrum band.
static const uint16_t DEFAULT_CHANNEL_WIDTH
static WifiPhyOfdmaTestSuite wifiPhyOfdmaTestSuite
the test suite
static const uint8_t DEFAULT_CHANNEL_NUMBER
static const WifiPhyBand DEFAULT_WIFI_BAND
static const uint16_t DEFAULT_GUARD_WIDTH
static const uint32_t DEFAULT_FREQUENCY