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/txop.h"
45#include "ns3/waveform-generator.h"
46#include "ns3/wifi-mac-header.h"
47#include "ns3/wifi-net-device.h"
48#include "ns3/wifi-phy-listener.h"
49#include "ns3/wifi-psdu.h"
50#include "ns3/wifi-spectrum-phy-interface.h"
51#include "ns3/wifi-spectrum-signal-parameters.h"
52#include "ns3/wifi-spectrum-value-helper.h"
53#include "ns3/wifi-utils.h"
54
55#include <algorithm>
56#include <iterator>
57#include <memory>
58
59using namespace ns3;
60
61NS_LOG_COMPONENT_DEFINE("WifiPhyOfdmaTest");
62
63static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
64static const uint32_t DEFAULT_FREQUENCY = 5180; // MHz
66static const uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
67static const uint16_t DEFAULT_GUARD_WIDTH =
68 DEFAULT_CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
69
70/**
71 * HE PHY slightly modified so as to return a given
72 * STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
73 */
74class OfdmaTestHePhy : public HePhy
75{
76 public:
77 /**
78 * Constructor
79 *
80 * \param staId the ID of the STA to which this PHY belongs to
81 */
82 OfdmaTestHePhy(uint16_t staId);
83 ~OfdmaTestHePhy() override;
84
85 /**
86 * Return the STA ID that has been assigned to the station this PHY belongs to.
87 * This is typically called for MU PPDUs, in order to pick the correct PSDU.
88 *
89 * \param ppdu the PPDU for which the STA ID is requested
90 * \return the STA ID
91 */
92 uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
93
94 /**
95 * Set the global PPDU UID counter.
96 *
97 * \param uid the value to which the global PPDU UID counter should be set
98 */
99 void SetGlobalPpduUid(uint64_t uid);
100
101 private:
102 uint16_t m_staId; ///< ID of the STA to which this PHY belongs to
103}; // class OfdmaTestHePhy
104
106 : HePhy(),
107 m_staId(staId)
108{
109}
110
112{
113}
114
115uint16_t
117{
118 if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
119 {
120 return m_staId;
121 }
122 return HePhy::GetStaId(ppdu);
123}
124
125void
127{
128 m_globalPpduUid = uid;
129}
130
131/**
132 * SpectrumWifiPhy used for testing OFDMA.
133 */
135{
136 public:
137 /**
138 * \brief Get the type ID.
139 * \return the object TypeId
140 */
141 static TypeId GetTypeId();
142 /**
143 * Constructor
144 *
145 * \param staId the ID of the STA to which this PHY belongs to
146 */
147 OfdmaSpectrumWifiPhy(uint16_t staId);
148 ~OfdmaSpectrumWifiPhy() override;
149
150 void DoInitialize() override;
151 void DoDispose() override;
152
153 using WifiPhy::Reset;
154 void StartTx(Ptr<const WifiPpdu> ppdu) override;
155
156 /**
157 * TracedCallback signature for UID of transmitted PPDU.
158 *
159 * \param uid the UID of the transmitted PPDU
160 */
161 typedef void (*TxPpduUidCallback)(uint64_t uid);
162
163 /**
164 * Set the global PPDU UID counter.
165 *
166 * \param uid the value to which the global PPDU UID counter should be set
167 */
168 void SetPpduUid(uint64_t uid);
169
170 /**
171 * Since we assume trigger frame was previously received from AP, this is used to set its UID
172 *
173 * \param uid the PPDU UID of the trigger frame
174 */
175 void SetTriggerFrameUid(uint64_t uid);
176
177 /**
178 * \return the current preamble events map
179 */
180 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
181 /**
182 * \return the current event
183 */
185
186 /**
187 * Wrapper to InterferenceHelper method.
188 *
189 * \param energyW the minimum energy (W) requested
190 * \param band identify the requested band
191 *
192 * \returns the expected amount of time the observed
193 * energy on the medium for a given band will
194 * be higher than the requested threshold.
195 */
196 Time GetEnergyDuration(double energyW, WifiSpectrumBandInfo band);
197
198 /**
199 * \return a const pointer to the HE PHY instance
200 */
202
203 private:
204 Ptr<OfdmaTestHePhy> m_ofdmTestHePhy; ///< Pointer to HE PHY instance used for OFDMA test
206 m_phyTxPpduUidTrace; //!< Callback providing UID of the PPDU that is about to be transmitted
207}; // class OfdmaSpectrumWifiPhy
208
209TypeId
211{
212 static TypeId tid =
213 TypeId("ns3::OfdmaSpectrumWifiPhy")
215 .SetGroupName("Wifi")
216 .AddTraceSource("TxPpduUid",
217 "UID of the PPDU to be transmitted",
219 "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
220 return tid;
221}
222
225{
226 m_ofdmTestHePhy = Create<OfdmaTestHePhy>(staId);
228}
229
231{
232}
233
234void
236{
237 // Replace HE PHY instance with test instance
240}
241
242void
244{
245 m_ofdmTestHePhy = nullptr;
247}
248
249void
251{
254}
255
256void
258{
260}
261
262void
264{
265 m_phyTxPpduUidTrace(ppdu->GetUid());
267}
268
269std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
271{
273}
274
277{
278 return m_currentEvent;
279}
280
281Time
283{
284 return m_interference->GetEnergyDuration(energyW, band);
285}
286
289{
290 return DynamicCast<const HePhy>(GetLatestPhyEntity());
291}
292
293/**
294 * \ingroup wifi-test
295 * \ingroup tests
296 *
297 * \brief DL-OFDMA PHY test
298 */
300{
301 public:
304
305 private:
306 void DoSetup() override;
307 void DoTeardown() override;
308 void DoRun() override;
309
310 /**
311 * Receive success function for STA 1
312 * \param psdu the PSDU
313 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
314 * \param txVector the transmit vector
315 * \param statusPerMpdu reception status per MPDU
316 */
318 RxSignalInfo rxSignalInfo,
319 WifiTxVector txVector,
320 std::vector<bool> statusPerMpdu);
321 /**
322 * Receive success function for STA 2
323 * \param psdu the PSDU
324 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
325 * \param txVector the transmit vector
326 * \param statusPerMpdu reception status per MPDU
327 */
329 RxSignalInfo rxSignalInfo,
330 WifiTxVector txVector,
331 std::vector<bool> statusPerMpdu);
332 /**
333 * Receive success function for STA 3
334 * \param psdu the PSDU
335 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
336 * \param txVector the transmit vector
337 * \param statusPerMpdu reception status per MPDU
338 */
340 RxSignalInfo rxSignalInfo,
341 WifiTxVector txVector,
342 std::vector<bool> statusPerMpdu);
343
344 /**
345 * Receive failure function for STA 1
346 * \param psdu the PSDU
347 */
349 /**
350 * Receive failure function for STA 2
351 * \param psdu the PSDU
352 */
354 /**
355 * Receive failure function for STA 3
356 * \param psdu the PSDU
357 */
359
360 /**
361 * Check the results for STA 1
362 * \param expectedRxSuccess the expected number of RX success
363 * \param expectedRxFailure the expected number of RX failures
364 * \param expectedRxBytes the expected number of RX bytes
365 */
366 void CheckResultsSta1(uint32_t expectedRxSuccess,
367 uint32_t expectedRxFailure,
368 uint32_t expectedRxBytes);
369 /**
370 * Check the results for STA 2
371 * \param expectedRxSuccess the expected number of RX success
372 * \param expectedRxFailure the expected number of RX failures
373 * \param expectedRxBytes the expected number of RX bytes
374 */
375 void CheckResultsSta2(uint32_t expectedRxSuccess,
376 uint32_t expectedRxFailure,
377 uint32_t expectedRxBytes);
378 /**
379 * Check the results for STA 3
380 * \param expectedRxSuccess the expected number of RX success
381 * \param expectedRxFailure the expected number of RX failures
382 * \param expectedRxBytes the expected number of RX bytes
383 */
384 void CheckResultsSta3(uint32_t expectedRxSuccess,
385 uint32_t expectedRxFailure,
386 uint32_t expectedRxBytes);
387
388 /**
389 * Reset the results
390 */
391 void ResetResults();
392
393 /**
394 * Send MU-PPDU function
395 * \param rxStaId1 the ID of the recipient STA for the first PSDU
396 * \param rxStaId2 the ID of the recipient STA for the second PSDU
397 */
398 void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
399
400 /**
401 * Generate interference function
402 * \param interferencePsd the PSD of the interference to be generated
403 * \param duration the duration of the interference
404 */
405 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
406 /**
407 * Stop interference function
408 */
409 void StopInterference();
410
411 /**
412 * Run one function
413 */
414 void RunOne();
415
416 /**
417 * Schedule now to check the PHY state
418 * \param phy the PHY
419 * \param expectedState the expected state of the PHY
420 */
422 /**
423 * Check the PHY state now
424 * \param phy the PHY
425 * \param expectedState the expected state of the PHY
426 */
428
429 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
430 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
431 uint32_t m_countRxSuccessSta3; ///< count RX success for STA 3
432 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
433 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
434 uint32_t m_countRxFailureSta3; ///< count RX failure for STA 3
435 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
436 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
437 uint32_t m_countRxBytesSta3; ///< count RX bytes for STA 3
438
444
445 uint16_t m_frequency; ///< frequency in MHz
446 uint16_t m_channelWidth; ///< channel width in MHz
447 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
448};
449
451 : TestCase("DL-OFDMA PHY test"),
452 m_countRxSuccessSta1(0),
453 m_countRxSuccessSta2(0),
454 m_countRxSuccessSta3(0),
455 m_countRxFailureSta1(0),
456 m_countRxFailureSta2(0),
457 m_countRxFailureSta3(0),
458 m_countRxBytesSta1(0),
459 m_countRxBytesSta2(0),
460 m_countRxBytesSta3(0),
461 m_frequency(DEFAULT_FREQUENCY),
462 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
463 m_expectedPpduDuration(NanoSeconds(306400))
464{
465}
466
467void
469{
479}
480
481void
482TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
483{
484 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
485 WifiConstPsduMap psdus;
487 0,
489 800,
490 1,
491 1,
492 0,
494 false,
495 false);
497 if (m_channelWidth == 20)
498 {
499 ruType = HeRu::RU_106_TONE;
500 txVector.SetRuAllocation({96}, 0);
501 }
502 else if (m_channelWidth == 40)
503 {
504 ruType = HeRu::RU_242_TONE;
505 txVector.SetRuAllocation({192, 192}, 0);
506 }
507 else if (m_channelWidth == 80)
508 {
509 ruType = HeRu::RU_484_TONE;
510 txVector.SetRuAllocation({200, 200, 200, 200}, 0);
511 }
512 else if (m_channelWidth == 160)
513 {
514 ruType = HeRu::RU_996_TONE;
515 txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208}, 0);
516 }
517 else
518 {
519 NS_ASSERT_MSG(false, "Unsupported channel width");
520 }
521
523
524 HeRu::RuSpec ru1(ruType, 1, true);
525 txVector.SetRu(ru1, rxStaId1);
526 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
527 txVector.SetNss(1, rxStaId1);
528
529 HeRu::RuSpec ru2(ruType, (m_channelWidth == 160 ? 1 : 2), m_channelWidth != 160);
530 txVector.SetRu(ru2, rxStaId2);
531 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
532 txVector.SetNss(1, rxStaId2);
533
534 Ptr<Packet> pkt1 = Create<Packet>(1000);
535 WifiMacHeader hdr1;
537 hdr1.SetQosTid(0);
538 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
539 hdr1.SetSequenceNumber(1);
540 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
541 psdus.insert(std::make_pair(rxStaId1, psdu1));
542
543 Ptr<Packet> pkt2 = Create<Packet>(1500);
544 WifiMacHeader hdr2;
546 hdr2.SetQosTid(0);
547 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
548 hdr2.SetSequenceNumber(2);
549 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
550 psdus.insert(std::make_pair(rxStaId2, psdu2));
551
552 m_phyAp->Send(psdus, txVector);
553}
554
555void
557{
559 m_phyInterferer->SetPeriod(duration);
562}
563
564void
566{
568}
569
571{
572}
573
574void
576 RxSignalInfo rxSignalInfo,
577 WifiTxVector txVector,
578 std::vector<bool> /*statusPerMpdu*/)
579{
580 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
582 m_countRxBytesSta1 += (psdu->GetSize() - 30);
583}
584
585void
587 RxSignalInfo rxSignalInfo,
588 WifiTxVector txVector,
589 std::vector<bool> /*statusPerMpdu*/)
590{
591 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
593 m_countRxBytesSta2 += (psdu->GetSize() - 30);
594}
595
596void
598 RxSignalInfo rxSignalInfo,
599 WifiTxVector txVector,
600 std::vector<bool> /*statusPerMpdu*/)
601{
602 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
604 m_countRxBytesSta3 += (psdu->GetSize() - 30);
605}
606
607void
609{
610 NS_LOG_FUNCTION(this << *psdu);
612}
613
614void
616{
617 NS_LOG_FUNCTION(this << *psdu);
619}
620
621void
623{
624 NS_LOG_FUNCTION(this << *psdu);
626}
627
628void
630 uint32_t expectedRxFailure,
631 uint32_t expectedRxBytes)
632{
634 expectedRxSuccess,
635 "The number of successfully received packets by STA 1 is not correct!");
637 expectedRxFailure,
638 "The number of unsuccessfuly received packets by STA 1 is not correct!");
640 expectedRxBytes,
641 "The number of bytes received by STA 1 is not correct!");
642}
643
644void
646 uint32_t expectedRxFailure,
647 uint32_t expectedRxBytes)
648{
650 expectedRxSuccess,
651 "The number of successfully received packets by STA 2 is not correct!");
653 expectedRxFailure,
654 "The number of unsuccessfuly received packets by STA 2 is not correct!");
656 expectedRxBytes,
657 "The number of bytes received by STA 2 is not correct!");
658}
659
660void
662 uint32_t expectedRxFailure,
663 uint32_t expectedRxBytes)
664{
666 expectedRxSuccess,
667 "The number of successfully received packets by STA 3 is not correct!");
669 expectedRxFailure,
670 "The number of unsuccessfuly received packets by STA 3 is not correct!");
672 expectedRxBytes,
673 "The number of bytes received by STA 3 is not correct!");
674}
675
676void
678{
679 // This is needed to make sure PHY state will be checked as the last event if a state change
680 // occurred at the exact same time as the check
682}
683
684void
686 WifiPhyState expectedState)
687{
688 WifiPhyState currentState;
689 PointerValue ptr;
690 phy->GetAttribute("State", ptr);
691 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
692 currentState = state->GetState();
693 NS_LOG_FUNCTION(this << currentState);
694 NS_TEST_ASSERT_MSG_EQ(currentState,
695 expectedState,
696 "PHY State " << currentState << " does not match expected state "
697 << expectedState << " at " << Simulator::Now());
698}
699
700void
702{
703 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
704 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
705 lossModel->SetFrequency(m_frequency * 1e6);
706 spectrumChannel->AddPropagationLossModel(lossModel);
708 CreateObject<ConstantSpeedPropagationDelayModel>();
709 spectrumChannel->SetPropagationDelayModel(delayModel);
710
711 Ptr<Node> apNode = CreateObject<Node>();
712 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
713 m_phyAp = CreateObject<SpectrumWifiPhy>();
714 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
715 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
716 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
717 m_phyAp->SetErrorRateModel(apErrorModel);
718 m_phyAp->SetDevice(apDev);
719 m_phyAp->AddChannel(spectrumChannel);
721 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
722 m_phyAp->SetMobility(apMobility);
723 apDev->SetPhy(m_phyAp);
724 apNode->AggregateObject(apMobility);
725 apNode->AddDevice(apDev);
726
727 Ptr<Node> sta1Node = CreateObject<Node>();
728 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
729 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
730 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
731 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
732 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
733 m_phySta1->SetErrorRateModel(sta1ErrorModel);
734 m_phySta1->SetDevice(sta1Dev);
735 m_phySta1->AddChannel(spectrumChannel);
740 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
741 m_phySta1->SetMobility(sta1Mobility);
742 sta1Dev->SetPhy(m_phySta1);
743 sta1Node->AggregateObject(sta1Mobility);
744 sta1Node->AddDevice(sta1Dev);
745
746 Ptr<Node> sta2Node = CreateObject<Node>();
747 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
748 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
749 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
750 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
751 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
752 m_phySta2->SetErrorRateModel(sta2ErrorModel);
753 m_phySta2->SetDevice(sta2Dev);
754 m_phySta2->AddChannel(spectrumChannel);
759 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
760 m_phySta2->SetMobility(sta2Mobility);
761 sta2Dev->SetPhy(m_phySta2);
762 sta2Node->AggregateObject(sta2Mobility);
763 sta2Node->AddDevice(sta2Dev);
764
765 Ptr<Node> sta3Node = CreateObject<Node>();
766 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
767 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
768 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
769 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
770 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
771 m_phySta3->SetErrorRateModel(sta3ErrorModel);
772 m_phySta3->SetDevice(sta3Dev);
773 m_phySta3->AddChannel(spectrumChannel);
778 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
779 m_phySta3->SetMobility(sta3Mobility);
780 sta3Dev->SetPhy(m_phySta3);
781 sta3Node->AggregateObject(sta3Mobility);
782 sta3Node->AddDevice(sta3Dev);
783
784 Ptr<Node> interfererNode = CreateObject<Node>();
785 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
786 m_phyInterferer = CreateObject<WaveformGenerator>();
787 m_phyInterferer->SetDevice(interfererDev);
788 m_phyInterferer->SetChannel(spectrumChannel);
790 interfererNode->AddDevice(interfererDev);
791}
792
793void
795{
796 m_phyAp->Dispose();
797 m_phyAp = nullptr;
799 m_phySta1 = nullptr;
801 m_phySta2 = nullptr;
803 m_phySta3 = nullptr;
805 m_phyInterferer = nullptr;
806}
807
808void
810{
813 int64_t streamNumber = 0;
814 m_phyAp->AssignStreams(streamNumber);
815 m_phySta1->AssignStreams(streamNumber);
816 m_phySta2->AssignStreams(streamNumber);
817 m_phySta3->AssignStreams(streamNumber);
818
819 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
824
833
835
836 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
837 // Each STA should receive its PSDU.
839
840 // Since it takes m_expectedPpduDuration to transmit the PPDU,
841 // all 3 PHYs should be back to IDLE at the same time,
842 // even the PHY that has no PSDU addressed to it.
845 this,
846 m_phySta1,
847 WifiPhyState::RX);
850 this,
851 m_phySta2,
852 WifiPhyState::RX);
855 this,
856 m_phySta3,
857 WifiPhyState::CCA_BUSY);
860 this,
861 m_phySta1,
862 WifiPhyState::IDLE);
865 this,
866 m_phySta2,
867 WifiPhyState::IDLE);
870 this,
871 m_phySta3,
872 WifiPhyState::IDLE);
873
874 // One PSDU of 1000 bytes should have been successfully received by STA 1
877 this,
878 1,
879 0,
880 1000);
881 // One PSDU of 1500 bytes should have been successfully received by STA 2
884 this,
885 1,
886 0,
887 1500);
888 // No PSDU should have been received by STA 3
890
892
893 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
894 // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
895 // but should keep its PHY busy during all PPDU duration.
897
898 // Since it takes m_expectedPpduDuration to transmit the PPDU,
899 // all 3 PHYs should be back to IDLE at the same time,
900 // even the PHY that has no PSDU addressed to it.
903 this,
904 m_phySta1,
905 WifiPhyState::RX);
908 this,
909 m_phySta2,
910 WifiPhyState::CCA_BUSY);
913 this,
914 m_phySta3,
915 WifiPhyState::RX);
918 this,
919 m_phySta1,
920 WifiPhyState::IDLE);
923 this,
924 m_phySta2,
925 WifiPhyState::IDLE);
928 this,
929 m_phySta3,
930 WifiPhyState::IDLE);
931
932 // One PSDU of 1000 bytes should have been successfully received by STA 1
935 this,
936 1,
937 0,
938 1000);
939 // No PSDU should have been received by STA 2
941 // One PSDU of 1500 bytes should have been successfully received by STA 3
944 this,
945 1,
946 0,
947 1500);
948
950
951 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
953
954 // A strong non-wifi interference is generated on RU 1 during PSDU reception
955 BandInfo bandInfo;
956 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
957 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
958 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
959 Bands bands;
960 bands.push_back(bandInfo);
961
962 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
963 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
964 double interferencePower = 0.1; // watts
965 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
966
969 this,
970 interferencePsdRu1,
971 MilliSeconds(100));
972
973 // Since it takes m_expectedPpduDuration to transmit the PPDU,
974 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
975 // even the PHY that has no PSDU addressed to it.
978 this,
979 m_phySta1,
980 WifiPhyState::RX);
983 this,
984 m_phySta2,
985 WifiPhyState::RX);
988 this,
989 m_phySta3,
990 WifiPhyState::CCA_BUSY);
993 this,
994 m_phySta1,
995 WifiPhyState::CCA_BUSY);
998 this,
999 m_phySta2,
1000 WifiPhyState::CCA_BUSY);
1003 this,
1004 m_phySta3,
1005 WifiPhyState::CCA_BUSY);
1006
1007 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1008 // occupies RU 1)
1010 // One PSDU of 1500 bytes should have been successfully received by STA 2
1013 this,
1014 1,
1015 0,
1016 1500);
1017 // No PSDU should have been received by STA3
1019
1021
1022 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1024
1025 // A strong non-wifi interference is generated on RU 2 during PSDU reception
1026 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
1027 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
1028 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
1029 bands.clear();
1030 bands.push_back(bandInfo);
1031
1032 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1033 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1034 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
1035
1038 this,
1039 interferencePsdRu2,
1040 MilliSeconds(100));
1041
1042 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1043 // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1044 // same time, even the PHY that has no PSDU addressed to it.
1047 this,
1048 m_phySta1,
1049 WifiPhyState::RX);
1052 this,
1053 m_phySta2,
1054 WifiPhyState::RX);
1057 this,
1058 m_phySta3,
1059 WifiPhyState::CCA_BUSY);
1062 this,
1063 m_phySta1,
1064 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1067 this,
1068 m_phySta2,
1069 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1072 this,
1073 m_phySta3,
1074 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1075
1076 // One PSDU of 1000 bytes should have been successfully received by STA 1
1079 this,
1080 1,
1081 0,
1082 1000);
1083 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1084 // occupies RU 2)
1086 // No PSDU should have been received by STA3
1088
1090
1091 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1093
1094 // A strong non-wifi interference is generated on the full band during PSDU reception
1095 bandInfo.fc = m_frequency * 1e6;
1096 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
1097 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
1098 bands.clear();
1099 bands.push_back(bandInfo);
1100
1101 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1102 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1103 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
1104
1107 this,
1108 interferencePsdAll,
1109 MilliSeconds(100));
1110
1111 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1112 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1113 // even the PHY that has no PSDU addressed to it.
1116 this,
1117 m_phySta1,
1118 WifiPhyState::RX);
1121 this,
1122 m_phySta2,
1123 WifiPhyState::RX);
1126 this,
1127 m_phySta3,
1128 WifiPhyState::CCA_BUSY);
1131 this,
1132 m_phySta1,
1133 WifiPhyState::CCA_BUSY);
1136 this,
1137 m_phySta2,
1138 WifiPhyState::CCA_BUSY);
1141 this,
1142 m_phySta3,
1143 WifiPhyState::CCA_BUSY);
1144
1145 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1146 // occupies RU 1)
1148 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1149 // occupies RU 2)
1151 // No PSDU should have been received by STA3
1153
1155
1157}
1158
1159void
1161{
1162 m_frequency = 5180;
1163 m_channelWidth = 20;
1165 RunOne();
1166
1167 m_frequency = 5190;
1168 m_channelWidth = 40;
1170 RunOne();
1171
1172 m_frequency = 5210;
1173 m_channelWidth = 80;
1175 RunOne();
1176
1177 m_frequency = 5250;
1178 m_channelWidth = 160;
1180 RunOne();
1181
1183}
1184
1185/**
1186 * \ingroup wifi-test
1187 * \ingroup tests
1188 *
1189 * \brief DL-OFDMA PHY puncturing test
1190 */
1192{
1193 public:
1195
1196 private:
1197 void DoSetup() override;
1198 void DoTeardown() override;
1199 void DoRun() override;
1200
1201 /**
1202 * Receive success function for STA 1
1203 * \param psdu the PSDU
1204 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1205 * \param txVector the transmit vector
1206 * \param statusPerMpdu reception status per MPDU
1207 */
1209 RxSignalInfo rxSignalInfo,
1210 WifiTxVector txVector,
1211 const std::vector<bool> statusPerMpdu);
1212
1213 /**
1214 * Receive success function for STA 2
1215 * \param psdu the PSDU
1216 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1217 * \param txVector the transmit vector
1218 * \param statusPerMpdu reception status per MPDU
1219 */
1221 RxSignalInfo rxSignalInfo,
1222 WifiTxVector txVector,
1223 std::vector<bool> statusPerMpdu);
1224
1225 /**
1226 * Receive failure function for STA 1
1227 * \param psdu the PSDU
1228 */
1230
1231 /**
1232 * Receive failure function for STA 2
1233 * \param psdu the PSDU
1234 */
1236
1237 /**
1238 * Check the results for STA 1
1239 * \param expectedRxSuccess the expected number of RX success
1240 * \param expectedRxFailure the expected number of RX failures
1241 * \param expectedRxBytes the expected number of RX bytes
1242 */
1243 void CheckResultsSta1(uint32_t expectedRxSuccess,
1244 uint32_t expectedRxFailure,
1245 uint32_t expectedRxBytes);
1246
1247 /**
1248 * Check the results for STA 2
1249 * \param expectedRxSuccess the expected number of RX success
1250 * \param expectedRxFailure the expected number of RX failures
1251 * \param expectedRxBytes the expected number of RX bytes
1252 */
1253 void CheckResultsSta2(uint32_t expectedRxSuccess,
1254 uint32_t expectedRxFailure,
1255 uint32_t expectedRxBytes);
1256
1257 /**
1258 * Reset the results
1259 */
1260 void ResetResults();
1261
1262 /**
1263 * Send MU-PPDU function
1264 * \param rxStaId1 the ID of the recipient STA for the first PSDU
1265 * \param rxStaId2 the ID of the recipient STA for the second PSDU
1266 * \param puncturedSubchannels indicates for each subchannel whether it is punctured or not. if
1267 * empty, preamble puncturing is not used.
1268 */
1269 void SendMuPpdu(uint16_t rxStaId1,
1270 uint16_t rxStaId2,
1271 const std::vector<bool>& puncturedSubchannels);
1272
1273 /**
1274 * Generate interference function
1275 * \param interferencePsd the PSD of the interference to be generated
1276 * \param duration the duration of the interference
1277 */
1278 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1279
1280 /**
1281 * Stop interference function
1282 */
1283 void StopInterference();
1284
1285 /**
1286 * Run one function
1287 */
1288 void RunOne();
1289
1290 /**
1291 * Schedule now to check the PHY state
1292 * \param phy the PHY
1293 * \param expectedState the expected state of the PHY
1294 */
1295 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
1296
1297 /**
1298 * Check the PHY state now
1299 * \param phy the PHY
1300 * \param expectedState the expected state of the PHY
1301 */
1303
1304 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
1305 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
1306 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
1307 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
1308 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
1309 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
1310
1315
1316 uint16_t m_frequency; ///< frequency in MHz
1317 uint16_t m_channelWidth; ///< channel width in MHz
1318
1319 uint8_t m_indexSubchannel; ///< Index of the subchannel (starting from 0) that should contain an
1320 ///< interference and be punctured during the test run
1321
1322 Time m_expectedPpduDuration20Mhz; ///< expected duration to send MU PPDU on 20 MHz RU
1323 Time m_expectedPpduDuration40Mhz; ///< expected duration to send MU PPDU on 40 MHz RU
1324};
1325
1327 : TestCase("DL-OFDMA PHY puncturing test"),
1328 m_countRxSuccessSta1(0),
1329 m_countRxSuccessSta2(0),
1330 m_countRxFailureSta1(0),
1331 m_countRxFailureSta2(0),
1332 m_countRxBytesSta1(0),
1333 m_countRxBytesSta2(0),
1334 m_frequency(5210),
1335 m_channelWidth(80),
1336 m_indexSubchannel(0),
1337 m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1338 m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1339{
1340}
1341
1342void
1344{
1351}
1352
1353void
1355 uint16_t rxStaId2,
1356 const std::vector<bool>& puncturedSubchannels)
1357{
1358 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1359 WifiConstPsduMap psdus;
1361 0,
1363 800,
1364 1,
1365 1,
1366 0,
1368 false,
1369 false);
1370
1371 HeRu::RuType ruType =
1372 puncturedSubchannels.empty()
1374 : (puncturedSubchannels.at(1) ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1375 HeRu::RuSpec ru1(ruType, 1, true);
1376 txVector.SetRu(ru1, rxStaId1);
1377 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1378 txVector.SetNss(1, rxStaId1);
1379
1380 ruType = puncturedSubchannels.empty()
1382 : (puncturedSubchannels.at(1) ? HeRu::RU_484_TONE : HeRu::RU_242_TONE);
1383 HeRu::RuSpec ru2(ruType,
1384 ruType == HeRu::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1385 true);
1386 txVector.SetRu(ru2, rxStaId2);
1387 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1388 txVector.SetNss(1, rxStaId2);
1389
1390 std::vector<uint8_t> ruAlloc;
1391 if (puncturedSubchannels.empty())
1392 {
1393 std::fill_n(std::back_inserter(ruAlloc), 4, 200);
1394 }
1395 else
1396 {
1397 ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1398 ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
1399 ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1400 : (puncturedSubchannels.at(3) ? 192 : 200));
1401 ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1402 : (puncturedSubchannels.at(3) ? 113 : 200));
1403 }
1404
1405 txVector.SetRuAllocation(ruAlloc, 0);
1406 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1407
1408 Ptr<Packet> pkt1 = Create<Packet>(1000);
1409 WifiMacHeader hdr1;
1411 hdr1.SetQosTid(0);
1412 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1413 hdr1.SetSequenceNumber(1);
1414 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1415 psdus.insert(std::make_pair(rxStaId1, psdu1));
1416
1417 Ptr<Packet> pkt2 = Create<Packet>(1500);
1418 WifiMacHeader hdr2;
1420 hdr2.SetQosTid(0);
1421 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1422 hdr2.SetSequenceNumber(2);
1423 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1424 psdus.insert(std::make_pair(rxStaId2, psdu2));
1425
1426 if (!puncturedSubchannels.empty())
1427 {
1428 txVector.SetInactiveSubchannels(puncturedSubchannels);
1429 }
1430
1431 m_phyAp->Send(psdus, txVector);
1432}
1433
1434void
1436{
1437 NS_LOG_FUNCTION(this << duration);
1439 m_phyInterferer->SetPeriod(duration);
1442}
1443
1444void
1446{
1447 NS_LOG_FUNCTION(this);
1449}
1450
1451void
1453 RxSignalInfo rxSignalInfo,
1454 WifiTxVector txVector,
1455 std::vector<bool> /*statusPerMpdu*/)
1456{
1457 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1459 m_countRxBytesSta1 += (psdu->GetSize() - 30);
1460}
1461
1462void
1464 RxSignalInfo rxSignalInfo,
1465 WifiTxVector txVector,
1466 std::vector<bool> /*statusPerMpdu*/)
1467{
1468 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1470 m_countRxBytesSta2 += (psdu->GetSize() - 30);
1471}
1472
1473void
1475{
1476 NS_LOG_FUNCTION(this << *psdu);
1478}
1479
1480void
1482{
1483 NS_LOG_FUNCTION(this << *psdu);
1485}
1486
1487void
1489 uint32_t expectedRxFailure,
1490 uint32_t expectedRxBytes)
1491{
1493 expectedRxSuccess,
1494 "The number of successfully received packets by STA 1 is not correct!");
1496 expectedRxFailure,
1497 "The number of unsuccessfuly received packets by STA 1 is not correct!");
1499 expectedRxBytes,
1500 "The number of bytes received by STA 1 is not correct!");
1501}
1502
1503void
1505 uint32_t expectedRxFailure,
1506 uint32_t expectedRxBytes)
1507{
1509 expectedRxSuccess,
1510 "The number of successfully received packets by STA 2 is not correct!");
1512 expectedRxFailure,
1513 "The number of unsuccessfuly received packets by STA 2 is not correct!");
1515 expectedRxBytes,
1516 "The number of bytes received by STA 2 is not correct!");
1517}
1518
1519void
1521{
1522 // This is needed to make sure PHY state will be checked as the last event if a state change
1523 // occurred at the exact same time as the check
1525}
1526
1527void
1529{
1530 WifiPhyState currentState;
1531 PointerValue ptr;
1532 phy->GetAttribute("State", ptr);
1533 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
1534 currentState = state->GetState();
1535 NS_LOG_FUNCTION(this << currentState);
1536 NS_TEST_ASSERT_MSG_EQ(currentState,
1537 expectedState,
1538 "PHY State " << currentState << " does not match expected state "
1539 << expectedState << " at " << Simulator::Now());
1540}
1541
1542void
1544{
1545 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1546 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1547 lossModel->SetFrequency(m_frequency * 1e6);
1548 spectrumChannel->AddPropagationLossModel(lossModel);
1550 CreateObject<ConstantSpeedPropagationDelayModel>();
1551 spectrumChannel->SetPropagationDelayModel(delayModel);
1552
1553 Ptr<Node> apNode = CreateObject<Node>();
1554 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1555 m_phyAp = CreateObject<SpectrumWifiPhy>();
1556 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1557 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1558 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1559 m_phyAp->SetErrorRateModel(apErrorModel);
1560 m_phyAp->SetDevice(apDev);
1561 m_phyAp->AddChannel(spectrumChannel);
1563 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1564 m_phyAp->SetMobility(apMobility);
1565 apDev->SetPhy(m_phyAp);
1566 apNode->AggregateObject(apMobility);
1567 apNode->AddDevice(apDev);
1568
1569 Ptr<Node> sta1Node = CreateObject<Node>();
1570 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1571 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1572 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1573 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1574 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1575 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1576 m_phySta1->SetDevice(sta1Dev);
1577 m_phySta1->AddChannel(spectrumChannel);
1582 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1583 m_phySta1->SetMobility(sta1Mobility);
1584 sta1Dev->SetPhy(m_phySta1);
1585 sta1Node->AggregateObject(sta1Mobility);
1586 sta1Node->AddDevice(sta1Dev);
1587
1588 Ptr<Node> sta2Node = CreateObject<Node>();
1589 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1590 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1591 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1592 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1593 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1594 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1595 m_phySta2->SetDevice(sta2Dev);
1596 m_phySta2->AddChannel(spectrumChannel);
1601 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1602 m_phySta2->SetMobility(sta2Mobility);
1603 sta2Dev->SetPhy(m_phySta2);
1604 sta2Node->AggregateObject(sta2Mobility);
1605 sta2Node->AddDevice(sta2Dev);
1606
1607 Ptr<Node> interfererNode = CreateObject<Node>();
1608 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
1609 m_phyInterferer = CreateObject<WaveformGenerator>();
1610 m_phyInterferer->SetDevice(interfererDev);
1611 m_phyInterferer->SetChannel(spectrumChannel);
1613 interfererNode->AddDevice(interfererDev);
1614}
1615
1616void
1618{
1619 m_phyAp->Dispose();
1620 m_phyAp = nullptr;
1621 m_phySta1->Dispose();
1622 m_phySta1 = nullptr;
1623 m_phySta2->Dispose();
1624 m_phySta2 = nullptr;
1626 m_phyInterferer = nullptr;
1627}
1628
1629void
1631{
1634 int64_t streamNumber = 0;
1635 m_phyAp->AssignStreams(streamNumber);
1636 m_phySta1->AssignStreams(streamNumber);
1637 m_phySta2->AssignStreams(streamNumber);
1638
1639 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1644
1651
1652 // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1653 // duration of the test run
1654 BandInfo bandInfo;
1655 bandInfo.fc = (m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20)) * 1e6;
1656 // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1657 // the border of another RU
1658 bandInfo.fl = bandInfo.fc - (5 * 1e6);
1659 bandInfo.fh = bandInfo.fc + (5 * 1e6);
1660 Bands bands;
1661 bands.push_back(bandInfo);
1662
1663 Ptr<SpectrumModel> spectrumInterference = Create<SpectrumModel>(bands);
1664 Ptr<SpectrumValue> interferencePsd = Create<SpectrumValue>(spectrumInterference);
1665 double interferencePower = 0.1; // watts
1666 *interferencePsd = interferencePower / 10e6;
1667
1670 this,
1671 interferencePsd,
1672 Seconds(3));
1673
1674 //---------------------------------------------------------------------------
1675 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1678 this,
1679 1,
1680 2,
1681 std::vector<bool>{});
1682
1683 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1684 // both PHYs should be back to IDLE at the same time.
1687 this,
1688 m_phySta1,
1689 WifiPhyState::RX);
1692 this,
1693 m_phySta2,
1694 WifiPhyState::RX);
1697 this,
1698 m_phySta1,
1699 WifiPhyState::IDLE);
1702 this,
1703 m_phySta2,
1704 WifiPhyState::IDLE);
1705
1706 if (m_indexSubchannel < 2) // interference in RU 1
1707 {
1708 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1711 this,
1712 0,
1713 1,
1714 0);
1715 // One PSDU of 1500 bytes should have been successfully received by STA 2
1718 this,
1719 1,
1720 0,
1721 1500);
1722 }
1723 else // interference in RU 2
1724 {
1725 // One PSDU of 1000 bytes should have been successfully received by STA 1
1728 this,
1729 1,
1730 0,
1731 1000);
1732 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1735 this,
1736 0,
1737 1,
1738 0);
1739 }
1740
1742
1743 //---------------------------------------------------------------------------
1744 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1745 // the punctured 20 MHz subchannel is the one that has interference
1746 std::vector<bool> puncturedSubchannels;
1747 for (std::size_t i = 0; i < (m_channelWidth / 20); ++i)
1748 {
1749 if (i == m_indexSubchannel)
1750 {
1751 puncturedSubchannels.push_back(true);
1752 }
1753 else
1754 {
1755 puncturedSubchannels.push_back(false);
1756 }
1757 }
1760 this,
1761 1,
1762 2,
1763 puncturedSubchannels);
1764
1765 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1766 // both PHYs should be back to IDLE at the same time.
1769 this,
1770 m_phySta1,
1771 WifiPhyState::RX);
1774 this,
1775 m_phySta2,
1776 WifiPhyState::RX);
1779 this,
1780 m_phySta1,
1781 WifiPhyState::IDLE);
1784 this,
1785 m_phySta2,
1786 WifiPhyState::IDLE);
1787
1788 // One PSDU of 1000 bytes should have been successfully received by STA 1
1791 this,
1792 1,
1793 0,
1794 1000);
1795 // One PSDU of 1500 bytes should have been successfully received by STA 2
1798 this,
1799 1,
1800 0,
1801 1500);
1802
1804
1806}
1807
1808void
1810{
1811 // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1812 // cannot be punctured
1813 for (auto index : {1, 2, 3})
1814 {
1815 m_indexSubchannel = index;
1816 RunOne();
1817 }
1819}
1820
1821/**
1822 * \ingroup wifi-test
1823 * \ingroup tests
1824 *
1825 * \brief UL-OFDMA PPDU UID attribution test
1826 */
1828{
1829 public:
1831 ~TestUlOfdmaPpduUid() override;
1832
1833 private:
1834 void DoSetup() override;
1835 void DoTeardown() override;
1836 void DoRun() override;
1837
1838 /**
1839 * Transmitted PPDU information function for AP
1840 * \param uid the UID of the transmitted PPDU
1841 */
1842 void TxPpduAp(uint64_t uid);
1843 /**
1844 * Transmitted PPDU information function for STA 1
1845 * \param uid the UID of the transmitted PPDU
1846 */
1847 void TxPpduSta1(uint64_t uid);
1848 /**
1849 * Transmitted PPDU information function for STA 2
1850 * \param uid the UID of the transmitted PPDU
1851 */
1852 void TxPpduSta2(uint64_t uid);
1853 /**
1854 * Reset the global PPDU UID counter in WifiPhy
1855 */
1856 void ResetPpduUid();
1857
1858 /**
1859 * Send MU-PPDU toward both STAs.
1860 */
1861 void SendMuPpdu();
1862 /**
1863 * Send TB-PPDU from both STAs.
1864 */
1865 void SendTbPpdu();
1866 /**
1867 * Send SU-PPDU function
1868 * \param txStaId the ID of the sending STA
1869 */
1870 void SendSuPpdu(uint16_t txStaId);
1871
1872 /**
1873 * Check the UID of the transmitted PPDU
1874 * \param staId the STA-ID of the PHY (0 for AP)
1875 * \param expectedUid the expected UID
1876 */
1877 void CheckUid(uint16_t staId, uint64_t expectedUid);
1878
1882
1883 uint64_t m_ppduUidAp; ///< UID of PPDU transmitted by AP
1884 uint64_t m_ppduUidSta1; ///< UID of PPDU transmitted by STA1
1885 uint64_t m_ppduUidSta2; ///< UID of PPDU transmitted by STA2
1886};
1887
1889 : TestCase("UL-OFDMA PPDU UID attribution test"),
1890 m_ppduUidAp(UINT64_MAX),
1891 m_ppduUidSta1(UINT64_MAX),
1892 m_ppduUidSta2(UINT64_MAX)
1893{
1894}
1895
1897{
1898}
1899
1900void
1902{
1903 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1904 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1905 lossModel->SetFrequency(DEFAULT_FREQUENCY);
1906 spectrumChannel->AddPropagationLossModel(lossModel);
1908 CreateObject<ConstantSpeedPropagationDelayModel>();
1909 spectrumChannel->SetPropagationDelayModel(delayModel);
1910
1911 Ptr<Node> apNode = CreateObject<Node>();
1912 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1913 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
1914 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1915 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1916 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1917 m_phyAp->SetErrorRateModel(apErrorModel);
1918 m_phyAp->AddChannel(spectrumChannel);
1920 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1927 m_phyAp->SetDevice(apDev);
1930 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1931 m_phyAp->SetMobility(apMobility);
1932 apDev->SetPhy(m_phyAp);
1933 apNode->AggregateObject(apMobility);
1934 apNode->AddDevice(apDev);
1935 apDev->SetStandard(WIFI_STANDARD_80211ax);
1936 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1937
1938 Ptr<Node> sta1Node = CreateObject<Node>();
1939 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1940 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1941 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1942 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1943 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1944 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1945 m_phySta1->AddChannel(spectrumChannel);
1949 m_phySta1->SetDevice(sta1Dev);
1952 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1953 m_phySta1->SetMobility(sta1Mobility);
1954 sta1Dev->SetPhy(m_phySta1);
1955 sta1Node->AggregateObject(sta1Mobility);
1956 sta1Node->AddDevice(sta1Dev);
1957
1958 Ptr<Node> sta2Node = CreateObject<Node>();
1959 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1960 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1961 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1962 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1963 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1964 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1965 m_phySta2->AddChannel(spectrumChannel);
1969 m_phySta2->SetDevice(sta2Dev);
1972 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1973 m_phySta2->SetMobility(sta2Mobility);
1974 sta2Dev->SetPhy(m_phySta2);
1975 sta2Node->AggregateObject(sta2Mobility);
1976 sta2Node->AddDevice(sta2Dev);
1977}
1978
1979void
1981{
1982 m_phyAp->Dispose();
1983 m_phyAp = nullptr;
1984 m_phySta1->Dispose();
1985 m_phySta1 = nullptr;
1986 m_phySta2->Dispose();
1987 m_phySta2 = nullptr;
1988}
1989
1990void
1991TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
1992{
1993 uint64_t uid;
1994 std::string device;
1995 switch (staId)
1996 {
1997 case 0:
1998 uid = m_ppduUidAp;
1999 device = "AP";
2000 break;
2001 case 1:
2002 uid = m_ppduUidSta1;
2003 device = "STA1";
2004 break;
2005 case 2:
2006 uid = m_ppduUidSta2;
2007 device = "STA2";
2008 break;
2009 default:
2010 NS_ABORT_MSG("Unexpected STA-ID");
2011 }
2013 expectedUid,
2014 "UID " << uid << " does not match expected one " << expectedUid << " for "
2015 << device << " at " << Simulator::Now());
2016}
2017
2018void
2020{
2021 NS_LOG_FUNCTION(this << uid);
2022 m_ppduUidAp = uid;
2023}
2024
2025void
2027{
2028 NS_LOG_FUNCTION(this << uid);
2029 m_ppduUidSta1 = uid;
2030}
2031
2032void
2034{
2035 NS_LOG_FUNCTION(this << uid);
2036 m_ppduUidSta2 = uid;
2037}
2038
2039void
2041{
2042 NS_LOG_FUNCTION(this);
2043 m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2044}
2045
2046void
2048{
2049 WifiConstPsduMap psdus;
2051 0,
2053 800,
2054 1,
2055 1,
2056 0,
2058 false,
2059 false);
2060
2061 uint16_t rxStaId1 = 1;
2062 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2063 txVector.SetRu(ru1, rxStaId1);
2064 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2065 txVector.SetNss(1, rxStaId1);
2066
2067 uint16_t rxStaId2 = 2;
2068 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2069 txVector.SetRu(ru2, rxStaId2);
2070 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2071 txVector.SetNss(1, rxStaId2);
2072 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2073 txVector.SetRuAllocation({96}, 0);
2074
2075 Ptr<Packet> pkt1 = Create<Packet>(1000);
2076 WifiMacHeader hdr1;
2078 hdr1.SetQosTid(0);
2079 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2080 hdr1.SetSequenceNumber(1);
2081 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2082 psdus.insert(std::make_pair(rxStaId1, psdu1));
2083
2084 Ptr<Packet> pkt2 = Create<Packet>(1500);
2085 WifiMacHeader hdr2;
2087 hdr2.SetQosTid(0);
2088 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2089 hdr2.SetSequenceNumber(2);
2090 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2091 psdus.insert(std::make_pair(rxStaId2, psdu2));
2092
2093 m_phyAp->Send(psdus, txVector);
2094}
2095
2096void
2098{
2099 WifiConstPsduMap psdus1;
2100 WifiConstPsduMap psdus2;
2101
2103 0,
2105 1600,
2106 1,
2107 1,
2108 0,
2110 false,
2111 false);
2112 WifiTxVector txVector2 = txVector1;
2113 WifiTxVector trigVector = txVector2;
2114
2115 uint16_t rxStaId1 = 1;
2116 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2117 txVector1.SetRu(ru1, rxStaId1);
2118 txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2119 txVector1.SetNss(1, rxStaId1);
2120 trigVector.SetRu(ru1, rxStaId1);
2121 trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2122 trigVector.SetNss(1, rxStaId1);
2123
2124 Ptr<Packet> pkt1 = Create<Packet>(1000);
2125 WifiMacHeader hdr1;
2127 hdr1.SetQosTid(0);
2128 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2129 hdr1.SetSequenceNumber(1);
2130 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2131 psdus1.insert(std::make_pair(rxStaId1, psdu1));
2132
2133 uint16_t rxStaId2 = 2;
2134 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, false);
2135 txVector2.SetRu(ru2, rxStaId2);
2136 txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2137 txVector2.SetNss(1, rxStaId2);
2138 trigVector.SetRu(ru2, rxStaId2);
2139 trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2140 trigVector.SetNss(1, rxStaId2);
2141
2142 Ptr<Packet> pkt2 = Create<Packet>(1500);
2143 WifiMacHeader hdr2;
2145 hdr2.SetQosTid(0);
2146 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2147 hdr2.SetSequenceNumber(2);
2148 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2149 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2150
2151 Time txDuration1 = m_phySta1->CalculateTxDuration(psdu1->GetSize(),
2152 txVector1,
2154 rxStaId1);
2155 Time txDuration2 = m_phySta2->CalculateTxDuration(psdu2->GetSize(),
2156 txVector2,
2158 rxStaId2);
2159 Time txDuration = std::max(txDuration1, txDuration2);
2160
2161 txVector1.SetLength(
2163 .first);
2164 txVector2.SetLength(
2166 .first);
2167
2168 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
2169 hePhyAp->SetTrigVector(trigVector, txDuration);
2170
2171 m_phySta1->Send(psdus1, txVector1);
2172 m_phySta2->Send(psdus2, txVector2);
2173}
2174
2175void
2177{
2178 WifiConstPsduMap psdus;
2180 0,
2182 800,
2183 1,
2184 1,
2185 0,
2187 false,
2188 false);
2189
2190 Ptr<Packet> pkt = Create<Packet>(1000);
2191 WifiMacHeader hdr;
2193 hdr.SetQosTid(0);
2195 hdr.SetSequenceNumber(1);
2196 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2197 psdus.insert(std::make_pair(SU_STA_ID, psdu));
2198
2199 switch (txStaId)
2200 {
2201 case 0:
2202 m_phyAp->Send(psdus, txVector);
2203 break;
2204 case 1:
2205 m_phySta1->Send(psdus, txVector);
2206 break;
2207 case 2:
2208 m_phySta2->Send(psdus, txVector);
2209 break;
2210 default:
2211 NS_ABORT_MSG("Unexpected STA-ID");
2212 }
2213}
2214
2215void
2217{
2220 int64_t streamNumber = 0;
2221 m_phyAp->AssignStreams(streamNumber);
2222 m_phySta1->AssignStreams(streamNumber);
2223 m_phySta2->AssignStreams(streamNumber);
2224
2225 // Reset PPDU UID so as not to be dependent on previously executed test cases,
2226 // since global attribute will be changed).
2227 ResetPpduUid();
2228
2229 // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2230 // PPDU UID should be equal to 0 (the first counter value).
2233
2234 // Send HE SU PPDU from AP.
2235 // PPDU UID should be incremented since this is a new PPDU.
2238
2239 // Send HE TB PPDU from STAs to AP.
2240 // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2241 // preceding correctly received PPDU (which normally contains the trigger frame).
2245
2246 // Send HE SU PPDU from STA1.
2247 // PPDU UID should be incremented since this is a new PPDU.
2250
2253}
2254
2255/**
2256 * \ingroup wifi-test
2257 * \ingroup tests
2258 *
2259 * \brief UL-OFDMA multiple RX events test
2260 */
2262{
2263 public:
2265 ~TestMultipleHeTbPreambles() override;
2266
2267 private:
2268 void DoSetup() override;
2269 void DoTeardown() override;
2270 void DoRun() override;
2271
2272 /**
2273 * Receive HE TB PPDU function.
2274 *
2275 * \param uid the UID used to identify a set of HE TB PPDUs belonging to the same UL-MU
2276 * transmission
2277 * \param staId the STA ID
2278 * \param txPowerWatts the TX power in watts
2279 * \param payloadSize the size of the payload in bytes
2280 */
2281 void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize);
2282
2283 /**
2284 * Receive OFDMA part of HE TB PPDU function.
2285 * Immediately schedules DoRxHeTbPpduOfdmaPart.
2286 *
2287 * \param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2288 */
2290 /**
2291 * Receive OFDMA part of HE TB PPDU function.
2292 * Actual reception call.
2293 *
2294 * \param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2295 */
2297
2298 /**
2299 * RX dropped function
2300 * \param p the packet
2301 * \param reason the reason
2302 */
2304
2305 /**
2306 * Reset function
2307 */
2308 void Reset();
2309
2310 /**
2311 * Check the received HE TB preambles
2312 * \param nEvents the number of events created by the PHY
2313 * \param uids the vector of expected UIDs
2314 */
2315 void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2316
2317 /**
2318 * Check the number of bytes dropped
2319 * \param expectedBytesDropped the expected number of bytes dropped
2320 */
2321 void CheckBytesDropped(size_t expectedBytesDropped);
2322
2324
2325 uint64_t m_totalBytesDropped; ///< total number of dropped bytes
2327};
2328
2330 : TestCase("UL-OFDMA multiple RX events test"),
2331 m_totalBytesDropped(0),
2332 m_trigVector(HePhy::GetHeMcs7(),
2333 0,
2335 1600,
2336 1,
2337 1,
2338 0,
2340 false,
2341 false)
2342{
2343}
2344
2346{
2347}
2348
2349void
2351{
2352 NS_LOG_FUNCTION(this);
2354 // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2355 m_phy->Reset();
2357}
2358
2359void
2361{
2362 NS_LOG_FUNCTION(this << p << reason);
2363 m_totalBytesDropped += (p->GetSize() - 30);
2364}
2365
2366void
2367TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2368{
2369 auto events = m_phy->GetCurrentPreambleEvents();
2370 NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2371 for (const auto& uid : uids)
2372 {
2373 auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2374 auto it = events.find(pair);
2375 bool found = (it != events.end());
2377 true,
2378 "HE TB PPDU with UID " << uid << " has not been received!");
2379 }
2380}
2381
2382void
2384{
2386 expectedBytesDropped,
2387 "The number of dropped bytes is not correct!");
2388}
2389
2390void
2392 uint16_t staId,
2393 double txPowerWatts,
2394 size_t payloadSize)
2395{
2396 WifiConstPsduMap psdus;
2398 0,
2400 1600,
2401 1,
2402 1,
2403 0,
2405 false,
2406 false);
2407
2408 HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2409 txVector.SetRu(ru, staId);
2410 txVector.SetMode(HePhy::GetHeMcs7(), staId);
2411 txVector.SetNss(1, staId);
2412
2413 m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2414
2415 Ptr<Packet> pkt = Create<Packet>(payloadSize);
2416 WifiMacHeader hdr;
2418 hdr.SetQosTid(0);
2419 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2420 hdr.SetSequenceNumber(1);
2421 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2422 psdus.insert(std::make_pair(staId, psdu));
2423
2424 Time ppduDuration =
2425 m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand(), staId);
2426 Ptr<HePpdu> ppdu = Create<HePpdu>(psdus,
2427 txVector,
2429 ppduDuration,
2430 uid,
2432
2433 // Send non-OFDMA part
2434 Time nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonHeDurationForHeTb(txVector);
2435 uint32_t centerFrequency = m_phy->GetHePhy()->GetCenterFrequencyForNonHePart(txVector, staId);
2436 uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2437 uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
2439 centerFrequency,
2440 channelWidth,
2441 txPowerWatts,
2442 m_phy->GetGuardBandwidth(channelWidth));
2443 Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters>();
2444 rxParams->psd = rxPsd;
2445 rxParams->txPhy = nullptr;
2446 rxParams->duration = nonOfdmaDuration;
2447 rxParams->ppdu = ppdu;
2448
2449 uint16_t length;
2450 std::tie(length, ppduDuration) =
2452 txVector.SetLength(length);
2453 m_trigVector.SetLength(length);
2454 auto hePhy = DynamicCast<HePhy>(m_phy->GetLatestPhyEntity());
2455 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2456 ppdu->ResetTxVector();
2457 m_phy->StartRx(rxParams, nullptr);
2458
2459 // Schedule OFDMA part
2460 Ptr<HePpdu> ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2461 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2462 const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2463 Ptr<SpectrumValue> rxPsdOfdma =
2466 txPowerWatts,
2468 band.indices);
2469 Ptr<WifiSpectrumSignalParameters> rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2470 rxParamsOfdma->psd = rxPsd;
2471 rxParamsOfdma->txPhy = nullptr;
2472 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2473 rxParamsOfdma->ppdu = ppduOfdma;
2474 Simulator::Schedule(nonOfdmaDuration,
2476 this,
2477 rxParamsOfdma);
2478}
2479
2480void
2482{
2484}
2485
2486void
2488{
2489 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2490 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2491 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2492 m_phy->StartRx(rxParamsOfdma, nullptr);
2493}
2494
2495void
2497{
2498 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
2499 Ptr<Node> node = CreateObject<Node>();
2500 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
2501 dev->SetStandard(WIFI_STANDARD_80211ax);
2502 m_phy = CreateObject<OfdmaSpectrumWifiPhy>(0);
2503 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2504 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2505 auto mac = CreateObjectWithAttributes<ApWifiMac>(
2506 "Txop",
2507 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
2508 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2509 dev->SetMac(mac);
2510 m_phy->SetInterferenceHelper(interferenceHelper);
2511 m_phy->SetErrorRateModel(error);
2512 m_phy->AddChannel(spectrumChannel);
2517 0});
2518 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2520 m_phy->SetDevice(dev);
2521 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2522 CreateObject<ThresholdPreambleDetectionModel>();
2523 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2524 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2525 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2526 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
2527 heConfiguration->SetMaxTbPpduDelay(NanoSeconds(400));
2528 dev->SetHeConfiguration(heConfiguration);
2529 dev->SetPhy(m_phy);
2530 node->AddDevice(dev);
2531}
2532
2533void
2535{
2536 m_phy->Dispose();
2537 m_phy = nullptr;
2538}
2539
2540void
2542{
2545 int64_t streamNumber = 0;
2546 m_phy->AssignStreams(streamNumber);
2547
2548 double txPowerWatts = 0.01;
2549
2550 {
2551 // Verify a single UL MU transmission with two stations belonging to the same BSS
2552 std::vector<uint64_t> uids{0};
2555 this,
2556 uids[0],
2557 1,
2558 txPowerWatts,
2559 1001);
2562 this,
2563 uids[0],
2564 2,
2565 txPowerWatts,
2566 1002);
2567 // Check that we received a single UL MU transmission with the corresponding UID
2570 this,
2571 1,
2572 uids);
2574 }
2575
2576 {
2577 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2578 // the second transmission arrives during the preamble detection window and with half the
2579 // power of the first transmission.
2580 std::vector<uint64_t> uids{1, 2};
2583 this,
2584 uids[0],
2585 1,
2586 txPowerWatts,
2587 1001);
2590 this,
2591 uids[0],
2592 2,
2593 txPowerWatts,
2594 1002);
2597 this,
2598 uids[1],
2599 1,
2600 txPowerWatts / 2,
2601 1003);
2604 this,
2605 uids[1],
2606 2,
2607 txPowerWatts / 2,
2608 1004);
2609 // Check that we received the correct reception of 2 UL MU transmissions with the
2610 // corresponding UIDs
2613 this,
2614 2,
2615 uids);
2617 // TODO: verify PPDUs from second UL MU transmission are dropped
2618 }
2619
2620 {
2621 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2622 // the second transmission arrives during the preamble detection window and with twice the
2623 // power of the first transmission.
2624 std::vector<uint64_t> uids{3, 4};
2627 this,
2628 uids[0],
2629 1,
2630 txPowerWatts / 2,
2631 1001);
2634 this,
2635 uids[0],
2636 2,
2637 txPowerWatts / 2,
2638 1002);
2641 this,
2642 uids[1],
2643 1,
2644 txPowerWatts,
2645 1003);
2648 this,
2649 uids[1],
2650 2,
2651 txPowerWatts,
2652 1004);
2653 // Check that we received the correct reception of 2 UL MU transmissions with the
2654 // corresponding UIDs
2657 this,
2658 2,
2659 uids);
2661 // TODO: verify PPDUs from first UL MU transmission are dropped
2662 }
2663
2664 {
2665 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2666 // the second transmission arrives during PHY header reception and with the same power as
2667 // the first transmission.
2668 std::vector<uint64_t> uids{5, 6};
2671 this,
2672 uids[0],
2673 1,
2674 txPowerWatts,
2675 1001);
2678 this,
2679 uids[0],
2680 2,
2681 txPowerWatts,
2682 1002);
2685 this,
2686 uids[1],
2687 1,
2688 txPowerWatts,
2689 1003);
2692 this,
2693 uids[1],
2694 2,
2695 txPowerWatts,
2696 1004);
2697 // Check that we received the correct reception of the first UL MU transmission with the
2698 // corresponding UID (second one dropped)
2701 this,
2702 1,
2703 std::vector<uint64_t>{uids[0]});
2704 // The packets of the second UL MU transmission should have been dropped
2707 this,
2708 1003 + 1004);
2710 }
2711
2712 {
2713 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2714 // BSS, where the second transmission arrives during payload reception and with the same
2715 // power as the first transmission.
2716 std::vector<uint64_t> uids{7, 8};
2719 this,
2720 uids[0],
2721 1,
2722 txPowerWatts,
2723 1001);
2726 this,
2727 uids[0],
2728 2,
2729 txPowerWatts,
2730 1002);
2733 this,
2734 uids[1],
2735 1,
2736 txPowerWatts,
2737 1003);
2740 this,
2741 uids[1],
2742 2,
2743 txPowerWatts,
2744 1004);
2745 // Check that we received the correct reception of the first UL MU transmission with the
2746 // corresponding UID (second one dropped)
2749 this,
2750 1,
2751 std::vector<uint64_t>{uids[0]});
2752 // The packets of the second UL MU transmission should have been dropped
2755 this,
2756 1003 + 1004);
2758 }
2759
2760 {
2761 // Verify the correct reception of a single UL MU transmission with two stations belonging
2762 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2763 // the configured delay spread of 400ns
2764 std::vector<uint64_t> uids{9};
2767 this,
2768 uids[0],
2769 1,
2770 txPowerWatts,
2771 1001);
2774 this,
2775 uids[0],
2776 2,
2777 txPowerWatts,
2778 1002);
2779 // Check that we received a single UL MU transmission with the corresponding UID
2782 this,
2783 1,
2784 uids);
2785 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2786 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2787 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2788 // second packet of 1002 bytes is dropped as well.
2791 this,
2792 1001 + 1002);
2794 }
2795
2798}
2799
2800/**
2801 * \ingroup wifi-test
2802 * \ingroup tests
2803 *
2804 * \brief PHY listener for OFDMA tests
2805 */
2807{
2808 public:
2810
2811 void NotifyRxStart(Time duration) override
2812 {
2813 NS_LOG_FUNCTION(this << duration);
2816 m_lastRxSuccess = false;
2817 }
2818
2819 void NotifyRxEndOk() override
2820 {
2821 NS_LOG_FUNCTION(this);
2823 ++m_notifyRxEnd;
2824 m_lastRxSuccess = true;
2825 }
2826
2827 void NotifyRxEndError() override
2828 {
2829 NS_LOG_FUNCTION(this);
2831 ++m_notifyRxEnd;
2832 m_lastRxSuccess = false;
2833 }
2834
2835 void NotifyTxStart(Time duration, double txPowerDbm) override
2836 {
2837 NS_LOG_FUNCTION(this << duration << txPowerDbm);
2838 }
2839
2841 WifiChannelListType channelType,
2842 const std::vector<Time>& /*per20MhzDurations*/) override
2843 {
2844 NS_LOG_FUNCTION(this << duration << channelType);
2845 }
2846
2847 void NotifySwitchingStart(Time duration) override
2848 {
2849 }
2850
2851 void NotifySleep() override
2852 {
2853 }
2854
2855 void NotifyOff() override
2856 {
2857 }
2858
2859 void NotifyWakeup() override
2860 {
2861 }
2862
2863 void NotifyOn() override
2864 {
2865 }
2866
2867 /**
2868 * Reset function.
2869 */
2870 void Reset()
2871 {
2872 m_notifyRxStart = 0;
2873 m_notifyRxEnd = 0;
2875 m_lastRxEnd = Seconds(0);
2876 m_lastRxSuccess = false;
2877 }
2878
2879 /**
2880 * Return the number of RX start notifications that has been received since the last reset.
2881 * \return the number of RX start notifications that has been received
2882 */
2884 {
2885 return m_notifyRxStart;
2886 }
2887
2888 /**
2889 * Return the number of RX end notifications that has been received since the last reset.
2890 * \return the number of RX end notifications that has been received
2891 */
2893 {
2894 return m_notifyRxEnd;
2895 }
2896
2897 /**
2898 * Return the time at which the last RX start notification has been received.
2899 * \return the time at which the last RX start notification has been received
2900 */
2902 {
2903 return m_lastRxStart;
2904 }
2905
2906 /**
2907 * Return the time at which the last RX end notification has been received.
2908 * \return the time at which the last RX end notification has been received
2909 */
2911 {
2912 return m_lastRxEnd;
2913 }
2914
2915 /**
2916 * Return whether last RX has been successful.
2917 * \return true if last RX has been successful, false otherwise
2918 */
2919 bool IsLastRxSuccess() const
2920 {
2921 return m_lastRxSuccess;
2922 }
2923
2924 private:
2925 uint32_t m_notifyRxStart{0}; ///< count number of RX start notifications
2926 uint32_t m_notifyRxEnd{0}; ///< count number of RX end notifications
2927 Time m_lastRxStart{Seconds(0)}; ///< last time a RX start notification has been received
2928 Time m_lastRxEnd{Seconds(0)}; ///< last time a RX end notification has been received
2929 bool m_lastRxSuccess{false}; ///< flag whether last RX has been successful
2930};
2931
2932/**
2933 * \ingroup wifi-test
2934 * \ingroup tests
2935 *
2936 * \brief UL-OFDMA PHY test
2937 */
2939{
2940 public:
2941 /**
2942 * Erroneous info included in a TRIGVECTOR
2943 */
2945 {
2946 NONE = 0,
2950 };
2951
2953 ~TestUlOfdmaPhyTransmission() override;
2954
2955 private:
2956 void DoSetup() override;
2957 void DoTeardown() override;
2958 void DoRun() override;
2959
2960 /**
2961 * Get TXVECTOR for HE TB PPDU.
2962 * \param txStaId the ID of the TX STA
2963 * \param index the RU index used for the transmission
2964 * \param bssColor the BSS color of the TX STA
2965 * \return the TXVECTOR for HE TB PPDU
2966 */
2967 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2968 std::size_t index,
2969 uint8_t bssColor) const;
2970 /**
2971 * Set TRIGVECTOR for HE TB PPDU
2972 *
2973 * \param bssColor the BSS color of the TX STA
2974 * \param error the erroneous info (if any) in the TRIGVECTOR to set
2975 */
2976 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2977 /**
2978 * Send HE TB PPDU function
2979 * \param txStaId the ID of the TX STA
2980 * \param index the RU index used for the transmission
2981 * \param payloadSize the size of the payload in bytes
2982 * \param uid the UID of the trigger frame that is initiating this transmission
2983 * \param bssColor the BSS color of the TX STA
2984 * \param incrementUid whether UID shall be incremented
2985 */
2986 void SendHeTbPpdu(uint16_t txStaId,
2987 std::size_t index,
2988 std::size_t payloadSize,
2989 uint64_t uid,
2990 uint8_t bssColor,
2991 bool incrementUid);
2992
2993 /**
2994 * Send HE SU PPDU function
2995 * \param txStaId the ID of the TX STA
2996 * \param payloadSize the size of the payload in bytes
2997 * \param uid the UID of the trigger frame that is initiating this transmission
2998 * \param bssColor the BSS color of the TX STA
2999 */
3000 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
3001
3002 /**
3003 * Set the BSS color
3004 * \param phy the PHY
3005 * \param bssColor the BSS color
3006 */
3007 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3008
3009 /**
3010 * Set the PSD limit
3011 * \param phy the PHY
3012 * \param psdLimit the PSD limit in dBm/MHz
3013 */
3014 void SetPsdLimit(Ptr<WifiPhy> phy, double psdLimit);
3015
3016 /**
3017 * Generate interference function
3018 * \param interferencePsd the PSD of the interference to be generated
3019 * \param duration the duration of the interference
3020 */
3021 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3022 /**
3023 * Stop interference function
3024 */
3025 void StopInterference();
3026
3027 /**
3028 * Run one function
3029 */
3030 void RunOne();
3031
3032 /**
3033 * Check the received PSDUs from STA1
3034 * \param expectedSuccess the expected number of success
3035 * \param expectedFailures the expected number of failures
3036 * \param expectedBytes the expected number of bytes
3037 */
3038 void CheckRxFromSta1(uint32_t expectedSuccess,
3039 uint32_t expectedFailures,
3040 uint32_t expectedBytes);
3041
3042 /**
3043 * Check the received PSDUs from STA2
3044 * \param expectedSuccess the expected number of success
3045 * \param expectedFailures the expected number of failures
3046 * \param expectedBytes the expected number of bytes
3047 */
3048 void CheckRxFromSta2(uint32_t expectedSuccess,
3049 uint32_t expectedFailures,
3050 uint32_t expectedBytes);
3051
3052 /**
3053 * Check the received power for the non-OFDMA of the HE TB PPDUs over the given band
3054 * \param phy the PHY
3055 * \param band the indices of the band over which the power is measured
3056 * \param expectedRxPower the expected received power in W
3057 */
3060 double expectedRxPower);
3061 /**
3062 * Check the received power for the OFDMA part of the HE TB PPDUs over the given band
3063 * \param phy the PHY
3064 * \param band the indices of the band over which the power is measured
3065 * \param expectedRxPower the expected received power in W
3066 */
3069 double expectedRxPower);
3070
3071 /**
3072 * Verify all events are cleared at end of TX or RX
3073 */
3074 void VerifyEventsCleared();
3075
3076 /**
3077 * Check the PHY state
3078 * \param phy the PHY
3079 * \param expectedState the expected state of the PHY
3080 */
3081 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
3082 /// \copydoc CheckPhyState
3084
3085 /**
3086 * Check the the number of RX start notifications at the AP as well as the last time a RX start
3087 * has been notified
3088 * \param expectedNotifications the expected number of RX start notifications at the AP
3089 * \param expectedLastNotification the expected time of the last RX start notification at the AP
3090 */
3091 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3092 /**
3093 * Check the the number of RX end notifications at the AP as well as the last time a RX end has
3094 * been notified
3095 * \param expectedNotifications the expected number of RX end notifications at the AP
3096 * \param expectedLastNotification the expected time of the last RX end notification at the AP
3097 * \param expectedSuccess true if the last RX notification indicates a success, false otherwise
3098 */
3099 void CheckApRxEnd(uint32_t expectedNotifications,
3100 Time expectedLastNotification,
3101 bool expectedSuccess);
3102
3103 /**
3104 * Reset function
3105 */
3106 void Reset();
3107
3108 /**
3109 * Receive success function
3110 * \param psdu the PSDU
3111 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
3112 * \param txVector the transmit vector
3113 * \param statusPerMpdu reception status per MPDU
3114 */
3116 RxSignalInfo rxSignalInfo,
3117 WifiTxVector txVector,
3118 std::vector<bool> statusPerMpdu);
3119
3120 /**
3121 * Receive failure function
3122 * \param psdu the PSDU
3123 */
3124 void RxFailure(Ptr<const WifiPsdu> psdu);
3125
3126 /**
3127 * Schedule test to perform.
3128 * The interference generation should be scheduled apart.
3129 *
3130 * \param delay the reference delay to schedule the events
3131 * \param solicited flag indicating if HE TB PPDUs were solicited by the AP
3132 * \param expectedStateAtEnd the expected state of the PHY at the end of the reception
3133 * \param expectedSuccessFromSta1 the expected number of success from STA 1
3134 * \param expectedFailuresFromSta1 the expected number of failures from STA 1
3135 * \param expectedBytesFromSta1 the expected number of bytes from STA 1
3136 * \param expectedSuccessFromSta2 the expected number of success from STA 2
3137 * \param expectedFailuresFromSta2 the expected number of failures from STA 2
3138 * \param expectedBytesFromSta2 the expected number of bytes from STA 2
3139 * \param scheduleTxSta1 flag indicating to schedule a HE TB PPDU from STA 1
3140 * \param ulTimeDifference delay between HE TB PPDU from STA 1 and HE TB PPDU from STA 2
3141 * are received
3142 * \param expectedStateBeforeEnd the expected state of the PHY before the end of the
3143 * transmission
3144 * \param error the erroneous info (if any) in the TRIGVECTOR to set
3145 */
3146 void ScheduleTest(Time delay,
3147 bool solicited,
3148 WifiPhyState expectedStateAtEnd,
3149 uint32_t expectedSuccessFromSta1,
3150 uint32_t expectedFailuresFromSta1,
3151 uint32_t expectedBytesFromSta1,
3152 uint32_t expectedSuccessFromSta2,
3153 uint32_t expectedFailuresFromSta2,
3154 uint32_t expectedBytesFromSta2,
3155 bool scheduleTxSta1 = true,
3156 Time ulTimeDifference = Seconds(0),
3157 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3158 TrigVectorInfo error = NONE);
3159
3160 /**
3161 * Schedule power measurement related checks.
3162 *
3163 * \param delay the reference delay used to schedule the events
3164 * \param rxPowerNonOfdmaRu1 the received power (in watts) on the non-OFDMA part of RU1
3165 * \param rxPowerNonOfdmaRu2 the received power (in watts) on the non-OFDMA part of RU2
3166 * \param rxPowerOfdmaRu1 the received power (in watts) on RU1
3167 * \param rxPowerOfdmaRu2 the received power (in watts) on RU2
3168 */
3170 double rxPowerNonOfdmaRu1,
3171 double rxPowerNonOfdmaRu2,
3172 double rxPowerOfdmaRu1,
3173 double rxPowerOfdmaRu2);
3174 /**
3175 * Log scenario description
3176 *
3177 * \param log the scenario description to add to log
3178 */
3179 void LogScenario(std::string log) const;
3180
3185
3186 std::shared_ptr<OfdmaTestPhyListener>
3187 m_apPhyStateListener; ///< listener for AP PHY state transitions
3188
3190
3191 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
3192 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
3193 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
3194 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
3195 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
3196 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
3197
3198 uint16_t m_frequency; ///< frequency in MHz
3199 uint16_t m_channelWidth; ///< channel width in MHz
3200 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
3201};
3202
3204 : TestCase("UL-OFDMA PHY test"),
3205 m_countRxSuccessFromSta1(0),
3206 m_countRxSuccessFromSta2(0),
3207 m_countRxFailureFromSta1(0),
3208 m_countRxFailureFromSta2(0),
3209 m_countRxBytesFromSta1(0),
3210 m_countRxBytesFromSta2(0),
3211 m_frequency(DEFAULT_FREQUENCY),
3212 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3213 m_expectedPpduDuration(NanoSeconds(271200))
3214{
3215}
3216
3217void
3219 std::size_t payloadSize,
3220 uint64_t uid,
3221 uint8_t bssColor)
3222{
3223 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3224 WifiConstPsduMap psdus;
3225
3227 0,
3229 800,
3230 1,
3231 1,
3232 0,
3234 false,
3235 false,
3236 false,
3237 bssColor);
3238
3239 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3240 WifiMacHeader hdr;
3242 hdr.SetQosTid(0);
3243 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3244 std::ostringstream addr;
3245 addr << "00:00:00:00:00:0" << txStaId;
3246 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3247 hdr.SetSequenceNumber(1);
3248 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3249 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3250
3252 if (txStaId == 1)
3253 {
3254 phy = m_phySta1;
3255 }
3256 else if (txStaId == 2)
3257 {
3258 phy = m_phySta2;
3259 }
3260 else if (txStaId == 3)
3261 {
3262 phy = m_phySta3;
3263 }
3264 else if (txStaId == 0)
3265 {
3266 phy = m_phyAp;
3267 }
3268 phy->SetPpduUid(uid);
3269 phy->Send(psdus, txVector);
3270}
3271
3274 std::size_t index,
3275 uint8_t bssColor) const
3276{
3278 0,
3280 1600,
3281 1,
3282 1,
3283 0,
3285 false,
3286 false,
3287 false,
3288 bssColor);
3289
3291 if (m_channelWidth == 20)
3292 {
3293 ruType = HeRu::RU_106_TONE;
3294 }
3295 else if (m_channelWidth == 40)
3296 {
3297 ruType = HeRu::RU_242_TONE;
3298 }
3299 else if (m_channelWidth == 80)
3300 {
3301 ruType = HeRu::RU_484_TONE;
3302 }
3303 else if (m_channelWidth == 160)
3304 {
3305 ruType = HeRu::RU_996_TONE;
3306 }
3307 else
3308 {
3309 NS_ASSERT_MSG(false, "Unsupported channel width");
3310 }
3311
3312 bool primary80MHz = true;
3313 if (m_channelWidth == 160 && index == 2)
3314 {
3315 primary80MHz = false;
3316 index = 1;
3317 }
3318 HeRu::RuSpec ru(ruType, index, primary80MHz);
3319 txVector.SetRu(ru, txStaId);
3320 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3321 txVector.SetNss(1, txStaId);
3322 return txVector;
3323}
3324
3325void
3327{
3328 uint16_t channelWidth = m_channelWidth;
3329 if (error == CHANNEL_WIDTH)
3330 {
3331 channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
3332 }
3333
3334 WifiTxVector txVector(HePhy::GetHeMcs7(),
3335 0,
3337 1600,
3338 1,
3339 1,
3340 0,
3341 channelWidth,
3342 false,
3343 false,
3344 false,
3345 bssColor);
3346
3348 if (channelWidth == 20)
3349 {
3350 ruType = HeRu::RU_106_TONE;
3351 }
3352 else if (channelWidth == 40)
3353 {
3354 ruType = HeRu::RU_242_TONE;
3355 }
3356 else if (channelWidth == 80)
3357 {
3358 ruType = HeRu::RU_484_TONE;
3359 }
3360 else if (channelWidth == 160)
3361 {
3362 ruType = HeRu::RU_996_TONE;
3363 }
3364 else
3365 {
3366 NS_ASSERT_MSG(false, "Unsupported channel width");
3367 }
3368
3369 uint16_t aid1 = (error == AID ? 3 : 1);
3370 uint16_t aid2 = (error == AID ? 4 : 2);
3371
3372 HeRu::RuSpec ru1(ruType, 1, true);
3373 txVector.SetRu(ru1, aid1);
3374 txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3375 txVector.SetNss(1, aid1);
3376
3377 HeRu::RuSpec ru2(ruType, (channelWidth == 160 ? 1 : 2), (channelWidth != 160));
3378 txVector.SetRu(ru2, aid2);
3379 txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3380 txVector.SetNss(1, aid2);
3381
3382 uint16_t length;
3383 std::tie(length, m_expectedPpduDuration) =
3385 txVector,
3386 m_phyAp->GetPhyBand());
3387 if (error == UL_LENGTH)
3388 {
3389 ++length;
3390 }
3391 txVector.SetLength(length);
3392 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
3393 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3394}
3395
3396void
3398 std::size_t index,
3399 std::size_t payloadSize,
3400 uint64_t uid,
3401 uint8_t bssColor,
3402 bool incrementUid)
3403{
3404 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3405 WifiConstPsduMap psdus;
3406
3407 if (incrementUid)
3408 {
3409 ++uid;
3410 }
3411
3412 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3413 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3414 WifiMacHeader hdr;
3416 hdr.SetQosTid(0);
3417 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3418 std::ostringstream addr;
3419 addr << "00:00:00:00:00:0" << txStaId;
3420 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3421 hdr.SetSequenceNumber(1);
3422 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3423 psdus.insert(std::make_pair(txStaId, psdu));
3424
3426 if (txStaId == 1)
3427 {
3428 phy = m_phySta1;
3429 }
3430 else if (txStaId == 2)
3431 {
3432 phy = m_phySta2;
3433 }
3434 else if (txStaId == 3)
3435 {
3436 phy = m_phySta3;
3437 }
3438
3439 Time txDuration =
3440 phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
3441 txVector.SetLength(
3442 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3443
3444 phy->SetPpduUid(uid);
3445 phy->Send(psdus, txVector);
3446}
3447
3448void
3450{
3451 NS_LOG_FUNCTION(this << duration);
3453 m_phyInterferer->SetPeriod(duration);
3456}
3457
3458void
3460{
3462}
3463
3465{
3466}
3467
3468void
3470 RxSignalInfo rxSignalInfo,
3471 WifiTxVector txVector,
3472 std::vector<bool> /*statusPerMpdu*/)
3473{
3474 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3475 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3476 {
3478 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3479 }
3480 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3481 {
3483 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3484 }
3485}
3486
3487void
3489{
3490 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3491 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3492 {
3494 }
3495 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3496 {
3498 }
3499}
3500
3501void
3503 uint32_t expectedFailures,
3504 uint32_t expectedBytes)
3505{
3507 expectedSuccess,
3508 "The number of successfully received packets from STA 1 is not correct!");
3511 expectedFailures,
3512 "The number of unsuccessfuly received packets from STA 1 is not correct!");
3514 expectedBytes,
3515 "The number of bytes received from STA 1 is not correct!");
3516}
3517
3518void
3520 uint32_t expectedFailures,
3521 uint32_t expectedBytes)
3522{
3524 expectedSuccess,
3525 "The number of successfully received packets from STA 2 is not correct!");
3528 expectedFailures,
3529 "The number of unsuccessfuly received packets from STA 2 is not correct!");
3531 expectedBytes,
3532 "The number of bytes received from STA 2 is not correct!");
3533}
3534
3535void
3538 double expectedRxPower)
3539{
3540 Ptr<Event> event = phy->GetCurrentEvent();
3541 NS_ASSERT(event);
3542 auto rxPower = event->GetRxPowerW(band);
3543 NS_LOG_FUNCTION(this << band << expectedRxPower << rxPower);
3544 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3546 expectedRxPower,
3547 5e-3,
3548 "RX power " << rxPower << " over (" << band
3549 << ") does not match expected power " << expectedRxPower
3550 << " at " << Simulator::Now());
3551}
3552
3553void
3556 double expectedRxPower)
3557{
3558 /**
3559 * The current event cannot be used since it points to the preamble part of the HE TB PPDU.
3560 * We will have to check if the expected power is indeed the max power returning a positive
3561 * duration when calling GetEnergyDuration.
3562 */
3563 NS_LOG_FUNCTION(this << band << expectedRxPower);
3564 double step = 5e-3;
3565 if (expectedRxPower > 0.0)
3566 {
3568 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3569 true,
3570 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3571 << Simulator::Now());
3573 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3574 false,
3575 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3576 << Simulator::Now());
3577 }
3578 else
3579 {
3581 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3582 false,
3583 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3584 << Simulator::Now());
3585 }
3586}
3587
3588void
3590{
3592 nullptr,
3593 "m_currentEvent for AP was not cleared");
3595 nullptr,
3596 "m_currentEvent for STA 1 was not cleared");
3598 nullptr,
3599 "m_currentEvent for STA 2 was not cleared");
3600}
3601
3602void
3604{
3605 // This is needed to make sure PHY state will be checked as the last event if a state change
3606 // occurred at the exact same time as the check
3608}
3609
3610void
3612 WifiPhyState expectedState)
3613{
3614 WifiPhyState currentState;
3615 PointerValue ptr;
3616 phy->GetAttribute("State", ptr);
3617 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
3618 currentState = state->GetState();
3619 NS_LOG_FUNCTION(this << currentState);
3620 NS_TEST_ASSERT_MSG_EQ(currentState,
3621 expectedState,
3622 "PHY State " << currentState << " does not match expected state "
3623 << expectedState << " at " << Simulator::Now());
3624}
3625
3626void
3628 Time expectedLastNotification)
3629{
3630 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxStartNotifications(),
3631 expectedNotifications,
3632 "Number of RX start notifications "
3633 << m_apPhyStateListener->GetNumRxStartNotifications()
3634 << " does not match expected count " << expectedNotifications
3635 << " for AP at " << Simulator::Now());
3636 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxStartNotification(),
3637 expectedLastNotification,
3638 "Last time RX start notification has been received "
3639 << m_apPhyStateListener->GetLastRxStartNotification()
3640 << " does not match expected time " << expectedLastNotification
3641 << " for AP at " << Simulator::Now());
3642}
3643
3644void
3646 Time expectedLastNotification,
3647 bool expectedSuccess)
3648{
3649 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxEndNotifications(),
3650 expectedNotifications,
3651 "Number of RX end notifications "
3652 << m_apPhyStateListener->GetNumRxEndNotifications()
3653 << " does not match expected count " << expectedNotifications
3654 << " for AP at " << Simulator::Now());
3655 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxEndNotification(),
3656 expectedLastNotification,
3657 "Last time RX end notification has been received "
3658 << m_apPhyStateListener->GetLastRxEndNotification()
3659 << " does not match expected time " << expectedLastNotification
3660 << " for AP at " << Simulator::Now());
3662 expectedSuccess,
3663 "Last time RX end notification indicated a "
3664 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3665 << " but expected a " << (expectedSuccess ? "success" : "failure")
3666 << " for AP at " << Simulator::Now());
3667}
3668
3669void
3671{
3681 SetBssColor(m_phyAp, 0);
3682 m_apPhyStateListener->Reset();
3683}
3684
3685void
3687{
3688 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3689 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3690 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3691}
3692
3693void
3695{
3696 NS_LOG_FUNCTION(this << phy << psdLimit);
3697 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3698}
3699
3700void
3702{
3703 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
3704 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
3705 lossModel->SetFrequency(m_frequency);
3706 spectrumChannel->AddPropagationLossModel(lossModel);
3708 CreateObject<ConstantSpeedPropagationDelayModel>();
3709 spectrumChannel->SetPropagationDelayModel(delayModel);
3710
3711 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3712 CreateObject<ThresholdPreambleDetectionModel>();
3713 preambleDetectionModel->SetAttribute(
3714 "MinimumRssi",
3716 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3717 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3718
3719 Ptr<Node> apNode = CreateObject<Node>();
3720 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
3721 apDev->SetStandard(WIFI_STANDARD_80211ax);
3722 auto apMac = CreateObjectWithAttributes<ApWifiMac>(
3723 "Txop",
3724 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
3725 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3726 apDev->SetMac(apMac);
3727 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
3728 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
3729 apDev->SetHeConfiguration(heConfiguration);
3730 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
3731 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3732 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
3733 m_phyAp->SetErrorRateModel(apErrorModel);
3734 m_phyAp->SetDevice(apDev);
3735 m_phyAp->AddChannel(spectrumChannel);
3739 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3740 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
3741 m_phyAp->SetMobility(apMobility);
3742 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3744 apDev->SetPhy(m_phyAp);
3745 apMac->SetWifiPhys({m_phyAp});
3746 apNode->AggregateObject(apMobility);
3747 apNode->AddDevice(apDev);
3748
3749 Ptr<Node> sta1Node = CreateObject<Node>();
3750 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
3751 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
3752 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3753 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
3754 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
3755 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3756 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
3757 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3758 m_phySta1->SetDevice(sta1Dev);
3759 m_phySta1->AddChannel(spectrumChannel);
3761 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3762 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
3763 m_phySta1->SetMobility(sta1Mobility);
3764 sta1Dev->SetPhy(m_phySta1);
3765 sta1Node->AggregateObject(sta1Mobility);
3766 sta1Node->AddDevice(sta1Dev);
3767
3768 Ptr<Node> sta2Node = CreateObject<Node>();
3769 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
3770 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
3771 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3772 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
3773 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
3774 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3775 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
3776 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3777 m_phySta2->SetDevice(sta2Dev);
3778 m_phySta2->AddChannel(spectrumChannel);
3780 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3781 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
3782 m_phySta2->SetMobility(sta2Mobility);
3783 sta2Dev->SetPhy(m_phySta2);
3784 sta2Node->AggregateObject(sta2Mobility);
3785 sta2Node->AddDevice(sta2Dev);
3786
3787 Ptr<Node> sta3Node = CreateObject<Node>();
3788 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
3789 sta3Dev->SetStandard(WIFI_STANDARD_80211ax);
3790 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3791 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
3792 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
3793 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3794 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
3795 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3796 m_phySta3->SetDevice(sta3Dev);
3797 m_phySta3->AddChannel(spectrumChannel);
3799 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3800 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
3801 m_phySta3->SetMobility(sta3Mobility);
3802 sta3Dev->SetPhy(m_phySta3);
3803 sta3Node->AggregateObject(sta3Mobility);
3804 sta3Node->AddDevice(sta3Dev);
3805
3806 Ptr<Node> interfererNode = CreateObject<Node>();
3807 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
3808 m_phyInterferer = CreateObject<WaveformGenerator>();
3809 m_phyInterferer->SetDevice(interfererDev);
3810 m_phyInterferer->SetChannel(spectrumChannel);
3812 interfererNode->AddDevice(interfererDev);
3813
3814 // Configure power attributes of all wifi devices
3815 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3816 for (auto& phy : phys)
3817 {
3818 phy->SetAttribute("TxGain", DoubleValue(1.0));
3819 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3820 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3821 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3822 phy->SetAttribute("RxGain", DoubleValue(2.0));
3823 // test assumes no rejection power for simplicity
3824 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3825 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3826 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3827 }
3828}
3829
3830void
3832{
3833 m_phyAp->Dispose();
3834 m_phyAp = nullptr;
3835 m_phySta1->Dispose();
3836 m_phySta1 = nullptr;
3837 m_phySta2->Dispose();
3838 m_phySta2 = nullptr;
3839 m_phySta3->Dispose();
3840 m_phySta3 = nullptr;
3842 m_phyInterferer = nullptr;
3843}
3844
3845void
3847{
3848 NS_LOG_INFO(log);
3849}
3850
3851void
3853 bool solicited,
3854 WifiPhyState expectedStateAtEnd,
3855 uint32_t expectedSuccessFromSta1,
3856 uint32_t expectedFailuresFromSta1,
3857 uint32_t expectedBytesFromSta1,
3858 uint32_t expectedSuccessFromSta2,
3859 uint32_t expectedFailuresFromSta2,
3860 uint32_t expectedBytesFromSta2,
3861 bool scheduleTxSta1,
3862 Time ulTimeDifference,
3863 WifiPhyState expectedStateBeforeEnd,
3864 TrigVectorInfo error)
3865{
3866 static uint64_t uid = 0;
3867
3868 // AP sends an SU packet preceding HE TB PPDUs
3871 this,
3872 0,
3873 50,
3874 ++uid,
3875 0);
3876 if (!solicited)
3877 {
3878 // UID of TB PPDUs will be different than the one of the preceding frame
3879 ++uid;
3880 }
3881 else
3882 {
3884 }
3885 // STA1 and STA2 send MU UL PPDUs addressed to AP
3888 m_apPhyStateListener.get());
3889 if (scheduleTxSta1)
3890 {
3891 Simulator::Schedule(delay,
3893 this,
3894 1,
3895 1,
3896 1000,
3897 uid,
3898 0,
3899 false);
3900 }
3901 Simulator::Schedule(delay + ulTimeDifference,
3903 this,
3904 2,
3905 2,
3906 1001,
3907 uid,
3908 0,
3909 false);
3910
3911 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3914 this,
3915 m_phyAp,
3916 expectedStateBeforeEnd);
3917 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3919 this,
3920 m_phyAp,
3921 expectedStateAtEnd);
3922 // TODO: add checks on TX stop for STAs
3923
3924 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3925 expectedFailuresFromSta2 >
3926 0)
3927 {
3928 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3929 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3930 // The expected time at which the reception is started corresponds to the time at which the
3931 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3932 const Time expectedPayloadStart = delay + MicroSeconds(48);
3933 // The expected time at which the reception is terminated corresponds to the time at which
3934 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3935 // received HE TB PPDU and the last received HE TB PPDU.
3936 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3937 // At the end of the transmission, verify that a single RX start notification shall have
3938 // been notified when the reception of the first HE RB PPDU starts.
3939 Simulator::Schedule(expectedPayloadEnd,
3941 this,
3942 1,
3943 Simulator::Now() + expectedPayloadStart);
3944 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3945 // notification shall have been notified when the reception of the last HE RB PPDU ends
3946 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3948 this,
3949 1,
3950 Simulator::Now() + expectedPayloadEnd,
3951 isSuccess);
3952 }
3953
3954 delay += MilliSeconds(100);
3955 // Check reception state from STA 1
3956 Simulator::Schedule(delay,
3958 this,
3959 expectedSuccessFromSta1,
3960 expectedFailuresFromSta1,
3961 expectedBytesFromSta1);
3962 // Check reception state from STA 2
3963 Simulator::Schedule(delay,
3965 this,
3966 expectedSuccessFromSta2,
3967 expectedFailuresFromSta2,
3968 expectedBytesFromSta2);
3969 // Verify events data have been cleared
3971
3972 delay += MilliSeconds(100);
3974}
3975
3976void
3978 double rxPowerNonOfdmaRu1,
3979 double rxPowerNonOfdmaRu2,
3980 double rxPowerOfdmaRu1,
3981 double rxPowerOfdmaRu2)
3982{
3983 Time detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3984 WifiTxVector txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3985 WifiTxVector txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3987 Time nonOfdmaDuration = hePhy->CalculateNonHeDurationForHeTb(txVectorSta2);
3988 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonHeDurationForHeTb(txVectorSta1));
3989
3990 std::vector<double> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3991 std::vector<WifiSpectrumBandInfo> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3992 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
3993 std::vector<double> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
3994 std::vector<WifiSpectrumBandInfo> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
3995 hePhy->GetRuBandForRx(txVectorSta2, 2)};
3996
3997 for (uint8_t i = 0; i < 2; ++i)
3998 {
3999 /**
4000 * Perform checks at AP
4001 */
4002 // Check received power on non-OFDMA portion
4004 delay + detectionDuration +
4005 NanoSeconds(1), // just after beginning of portion (once event is stored)
4007 this,
4008 m_phyAp,
4009 nonOfdmaBand[i],
4010 rxPowerNonOfdma[i]);
4011 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4013 this,
4014 m_phyAp,
4015 nonOfdmaBand[i],
4016 rxPowerNonOfdma[i]);
4017 // Check received power on OFDMA portion
4018 Simulator::Schedule(delay + nonOfdmaDuration +
4019 NanoSeconds(1), // just after beginning of portion
4021 this,
4022 m_phyAp,
4023 ofdmaBand[i],
4024 rxPowerOfdma[i]);
4026 NanoSeconds(1), // just before end of portion
4028 this,
4029 m_phyAp,
4030 ofdmaBand[i],
4031 rxPowerOfdma[i]);
4032
4033 /**
4034 * Perform checks for non-transmitting STA (STA 3).
4035 * Cannot use CheckNonOfdmaRxPower method since current event may be reset if
4036 * preamble not detected (e.g. not on primary).
4037 */
4038 // Check received power on non-OFDMA portion
4040 delay + detectionDuration +
4041 NanoSeconds(1), // just after beginning of portion (once event is stored)
4043 this,
4044 m_phySta3,
4045 nonOfdmaBand[i],
4046 rxPowerNonOfdma[i]);
4047 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4049 this,
4050 m_phySta3,
4051 nonOfdmaBand[i],
4052 rxPowerNonOfdma[i]);
4053 // Check received power on OFDMA portion
4054 Simulator::Schedule(delay + nonOfdmaDuration +
4055 NanoSeconds(1), // just after beginning of portion
4057 this,
4058 m_phySta3,
4059 ofdmaBand[i],
4060 rxPowerOfdma[i]);
4062 NanoSeconds(1), // just before end of portion
4064 this,
4065 m_phySta3,
4066 ofdmaBand[i],
4067 rxPowerOfdma[i]);
4068 }
4069
4070 if (rxPowerOfdmaRu1 != 0.0)
4071 {
4072 /**
4073 * Perform checks for transmitting STA (STA 2) to ensure it has correctly logged
4074 * power received from other transmitting STA (STA 1).
4075 * Cannot use CheckNonOfdmaRxPower method since current event not set.
4076 */
4077 double rxPowerNonOfdmaSta1Only =
4078 (m_channelWidth >= 40)
4079 ? rxPowerNonOfdma[0]
4080 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4081 // Check received power on non-OFDMA portion
4083 delay + detectionDuration +
4084 NanoSeconds(1), // just after beginning of portion (once event is stored)
4086 this,
4087 m_phySta2,
4088 nonOfdmaBand[0],
4089 rxPowerNonOfdmaSta1Only);
4090 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4092 this,
4093 m_phySta2,
4094 nonOfdmaBand[0],
4095 rxPowerNonOfdmaSta1Only);
4096 // Check received power on OFDMA portion
4097 Simulator::Schedule(delay + nonOfdmaDuration +
4098 NanoSeconds(1), // just after beginning of portion
4100 this,
4101 m_phySta2,
4102 ofdmaBand[0],
4103 rxPowerOfdma[0]);
4105 NanoSeconds(1), // just before end of portion
4107 this,
4108 m_phySta2,
4109 ofdmaBand[0],
4110 rxPowerOfdma[0]);
4111 }
4112}
4113
4114void
4116{
4119 int64_t streamNumber = 0;
4120 m_phyAp->AssignStreams(streamNumber);
4121 m_phySta1->AssignStreams(streamNumber);
4122 m_phySta2->AssignStreams(streamNumber);
4123 m_phySta3->AssignStreams(streamNumber);
4124
4125 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
4130
4139
4140 Time delay = Seconds(0.0);
4142 delay += Seconds(1.0);
4143
4144 /**
4145 * In all the following tests, 2 HE TB PPDUs of the same UL MU transmission
4146 * are sent on RU 1 for STA 1 and RU 2 for STA 2.
4147 * The difference between solicited and unsolicited lies in that their PPDU
4148 * ID correspond to the one of the immediately preceding HE SU PPDU (thus
4149 * mimicking trigger frame reception).
4150 */
4151
4152 //---------------------------------------------------------------------------
4153 // Verify that both solicited HE TB PPDUs have been corrected received
4154 Simulator::Schedule(delay,
4156 this,
4157 "Reception of solicited HE TB PPDUs");
4158 ScheduleTest(delay,
4159 true,
4160 WifiPhyState::IDLE,
4161 1,
4162 0,
4163 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4164 1,
4165 0,
4166 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4167 delay += Seconds(1.0);
4168
4169 //---------------------------------------------------------------------------
4170 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4171 // corrected received
4173 delay,
4175 this,
4176 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4177 ScheduleTest(delay,
4178 true,
4179 WifiPhyState::IDLE,
4180 1,
4181 0,
4182 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4183 1,
4184 0,
4185 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4186 true,
4187 NanoSeconds(100));
4188 delay += Seconds(1.0);
4189
4190 //---------------------------------------------------------------------------
4191 // Verify that no unsolicited HE TB PPDU is received
4192 Simulator::Schedule(delay,
4194 this,
4195 "Dropping of unsolicited HE TB PPDUs");
4196 ScheduleTest(delay,
4197 false,
4198 WifiPhyState::IDLE,
4199 0,
4200 0,
4201 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4202 0,
4203 0,
4204 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4205 true,
4206 Seconds(0),
4207 WifiPhyState::CCA_BUSY);
4208 delay += Seconds(1.0);
4209
4210 //---------------------------------------------------------------------------
4211 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4212 Simulator::Schedule(delay,
4214 this,
4215 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4216 ScheduleTest(delay,
4217 true,
4218 WifiPhyState::IDLE,
4219 0,
4220 0,
4221 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4222 0,
4223 0,
4224 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4225 true,
4226 Seconds(0),
4227 WifiPhyState::CCA_BUSY,
4229 delay += Seconds(1.0);
4230
4231 //---------------------------------------------------------------------------
4232 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4233 Simulator::Schedule(delay,
4235 this,
4236 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4237 ScheduleTest(delay,
4238 true,
4239 WifiPhyState::IDLE,
4240 0,
4241 0,
4242 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4243 0,
4244 0,
4245 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4246 true,
4247 Seconds(0),
4248 WifiPhyState::CCA_BUSY,
4249 UL_LENGTH);
4250 delay += Seconds(1.0);
4251
4252 //---------------------------------------------------------------------------
4253 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4254 Simulator::Schedule(delay,
4256 this,
4257 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4258 ScheduleTest(delay,
4259 true,
4260 WifiPhyState::IDLE,
4261 0,
4262 0,
4263 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4264 0,
4265 0,
4266 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4267 true,
4268 Seconds(0),
4269 WifiPhyState::CCA_BUSY,
4270 AID);
4271 delay += Seconds(1.0);
4272
4273 //---------------------------------------------------------------------------
4274 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4275 // impacted
4277 delay,
4279 this,
4280 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4281 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4282 BandInfo bandInfo;
4283 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
4284 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4285 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4286 Bands bands;
4287 bands.push_back(bandInfo);
4288
4289 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4290 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4291 double interferencePower = 0.1; // watts
4292 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
4293
4296 this,
4297 interferencePsdRu1,
4298 MilliSeconds(100));
4300 delay,
4301 true,
4302 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4303 // interference
4304 0,
4305 1,
4306 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4307 1,
4308 0,
4309 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4310 delay += Seconds(1.0);
4311
4312 //---------------------------------------------------------------------------
4313 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4314 // impacted
4316 delay,
4318 this,
4319 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4320 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4321 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
4322 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4323 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4324 bands.clear();
4325 bands.push_back(bandInfo);
4326
4327 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4328 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4329 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
4330
4333 this,
4334 interferencePsdRu2,
4335 MilliSeconds(100));
4336 ScheduleTest(delay,
4337 true,
4338 (m_channelWidth >= 40)
4339 ? WifiPhyState::IDLE
4340 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4341 // generated in its primary channel
4342 1,
4343 0,
4344 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4345 0,
4346 1,
4347 0); // Reception of the PSDU from STA 2 should have failed (since interference
4348 // occupies RU 2)
4349 delay += Seconds(1.0);
4350
4351 //---------------------------------------------------------------------------
4352 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4353 // been impacted
4354 Simulator::Schedule(delay,
4356 this,
4357 "Reception of solicited HE TB PPDUs with interference on the full band "
4358 "during PSDU reception");
4359 // A strong non-wifi interference is generated on the full band during PSDU reception
4360 bandInfo.fc = m_frequency * 1e6;
4361 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
4362 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
4363 bands.clear();
4364 bands.push_back(bandInfo);
4365
4366 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4367 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4368 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
4369
4372 this,
4373 interferencePsdAll,
4374 MilliSeconds(100));
4376 delay,
4377 true,
4378 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4379 // interference
4380 0,
4381 1,
4382 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4383 0,
4384 1,
4385 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4386 // 2)
4387 delay += Seconds(1.0);
4388
4389 //---------------------------------------------------------------------------
4390 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4391 // solicited HE TB PPDUs have been impacted if they are on the same
4392 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4393 Simulator::Schedule(delay,
4395 this,
4396 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4397 "1 during PSDU reception");
4398 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4401 this,
4402 3,
4403 1,
4404 1002,
4405 1,
4406 0,
4407 false);
4408 // Expected figures from STA 2
4409 uint32_t succ;
4410 uint32_t fail;
4411 uint32_t bytes;
4412 if (m_channelWidth > 20)
4413 {
4414 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4415 // interference from STA 3 on distinct 20 MHz channel)
4416 succ = 1;
4417 fail = 0;
4418 bytes = 1001;
4419 }
4420 else
4421 {
4422 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4423 // same 20 MHz channel)
4424 succ = 0;
4425 fail = 1;
4426 bytes = 0;
4427 }
4428 ScheduleTest(delay,
4429 true,
4430 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4431 // interference on measurement channel width
4432 0,
4433 1,
4434 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4435 // STA 3 on same 20 MHz channel)
4436 succ,
4437 fail,
4438 bytes);
4439 delay += Seconds(1.0);
4440
4441 //---------------------------------------------------------------------------
4442 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4443 // solicited HE TB PPDUs have been impacted if they are on the same
4444 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4445 Simulator::Schedule(delay,
4447 this,
4448 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4449 "2 during PSDU reception");
4450 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4453 this,
4454 3,
4455 2,
4456 1002,
4457 1,
4458 0,
4459 false);
4460 // Expected figures from STA 1
4461 if (m_channelWidth > 20)
4462 {
4463 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4464 // interference from STA 3 on distinct 20 MHz channel)
4465 succ = 1;
4466 fail = 0;
4467 bytes = 1000;
4468 }
4469 else
4470 {
4471 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4472 // same 20 MHz channel)
4473 succ = 0;
4474 fail = 1;
4475 bytes = 0;
4476 }
4477 ScheduleTest(delay,
4478 true,
4479 (m_channelWidth >= 40)
4480 ? WifiPhyState::IDLE
4481 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4482 // TB PPDU on primary channel
4483 succ,
4484 fail,
4485 bytes,
4486 0,
4487 1,
4488 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4489 // STA 3 on same 20 MHz channel)
4490 delay += Seconds(1.0);
4491
4492 //---------------------------------------------------------------------------
4493 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4494 // impacted
4496 delay,
4498 this,
4499 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4500 // One HE SU arrives at AP during the 400ns window
4501 Simulator::Schedule(delay + NanoSeconds(300),
4503 this,
4504 3,
4505 1002,
4506 1,
4507 0);
4509 delay,
4510 true,
4511 WifiPhyState::IDLE,
4512 0,
4513 1,
4514 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4515 0,
4516 1,
4517 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4518 delay += Seconds(1.0);
4519
4520 //---------------------------------------------------------------------------
4521 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4522 // received
4523 Simulator::Schedule(delay,
4525 this,
4526 "Reception of solicited HE TB PPDU only on RU 2");
4527 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4528 // otherwise
4531 this,
4532 m_phySta3,
4533 (m_channelWidth >= 40)
4534 ? WifiPhyState::IDLE
4535 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4536 // IDLE if HE TB PPDU on primary channel
4537 ScheduleTest(delay,
4538 true,
4539 WifiPhyState::IDLE,
4540 0,
4541 0,
4542 0, // No transmission scheduled for STA 1
4543 1,
4544 0,
4545 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4546 false,
4547 Seconds(0),
4548 WifiPhyState::RX); // Measurement channel is total channel width
4549 delay += Seconds(1.0);
4550
4551 //---------------------------------------------------------------------------
4552 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4553 Simulator::Schedule(delay,
4555 this,
4556 "Measure power for reception of HE TB PPDU only on RU 2");
4557 double rxPower =
4558 DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4560 (m_channelWidth >= 40) ? 0.0 : rxPower,
4561 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4562 0.0,
4563 rxPower);
4564 ScheduleTest(delay,
4565 true,
4566 WifiPhyState::IDLE,
4567 0,
4568 0,
4569 0, // No transmission scheduled for STA 1
4570 1,
4571 0,
4572 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4573 false,
4574 Seconds(0),
4575 WifiPhyState::RX); // Measurement channel is total channel width
4576 delay += Seconds(1.0);
4577
4578 //---------------------------------------------------------------------------
4579 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4580 // limitation enforced
4582 delay,
4584 this,
4585 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4586 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4587 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4588 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4590 this,
4591 m_phySta2,
4592 3.0);
4593
4594 rxPower = (m_channelWidth > 40)
4595 ? DbmToW(19)
4596 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4597 // transmitted only on one 20 MHz channel
4598 double rxPowerOfdma = rxPower;
4599 if (m_channelWidth <= 40)
4600 {
4601 rxPowerOfdma = (m_channelWidth == 20)
4602 ? DbmToW(14.0309) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4603 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4604 }
4606 (m_channelWidth >= 40) ? 0.0 : rxPower,
4607 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4608 0.0,
4609 rxPowerOfdma);
4610
4611 // Reset PSD limitation once HE TB has been sent
4614 this,
4615 m_phySta2,
4616 100.0);
4617 ScheduleTest(delay,
4618 true,
4619 WifiPhyState::IDLE,
4620 0,
4621 0,
4622 0, // No transmission scheduled for STA 1
4623 1,
4624 0,
4625 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4626 false,
4627 Seconds(0),
4628 WifiPhyState::RX); // Measurement channel is total channel width
4629 delay += Seconds(1.0);
4630
4631 //---------------------------------------------------------------------------
4632 // Measure the power of 2 solicited HE TB PPDU from both STAs
4633 Simulator::Schedule(delay,
4635 this,
4636 "Measure power for reception of HE TB PPDU on both RUs");
4637 rxPower = DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4638 double rxPowerNonOfdma = (m_channelWidth >= 40)
4639 ? rxPower
4640 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4641 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4642 ScheduleTest(delay,
4643 true,
4644 WifiPhyState::IDLE,
4645 1,
4646 0,
4647 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4648 1,
4649 0,
4650 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4651 delay += Seconds(1.0);
4652
4653 //---------------------------------------------------------------------------
4654 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4655 // ongoing)
4656 Simulator::Schedule(delay,
4658 this,
4659 "Reception of an HE TB PPDU from another BSS");
4660 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4662 Simulator::Schedule(delay + MilliSeconds(100),
4664 this,
4665 3,
4666 1,
4667 1002,
4668 1,
4669 2,
4670 false);
4671
4672 // Verify events data have been cleared
4673 Simulator::Schedule(delay + MilliSeconds(200),
4675 this);
4676
4678 delay += Seconds(1.0);
4679
4680 //---------------------------------------------------------------------------
4681 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4682 // corrected received
4684 delay,
4686 this,
4687 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4688 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4692 this,
4693 3,
4694 1,
4695 1002,
4696 1,
4697 2,
4698 true);
4699 ScheduleTest(delay,
4700 true,
4701 WifiPhyState::CCA_BUSY,
4702 1,
4703 0,
4704 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4705 1,
4706 0,
4707 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4708 true,
4709 NanoSeconds(200));
4710 delay += Seconds(1.0);
4711
4713}
4714
4715void
4717{
4718 m_frequency = 5180;
4719 m_channelWidth = 20;
4721 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4722 RunOne();
4723
4724 m_frequency = 5190;
4725 m_channelWidth = 40;
4727 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4728 RunOne();
4729
4730 m_frequency = 5210;
4731 m_channelWidth = 80;
4733 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4734 RunOne();
4735
4736 m_frequency = 5250;
4737 m_channelWidth = 160;
4739 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4740 RunOne();
4741
4743}
4744
4745/**
4746 * \ingroup wifi-test
4747 * \ingroup tests
4748 *
4749 * \brief PHY padding exclusion test
4750 */
4752{
4753 public:
4755 ~TestPhyPaddingExclusion() override;
4756
4757 private:
4758 void DoSetup() override;
4759 void DoTeardown() override;
4760 void DoRun() override;
4761
4762 /**
4763 * Send HE TB PPDU function
4764 * \param txStaId the ID of the TX STA
4765 * \param index the RU index used for the transmission
4766 * \param payloadSize the size of the payload in bytes
4767 * \param txDuration the duration of the PPDU
4768 */
4769 void SendHeTbPpdu(uint16_t txStaId,
4770 std::size_t index,
4771 std::size_t payloadSize,
4772 Time txDuration);
4773 /**
4774 * Set TRIGVECTOR for HE TB PPDU
4775 *
4776 * \param ppduDuration the duration of the HE TB PPDU
4777 */
4778 void SetTrigVector(Time ppduDuration);
4779
4780 /**
4781 * Generate interference function
4782 * \param interferencePsd the PSD of the interference to be generated
4783 * \param duration the duration of the interference
4784 */
4785 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4786 /**
4787 * Stop interference function
4788 */
4789 void StopInterference();
4790
4791 /**
4792 * Run one function
4793 */
4794 void RunOne();
4795
4796 /**
4797 * Check the received PSDUs from STA1
4798 * \param expectedSuccess the expected number of success
4799 * \param expectedFailures the expected number of failures
4800 * \param expectedBytes the expected number of bytes
4801 */
4802 void CheckRxFromSta1(uint32_t expectedSuccess,
4803 uint32_t expectedFailures,
4804 uint32_t expectedBytes);
4805
4806 /**
4807 * Check the received PSDUs from STA2
4808 * \param expectedSuccess the expected number of success
4809 * \param expectedFailures the expected number of failures
4810 * \param expectedBytes the expected number of bytes
4811 */
4812 void CheckRxFromSta2(uint32_t expectedSuccess,
4813 uint32_t expectedFailures,
4814 uint32_t expectedBytes);
4815
4816 /**
4817 * Verify all events are cleared at end of TX or RX
4818 */
4819 void VerifyEventsCleared();
4820
4821 /**
4822 * Check the PHY state
4823 * \param phy the PHY
4824 * \param expectedState the expected state of the PHY
4825 */
4826 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
4827 /// \copydoc CheckPhyState
4829
4830 /**
4831 * Reset function
4832 */
4833 void Reset();
4834
4835 /**
4836 * Receive success function
4837 * \param psdu the PSDU
4838 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
4839 * \param txVector the transmit vector
4840 * \param statusPerMpdu reception status per MPDU
4841 */
4843 RxSignalInfo rxSignalInfo,
4844 WifiTxVector txVector,
4845 std::vector<bool> statusPerMpdu);
4846
4847 /**
4848 * Receive failure function
4849 * \param psdu the PSDU
4850 */
4851 void RxFailure(Ptr<const WifiPsdu> psdu);
4852
4856
4858
4859 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
4860 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
4861 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
4862 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
4863 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
4864 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
4865};
4866
4868 : TestCase("PHY padding exclusion test"),
4869 m_countRxSuccessFromSta1(0),
4870 m_countRxSuccessFromSta2(0),
4871 m_countRxFailureFromSta1(0),
4872 m_countRxFailureFromSta2(0),
4873 m_countRxBytesFromSta1(0),
4874 m_countRxBytesFromSta2(0)
4875{
4876}
4877
4878void
4880 std::size_t index,
4881 std::size_t payloadSize,
4882 Time txDuration)
4883{
4884 WifiConstPsduMap psdus;
4885
4887 0,
4889 1600,
4890 1,
4891 1,
4892 0,
4894 false,
4895 false,
4896 true);
4897
4898 HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4899 txVector.SetRu(ru, txStaId);
4900 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4901 txVector.SetNss(1, txStaId);
4902
4903 Ptr<Packet> pkt = Create<Packet>(payloadSize);
4904 WifiMacHeader hdr;
4906 hdr.SetQosTid(0);
4907 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4908 std::ostringstream addr;
4909 addr << "00:00:00:00:00:0" << txStaId;
4910 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4911 hdr.SetSequenceNumber(1);
4912 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4913 psdus.insert(std::make_pair(txStaId, psdu));
4914
4916 if (txStaId == 1)
4917 {
4918 phy = m_phySta1;
4919 }
4920 else if (txStaId == 2)
4921 {
4922 phy = m_phySta2;
4923 }
4924
4925 txVector.SetLength(
4926 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4927
4928 phy->SetPpduUid(0);
4929 phy->Send(psdus, txVector);
4930}
4931
4932void
4934{
4936 m_phyInterferer->SetPeriod(duration);
4939}
4940
4941void
4943{
4945}
4946
4948{
4949}
4950
4951void
4953 RxSignalInfo rxSignalInfo,
4954 WifiTxVector txVector,
4955 std::vector<bool> /*statusPerMpdu*/)
4956{
4957 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
4958 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4959 {
4961 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
4962 }
4963 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4964 {
4966 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
4967 }
4968}
4969
4970void
4972{
4973 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
4974 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4975 {
4977 }
4978 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4979 {
4981 }
4982}
4983
4984void
4986 uint32_t expectedFailures,
4987 uint32_t expectedBytes)
4988{
4990 expectedSuccess,
4991 "The number of successfully received packets from STA 1 is not correct!");
4994 expectedFailures,
4995 "The number of unsuccessfuly received packets from STA 1 is not correct!");
4997 expectedBytes,
4998 "The number of bytes received from STA 1 is not correct!");
4999}
5000
5001void
5003 uint32_t expectedFailures,
5004 uint32_t expectedBytes)
5005{
5007 expectedSuccess,
5008 "The number of successfully received packets from STA 2 is not correct!");
5011 expectedFailures,
5012 "The number of unsuccessfuly received packets from STA 2 is not correct!");
5014 expectedBytes,
5015 "The number of bytes received from STA 2 is not correct!");
5016}
5017
5018void
5020{
5022 nullptr,
5023 "m_currentEvent for AP was not cleared");
5025 nullptr,
5026 "m_currentEvent for STA 1 was not cleared");
5028 nullptr,
5029 "m_currentEvent for STA 2 was not cleared");
5030}
5031
5032void
5034{
5035 // This is needed to make sure PHY state will be checked as the last event if a state change
5036 // occurred at the exact same time as the check
5038}
5039
5040void
5042{
5043 WifiPhyState currentState = phy->GetState()->GetState();
5044 NS_LOG_FUNCTION(this << currentState);
5045 NS_TEST_ASSERT_MSG_EQ(currentState,
5046 expectedState,
5047 "PHY State " << currentState << " does not match expected state "
5048 << expectedState << " at " << Simulator::Now());
5049}
5050
5051void
5053{
5063}
5064
5065void
5067{
5070 int64_t streamNumber = 0;
5071
5072 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5073 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
5074 lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
5075 spectrumChannel->AddPropagationLossModel(lossModel);
5077 CreateObject<ConstantSpeedPropagationDelayModel>();
5078 spectrumChannel->SetPropagationDelayModel(delayModel);
5079
5080 Ptr<Node> apNode = CreateObject<Node>();
5081 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
5082 auto apMac = CreateObjectWithAttributes<ApWifiMac>(
5083 "Txop",
5084 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
5085 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5086 apDev->SetMac(apMac);
5087 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
5088 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
5089 apDev->SetHeConfiguration(heConfiguration);
5090 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
5091 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5092 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
5093 m_phyAp->SetErrorRateModel(apErrorModel);
5094 m_phyAp->SetDevice(apDev);
5095 m_phyAp->AddChannel(spectrumChannel);
5097 m_phyAp->AssignStreams(streamNumber);
5098 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
5103
5108 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
5109 m_phyAp->SetMobility(apMobility);
5110 apDev->SetPhy(m_phyAp);
5111 apDev->SetStandard(WIFI_STANDARD_80211ax);
5112 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5113 apMac->SetWifiPhys({m_phyAp});
5114 apNode->AggregateObject(apMobility);
5115 apNode->AddDevice(apDev);
5116
5117 Ptr<Node> sta1Node = CreateObject<Node>();
5118 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
5119 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
5120 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
5121 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5122 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
5123 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5124 m_phySta1->SetDevice(sta1Dev);
5125 m_phySta1->AddChannel(spectrumChannel);
5127 m_phySta1->AssignStreams(streamNumber);
5130 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
5131 m_phySta1->SetMobility(sta1Mobility);
5132 sta1Dev->SetPhy(m_phySta1);
5133 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
5134 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5135 sta1Node->AggregateObject(sta1Mobility);
5136 sta1Node->AddDevice(sta1Dev);
5137
5138 Ptr<Node> sta2Node = CreateObject<Node>();
5139 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
5140 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
5141 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
5142 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5143 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
5144 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5145 m_phySta2->SetDevice(sta2Dev);
5146 m_phySta2->AddChannel(spectrumChannel);
5148 m_phySta2->AssignStreams(streamNumber);
5151 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
5152 m_phySta2->SetMobility(sta2Mobility);
5153 sta2Dev->SetPhy(m_phySta2);
5154 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
5155 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5156 sta2Node->AggregateObject(sta2Mobility);
5157 sta2Node->AddDevice(sta2Dev);
5158
5159 Ptr<Node> interfererNode = CreateObject<Node>();
5160 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
5161 m_phyInterferer = CreateObject<WaveformGenerator>();
5162 m_phyInterferer->SetDevice(interfererDev);
5163 m_phyInterferer->SetChannel(spectrumChannel);
5165 interfererNode->AddDevice(interfererDev);
5166}
5167
5168void
5170{
5171 m_phyAp->Dispose();
5172 m_phyAp = nullptr;
5173 m_phySta1->Dispose();
5174 m_phySta1 = nullptr;
5175 m_phySta2->Dispose();
5176 m_phySta2 = nullptr;
5178 m_phyInterferer = nullptr;
5179}
5180
5181void
5183{
5184 WifiTxVector trigVector(HePhy::GetHeMcs7(),
5185 0,
5187 1600,
5188 1,
5189 1,
5190 0,
5192 false,
5193 false,
5194 true);
5195 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5196 trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5197 trigVector.SetNss(1, 1);
5198 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5199 trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5200 trigVector.SetNss(1, 2);
5201 uint16_t length;
5202 std::tie(length, ppduDuration) =
5204 trigVector.SetLength(length);
5205 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
5206 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5207}
5208
5209void
5211{
5212 Time expectedPpduDuration = NanoSeconds(292800);
5213 Time ppduWithPaddingDuration =
5214 expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5215
5217
5218 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5221 this,
5222 1,
5223 1,
5224 1000,
5225 ppduWithPaddingDuration);
5228 this,
5229 2,
5230 2,
5231 1001,
5232 ppduWithPaddingDuration);
5233
5234 // Set TRIGVECTOR on AP
5237 this,
5238 ppduWithPaddingDuration);
5239
5240 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5241 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration - NanoSeconds(1),
5243 this,
5244 m_phyAp,
5245 WifiPhyState::RX);
5246 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration,
5248 this,
5249 m_phyAp,
5250 WifiPhyState::IDLE);
5251
5252 // One PSDU of 1000 bytes should have been successfully received from STA 1
5254 // One PSDU of 1001 bytes should have been successfully received from STA 2
5256 // Verify events data have been cleared
5258
5260
5261 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5264 this,
5265 1,
5266 1,
5267 1000,
5268 ppduWithPaddingDuration);
5271 this,
5272 2,
5273 2,
5274 1001,
5275 ppduWithPaddingDuration);
5276
5277 // Set TRIGVECTOR on AP
5280 this,
5281 ppduWithPaddingDuration);
5282
5283 // A strong non-wifi interference is generated on RU 1 during padding reception
5284 BandInfo bandInfo;
5285 bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
5286 bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5287 bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5288 Bands bands;
5289 bands.push_back(bandInfo);
5290
5291 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5292 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5293 double interferencePower = 0.1; // watts
5294 *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
5295
5296 Simulator::Schedule(Seconds(2.0) + MicroSeconds(50) + expectedPpduDuration,
5298 this,
5299 interferencePsdRu1,
5300 MilliSeconds(100));
5301
5302 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5303 // CCA_BUSY instead of IDLE due to the interference)
5304 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration - NanoSeconds(1),
5306 this,
5307 m_phyAp,
5308 WifiPhyState::RX);
5309 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration,
5311 this,
5312 m_phyAp,
5313 WifiPhyState::CCA_BUSY);
5314
5315 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5316 // occupies RU 1 after payload, during PHY padding)
5318 // One PSDU of 1001 bytes should have been successfully received from STA 2
5320 // Verify events data have been cleared
5322
5324
5326
5328}
5329
5330/**
5331 * \ingroup wifi-test
5332 * \ingroup tests
5333 *
5334 * \brief UL-OFDMA power control test
5335 */
5337{
5338 public:
5340 ~TestUlOfdmaPowerControl() override;
5341
5342 private:
5343 void DoSetup() override;
5344 void DoTeardown() override;
5345 void DoRun() override;
5346
5347 /**
5348 * Send a MU BAR through the AP to the STAs listed in the provided vector.
5349 *
5350 * \param staIds the vector of STA-IDs of STAs to address the MU-BAR to
5351 */
5352 void SendMuBar(std::vector<uint16_t> staIds);
5353
5354 /**
5355 * Send a QoS Data packet to the destination station in order
5356 * to set up a block Ack session (so that the MU-BAR may have a reply).
5357 *
5358 * \param destination the address of the destination station
5359 */
5360 void SetupBa(Address destination);
5361
5362 /**
5363 * Run one simulation with an optional BA session set up phase.
5364 *
5365 * \param setupBa true if BA session should be set up (i.e. upon first run),
5366 * false otherwise
5367 */
5368 void RunOne(bool setupBa);
5369
5370 /**
5371 * Replace the AP's callback on its PHY's ReceiveOkCallback
5372 * by the ReceiveOkCallbackAtAp method.
5373 */
5375
5376 /**
5377 * Receive OK callback function at AP.
5378 * This method will be plugged into the AP PHY's ReceiveOkCallback once the
5379 * block Ack session has been set up. This is done in the Reset function.
5380 * \param psdu the PSDU
5381 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
5382 * \param txVector the TXVECTOR used for the packet
5383 * \param statusPerMpdu reception status per MPDU
5384 */
5386 RxSignalInfo rxSignalInfo,
5387 WifiTxVector txVector,
5388 std::vector<bool> statusPerMpdu);
5389
5390 uint8_t m_bssColor; ///< BSS color
5391
5392 Ptr<WifiNetDevice> m_apDev; ///< network device of AP
5393 Ptr<WifiNetDevice> m_sta1Dev; ///< network device of STA 1
5394 Ptr<WifiNetDevice> m_sta2Dev; ///< network device of STA 2
5395
5397
5398 double m_txPowerAp; ///< transmit power (in dBm) of AP
5399 double m_txPowerStart; ///< minimum transmission power (in dBm) for STAs
5400 double m_txPowerEnd; ///< maximum transmission power (in dBm) for STAs
5401 uint8_t m_txPowerLevels; ///< number of transmission power levels for STAs
5402
5403 double m_requestedRssiSta1; ///< requested RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
5404 double m_requestedRssiSta2; ///< requested RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
5405
5406 double m_rssiSta1; ///< expected RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
5407 double m_rssiSta2; ///< expected RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
5408
5409 double m_tol; ///< tolerance (in dB) between received and expected RSSIs
5410};
5411
5413 : TestCase("UL-OFDMA power control test"),
5414 m_bssColor(1),
5415 m_txPowerAp(0),
5416 m_txPowerStart(0),
5417 m_txPowerEnd(0),
5418 m_txPowerLevels(0),
5419 m_requestedRssiSta1(0),
5420 m_requestedRssiSta2(0),
5421 m_rssiSta1(0),
5422 m_rssiSta2(0),
5423 m_tol(0.1)
5424{
5425}
5426
5428{
5429 m_phyAp = nullptr;
5430 m_apDev = nullptr;
5431 m_sta1Dev = nullptr;
5432 m_sta2Dev = nullptr;
5433}
5434
5435void
5437{
5438 // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5439 Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5440 m_apDev->Send(pkt, destination, 0);
5441}
5442
5443void
5444TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5445{
5446 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5447
5448 // Build MU-BAR trigger frame
5449 CtrlTriggerHeader muBar;
5450 muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5451 muBar.SetMoreTF(true);
5452 muBar.SetCsRequired(true);
5454 muBar.SetGiAndLtfType(1600, 2);
5455 muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5456 muBar.SetUlSpatialReuse(60500);
5457
5458 HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5459 std::size_t index = 1;
5460 int8_t ulTargetRssi = -40; // will be overwritten
5461 for (const auto& staId : staIds)
5462 {
5464 ui.SetAid12(staId);
5465 ui.SetRuAllocation({ru, index, true});
5466 ui.SetUlFecCodingType(true);
5467 ui.SetUlMcs(7);
5468 ui.SetUlDcm(false);
5469 ui.SetSsAllocation(1, 1);
5470 if (staId == 1)
5471 {
5472 ulTargetRssi = m_requestedRssiSta1;
5473 }
5474 else if (staId == 2)
5475 {
5476 ulTargetRssi = m_requestedRssiSta2;
5477 }
5478 else
5479 {
5480 NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5481 }
5482 ui.SetUlTargetRssi(ulTargetRssi);
5483
5486 bar.SetTidInfo(0);
5487 bar.SetStartingSequence(4095);
5489
5490 ++index;
5491 }
5492
5493 WifiTxVector tbTxVector = muBar.GetHeTbTxVector(staIds.front());
5495 tbTxVector,
5497 .first);
5498
5499 WifiConstPsduMap psdus;
5501 0,
5503 800,
5504 1,
5505 1,
5506 0,
5508 false,
5509 false,
5510 false,
5511 m_bssColor);
5512
5513 Ptr<Packet> bar = Create<Packet>();
5514 bar->AddHeader(muBar);
5515
5517 if (staIds.size() == 1)
5518 {
5519 uint16_t aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5520 if (staIds.front() == aidSta1)
5521 {
5523 }
5524 else
5525 {
5526 NS_ASSERT(staIds.front() ==
5527 DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5529 }
5530 }
5531
5532 WifiMacHeader hdr;
5534 hdr.SetAddr1(receiver);
5537 hdr.SetDsNotTo();
5538 hdr.SetDsFrom();
5539 hdr.SetNoRetry();
5540 hdr.SetNoMoreFragments();
5541 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(bar, hdr);
5542
5543 Time nav = m_apDev->GetPhy()->GetSifs();
5544 uint16_t staId = staIds.front(); // either will do
5546 tbTxVector,
5548 staId);
5549 psdu->SetDuration(nav);
5550 psdus.insert(std::make_pair(SU_STA_ID, psdu));
5551
5552 m_phyAp->Send(psdus, txVector);
5553}
5554
5555void
5557 RxSignalInfo rxSignalInfo,
5558 WifiTxVector txVector,
5559 std::vector<bool> /*statusPerMpdu*/)
5560{
5561 NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5562 double rssi = rxSignalInfo.rssi;
5563 NS_ASSERT(psdu->GetNMpdus() == 1);
5564 WifiMacHeader hdr = psdu->GetHeader(0);
5565 NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5566 if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5567 {
5569 rssi,
5570 m_rssiSta1,
5571 m_tol,
5572 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5573 << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5574 }
5575 else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5576 {
5578 rssi,
5579 m_rssiSta2,
5580 m_tol,
5581 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5582 << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5583 }
5584 else
5585 {
5586 NS_ABORT_MSG("The receiver address is unknown");
5587 }
5588}
5589
5590void
5592{
5593 // Now that BA session has been established we can plug our method
5596}
5597
5598void
5600{
5601 Ptr<Node> apNode = CreateObject<Node>();
5602 NodeContainer staNodes;
5603 staNodes.Create(2);
5604
5605 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5606 Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel>();
5607 spectrumChannel->AddPropagationLossModel(lossModel);
5609 CreateObject<ConstantSpeedPropagationDelayModel>();
5610 spectrumChannel->SetPropagationDelayModel(delayModel);
5611
5612 SpectrumWifiPhyHelper spectrumPhy;
5613 spectrumPhy.SetChannel(spectrumChannel);
5614 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5615 spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5616
5617 WifiHelper wifi;
5618 wifi.SetStandard(WIFI_STANDARD_80211ax);
5619 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5620 "DataMode",
5621 StringValue("HeMcs7"),
5622 "ControlMode",
5623 StringValue("HeMcs7"));
5624
5625 WifiMacHelper mac;
5626 mac.SetType("ns3::StaWifiMac");
5627 NetDeviceContainer staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5628 wifi.AssignStreams(staDevs, 0);
5629 m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5631 m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5633
5634 // Set the beacon interval long enough so that associated STAs may not consider link lost when
5635 // beacon generation is disabled during the actual tests. Having such a long interval also
5636 // avoids bloating logs with beacons during the set up phase.
5637 mac.SetType("ns3::ApWifiMac",
5638 "BeaconGeneration",
5639 BooleanValue(true),
5640 "BeaconInterval",
5641 TimeValue(MicroSeconds(1024 * 600)));
5642 m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5644 m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5645 m_phyAp = DynamicCast<SpectrumWifiPhy>(m_apDev->GetPhy());
5647 // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5648 // set up for both STAs
5649
5650 MobilityHelper mobility;
5651 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5652 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
5653 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5654 positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5655 positionAlloc->Add(
5656 Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5657 mobility.SetPositionAllocator(positionAlloc);
5658
5659 mobility.Install(apNode);
5660 mobility.Install(staNodes);
5661
5662 lossModel->SetDefaultLoss(50.0);
5663 lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5664 staNodes.Get(1)->GetObject<MobilityModel>(),
5665 56.0,
5666 true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5667}
5668
5669void
5671{
5672 m_phyAp->Dispose();
5673 m_phyAp = nullptr;
5674 m_apDev->Dispose();
5675 m_apDev = nullptr;
5676 m_sta1Dev->Dispose();
5677 m_sta1Dev = nullptr;
5678 m_sta2Dev->Dispose();
5679 m_sta2Dev = nullptr;
5680}
5681
5682void
5684{
5687 int64_t streamNumber = 0;
5688
5689 Ptr<WifiPhy> phySta1 = m_sta1Dev->GetPhy();
5690 Ptr<WifiPhy> phySta2 = m_sta2Dev->GetPhy();
5691
5692 m_phyAp->AssignStreams(streamNumber);
5693 phySta1->AssignStreams(streamNumber);
5694 phySta2->AssignStreams(streamNumber);
5695
5696 m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5698 m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5699
5700 phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5701 phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5702 phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5703
5704 phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5705 phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5706 phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5707
5708 Time relativeStart = MilliSeconds(0);
5709 if (setupBa)
5710 {
5711 // Set up BA for each station once the association phase has ended
5712 // so that a BA session is established when the MU-BAR is received.
5715 this,
5719 this,
5721 relativeStart = MilliSeconds(1000);
5722 }
5723 else
5724 {
5725 Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5726 NS_ASSERT(apMac);
5727 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5728 }
5729
5730 Simulator::Schedule(relativeStart,
5732 this);
5733
5734 {
5735 // Verify that the RSSI from STA 1 is consistent with what was requested
5736 std::vector<uint16_t> staIds{1};
5737 Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5738 }
5739
5740 {
5741 // Verify that the RSSI from STA 2 is consistent with what was requested
5742 std::vector<uint16_t> staIds{2};
5743 Simulator::Schedule(relativeStart + MilliSeconds(20),
5745 this,
5746 staIds);
5747 }
5748
5749 {
5750 // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5751 std::vector<uint16_t> staIds{1, 2};
5752 Simulator::Schedule(relativeStart + MilliSeconds(40),
5754 this,
5755 staIds);
5756 }
5757
5758 Simulator::Stop(relativeStart + MilliSeconds(100));
5760}
5761
5762void
5764{
5765 // Power configurations
5766 m_txPowerAp = 20; // dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
5767 // since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5768 m_txPowerStart = 15; // dBm
5769
5770 // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5771 m_requestedRssiSta1 = -30.0;
5772 m_requestedRssiSta2 = -36.0;
5773
5774 // Test single power level
5775 {
5776 // STA power configurations: 15 dBm only
5777 m_txPowerEnd = 15;
5778 m_txPowerLevels = 1;
5779
5780 // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5781 // regardless of the estimated path loss.
5782 m_rssiSta1 = -35.0; // 15 dBm - 50 dB
5783 m_rssiSta2 = -41.0; // 15 dBm - 56 dB
5784
5785 RunOne(true);
5786 }
5787
5788 // Test 2 dBm granularity
5789 {
5790 // STA power configurations: [15:2:25] dBm
5791 m_txPowerEnd = 25;
5792 m_txPowerLevels = 6;
5793
5794 // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5795 // requested
5796 m_rssiSta1 = -29.0; // 21 dBm - 50 dB
5797 m_rssiSta2 = -35.0; // 21 dBm - 50 dB
5798
5799 RunOne(false);
5800 }
5801
5802 // Test 1 dBm granularity
5803 {
5804 // STA power configurations: [15:1:25] dBm
5805 m_txPowerEnd = 25;
5806 m_txPowerLevels = 11;
5807
5808 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5809 m_rssiSta1 = -30.0; // 20 dBm - 50 dB
5810 m_rssiSta2 = -36.0; // 20 dBm - 56 dB
5811
5812 RunOne(false);
5813 }
5814
5815 // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5816 {
5817 // STA power configurations: [15:1:25] dBm
5818 m_txPowerEnd = 25;
5819 m_txPowerLevels = 11;
5820
5821 // Requested UL RSSIs
5822 m_requestedRssiSta1 = -28.0; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5823 m_requestedRssiSta2 = -37.0; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5824
5825 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5826 m_rssiSta1 = -28.0; // 22 dBm - 50 dB
5827 m_rssiSta2 = -37.0; // 19 dBm - 56 dB
5828
5829 RunOne(false);
5830 }
5831
5833}
5834
5835/**
5836 * \ingroup wifi-test
5837 * \ingroup tests
5838 *
5839 * \brief wifi PHY OFDMA Test Suite
5840 */
5842{
5843 public:
5845};
5846
5848 : TestSuite("wifi-phy-ofdma", Type::UNIT)
5849{
5850 AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5851 AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::Duration::QUICK);
5852 AddTestCase(new TestUlOfdmaPpduUid, TestCase::Duration::QUICK);
5853 AddTestCase(new TestMultipleHeTbPreambles, TestCase::Duration::QUICK);
5854 AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5855 AddTestCase(new TestPhyPaddingExclusion, TestCase::Duration::QUICK);
5856 AddTestCase(new TestUlOfdmaPowerControl, TestCase::Duration::QUICK);
5857}
5858
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
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:458
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:767
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:302
A suite of tests to run.
Definition: test.h:1273
Type
Type of test.
Definition: test.h:1280
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
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:551
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:662
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:1759
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:671
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:1335
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:813
static Time GetPreambleDetectionDuration()
Definition: wifi-phy.cc:1480
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:473
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:993
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1539
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1358
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition: wifi-phy.cc:479
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:1130
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1053
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1333
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:744
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1338
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:692
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:926
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:637
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1320
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:467
void Reset()
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1907
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1065
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition: wifi-phy.cc:759
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:2298
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:1343
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1355
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1331
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:700
std::vector< BandInfo > Bands
Container of BandInfo.
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:42
@ 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:68
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