A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-phy-ofdma-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 University of Washington
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "ns3/ap-wifi-mac.h"
10#include "ns3/boolean.h"
11#include "ns3/constant-position-mobility-model.h"
12#include "ns3/ctrl-headers.h"
13#include "ns3/double.h"
14#include "ns3/he-configuration.h"
15#include "ns3/he-phy.h"
16#include "ns3/he-ppdu.h"
17#include "ns3/interference-helper.h"
18#include "ns3/log.h"
19#include "ns3/mobility-helper.h"
20#include "ns3/multi-model-spectrum-channel.h"
21#include "ns3/nist-error-rate-model.h"
22#include "ns3/node.h"
23#include "ns3/non-communicating-net-device.h"
24#include "ns3/pointer.h"
25#include "ns3/rng-seed-manager.h"
26#include "ns3/simulator.h"
27#include "ns3/spectrum-wifi-helper.h"
28#include "ns3/spectrum-wifi-phy.h"
29#include "ns3/sta-wifi-mac.h"
30#include "ns3/string.h"
31#include "ns3/test.h"
32#include "ns3/threshold-preamble-detection-model.h"
33#include "ns3/txop.h"
34#include "ns3/waveform-generator.h"
35#include "ns3/wifi-mac-header.h"
36#include "ns3/wifi-net-device.h"
37#include "ns3/wifi-phy-listener.h"
38#include "ns3/wifi-psdu.h"
39#include "ns3/wifi-spectrum-phy-interface.h"
40#include "ns3/wifi-spectrum-signal-parameters.h"
41#include "ns3/wifi-spectrum-value-helper.h"
42#include "ns3/wifi-utils.h"
43
44#include <algorithm>
45#include <iterator>
46#include <memory>
47
48using namespace ns3;
49
50NS_LOG_COMPONENT_DEFINE("WifiPhyOfdmaTest");
51
52static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
53static const MHz_u DEFAULT_FREQUENCY{5180};
57 DEFAULT_CHANNEL_WIDTH; // expanded to channel width to model spectrum mask
58
59/**
60 * HE PHY slightly modified so as to return a given
61 * STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
62 */
63class OfdmaTestHePhy : public HePhy
64{
65 public:
66 /**
67 * Constructor
68 *
69 * @param staId the ID of the STA to which this PHY belongs to
70 */
71 OfdmaTestHePhy(uint16_t staId);
72 ~OfdmaTestHePhy() override;
73
74 /**
75 * Return the STA ID that has been assigned to the station this PHY belongs to.
76 * This is typically called for MU PPDUs, in order to pick the correct PSDU.
77 *
78 * @param ppdu the PPDU for which the STA ID is requested
79 * @return the STA ID
80 */
81 uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
82
83 /**
84 * Set the global PPDU UID counter.
85 *
86 * @param uid the value to which the global PPDU UID counter should be set
87 */
88 void SetGlobalPpduUid(uint64_t uid);
89
90 /**
91 * Get the band used to transmit the non-OFDMA part of an HE TB PPDU.
92 *
93 * @param txVector the TXVECTOR used for the transmission
94 * @param staId the STA-ID of the station taking part of the UL MU
95 *
96 * @return the spectrum band used to transmit the non-OFDMA part of an HE TB PPDU
97 */
98 WifiSpectrumBandInfo GetNonOfdmaBand(const WifiTxVector& txVector, uint16_t staId) const;
99
100 private:
101 uint16_t m_staId; ///< ID of the STA to which this PHY belongs to
102
103 // end of class OfdmaTestHePhy
104};
105
107 : HePhy(),
108 m_staId(staId)
109{
110}
111
115
116uint16_t
118{
119 if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
120 {
121 return m_staId;
122 }
123 return HePhy::GetStaId(ppdu);
124}
125
126void
128{
129 m_globalPpduUid = uid;
130}
131
133OfdmaTestHePhy::GetNonOfdmaBand(const WifiTxVector& txVector, uint16_t staId) const
134{
135 NS_ASSERT(txVector.IsUlMu() && (txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE));
136 const auto channelWidth = txVector.GetChannelWidth();
137 NS_ASSERT(channelWidth <= m_wifiPhy->GetChannelWidth());
138
139 auto ru = txVector.GetRu(staId);
140 const auto nonOfdmaWidth = GetNonOfdmaWidth(ru);
141
142 // Find the RU that encompasses the non-OFDMA part of the HE TB PPDU for the STA-ID
143 auto nonOfdmaRu = WifiRu::FindOverlappingRu(channelWidth, ru, WifiRu::GetRuType(nonOfdmaWidth));
144
145 const auto groupPreamble = HeRu::GetSubcarrierGroup(
146 channelWidth,
147 WifiRu::GetRuType(nonOfdmaRu),
148 WifiRu::GetPhyIndex(nonOfdmaRu,
149 channelWidth,
151 const auto indices = ConvertHeRuSubcarriers(
152 channelWidth,
157 {groupPreamble.front().first, groupPreamble.back().second},
159 WifiSpectrumBandInfo nonOfdmaBand{};
160 for (const auto& indicesPerSegment : indices)
161 {
162 nonOfdmaBand.indices.emplace_back(indicesPerSegment);
163 nonOfdmaBand.frequencies.emplace_back(
164 m_wifiPhy->ConvertIndicesToFrequencies(indicesPerSegment));
165 }
166 return nonOfdmaBand;
167}
168
169/**
170 * SpectrumWifiPhy used for testing OFDMA.
171 */
173{
174 public:
175 /**
176 * @brief Get the type ID.
177 * @return the object TypeId
178 */
179 static TypeId GetTypeId();
180 /**
181 * Constructor
182 *
183 * @param staId the ID of the STA to which this PHY belongs to
184 */
185 OfdmaSpectrumWifiPhy(uint16_t staId);
186 ~OfdmaSpectrumWifiPhy() override;
187
188 void DoInitialize() override;
189 void DoDispose() override;
190
191 using WifiPhy::Reset;
192 void StartTx(Ptr<const WifiPpdu> ppdu) override;
193
194 /**
195 * TracedCallback signature for UID of transmitted PPDU.
196 *
197 * @param uid the UID of the transmitted PPDU
198 */
199 typedef void (*TxPpduUidCallback)(uint64_t uid);
200
201 /**
202 * Set the global PPDU UID counter.
203 *
204 * @param uid the value to which the global PPDU UID counter should be set
205 */
206 void SetPpduUid(uint64_t uid);
207
208 /**
209 * Since we assume trigger frame was previously received from AP, this is used to set its UID
210 *
211 * @param uid the PPDU UID of the trigger frame
212 */
213 void SetTriggerFrameUid(uint64_t uid);
214
215 /**
216 * @return the current preamble events map
217 */
218 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
219 /**
220 * @return the current event
221 */
223
224 /**
225 * Wrapper to InterferenceHelper method.
226 *
227 * @param energy the minimum energy requested
228 * @param band identify the requested band
229 *
230 * @returns the expected amount of time the observed
231 * energy on the medium for a given band will
232 * be higher than the requested threshold.
233 */
235
236 /**
237 * @return a const pointer to the HE PHY instance
238 */
240
241 private:
242 /// Pointer to HE PHY instance used for OFDMA test
244
245 /// Callback providing UID of the PPDU that is about to be transmitted
247
248 // end of class OfdmaSpectrumWifiPhy
249};
250
251TypeId
253{
254 static TypeId tid =
255 TypeId("ns3::OfdmaSpectrumWifiPhy")
257 .SetGroupName("Wifi")
258 .AddTraceSource("TxPpduUid",
259 "UID of the PPDU to be transmitted",
261 "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
262 return tid;
263}
264
271
275
276void
278{
279 // Replace HE PHY instance with test instance
282}
283
284void
290
291void
297
298void
303
304void
310
311std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
316
322
323Time
325{
326 return m_interference->GetEnergyDuration(energy, band);
327}
328
334
335/**
336 * @ingroup wifi-test
337 * @ingroup tests
338 *
339 * @brief DL-OFDMA PHY test
340 */
342{
343 public:
346
347 private:
348 void DoSetup() override;
349 void DoTeardown() override;
350 void DoRun() override;
351
352 /**
353 * Receive success function for STA 1
354 * @param psdu the PSDU
355 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
356 * @param txVector the transmit vector
357 * @param statusPerMpdu reception status per MPDU
358 */
360 RxSignalInfo rxSignalInfo,
361 const WifiTxVector& txVector,
362 const std::vector<bool>& statusPerMpdu);
363 /**
364 * Receive success function for STA 2
365 * @param psdu the PSDU
366 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
367 * @param txVector the transmit vector
368 * @param statusPerMpdu reception status per MPDU
369 */
371 RxSignalInfo rxSignalInfo,
372 const WifiTxVector& txVector,
373 const std::vector<bool>& statusPerMpdu);
374 /**
375 * Receive success function for STA 3
376 * @param psdu the PSDU
377 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
378 * @param txVector the transmit vector
379 * @param statusPerMpdu reception status per MPDU
380 */
382 RxSignalInfo rxSignalInfo,
383 const WifiTxVector& txVector,
384 const std::vector<bool>& statusPerMpdu);
385
386 /**
387 * Receive failure function for STA 1
388 * @param psdu the PSDU
389 */
391 /**
392 * Receive failure function for STA 2
393 * @param psdu the PSDU
394 */
396 /**
397 * Receive failure function for STA 3
398 * @param psdu the PSDU
399 */
401
402 /**
403 * Check the results for STA 1
404 * @param expectedRxSuccess the expected number of RX success
405 * @param expectedRxFailure the expected number of RX failures
406 * @param expectedRxBytes the expected number of RX bytes
407 */
408 void CheckResultsSta1(uint32_t expectedRxSuccess,
409 uint32_t expectedRxFailure,
410 uint32_t expectedRxBytes);
411 /**
412 * Check the results for STA 2
413 * @param expectedRxSuccess the expected number of RX success
414 * @param expectedRxFailure the expected number of RX failures
415 * @param expectedRxBytes the expected number of RX bytes
416 */
417 void CheckResultsSta2(uint32_t expectedRxSuccess,
418 uint32_t expectedRxFailure,
419 uint32_t expectedRxBytes);
420 /**
421 * Check the results for STA 3
422 * @param expectedRxSuccess the expected number of RX success
423 * @param expectedRxFailure the expected number of RX failures
424 * @param expectedRxBytes the expected number of RX bytes
425 */
426 void CheckResultsSta3(uint32_t expectedRxSuccess,
427 uint32_t expectedRxFailure,
428 uint32_t expectedRxBytes);
429
430 /**
431 * Reset the results
432 */
433 void ResetResults();
434
435 /**
436 * Send MU-PPDU function
437 * @param rxStaId1 the ID of the recipient STA for the first PSDU
438 * @param rxStaId2 the ID of the recipient STA for the second PSDU
439 */
440 void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
441
442 /**
443 * Generate interference function
444 * @param interferencePsd the PSD of the interference to be generated
445 * @param duration the duration of the interference
446 */
447 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
448 /**
449 * Stop interference function
450 */
451 void StopInterference();
452
453 /**
454 * Run one function
455 */
456 void RunOne();
457
458 /**
459 * Schedule now to check the PHY state
460 * @param phy the PHY
461 * @param expectedState the expected state of the PHY
462 */
464 /**
465 * Check the PHY state now
466 * @param phy the PHY
467 * @param expectedState the expected state of the PHY
468 */
470
471 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
472 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
473 uint32_t m_countRxSuccessSta3; ///< count RX success for STA 3
474 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
475 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
476 uint32_t m_countRxFailureSta3; ///< count RX failure for STA 3
477 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
478 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
479 uint32_t m_countRxBytesSta3; ///< count RX bytes for STA 3
480
486
487 MHz_u m_frequency; ///< frequency
488 MHz_u m_channelWidth; ///< channel width
489 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
490};
491
493 : TestCase("DL-OFDMA PHY test"),
494 m_countRxSuccessSta1(0),
495 m_countRxSuccessSta2(0),
496 m_countRxSuccessSta3(0),
497 m_countRxFailureSta1(0),
498 m_countRxFailureSta2(0),
499 m_countRxFailureSta3(0),
500 m_countRxBytesSta1(0),
501 m_countRxBytesSta2(0),
502 m_countRxBytesSta3(0),
503 m_frequency(DEFAULT_FREQUENCY),
504 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
505 m_expectedPpduDuration(NanoSeconds(306400))
506{
507}
508
509void
522
523void
524TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
525{
526 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
527 WifiConstPsduMap psdus;
529 0,
531 NanoSeconds(800),
532 1,
533 1,
534 0,
536 false,
537 false};
538 RuType ruType = RuType::RU_106_TONE;
539 if (m_channelWidth == MHz_u{20})
540 {
541 ruType = RuType::RU_106_TONE;
542 txVector.SetRuAllocation({96}, 0);
543 }
544 else if (m_channelWidth == MHz_u{40})
545 {
546 ruType = RuType::RU_242_TONE;
547 txVector.SetRuAllocation({192, 192}, 0);
548 }
549 else if (m_channelWidth == MHz_u{80})
550 {
551 ruType = RuType::RU_484_TONE;
552 const uint16_t ruAllocUser = 200;
553 const uint16_t ruAllocNoUser = 114;
554 txVector.SetRuAllocation({ruAllocUser, ruAllocNoUser, ruAllocNoUser, ruAllocUser}, 0);
555 }
556 else if (m_channelWidth == MHz_u{160})
557 {
558 ruType = RuType::RU_996_TONE;
559 const uint16_t ruAllocUser = 208;
560 const uint16_t ruAllocNoUser = 115;
561 txVector.SetRuAllocation({ruAllocUser,
562 ruAllocNoUser,
563 ruAllocUser,
564 ruAllocNoUser,
565 ruAllocNoUser,
566 ruAllocUser,
567 ruAllocNoUser,
568 ruAllocUser},
569 0);
570 }
571 else
572 {
573 NS_ASSERT_MSG(false, "Unsupported channel width");
574 }
575
576 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
577
578 HeRu::RuSpec ru1(ruType, 1, true);
579 txVector.SetRu(ru1, rxStaId1);
580 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
581 txVector.SetNss(1, rxStaId1);
582
583 HeRu::RuSpec ru2(ruType, (m_channelWidth == MHz_u{160} ? 1 : 2), m_channelWidth != MHz_u{160});
584 txVector.SetRu(ru2, rxStaId2);
585 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
586 txVector.SetNss(1, rxStaId2);
587
588 Ptr<Packet> pkt1 = Create<Packet>(1000);
589 WifiMacHeader hdr1;
591 hdr1.SetQosTid(0);
592 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
593 hdr1.SetSequenceNumber(1);
594 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
595 psdus.insert(std::make_pair(rxStaId1, psdu1));
596
597 Ptr<Packet> pkt2 = Create<Packet>(1500);
598 WifiMacHeader hdr2;
600 hdr2.SetQosTid(0);
601 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
602 hdr2.SetSequenceNumber(2);
603 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
604 psdus.insert(std::make_pair(rxStaId2, psdu2));
605
606 m_phyAp->Send(psdus, txVector);
607}
608
609void
611{
612 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
613 m_phyInterferer->SetPeriod(duration);
614 m_phyInterferer->Start();
616}
617
618void
623
627
628void
630 RxSignalInfo rxSignalInfo,
631 const WifiTxVector& txVector,
632 const std::vector<bool>& /*statusPerMpdu*/)
633{
634 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
636 m_countRxBytesSta1 += (psdu->GetSize() - 30);
637}
638
639void
641 RxSignalInfo rxSignalInfo,
642 const WifiTxVector& txVector,
643 const std::vector<bool>& /*statusPerMpdu*/)
644{
645 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
647 m_countRxBytesSta2 += (psdu->GetSize() - 30);
648}
649
650void
652 RxSignalInfo rxSignalInfo,
653 const WifiTxVector& txVector,
654 const std::vector<bool>& /*statusPerMpdu*/)
655{
656 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
658 m_countRxBytesSta3 += (psdu->GetSize() - 30);
659}
660
661void
667
668void
674
675void
681
682void
684 uint32_t expectedRxFailure,
685 uint32_t expectedRxBytes)
686{
688 expectedRxSuccess,
689 "The number of successfully received packets by STA 1 is not correct!");
691 expectedRxFailure,
692 "The number of unsuccessfuly received packets by STA 1 is not correct!");
694 expectedRxBytes,
695 "The number of bytes received by STA 1 is not correct!");
696}
697
698void
700 uint32_t expectedRxFailure,
701 uint32_t expectedRxBytes)
702{
704 expectedRxSuccess,
705 "The number of successfully received packets by STA 2 is not correct!");
707 expectedRxFailure,
708 "The number of unsuccessfuly received packets by STA 2 is not correct!");
710 expectedRxBytes,
711 "The number of bytes received by STA 2 is not correct!");
712}
713
714void
716 uint32_t expectedRxFailure,
717 uint32_t expectedRxBytes)
718{
720 expectedRxSuccess,
721 "The number of successfully received packets by STA 3 is not correct!");
723 expectedRxFailure,
724 "The number of unsuccessfuly received packets by STA 3 is not correct!");
726 expectedRxBytes,
727 "The number of bytes received by STA 3 is not correct!");
728}
729
730void
732{
733 // This is needed to make sure PHY state will be checked as the last event if a state change
734 // occurred at the exact same time as the check
736}
737
738void
740 WifiPhyState expectedState)
741{
742 WifiPhyState currentState;
743 PointerValue ptr;
744 phy->GetAttribute("State", ptr);
746 currentState = state->GetState();
747 NS_LOG_FUNCTION(this << currentState);
748 NS_TEST_ASSERT_MSG_EQ(currentState,
749 expectedState,
750 "PHY State " << currentState << " does not match expected state "
751 << expectedState << " at " << Simulator::Now());
752}
753
754void
756{
759 lossModel->SetFrequency(MHzToHz(m_frequency));
760 spectrumChannel->AddPropagationLossModel(lossModel);
763 spectrumChannel->SetPropagationDelayModel(delayModel);
764
765 Ptr<Node> apNode = CreateObject<Node>();
769 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
771 m_phyAp->SetErrorRateModel(apErrorModel);
772 m_phyAp->SetDevice(apDev);
773 m_phyAp->AddChannel(spectrumChannel);
774 m_phyAp->ConfigureStandard(WIFI_STANDARD_80211ax);
776 m_phyAp->SetMobility(apMobility);
777 apDev->SetPhy(m_phyAp);
778 apNode->AggregateObject(apMobility);
779 apNode->AddDevice(apDev);
780
781 Ptr<Node> sta1Node = CreateObject<Node>();
785 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
787 m_phySta1->SetErrorRateModel(sta1ErrorModel);
788 m_phySta1->SetDevice(sta1Dev);
789 m_phySta1->AddChannel(spectrumChannel);
795 m_phySta1->SetMobility(sta1Mobility);
796 sta1Dev->SetPhy(m_phySta1);
797 sta1Node->AggregateObject(sta1Mobility);
798 sta1Node->AddDevice(sta1Dev);
799
800 Ptr<Node> sta2Node = CreateObject<Node>();
804 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
806 m_phySta2->SetErrorRateModel(sta2ErrorModel);
807 m_phySta2->SetDevice(sta2Dev);
808 m_phySta2->AddChannel(spectrumChannel);
814 m_phySta2->SetMobility(sta2Mobility);
815 sta2Dev->SetPhy(m_phySta2);
816 sta2Node->AggregateObject(sta2Mobility);
817 sta2Node->AddDevice(sta2Dev);
818
819 Ptr<Node> sta3Node = CreateObject<Node>();
823 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
825 m_phySta3->SetErrorRateModel(sta3ErrorModel);
826 m_phySta3->SetDevice(sta3Dev);
827 m_phySta3->AddChannel(spectrumChannel);
833 m_phySta3->SetMobility(sta3Mobility);
834 sta3Dev->SetPhy(m_phySta3);
835 sta3Node->AggregateObject(sta3Mobility);
836 sta3Node->AddDevice(sta3Dev);
837
838 Ptr<Node> interfererNode = CreateObject<Node>();
841 m_phyInterferer->SetDevice(interfererDev);
842 m_phyInterferer->SetChannel(spectrumChannel);
843 m_phyInterferer->SetDutyCycle(1);
844 interfererNode->AddDevice(interfererDev);
845}
846
847void
849{
850 m_phyAp->Dispose();
851 m_phyAp = nullptr;
853 m_phySta1 = nullptr;
855 m_phySta2 = nullptr;
857 m_phySta3 = nullptr;
859 m_phyInterferer = nullptr;
860}
861
862void
864{
867 int64_t streamNumber = 0;
868 m_phyAp->AssignStreams(streamNumber);
869 m_phySta1->AssignStreams(streamNumber);
870 m_phySta2->AssignStreams(streamNumber);
871 m_phySta3->AssignStreams(streamNumber);
872
873 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
878 ->number;
879
880 m_phyAp->SetOperatingChannel(
888
890
891 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
892 // Each STA should receive its PSDU.
894
895 // Since it takes m_expectedPpduDuration to transmit the PPDU,
896 // all 3 PHYs should be back to IDLE at the same time,
897 // even the PHY that has no PSDU addressed to it.
900 this,
901 m_phySta1,
902 WifiPhyState::RX);
905 this,
906 m_phySta2,
907 WifiPhyState::RX);
910 this,
911 m_phySta3,
912 WifiPhyState::CCA_BUSY);
915 this,
916 m_phySta1,
917 WifiPhyState::IDLE);
920 this,
921 m_phySta2,
922 WifiPhyState::IDLE);
925 this,
926 m_phySta3,
927 WifiPhyState::IDLE);
928
929 // One PSDU of 1000 bytes should have been successfully received by STA 1
932 this,
933 1,
934 0,
935 1000);
936 // One PSDU of 1500 bytes should have been successfully received by STA 2
939 this,
940 1,
941 0,
942 1500);
943 // No PSDU should have been received by STA 3
945
947
948 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
949 // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
950 // but should keep its PHY busy during all PPDU duration.
952
953 // Since it takes m_expectedPpduDuration to transmit the PPDU,
954 // all 3 PHYs should be back to IDLE at the same time,
955 // even the PHY that has no PSDU addressed to it.
958 this,
959 m_phySta1,
960 WifiPhyState::RX);
963 this,
964 m_phySta2,
965 WifiPhyState::CCA_BUSY);
968 this,
969 m_phySta3,
970 WifiPhyState::RX);
973 this,
974 m_phySta1,
975 WifiPhyState::IDLE);
978 this,
979 m_phySta2,
980 WifiPhyState::IDLE);
983 this,
984 m_phySta3,
985 WifiPhyState::IDLE);
986
987 // One PSDU of 1000 bytes should have been successfully received by STA 1
990 this,
991 1,
992 0,
993 1000);
994 // No PSDU should have been received by STA 2
996 // One PSDU of 1500 bytes should have been successfully received by STA 3
999 this,
1000 1,
1001 0,
1002 1500);
1003
1005
1006 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1008
1009 // A strong non-wifi interference is generated on RU 1 during PSDU reception
1010 BandInfo bandInfo;
1011 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 4));
1012 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
1013 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
1014 Bands bands;
1015 bands.push_back(bandInfo);
1016
1017 auto SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
1018 auto interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
1019 Watt_u interferencePower{0.1};
1020 *interferencePsdRu1 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
1021
1024 this,
1025 interferencePsdRu1,
1026 MilliSeconds(100));
1027
1028 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1029 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1030 // even the PHY that has no PSDU addressed to it.
1033 this,
1034 m_phySta1,
1035 WifiPhyState::RX);
1038 this,
1039 m_phySta2,
1040 WifiPhyState::RX);
1043 this,
1044 m_phySta3,
1045 WifiPhyState::CCA_BUSY);
1048 this,
1049 m_phySta1,
1050 WifiPhyState::CCA_BUSY);
1053 this,
1054 m_phySta2,
1055 WifiPhyState::CCA_BUSY);
1058 this,
1059 m_phySta3,
1060 WifiPhyState::CCA_BUSY);
1061
1062 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1063 // occupies RU 1)
1065 // One PSDU of 1500 bytes should have been successfully received by STA 2
1068 this,
1069 1,
1070 0,
1071 1500);
1072 // No PSDU should have been received by STA3
1074
1076
1077 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1079
1080 // A strong non-wifi interference is generated on RU 2 during PSDU reception
1081 bandInfo.fc = MHzToHz(m_frequency + (m_channelWidth / 4));
1082 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
1083 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
1084 bands.clear();
1085 bands.push_back(bandInfo);
1086
1087 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1088 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1089 *interferencePsdRu2 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
1090
1093 this,
1094 interferencePsdRu2,
1095 MilliSeconds(100));
1096
1097 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1098 // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1099 // same time, even the PHY that has no PSDU addressed to it.
1102 this,
1103 m_phySta1,
1104 WifiPhyState::RX);
1107 this,
1108 m_phySta2,
1109 WifiPhyState::RX);
1112 this,
1113 m_phySta3,
1114 WifiPhyState::CCA_BUSY);
1117 this,
1118 m_phySta1,
1119 (m_channelWidth >= MHz_u{40}) ? WifiPhyState::IDLE
1120 : WifiPhyState::CCA_BUSY);
1123 this,
1124 m_phySta2,
1125 (m_channelWidth >= MHz_u{40}) ? WifiPhyState::IDLE
1126 : WifiPhyState::CCA_BUSY);
1129 this,
1130 m_phySta3,
1131 (m_channelWidth >= MHz_u{40}) ? WifiPhyState::IDLE
1132 : WifiPhyState::CCA_BUSY);
1133
1134 // One PSDU of 1000 bytes should have been successfully received by STA 1
1137 this,
1138 1,
1139 0,
1140 1000);
1141 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1142 // occupies RU 2)
1144 // No PSDU should have been received by STA3
1146
1148
1149 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1151
1152 // A strong non-wifi interference is generated on the full band during PSDU reception
1153 bandInfo.fc = MHzToHz(m_frequency);
1154 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 2);
1155 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 2);
1156 bands.clear();
1157 bands.push_back(bandInfo);
1158
1159 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1160 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1161 *interferencePsdAll = interferencePower / (MHzToHz(m_channelWidth) * 20);
1162
1165 this,
1166 interferencePsdAll,
1167 MilliSeconds(100));
1168
1169 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1170 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1171 // even the PHY that has no PSDU addressed to it.
1174 this,
1175 m_phySta1,
1176 WifiPhyState::RX);
1179 this,
1180 m_phySta2,
1181 WifiPhyState::RX);
1184 this,
1185 m_phySta3,
1186 WifiPhyState::CCA_BUSY);
1189 this,
1190 m_phySta1,
1191 WifiPhyState::CCA_BUSY);
1194 this,
1195 m_phySta2,
1196 WifiPhyState::CCA_BUSY);
1199 this,
1200 m_phySta3,
1201 WifiPhyState::CCA_BUSY);
1202
1203 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1204 // occupies RU 1)
1206 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1207 // occupies RU 2)
1209 // No PSDU should have been received by STA3
1211
1213
1215}
1216
1217void
1219{
1220 m_frequency = MHz_u{5180};
1221 m_channelWidth = MHz_u{20};
1223 RunOne();
1224
1225 m_frequency = MHz_u{5190};
1226 m_channelWidth = MHz_u{40};
1228 RunOne();
1229
1230 m_frequency = MHz_u{5210};
1231 m_channelWidth = MHz_u{80};
1233 RunOne();
1234
1235 m_frequency = MHz_u{5250};
1236 m_channelWidth = MHz_u{160};
1238 RunOne();
1239
1241}
1242
1243/**
1244 * @ingroup wifi-test
1245 * @ingroup tests
1246 *
1247 * @brief DL-OFDMA PHY puncturing test
1248 */
1250{
1251 public:
1253
1254 private:
1255 void DoSetup() override;
1256 void DoTeardown() override;
1257 void DoRun() override;
1258
1259 /**
1260 * Receive success function for STA 1
1261 * @param psdu the PSDU
1262 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1263 * @param txVector the transmit vector
1264 * @param statusPerMpdu reception status per MPDU
1265 */
1267 RxSignalInfo rxSignalInfo,
1268 const WifiTxVector& txVector,
1269 const std::vector<bool>& statusPerMpdu);
1270
1271 /**
1272 * Receive success function for STA 2
1273 * @param psdu the PSDU
1274 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1275 * @param txVector the transmit vector
1276 * @param statusPerMpdu reception status per MPDU
1277 */
1279 RxSignalInfo rxSignalInfo,
1280 const WifiTxVector& txVector,
1281 const std::vector<bool>& statusPerMpdu);
1282
1283 /**
1284 * Receive failure function for STA 1
1285 * @param psdu the PSDU
1286 */
1288
1289 /**
1290 * Receive failure function for STA 2
1291 * @param psdu the PSDU
1292 */
1294
1295 /**
1296 * Check the results for STA 1
1297 * @param expectedRxSuccess the expected number of RX success
1298 * @param expectedRxFailure the expected number of RX failures
1299 * @param expectedRxBytes the expected number of RX bytes
1300 */
1301 void CheckResultsSta1(uint32_t expectedRxSuccess,
1302 uint32_t expectedRxFailure,
1303 uint32_t expectedRxBytes);
1304
1305 /**
1306 * Check the results for STA 2
1307 * @param expectedRxSuccess the expected number of RX success
1308 * @param expectedRxFailure the expected number of RX failures
1309 * @param expectedRxBytes the expected number of RX bytes
1310 */
1311 void CheckResultsSta2(uint32_t expectedRxSuccess,
1312 uint32_t expectedRxFailure,
1313 uint32_t expectedRxBytes);
1314
1315 /**
1316 * Reset the results
1317 */
1318 void ResetResults();
1319
1320 /**
1321 * Send MU-PPDU function
1322 * @param rxStaId1 the ID of the recipient STA for the first PSDU
1323 * @param rxStaId2 the ID of the recipient STA for the second PSDU
1324 * @param puncturedSubchannels indicates for each subchannel whether it is punctured or not. if
1325 * empty, preamble puncturing is not used.
1326 */
1327 void SendMuPpdu(uint16_t rxStaId1,
1328 uint16_t rxStaId2,
1329 const std::vector<bool>& puncturedSubchannels);
1330
1331 /**
1332 * Generate interference function
1333 * @param interferencePsd the PSD of the interference to be generated
1334 * @param duration the duration of the interference
1335 */
1336 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1337
1338 /**
1339 * Stop interference function
1340 */
1341 void StopInterference();
1342
1343 /**
1344 * Run one function
1345 */
1346 void RunOne();
1347
1348 /**
1349 * Schedule now to check the PHY state
1350 * @param phy the PHY
1351 * @param expectedState the expected state of the PHY
1352 */
1353 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
1354
1355 /**
1356 * Check the PHY state now
1357 * @param phy the PHY
1358 * @param expectedState the expected state of the PHY
1359 */
1361
1362 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
1363 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
1364 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
1365 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
1366 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
1367 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
1368
1373
1374 MHz_u m_frequency; ///< frequency
1375 MHz_u m_channelWidth; ///< channel width
1376
1377 uint8_t m_indexSubchannel; ///< Index of the subchannel (starting from 0) that should contain an
1378 ///< interference and be punctured during the test run
1379
1380 Time m_expectedPpduDuration20Mhz; ///< expected duration to send MU PPDU on 20 MHz RU
1381 Time m_expectedPpduDuration40Mhz; ///< expected duration to send MU PPDU on 40 MHz RU
1382};
1383
1385 : TestCase("DL-OFDMA PHY puncturing test"),
1386 m_countRxSuccessSta1(0),
1387 m_countRxSuccessSta2(0),
1388 m_countRxFailureSta1(0),
1389 m_countRxFailureSta2(0),
1390 m_countRxBytesSta1(0),
1391 m_countRxBytesSta2(0),
1392 m_frequency(MHz_u{5210}),
1393 m_channelWidth(MHz_u{80}),
1394 m_indexSubchannel(0),
1395 m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1396 m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1397{
1398}
1399
1400void
1410
1411void
1413 uint16_t rxStaId2,
1414 const std::vector<bool>& puncturedSubchannels)
1415{
1416 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1417 WifiConstPsduMap psdus;
1418 WifiTxVector txVector{HePhy::GetHeMcs7(),
1419 0,
1421 NanoSeconds(800),
1422 1,
1423 1,
1424 0,
1426 false,
1427 false};
1428
1429 RuType ruType = puncturedSubchannels.empty()
1430 ? RuType::RU_484_TONE
1431 : (puncturedSubchannels.at(1) ? RuType::RU_242_TONE : RuType::RU_484_TONE);
1432 HeRu::RuSpec ru1(ruType, 1, true);
1433 txVector.SetRu(ru1, rxStaId1);
1434 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1435 txVector.SetNss(1, rxStaId1);
1436
1437 ruType = puncturedSubchannels.empty()
1438 ? RuType::RU_484_TONE
1439 : (puncturedSubchannels.at(1) ? RuType::RU_484_TONE : RuType::RU_242_TONE);
1440 HeRu::RuSpec ru2(ruType,
1441 ruType == RuType::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1442 true);
1443 txVector.SetRu(ru2, rxStaId2);
1444 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1445 txVector.SetNss(1, rxStaId2);
1446
1447 RuAllocation ruAlloc;
1448 if (puncturedSubchannels.empty())
1449 {
1450 ruAlloc.push_back(200);
1451 ruAlloc.push_back(114);
1452 ruAlloc.push_back(114);
1453 ruAlloc.push_back(200);
1454 }
1455 else
1456 {
1457 ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1458 ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 114);
1459 ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1460 : (puncturedSubchannels.at(3) ? 192 : 114));
1461 ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1462 : (puncturedSubchannels.at(3) ? 113 : 200));
1463 }
1464
1465 txVector.SetRuAllocation(ruAlloc, 0);
1466 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1467
1468 Ptr<Packet> pkt1 = Create<Packet>(1000);
1469 WifiMacHeader hdr1;
1471 hdr1.SetQosTid(0);
1472 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1473 hdr1.SetSequenceNumber(1);
1474 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1475 psdus.insert(std::make_pair(rxStaId1, psdu1));
1476
1477 Ptr<Packet> pkt2 = Create<Packet>(1500);
1478 WifiMacHeader hdr2;
1480 hdr2.SetQosTid(0);
1481 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1482 hdr2.SetSequenceNumber(2);
1483 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1484 psdus.insert(std::make_pair(rxStaId2, psdu2));
1485
1486 if (!puncturedSubchannels.empty())
1487 {
1488 txVector.SetInactiveSubchannels(puncturedSubchannels);
1489 }
1490
1491 m_phyAp->Send(psdus, txVector);
1492}
1493
1494void
1496{
1497 NS_LOG_FUNCTION(this << duration);
1498 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
1499 m_phyInterferer->SetPeriod(duration);
1500 m_phyInterferer->Start();
1502}
1503
1504void
1510
1511void
1513 RxSignalInfo rxSignalInfo,
1514 const WifiTxVector& txVector,
1515 const std::vector<bool>& /*statusPerMpdu*/)
1516{
1517 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1519 m_countRxBytesSta1 += (psdu->GetSize() - 30);
1520}
1521
1522void
1524 RxSignalInfo rxSignalInfo,
1525 const WifiTxVector& txVector,
1526 const std::vector<bool>& /*statusPerMpdu*/)
1527{
1528 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1530 m_countRxBytesSta2 += (psdu->GetSize() - 30);
1531}
1532
1533void
1539
1540void
1546
1547void
1549 uint32_t expectedRxFailure,
1550 uint32_t expectedRxBytes)
1551{
1553 expectedRxSuccess,
1554 "The number of successfully received packets by STA 1 is not correct!");
1556 expectedRxFailure,
1557 "The number of unsuccessfuly received packets by STA 1 is not correct!");
1559 expectedRxBytes,
1560 "The number of bytes received by STA 1 is not correct!");
1561}
1562
1563void
1565 uint32_t expectedRxFailure,
1566 uint32_t expectedRxBytes)
1567{
1569 expectedRxSuccess,
1570 "The number of successfully received packets by STA 2 is not correct!");
1572 expectedRxFailure,
1573 "The number of unsuccessfuly received packets by STA 2 is not correct!");
1575 expectedRxBytes,
1576 "The number of bytes received by STA 2 is not correct!");
1577}
1578
1579void
1581{
1582 // This is needed to make sure PHY state will be checked as the last event if a state change
1583 // occurred at the exact same time as the check
1585}
1586
1587void
1589{
1590 WifiPhyState currentState;
1591 PointerValue ptr;
1592 phy->GetAttribute("State", ptr);
1594 currentState = state->GetState();
1595 NS_LOG_FUNCTION(this << currentState);
1596 NS_TEST_ASSERT_MSG_EQ(currentState,
1597 expectedState,
1598 "PHY State " << currentState << " does not match expected state "
1599 << expectedState << " at " << Simulator::Now());
1600}
1601
1602void
1604{
1607 lossModel->SetFrequency(MHzToHz(m_frequency));
1608 spectrumChannel->AddPropagationLossModel(lossModel);
1611 spectrumChannel->SetPropagationDelayModel(delayModel);
1612
1613 Ptr<Node> apNode = CreateObject<Node>();
1617 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1619 m_phyAp->SetErrorRateModel(apErrorModel);
1620 m_phyAp->SetDevice(apDev);
1621 m_phyAp->AddChannel(spectrumChannel);
1622 m_phyAp->ConfigureStandard(WIFI_STANDARD_80211ax);
1624 m_phyAp->SetMobility(apMobility);
1625 apDev->SetPhy(m_phyAp);
1626 apNode->AggregateObject(apMobility);
1627 apNode->AddDevice(apDev);
1628
1629 Ptr<Node> sta1Node = CreateObject<Node>();
1633 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1635 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1636 m_phySta1->SetDevice(sta1Dev);
1637 m_phySta1->AddChannel(spectrumChannel);
1643 m_phySta1->SetMobility(sta1Mobility);
1644 sta1Dev->SetPhy(m_phySta1);
1645 sta1Node->AggregateObject(sta1Mobility);
1646 sta1Node->AddDevice(sta1Dev);
1647
1648 Ptr<Node> sta2Node = CreateObject<Node>();
1652 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1654 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1655 m_phySta2->SetDevice(sta2Dev);
1656 m_phySta2->AddChannel(spectrumChannel);
1662 m_phySta2->SetMobility(sta2Mobility);
1663 sta2Dev->SetPhy(m_phySta2);
1664 sta2Node->AggregateObject(sta2Mobility);
1665 sta2Node->AddDevice(sta2Dev);
1666
1667 Ptr<Node> interfererNode = CreateObject<Node>();
1670 m_phyInterferer->SetDevice(interfererDev);
1671 m_phyInterferer->SetChannel(spectrumChannel);
1672 m_phyInterferer->SetDutyCycle(1);
1673 interfererNode->AddDevice(interfererDev);
1674}
1675
1676void
1678{
1679 m_phyAp->Dispose();
1680 m_phyAp = nullptr;
1681 m_phySta1->Dispose();
1682 m_phySta1 = nullptr;
1683 m_phySta2->Dispose();
1684 m_phySta2 = nullptr;
1686 m_phyInterferer = nullptr;
1687}
1688
1689void
1691{
1694 int64_t streamNumber = 0;
1695 m_phyAp->AssignStreams(streamNumber);
1696 m_phySta1->AssignStreams(streamNumber);
1697 m_phySta2->AssignStreams(streamNumber);
1698
1699 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
1704 ->number;
1705
1706 m_phyAp->SetOperatingChannel(
1712
1713 // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1714 // duration of the test run
1715 BandInfo bandInfo;
1716 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20));
1717 // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1718 // the border of another RU
1719 bandInfo.fl = bandInfo.fc - MHzToHz(5);
1720 bandInfo.fh = bandInfo.fc + MHzToHz(5);
1721 Bands bands;
1722 bands.push_back(bandInfo);
1723
1724 auto spectrumInterference = Create<SpectrumModel>(bands);
1725 auto interferencePsd = Create<SpectrumValue>(spectrumInterference);
1726 Watt_u interferencePower{0.1};
1727 *interferencePsd = interferencePower / 10e6;
1728
1731 this,
1732 interferencePsd,
1733 Seconds(3));
1734
1735 //---------------------------------------------------------------------------
1736 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1739 this,
1740 1,
1741 2,
1742 std::vector<bool>{});
1743
1744 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1745 // both PHYs should be back to IDLE at the same time.
1748 this,
1749 m_phySta1,
1750 WifiPhyState::RX);
1753 this,
1754 m_phySta2,
1755 WifiPhyState::RX);
1758 this,
1759 m_phySta1,
1760 WifiPhyState::IDLE);
1763 this,
1764 m_phySta2,
1765 WifiPhyState::IDLE);
1766
1767 if (m_indexSubchannel < 2) // interference in RU 1
1768 {
1769 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1772 this,
1773 0,
1774 1,
1775 0);
1776 // One PSDU of 1500 bytes should have been successfully received by STA 2
1779 this,
1780 1,
1781 0,
1782 1500);
1783 }
1784 else // interference in RU 2
1785 {
1786 // One PSDU of 1000 bytes should have been successfully received by STA 1
1789 this,
1790 1,
1791 0,
1792 1000);
1793 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1796 this,
1797 0,
1798 1,
1799 0);
1800 }
1801
1803
1804 //---------------------------------------------------------------------------
1805 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1806 // the punctured 20 MHz subchannel is the one that has interference
1807 std::vector<bool> puncturedSubchannels;
1808 const auto num20MhzSubchannels = Count20MHzSubchannels(m_channelWidth);
1809 for (std::size_t i = 0; i < num20MhzSubchannels; ++i)
1810 {
1811 if (i == m_indexSubchannel)
1812 {
1813 puncturedSubchannels.push_back(true);
1814 }
1815 else
1816 {
1817 puncturedSubchannels.push_back(false);
1818 }
1819 }
1822 this,
1823 1,
1824 2,
1825 puncturedSubchannels);
1826
1827 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1828 // both PHYs should be back to IDLE at the same time.
1831 this,
1832 m_phySta1,
1833 WifiPhyState::RX);
1836 this,
1837 m_phySta2,
1838 WifiPhyState::RX);
1841 this,
1842 m_phySta1,
1843 WifiPhyState::IDLE);
1846 this,
1847 m_phySta2,
1848 WifiPhyState::IDLE);
1849
1850 // One PSDU of 1000 bytes should have been successfully received by STA 1
1853 this,
1854 1,
1855 0,
1856 1000);
1857 // One PSDU of 1500 bytes should have been successfully received by STA 2
1860 this,
1861 1,
1862 0,
1863 1500);
1864
1866
1868}
1869
1870void
1872{
1873 // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1874 // cannot be punctured
1875 for (auto index : {1, 2, 3})
1876 {
1877 m_indexSubchannel = index;
1878 RunOne();
1879 }
1881}
1882
1883/**
1884 * @ingroup wifi-test
1885 * @ingroup tests
1886 *
1887 * @brief UL-OFDMA PPDU UID attribution test
1888 */
1890{
1891 public:
1893 ~TestUlOfdmaPpduUid() override;
1894
1895 private:
1896 void DoSetup() override;
1897 void DoTeardown() override;
1898 void DoRun() override;
1899
1900 /**
1901 * Transmitted PPDU information function for AP
1902 * @param uid the UID of the transmitted PPDU
1903 */
1904 void TxPpduAp(uint64_t uid);
1905 /**
1906 * Transmitted PPDU information function for STA 1
1907 * @param uid the UID of the transmitted PPDU
1908 */
1909 void TxPpduSta1(uint64_t uid);
1910 /**
1911 * Transmitted PPDU information function for STA 2
1912 * @param uid the UID of the transmitted PPDU
1913 */
1914 void TxPpduSta2(uint64_t uid);
1915 /**
1916 * Reset the global PPDU UID counter in WifiPhy
1917 */
1918 void ResetPpduUid();
1919
1920 /**
1921 * Send MU-PPDU toward both STAs.
1922 */
1923 void SendMuPpdu();
1924 /**
1925 * Send TB-PPDU from both STAs.
1926 */
1927 void SendTbPpdu();
1928 /**
1929 * Send SU-PPDU function
1930 * @param txStaId the ID of the sending STA
1931 */
1932 void SendSuPpdu(uint16_t txStaId);
1933
1934 /**
1935 * Check the UID of the transmitted PPDU
1936 * @param staId the STA-ID of the PHY (0 for AP)
1937 * @param expectedUid the expected UID
1938 */
1939 void CheckUid(uint16_t staId, uint64_t expectedUid);
1940
1944
1945 uint64_t m_ppduUidAp; ///< UID of PPDU transmitted by AP
1946 uint64_t m_ppduUidSta1; ///< UID of PPDU transmitted by STA1
1947 uint64_t m_ppduUidSta2; ///< UID of PPDU transmitted by STA2
1948};
1949
1951 : TestCase("UL-OFDMA PPDU UID attribution test"),
1952 m_ppduUidAp(UINT64_MAX),
1953 m_ppduUidSta1(UINT64_MAX),
1954 m_ppduUidSta2(UINT64_MAX)
1955{
1956}
1957
1961
1962void
1964{
1967 lossModel->SetFrequency(DEFAULT_FREQUENCY);
1968 spectrumChannel->AddPropagationLossModel(lossModel);
1971 spectrumChannel->SetPropagationDelayModel(delayModel);
1972
1973 Ptr<Node> apNode = CreateObject<Node>();
1977 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1979 m_phyAp->SetErrorRateModel(apErrorModel);
1980 m_phyAp->AddChannel(spectrumChannel);
1982 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
1987 ->number;
1990 m_phyAp->SetDevice(apDev);
1994 m_phyAp->SetMobility(apMobility);
1995 apDev->SetPhy(m_phyAp);
1996 apNode->AggregateObject(apMobility);
1997 apNode->AddDevice(apDev);
1998 apDev->SetStandard(WIFI_STANDARD_80211ax);
1999 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
2000
2001 Ptr<Node> sta1Node = CreateObject<Node>();
2005 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
2007 m_phySta1->SetErrorRateModel(sta1ErrorModel);
2008 m_phySta1->AddChannel(spectrumChannel);
2012 m_phySta1->SetDevice(sta1Dev);
2016 m_phySta1->SetMobility(sta1Mobility);
2017 sta1Dev->SetPhy(m_phySta1);
2018 sta1Node->AggregateObject(sta1Mobility);
2019 sta1Node->AddDevice(sta1Dev);
2020
2021 Ptr<Node> sta2Node = CreateObject<Node>();
2025 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
2027 m_phySta2->SetErrorRateModel(sta2ErrorModel);
2028 m_phySta2->AddChannel(spectrumChannel);
2032 m_phySta2->SetDevice(sta2Dev);
2036 m_phySta2->SetMobility(sta2Mobility);
2037 sta2Dev->SetPhy(m_phySta2);
2038 sta2Node->AggregateObject(sta2Mobility);
2039 sta2Node->AddDevice(sta2Dev);
2040}
2041
2042void
2044{
2045 m_phyAp->Dispose();
2046 m_phyAp = nullptr;
2047 m_phySta1->Dispose();
2048 m_phySta1 = nullptr;
2049 m_phySta2->Dispose();
2050 m_phySta2 = nullptr;
2051}
2052
2053void
2054TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
2055{
2056 uint64_t uid;
2057 std::string device;
2058 switch (staId)
2059 {
2060 case 0:
2061 uid = m_ppduUidAp;
2062 device = "AP";
2063 break;
2064 case 1:
2065 uid = m_ppduUidSta1;
2066 device = "STA1";
2067 break;
2068 case 2:
2069 uid = m_ppduUidSta2;
2070 device = "STA2";
2071 break;
2072 default:
2073 NS_ABORT_MSG("Unexpected STA-ID");
2074 }
2076 expectedUid,
2077 "UID " << uid << " does not match expected one " << expectedUid << " for "
2078 << device << " at " << Simulator::Now());
2079}
2080
2081void
2083{
2084 NS_LOG_FUNCTION(this << uid);
2085 m_ppduUidAp = uid;
2086}
2087
2088void
2090{
2091 NS_LOG_FUNCTION(this << uid);
2092 m_ppduUidSta1 = uid;
2093}
2094
2095void
2097{
2098 NS_LOG_FUNCTION(this << uid);
2099 m_ppduUidSta2 = uid;
2100}
2101
2102void
2104{
2105 NS_LOG_FUNCTION(this);
2106 m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2107}
2108
2109void
2111{
2112 WifiConstPsduMap psdus;
2113 WifiTxVector txVector{HePhy::GetHeMcs7(),
2114 0,
2116 NanoSeconds(800),
2117 1,
2118 1,
2119 0,
2121 false,
2122 false};
2123
2124 uint16_t rxStaId1 = 1;
2125 HeRu::RuSpec ru1(RuType::RU_106_TONE, 1, true);
2126 txVector.SetRu(ru1, rxStaId1);
2127 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2128 txVector.SetNss(1, rxStaId1);
2129
2130 uint16_t rxStaId2 = 2;
2131 HeRu::RuSpec ru2(RuType::RU_106_TONE, 2, true);
2132 txVector.SetRu(ru2, rxStaId2);
2133 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2134 txVector.SetNss(1, rxStaId2);
2135 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2136 txVector.SetRuAllocation({96}, 0);
2137
2138 Ptr<Packet> pkt1 = Create<Packet>(1000);
2139 WifiMacHeader hdr1;
2141 hdr1.SetQosTid(0);
2142 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2143 hdr1.SetSequenceNumber(1);
2144 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2145 psdus.insert(std::make_pair(rxStaId1, psdu1));
2146
2147 Ptr<Packet> pkt2 = Create<Packet>(1500);
2148 WifiMacHeader hdr2;
2150 hdr2.SetQosTid(0);
2151 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2152 hdr2.SetSequenceNumber(2);
2153 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2154 psdus.insert(std::make_pair(rxStaId2, psdu2));
2155
2156 m_phyAp->Send(psdus, txVector);
2157}
2158
2159void
2161{
2162 WifiConstPsduMap psdus1;
2163 WifiConstPsduMap psdus2;
2164
2165 WifiTxVector txVector1{HePhy::GetHeMcs7(),
2166 0,
2168 NanoSeconds(1600),
2169 1,
2170 1,
2171 0,
2173 false,
2174 false};
2175 WifiTxVector txVector2{txVector1};
2176 WifiTxVector trigVector{txVector2};
2177
2178 uint16_t rxStaId1 = 1;
2179 HeRu::RuSpec ru1(RuType::RU_106_TONE, 1, false);
2180 txVector1.SetRu(ru1, rxStaId1);
2181 txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2182 txVector1.SetNss(1, rxStaId1);
2183 trigVector.SetRu(ru1, rxStaId1);
2184 trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2185 trigVector.SetNss(1, rxStaId1);
2186
2187 auto pkt1 = Create<Packet>(1000);
2188 WifiMacHeader hdr1;
2190 hdr1.SetQosTid(0);
2191 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2192 hdr1.SetSequenceNumber(1);
2193 auto psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2194 psdus1.insert(std::make_pair(rxStaId1, psdu1));
2195
2196 uint16_t rxStaId2 = 2;
2197 HeRu::RuSpec ru2(RuType::RU_106_TONE, 2, false);
2198 txVector2.SetRu(ru2, rxStaId2);
2199 txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2200 txVector2.SetNss(1, rxStaId2);
2201 trigVector.SetRu(ru2, rxStaId2);
2202 trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2203 trigVector.SetNss(1, rxStaId2);
2204
2205 auto pkt2 = Create<Packet>(1500);
2206 WifiMacHeader hdr2;
2208 hdr2.SetQosTid(0);
2209 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2210 hdr2.SetSequenceNumber(2);
2211 auto psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2212 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2213
2214 const auto txDuration1 = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu1->GetSize(),
2215 txVector1,
2217 rxStaId1);
2218 const auto txDuration2 = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu2->GetSize(),
2219 txVector2,
2221 rxStaId2);
2222 const auto txDuration = std::max(txDuration1, txDuration2);
2223
2224 txVector1.SetLength(
2226 .first);
2227 txVector2.SetLength(
2229 .first);
2230
2232 hePhyAp->SetTrigVector(trigVector, txDuration);
2233
2234 m_phySta1->Send(psdus1, txVector1);
2235 m_phySta2->Send(psdus2, txVector2);
2236}
2237
2238void
2240{
2241 WifiConstPsduMap psdus;
2242 WifiTxVector txVector{HePhy::GetHeMcs7(),
2243 0,
2245 NanoSeconds(800),
2246 1,
2247 1,
2248 0,
2250 false,
2251 false};
2252
2253 auto pkt = Create<Packet>(1000);
2254 WifiMacHeader hdr;
2256 hdr.SetQosTid(0);
2258 hdr.SetSequenceNumber(1);
2259 auto psdu = Create<WifiPsdu>(pkt, hdr);
2260 psdus.insert(std::make_pair(SU_STA_ID, psdu));
2261
2262 switch (txStaId)
2263 {
2264 case 0:
2265 m_phyAp->Send(psdus, txVector);
2266 break;
2267 case 1:
2268 m_phySta1->Send(psdus, txVector);
2269 break;
2270 case 2:
2271 m_phySta2->Send(psdus, txVector);
2272 break;
2273 default:
2274 NS_ABORT_MSG("Unexpected STA-ID");
2275 }
2276}
2277
2278void
2280{
2283 int64_t streamNumber = 0;
2284 m_phyAp->AssignStreams(streamNumber);
2285 m_phySta1->AssignStreams(streamNumber);
2286 m_phySta2->AssignStreams(streamNumber);
2287
2288 // Reset PPDU UID so as not to be dependent on previously executed test cases,
2289 // since global attribute will be changed).
2290 ResetPpduUid();
2291
2292 // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2293 // PPDU UID should be equal to 0 (the first counter value).
2296
2297 // Send HE SU PPDU from AP.
2298 // PPDU UID should be incremented since this is a new PPDU.
2301
2302 // Send HE TB PPDU from STAs to AP.
2303 // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2304 // preceding correctly received PPDU (which normally contains the trigger frame).
2308
2309 // Send HE SU PPDU from STA1.
2310 // PPDU UID should be incremented since this is a new PPDU.
2313
2316}
2317
2318/**
2319 * @ingroup wifi-test
2320 * @ingroup tests
2321 *
2322 * @brief UL-OFDMA multiple RX events test
2323 */
2325{
2326 public:
2328 ~TestMultipleHeTbPreambles() override;
2329
2330 private:
2331 void DoSetup() override;
2332 void DoTeardown() override;
2333 void DoRun() override;
2334
2335 /**
2336 * Receive HE TB PPDU function.
2337 *
2338 * @param uid the UID used to identify a set of HE TB PPDUs belonging to the same UL-MU
2339 * transmission
2340 * @param staId the STA ID
2341 * @param txPower the TX power
2342 * @param payloadSize the size of the payload in bytes
2343 */
2344 void RxHeTbPpdu(uint64_t uid, uint16_t staId, Watt_u txPower, size_t payloadSize);
2345
2346 /**
2347 * Receive OFDMA part of HE TB PPDU function.
2348 * Immediately schedules DoRxHeTbPpduOfdmaPart.
2349 *
2350 * @param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2351 */
2353 /**
2354 * Receive OFDMA part of HE TB PPDU function.
2355 * Actual reception call.
2356 *
2357 * @param rxParamsOfdma the spectrum signal parameters to send for OFDMA part
2358 */
2360
2361 /**
2362 * RX dropped function
2363 * @param p the packet
2364 * @param reason the reason
2365 */
2367
2368 /**
2369 * Reset function
2370 */
2371 void Reset();
2372
2373 /**
2374 * Check the received HE TB preambles
2375 * @param nEvents the number of events created by the PHY
2376 * @param uids the vector of expected UIDs
2377 */
2378 void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2379
2380 /**
2381 * Check the number of bytes dropped
2382 * @param expectedBytesDropped the expected number of bytes dropped
2383 */
2384 void CheckBytesDropped(size_t expectedBytesDropped);
2385
2387
2388 uint64_t m_totalBytesDropped; ///< total number of dropped bytes
2390};
2391
2393 : TestCase("UL-OFDMA multiple RX events test"),
2394 m_totalBytesDropped(0),
2395 m_trigVector(HePhy::GetHeMcs7(),
2396 0,
2398 NanoSeconds(1600),
2399 1,
2400 1,
2401 0,
2403 false,
2404 false)
2405{
2406}
2407
2411
2412void
2414{
2415 NS_LOG_FUNCTION(this);
2417 // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2418 m_phy->Reset();
2420}
2421
2422void
2424{
2425 NS_LOG_FUNCTION(this << p << reason);
2426 m_totalBytesDropped += (p->GetSize() - 30);
2427}
2428
2429void
2430TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2431{
2432 auto events = m_phy->GetCurrentPreambleEvents();
2433 NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2434 for (const auto& uid : uids)
2435 {
2436 auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2437 auto it = events.find(pair);
2438 bool found = (it != events.end());
2440 true,
2441 "HE TB PPDU with UID " << uid << " has not been received!");
2442 }
2443}
2444
2445void
2447{
2449 expectedBytesDropped,
2450 "The number of dropped bytes is not correct!");
2451}
2452
2453void
2455 uint16_t staId,
2456 Watt_u txPower,
2457 size_t payloadSize)
2458{
2459 WifiConstPsduMap psdus;
2460 WifiTxVector txVector{HePhy::GetHeMcs7(),
2461 0,
2463 NanoSeconds(1600),
2464 1,
2465 1,
2466 0,
2468 false,
2469 false};
2470
2471 HeRu::RuSpec ru(RuType::RU_106_TONE, staId, false);
2472 txVector.SetRu(ru, staId);
2473 txVector.SetMode(HePhy::GetHeMcs7(), staId);
2474 txVector.SetNss(1, staId);
2475
2476 m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2477
2478 auto pkt = Create<Packet>(payloadSize);
2479 WifiMacHeader hdr;
2481 hdr.SetQosTid(0);
2482 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2483 hdr.SetSequenceNumber(1);
2484 auto psdu = Create<WifiPsdu>(pkt, hdr);
2485 psdus.insert(std::make_pair(staId, psdu));
2486
2487 auto ppduDuration = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu->GetSize(),
2488 txVector,
2489 m_phy->GetPhyBand(),
2490 staId);
2491 auto ppdu = Create<HePpdu>(psdus,
2492 txVector,
2494 ppduDuration,
2495 uid,
2497
2498 // Send non-OFDMA part
2499 const auto nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonHeDurationForHeTb(txVector);
2500 const auto centerFrequency =
2501 m_phy->GetHePhy()->GetCenterFrequenciesForNonHePart(ppdu, staId).front();
2502 auto ruWidth = WifiRu::GetBandwidth(WifiRu::GetRuType(txVector.GetRu(staId)));
2503 auto channelWidth = ruWidth < MHz_u{20} ? MHz_u{20} : ruWidth;
2505 centerFrequency,
2506 channelWidth,
2507 txPower,
2508 m_phy->GetGuardBandwidth(channelWidth));
2509 auto rxParams = Create<WifiSpectrumSignalParameters>();
2510 rxParams->psd = rxPsd;
2511 rxParams->txPhy = nullptr;
2512 rxParams->duration = nonOfdmaDuration;
2513 rxParams->ppdu = ppdu;
2514
2515 uint16_t length;
2516 std::tie(length, ppduDuration) =
2518 txVector.SetLength(length);
2519 m_trigVector.SetLength(length);
2521 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2522 ppdu->ResetTxVector();
2523 m_phy->StartRx(rxParams, nullptr);
2524
2525 // Schedule OFDMA part
2526 auto ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2527 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2528 const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2529 auto rxPsdOfdma =
2532 txPower,
2534 band.indices);
2535 auto rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2536 rxParamsOfdma->psd = rxPsd;
2537 rxParamsOfdma->txPhy = nullptr;
2538 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2539 rxParamsOfdma->ppdu = ppduOfdma;
2540 Simulator::Schedule(nonOfdmaDuration,
2542 this,
2543 rxParamsOfdma);
2544}
2545
2546void
2551
2552void
2554{
2555 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2556 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2557 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2558 m_phy->StartRx(rxParamsOfdma, nullptr);
2559}
2560
2561void
2563{
2567 dev->SetStandard(WIFI_STANDARD_80211ax);
2572 "Txop",
2573 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
2574 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2575 dev->SetMac(mac);
2576 m_phy->SetInterferenceHelper(interferenceHelper);
2577 m_phy->SetErrorRateModel(error);
2578 m_phy->AddChannel(spectrumChannel);
2583 0});
2584 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2586 m_phy->SetDevice(dev);
2587 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2589 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2590 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2591 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2593 heConfiguration->m_maxTbPpduDelay = NanoSeconds(400);
2594 dev->SetHeConfiguration(heConfiguration);
2595 dev->SetPhy(m_phy);
2596 node->AddDevice(dev);
2597}
2598
2599void
2601{
2602 m_phy->Dispose();
2603 m_phy = nullptr;
2604}
2605
2606void
2608{
2611 int64_t streamNumber = 0;
2612 m_phy->AssignStreams(streamNumber);
2613
2614 Watt_u txPower{0.01};
2615
2616 {
2617 // Verify a single UL MU transmission with two stations belonging to the same BSS
2618 std::vector<uint64_t> uids{0};
2621 this,
2622 uids[0],
2623 1,
2624 txPower,
2625 1001);
2628 this,
2629 uids[0],
2630 2,
2631 txPower,
2632 1002);
2633 // Check that we received a single UL MU transmission with the corresponding UID
2636 this,
2637 1,
2638 uids);
2640 }
2641
2642 {
2643 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2644 // the second transmission arrives during the preamble detection window and with half the
2645 // power of the first transmission.
2646 std::vector<uint64_t> uids{1, 2};
2649 this,
2650 uids[0],
2651 1,
2652 txPower,
2653 1001);
2656 this,
2657 uids[0],
2658 2,
2659 txPower,
2660 1002);
2663 this,
2664 uids[1],
2665 1,
2666 txPower / 2,
2667 1003);
2670 this,
2671 uids[1],
2672 2,
2673 txPower / 2,
2674 1004);
2675 // Check that we received the correct reception of 2 UL MU transmissions with the
2676 // corresponding UIDs
2679 this,
2680 2,
2681 uids);
2683 // TODO: verify PPDUs from second UL MU transmission are dropped
2684 }
2685
2686 {
2687 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2688 // the second transmission arrives during the preamble detection window and with twice the
2689 // power of the first transmission.
2690 std::vector<uint64_t> uids{3, 4};
2693 this,
2694 uids[0],
2695 1,
2696 txPower / 2,
2697 1001);
2700 this,
2701 uids[0],
2702 2,
2703 txPower / 2,
2704 1002);
2707 this,
2708 uids[1],
2709 1,
2710 txPower,
2711 1003);
2714 this,
2715 uids[1],
2716 2,
2717 txPower,
2718 1004);
2719 // Check that we received the correct reception of 2 UL MU transmissions with the
2720 // corresponding UIDs
2723 this,
2724 2,
2725 uids);
2727 // TODO: verify PPDUs from first UL MU transmission are dropped
2728 }
2729
2730 {
2731 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2732 // the second transmission arrives during PHY header reception and with the same power as
2733 // the first transmission.
2734 std::vector<uint64_t> uids{5, 6};
2737 this,
2738 uids[0],
2739 1,
2740 txPower,
2741 1001);
2744 this,
2745 uids[0],
2746 2,
2747 txPower,
2748 1002);
2751 this,
2752 uids[1],
2753 1,
2754 txPower,
2755 1003);
2758 this,
2759 uids[1],
2760 2,
2761 txPower,
2762 1004);
2763 // Check that we received the correct reception of the first UL MU transmission with the
2764 // corresponding UID (second one dropped)
2767 this,
2768 1,
2769 std::vector<uint64_t>{uids[0]});
2770 // The packets of the second UL MU transmission should have been dropped
2773 this,
2774 1003 + 1004);
2776 }
2777
2778 {
2779 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2780 // BSS, where the second transmission arrives during payload reception and with the same
2781 // power as the first transmission.
2782 std::vector<uint64_t> uids{7, 8};
2785 this,
2786 uids[0],
2787 1,
2788 txPower,
2789 1001);
2792 this,
2793 uids[0],
2794 2,
2795 txPower,
2796 1002);
2799 this,
2800 uids[1],
2801 1,
2802 txPower,
2803 1003);
2806 this,
2807 uids[1],
2808 2,
2809 txPower,
2810 1004);
2811 // Check that we received the correct reception of the first UL MU transmission with the
2812 // corresponding UID (second one dropped)
2815 this,
2816 1,
2817 std::vector<uint64_t>{uids[0]});
2818 // The packets of the second UL MU transmission should have been dropped
2821 this,
2822 1003 + 1004);
2824 }
2825
2826 {
2827 // Verify the correct reception of a single UL MU transmission with two stations belonging
2828 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2829 // the configured delay spread of 400ns
2830 std::vector<uint64_t> uids{9};
2833 this,
2834 uids[0],
2835 1,
2836 txPower,
2837 1001);
2840 this,
2841 uids[0],
2842 2,
2843 txPower,
2844 1002);
2845 // Check that we received a single UL MU transmission with the corresponding UID
2848 this,
2849 1,
2850 uids);
2851 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2852 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2853 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2854 // second packet of 1002 bytes is dropped as well.
2857 this,
2858 1001 + 1002);
2860 }
2861
2864}
2865
2866/**
2867 * @ingroup wifi-test
2868 * @ingroup tests
2869 *
2870 * @brief PHY listener for OFDMA tests
2871 */
2873{
2874 public:
2876
2877 void NotifyRxStart(Time duration) override
2878 {
2879 NS_LOG_FUNCTION(this << duration);
2882 m_lastRxSuccess = false;
2883 }
2884
2885 void NotifyRxEndOk() override
2886 {
2887 NS_LOG_FUNCTION(this);
2889 ++m_notifyRxEnd;
2890 m_lastRxSuccess = true;
2891 }
2892
2893 void NotifyRxEndError() override
2894 {
2895 NS_LOG_FUNCTION(this);
2897 ++m_notifyRxEnd;
2898 m_lastRxSuccess = false;
2899 }
2900
2901 void NotifyTxStart(Time duration, dBm_u txPower) override
2902 {
2903 NS_LOG_FUNCTION(this << duration << txPower);
2904 }
2905
2907 WifiChannelListType channelType,
2908 const std::vector<Time>& /*per20MhzDurations*/) override
2909 {
2910 NS_LOG_FUNCTION(this << duration << channelType);
2911 }
2912
2913 void NotifySwitchingStart(Time duration) override
2914 {
2915 }
2916
2917 void NotifySleep() override
2918 {
2919 }
2920
2921 void NotifyOff() override
2922 {
2923 }
2924
2925 void NotifyWakeup() override
2926 {
2927 }
2928
2929 void NotifyOn() override
2930 {
2931 }
2932
2933 /**
2934 * Reset function.
2935 */
2936 void Reset()
2937 {
2938 m_notifyRxStart = 0;
2939 m_notifyRxEnd = 0;
2941 m_lastRxEnd = Seconds(0);
2942 m_lastRxSuccess = false;
2943 }
2944
2945 /**
2946 * Return the number of RX start notifications that has been received since the last reset.
2947 * @return the number of RX start notifications that has been received
2948 */
2950 {
2951 return m_notifyRxStart;
2952 }
2953
2954 /**
2955 * Return the number of RX end notifications that has been received since the last reset.
2956 * @return the number of RX end notifications that has been received
2957 */
2959 {
2960 return m_notifyRxEnd;
2961 }
2962
2963 /**
2964 * Return the time at which the last RX start notification has been received.
2965 * @return the time at which the last RX start notification has been received
2966 */
2968 {
2969 return m_lastRxStart;
2970 }
2971
2972 /**
2973 * Return the time at which the last RX end notification has been received.
2974 * @return the time at which the last RX end notification has been received
2975 */
2977 {
2978 return m_lastRxEnd;
2979 }
2980
2981 /**
2982 * Return whether last RX has been successful.
2983 * @return true if last RX has been successful, false otherwise
2984 */
2985 bool IsLastRxSuccess() const
2986 {
2987 return m_lastRxSuccess;
2988 }
2989
2990 private:
2991 uint32_t m_notifyRxStart{0}; ///< count number of RX start notifications
2992 uint32_t m_notifyRxEnd{0}; ///< count number of RX end notifications
2993 Time m_lastRxStart{Seconds(0)}; ///< last time a RX start notification has been received
2994 Time m_lastRxEnd{Seconds(0)}; ///< last time a RX end notification has been received
2995 bool m_lastRxSuccess{false}; ///< flag whether last RX has been successful
2996};
2997
2998/**
2999 * @ingroup wifi-test
3000 * @ingroup tests
3001 *
3002 * @brief UL-OFDMA PHY test
3003 */
3005{
3006 public:
3007 /**
3008 * Erroneous info included in a TRIGVECTOR
3009 */
3017
3019 ~TestUlOfdmaPhyTransmission() override;
3020
3021 private:
3022 void DoSetup() override;
3023 void DoTeardown() override;
3024 void DoRun() override;
3025
3026 /**
3027 * Get TXVECTOR for HE TB PPDU.
3028 * @param txStaId the ID of the TX STA
3029 * @param index the RU index used for the transmission
3030 * @param bssColor the BSS color of the TX STA
3031 * @return the TXVECTOR for HE TB PPDU
3032 */
3033 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
3034 std::size_t index,
3035 uint8_t bssColor) const;
3036 /**
3037 * Set TRIGVECTOR for HE TB PPDU
3038 *
3039 * @param bssColor the BSS color of the TX STA
3040 * @param error the erroneous info (if any) in the TRIGVECTOR to set
3041 */
3042 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
3043 /**
3044 * Send HE TB PPDU function
3045 * @param txStaId the ID of the TX STA
3046 * @param index the RU index used for the transmission
3047 * @param payloadSize the size of the payload in bytes
3048 * @param uid the UID of the trigger frame that is initiating this transmission
3049 * @param bssColor the BSS color of the TX STA
3050 * @param incrementUid whether UID shall be incremented
3051 */
3052 void SendHeTbPpdu(uint16_t txStaId,
3053 std::size_t index,
3054 std::size_t payloadSize,
3055 uint64_t uid,
3056 uint8_t bssColor,
3057 bool incrementUid);
3058
3059 /**
3060 * Send HE SU PPDU function
3061 * @param txStaId the ID of the TX STA
3062 * @param payloadSize the size of the payload in bytes
3063 * @param uid the UID of the trigger frame that is initiating this transmission
3064 * @param bssColor the BSS color of the TX STA
3065 */
3066 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
3067
3068 /**
3069 * Set the BSS color
3070 * @param phy the PHY
3071 * @param bssColor the BSS color
3072 */
3073 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3074
3075 /**
3076 * Set the PSD limit
3077 * @param phy the PHY
3078 * @param psdLimit the PSD limit
3079 */
3080 void SetPsdLimit(Ptr<WifiPhy> phy, dBm_per_MHz_u psdLimit);
3081
3082 /**
3083 * Generate interference function
3084 * @param interferencePsd the PSD of the interference to be generated
3085 * @param duration the duration of the interference
3086 */
3087 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3088 /**
3089 * Stop interference function
3090 */
3091 void StopInterference();
3092
3093 /**
3094 * Run one function
3095 */
3096 void RunOne();
3097
3098 /**
3099 * Check the received PSDUs from STA1
3100 * @param expectedSuccess the expected number of success
3101 * @param expectedFailures the expected number of failures
3102 * @param expectedBytes the expected number of bytes
3103 */
3104 void CheckRxFromSta1(uint32_t expectedSuccess,
3105 uint32_t expectedFailures,
3106 uint32_t expectedBytes);
3107
3108 /**
3109 * Check the received PSDUs from STA2
3110 * @param expectedSuccess the expected number of success
3111 * @param expectedFailures the expected number of failures
3112 * @param expectedBytes the expected number of bytes
3113 */
3114 void CheckRxFromSta2(uint32_t expectedSuccess,
3115 uint32_t expectedFailures,
3116 uint32_t expectedBytes);
3117
3118 /**
3119 * Check the received power for the non-OFDMA of the HE TB PPDUs over the given band
3120 * @param phy the PHY
3121 * @param band the indices of the band over which the power is measured
3122 * @param expectedRxPower the expected received power
3123 */
3126 Watt_u expectedRxPower);
3127 /**
3128 * Check the received power for the OFDMA part of the HE TB PPDUs over the given band
3129 * @param phy the PHY
3130 * @param band the indices of the band over which the power is measured
3131 * @param expectedRxPower the expected received power
3132 */
3135 Watt_u expectedRxPower);
3136
3137 /**
3138 * Verify all events are cleared at end of TX or RX
3139 */
3140 void VerifyEventsCleared();
3141
3142 /**
3143 * Check the PHY state
3144 * @param phy the PHY
3145 * @param expectedState the expected state of the PHY
3146 */
3147 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
3148 /// @copydoc CheckPhyState
3150
3151 /**
3152 * Check the the number of RX start notifications at the AP as well as the last time a RX start
3153 * has been notified
3154 * @param expectedNotifications the expected number of RX start notifications at the AP
3155 * @param expectedLastNotification the expected time of the last RX start notification at the AP
3156 */
3157 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3158 /**
3159 * Check the the number of RX end notifications at the AP as well as the last time a RX end has
3160 * been notified
3161 * @param expectedNotifications the expected number of RX end notifications at the AP
3162 * @param expectedLastNotification the expected time of the last RX end notification at the AP
3163 * @param expectedSuccess true if the last RX notification indicates a success, false otherwise
3164 */
3165 void CheckApRxEnd(uint32_t expectedNotifications,
3166 Time expectedLastNotification,
3167 bool expectedSuccess);
3168
3169 /**
3170 * Reset function
3171 */
3172 void Reset();
3173
3174 /**
3175 * Receive success function
3176 * @param psdu the PSDU
3177 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
3178 * @param txVector the transmit vector
3179 * @param statusPerMpdu reception status per MPDU
3180 */
3182 RxSignalInfo rxSignalInfo,
3183 const WifiTxVector& txVector,
3184 const std::vector<bool>& statusPerMpdu);
3185
3186 /**
3187 * Receive failure function
3188 * @param psdu the PSDU
3189 */
3190 void RxFailure(Ptr<const WifiPsdu> psdu);
3191
3192 /**
3193 * Schedule test to perform.
3194 * The interference generation should be scheduled apart.
3195 *
3196 * @param delay the reference delay to schedule the events
3197 * @param solicited flag indicating if HE TB PPDUs were solicited by the AP
3198 * @param expectedStateAtEnd the expected state of the PHY at the end of the reception
3199 * @param expectedSuccessFromSta1 the expected number of success from STA 1
3200 * @param expectedFailuresFromSta1 the expected number of failures from STA 1
3201 * @param expectedBytesFromSta1 the expected number of bytes from STA 1
3202 * @param expectedSuccessFromSta2 the expected number of success from STA 2
3203 * @param expectedFailuresFromSta2 the expected number of failures from STA 2
3204 * @param expectedBytesFromSta2 the expected number of bytes from STA 2
3205 * @param scheduleTxSta1 flag indicating to schedule a HE TB PPDU from STA 1
3206 * @param ulTimeDifference delay between HE TB PPDU from STA 1 and HE TB PPDU from STA 2
3207 * are received
3208 * @param expectedStateBeforeEnd the expected state of the PHY before the end of the
3209 * transmission
3210 * @param error the erroneous info (if any) in the TRIGVECTOR to set
3211 */
3212 void ScheduleTest(Time delay,
3213 bool solicited,
3214 WifiPhyState expectedStateAtEnd,
3215 uint32_t expectedSuccessFromSta1,
3216 uint32_t expectedFailuresFromSta1,
3217 uint32_t expectedBytesFromSta1,
3218 uint32_t expectedSuccessFromSta2,
3219 uint32_t expectedFailuresFromSta2,
3220 uint32_t expectedBytesFromSta2,
3221 bool scheduleTxSta1 = true,
3222 Time ulTimeDifference = Seconds(0),
3223 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3224 TrigVectorInfo error = NONE);
3225
3226 /**
3227 * Schedule power measurement related checks.
3228 *
3229 * @param delay the reference delay used to schedule the events
3230 * @param rxPowerNonOfdmaRu1 the received power on the non-OFDMA part of RU1
3231 * @param rxPowerNonOfdmaRu2 the received power on the non-OFDMA part of RU2
3232 * @param rxPowerOfdmaRu1 the received power on RU1
3233 * @param rxPowerOfdmaRu2 the received power on RU2
3234 */
3236 Watt_u rxPowerNonOfdmaRu1,
3237 Watt_u rxPowerNonOfdmaRu2,
3238 Watt_u rxPowerOfdmaRu1,
3239 Watt_u rxPowerOfdmaRu2);
3240 /**
3241 * Log scenario description
3242 *
3243 * @param log the scenario description to add to log
3244 */
3245 void LogScenario(std::string log) const;
3246
3251
3252 std::shared_ptr<OfdmaTestPhyListener>
3253 m_apPhyStateListener; ///< listener for AP PHY state transitions
3254
3256
3257 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
3258 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
3259 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
3260 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
3261 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
3262 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
3263
3264 MHz_u m_frequency; ///< frequency
3265 MHz_u m_channelWidth; ///< channel width
3266 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
3267};
3268
3270 : TestCase("UL-OFDMA PHY test"),
3271 m_countRxSuccessFromSta1(0),
3272 m_countRxSuccessFromSta2(0),
3273 m_countRxFailureFromSta1(0),
3274 m_countRxFailureFromSta2(0),
3275 m_countRxBytesFromSta1(0),
3276 m_countRxBytesFromSta2(0),
3277 m_frequency(DEFAULT_FREQUENCY),
3278 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3279 m_expectedPpduDuration(NanoSeconds(271200))
3280{
3281}
3282
3283void
3285 std::size_t payloadSize,
3286 uint64_t uid,
3287 uint8_t bssColor)
3288{
3289 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3290 WifiConstPsduMap psdus;
3291
3292 WifiTxVector txVector{HePhy::GetHeMcs7(),
3293 0,
3295 NanoSeconds(800),
3296 1,
3297 1,
3298 0,
3300 false,
3301 false,
3302 false,
3303 bssColor};
3304
3305 auto pkt = Create<Packet>(payloadSize);
3306 WifiMacHeader hdr;
3308 hdr.SetQosTid(0);
3309 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3310 std::ostringstream addr;
3311 addr << "00:00:00:00:00:0" << txStaId;
3312 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3313 hdr.SetSequenceNumber(1);
3314 auto psdu = Create<WifiPsdu>(pkt, hdr);
3315 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3316
3318 if (txStaId == 1)
3319 {
3320 phy = m_phySta1;
3321 }
3322 else if (txStaId == 2)
3323 {
3324 phy = m_phySta2;
3325 }
3326 else if (txStaId == 3)
3327 {
3328 phy = m_phySta3;
3329 }
3330 else if (txStaId == 0)
3331 {
3332 phy = m_phyAp;
3333 }
3334 phy->SetPpduUid(uid);
3335 phy->Send(psdus, txVector);
3336}
3337
3340 std::size_t index,
3341 uint8_t bssColor) const
3342{
3343 WifiTxVector txVector{HePhy::GetHeMcs7(),
3344 0,
3346 NanoSeconds(1600),
3347 1,
3348 1,
3349 0,
3351 false,
3352 false,
3353 false,
3354 bssColor};
3355
3356 auto ruType = RuType::RU_106_TONE;
3357 if (m_channelWidth == MHz_u{20})
3358 {
3359 ruType = RuType::RU_106_TONE;
3360 }
3361 else if (m_channelWidth == MHz_u{40})
3362 {
3363 ruType = RuType::RU_242_TONE;
3364 }
3365 else if (m_channelWidth == MHz_u{80})
3366 {
3367 ruType = RuType::RU_484_TONE;
3368 }
3369 else if (m_channelWidth == MHz_u{160})
3370 {
3371 ruType = RuType::RU_996_TONE;
3372 }
3373 else
3374 {
3375 NS_ASSERT_MSG(false, "Unsupported channel width");
3376 }
3377
3378 auto primary80MHz{true};
3379 if (m_channelWidth == MHz_u{160} && index == 2)
3380 {
3381 primary80MHz = HeRu::GetPrimary80MHzFlag(m_channelWidth, ruType, index, 0);
3382 ;
3383 index = HeRu::GetIndexIn80MHzSegment(m_channelWidth, ruType, index);
3384 }
3385 HeRu::RuSpec ru(ruType, index, primary80MHz);
3386 txVector.SetRu(ru, txStaId);
3387 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3388 txVector.SetNss(1, txStaId);
3389 return txVector;
3390}
3391
3392void
3394{
3395 auto channelWidth = m_channelWidth;
3396 if (error == CHANNEL_WIDTH)
3397 {
3398 channelWidth = (channelWidth == MHz_u{160} ? MHz_u{20} : channelWidth * 2);
3399 }
3400
3401 WifiTxVector txVector(HePhy::GetHeMcs7(),
3402 0,
3404 NanoSeconds(1600),
3405 1,
3406 1,
3407 0,
3408 channelWidth,
3409 false,
3410 false,
3411 false,
3412 bssColor);
3413
3414 RuType ruType = RuType::RU_106_TONE;
3415 if (channelWidth == MHz_u{20})
3416 {
3417 ruType = RuType::RU_106_TONE;
3418 }
3419 else if (channelWidth == MHz_u{40})
3420 {
3421 ruType = RuType::RU_242_TONE;
3422 }
3423 else if (channelWidth == MHz_u{80})
3424 {
3425 ruType = RuType::RU_484_TONE;
3426 }
3427 else if (channelWidth == MHz_u{160})
3428 {
3429 ruType = RuType::RU_996_TONE;
3430 }
3431 else
3432 {
3433 NS_ASSERT_MSG(false, "Unsupported channel width");
3434 }
3435
3436 uint16_t aid1 = (error == AID ? 3 : 1);
3437 uint16_t aid2 = (error == AID ? 4 : 2);
3438
3439 HeRu::RuSpec ru1(ruType, 1, true);
3440 txVector.SetRu(ru1, aid1);
3441 txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3442 txVector.SetNss(1, aid1);
3443
3444 HeRu::RuSpec ru2(ruType, (channelWidth == MHz_u{160} ? 1 : 2), (channelWidth != MHz_u{160}));
3445 txVector.SetRu(ru2, aid2);
3446 txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3447 txVector.SetNss(1, aid2);
3448
3449 uint16_t length;
3450 std::tie(length, m_expectedPpduDuration) =
3452 txVector,
3453 m_phyAp->GetPhyBand());
3454 if (error == UL_LENGTH)
3455 {
3456 ++length;
3457 }
3458 txVector.SetLength(length);
3460 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3461}
3462
3463void
3465 std::size_t index,
3466 std::size_t payloadSize,
3467 uint64_t uid,
3468 uint8_t bssColor,
3469 bool incrementUid)
3470{
3471 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3472 WifiConstPsduMap psdus;
3473
3474 if (incrementUid)
3475 {
3476 ++uid;
3477 }
3478
3479 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3480 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3481 WifiMacHeader hdr;
3483 hdr.SetQosTid(0);
3484 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3485 std::ostringstream addr;
3486 addr << "00:00:00:00:00:0" << txStaId;
3487 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3488 hdr.SetSequenceNumber(1);
3489 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3490 psdus.insert(std::make_pair(txStaId, psdu));
3491
3493 if (txStaId == 1)
3494 {
3495 phy = m_phySta1;
3496 }
3497 else if (txStaId == 2)
3498 {
3499 phy = m_phySta2;
3500 }
3501 else if (txStaId == 3)
3502 {
3503 phy = m_phySta3;
3504 }
3505
3506 Time txDuration = OfdmaSpectrumWifiPhy::CalculateTxDuration(psdu->GetSize(),
3507 txVector,
3508 phy->GetPhyBand(),
3509 txStaId);
3510 txVector.SetLength(
3511 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3512
3513 phy->SetPpduUid(uid);
3514 phy->Send(psdus, txVector);
3515}
3516
3517void
3519{
3520 NS_LOG_FUNCTION(this << duration);
3521 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
3522 m_phyInterferer->SetPeriod(duration);
3523 m_phyInterferer->Start();
3525}
3526
3527void
3532
3536
3537void
3539 RxSignalInfo rxSignalInfo,
3540 const WifiTxVector& txVector,
3541 const std::vector<bool>& /*statusPerMpdu*/)
3542{
3543 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3544 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3545 {
3547 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3548 }
3549 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3550 {
3552 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3553 }
3554}
3555
3556void
3558{
3559 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3560 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3561 {
3563 }
3564 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3565 {
3567 }
3568}
3569
3570void
3572 uint32_t expectedFailures,
3573 uint32_t expectedBytes)
3574{
3576 expectedSuccess,
3577 "The number of successfully received packets from STA 1 is not correct!");
3580 expectedFailures,
3581 "The number of unsuccessfuly received packets from STA 1 is not correct!");
3583 expectedBytes,
3584 "The number of bytes received from STA 1 is not correct!");
3585}
3586
3587void
3589 uint32_t expectedFailures,
3590 uint32_t expectedBytes)
3591{
3593 expectedSuccess,
3594 "The number of successfully received packets from STA 2 is not correct!");
3597 expectedFailures,
3598 "The number of unsuccessfuly received packets from STA 2 is not correct!");
3600 expectedBytes,
3601 "The number of bytes received from STA 2 is not correct!");
3602}
3603
3604void
3607 Watt_u expectedRxPower)
3608{
3609 auto event = phy->GetCurrentEvent();
3610 NS_ASSERT(event);
3611 auto rxPower = event->GetRxPower(band);
3612 NS_LOG_FUNCTION(this << band << expectedRxPower << rxPower);
3613 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3615 expectedRxPower,
3616 Watt_u{5e-3},
3617 "RX power " << rxPower << " over (" << band
3618 << ") does not match expected power " << expectedRxPower
3619 << " at " << Simulator::Now());
3620}
3621
3622void
3625 Watt_u expectedRxPower)
3626{
3627 /**
3628 * The current event cannot be used since it points to the preamble part of the HE TB PPDU.
3629 * We will have to check if the expected power is indeed the max power returning a positive
3630 * duration when calling GetEnergyDuration.
3631 */
3632 NS_LOG_FUNCTION(this << band << expectedRxPower);
3633 Watt_u step{5e-3};
3634 if (expectedRxPower > Watt_u{0.0})
3635 {
3637 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3638 true,
3639 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3640 << Simulator::Now());
3642 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3643 false,
3644 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3645 << Simulator::Now());
3646 }
3647 else
3648 {
3650 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3651 false,
3652 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3653 << Simulator::Now());
3654 }
3655}
3656
3657void
3659{
3661 nullptr,
3662 "m_currentEvent for AP was not cleared");
3664 nullptr,
3665 "m_currentEvent for STA 1 was not cleared");
3667 nullptr,
3668 "m_currentEvent for STA 2 was not cleared");
3669}
3670
3671void
3673{
3674 // This is needed to make sure PHY state will be checked as the last event if a state change
3675 // occurred at the exact same time as the check
3677}
3678
3679void
3681 WifiPhyState expectedState)
3682{
3683 WifiPhyState currentState;
3684 PointerValue ptr;
3685 phy->GetAttribute("State", ptr);
3687 currentState = state->GetState();
3688 NS_LOG_FUNCTION(this << currentState);
3689 NS_TEST_ASSERT_MSG_EQ(currentState,
3690 expectedState,
3691 "PHY State " << currentState << " does not match expected state "
3692 << expectedState << " at " << Simulator::Now());
3693}
3694
3695void
3697 Time expectedLastNotification)
3698{
3700 expectedNotifications,
3701 "Number of RX start notifications "
3703 << " does not match expected count " << expectedNotifications
3704 << " for AP at " << Simulator::Now());
3706 expectedLastNotification,
3707 "Last time RX start notification has been received "
3709 << " does not match expected time " << expectedLastNotification
3710 << " for AP at " << Simulator::Now());
3711}
3712
3713void
3715 Time expectedLastNotification,
3716 bool expectedSuccess)
3717{
3719 expectedNotifications,
3720 "Number of RX end notifications "
3722 << " does not match expected count " << expectedNotifications
3723 << " for AP at " << Simulator::Now());
3725 expectedLastNotification,
3726 "Last time RX end notification has been received "
3728 << " does not match expected time " << expectedLastNotification
3729 << " for AP at " << Simulator::Now());
3731 expectedSuccess,
3732 "Last time RX end notification indicated a "
3733 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3734 << " but expected a " << (expectedSuccess ? "success" : "failure")
3735 << " for AP at " << Simulator::Now());
3736}
3737
3738void
3753
3754void
3756{
3757 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3758 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3759 heConfiguration->m_bssColor = bssColor;
3760}
3761
3762void
3764{
3765 NS_LOG_FUNCTION(this << phy << psdLimit);
3766 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3767}
3768
3769void
3771{
3774 lossModel->SetFrequency(m_frequency);
3775 spectrumChannel->AddPropagationLossModel(lossModel);
3778 spectrumChannel->SetPropagationDelayModel(delayModel);
3779
3780 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3782 preambleDetectionModel->SetAttribute(
3783 "MinimumRssi",
3785 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3786 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3787
3788 Ptr<Node> apNode = CreateObject<Node>();
3790 apDev->SetStandard(WIFI_STANDARD_80211ax);
3792 "Txop",
3793 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
3794 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3795 apDev->SetMac(apMac);
3798 apDev->SetHeConfiguration(heConfiguration);
3800 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3802 m_phyAp->SetErrorRateModel(apErrorModel);
3803 m_phyAp->SetDevice(apDev);
3804 m_phyAp->AddChannel(spectrumChannel);
3808 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3810 m_phyAp->SetMobility(apMobility);
3811 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3813 apDev->SetPhy(m_phyAp);
3814 apMac->SetWifiPhys({m_phyAp});
3815 apNode->AggregateObject(apMobility);
3816 apNode->AddDevice(apDev);
3817
3818 Ptr<Node> sta1Node = CreateObject<Node>();
3820 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
3821 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3824 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3826 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3827 m_phySta1->SetDevice(sta1Dev);
3828 m_phySta1->AddChannel(spectrumChannel);
3830 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3832 m_phySta1->SetMobility(sta1Mobility);
3833 sta1Dev->SetPhy(m_phySta1);
3834 sta1Node->AggregateObject(sta1Mobility);
3835 sta1Node->AddDevice(sta1Dev);
3836
3837 Ptr<Node> sta2Node = CreateObject<Node>();
3839 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
3840 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3843 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3845 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3846 m_phySta2->SetDevice(sta2Dev);
3847 m_phySta2->AddChannel(spectrumChannel);
3849 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3851 m_phySta2->SetMobility(sta2Mobility);
3852 sta2Dev->SetPhy(m_phySta2);
3853 sta2Node->AggregateObject(sta2Mobility);
3854 sta2Node->AddDevice(sta2Dev);
3855
3856 Ptr<Node> sta3Node = CreateObject<Node>();
3858 sta3Dev->SetStandard(WIFI_STANDARD_80211ax);
3859 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3862 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3864 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3865 m_phySta3->SetDevice(sta3Dev);
3866 m_phySta3->AddChannel(spectrumChannel);
3868 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3870 m_phySta3->SetMobility(sta3Mobility);
3871 sta3Dev->SetPhy(m_phySta3);
3872 sta3Node->AggregateObject(sta3Mobility);
3873 sta3Node->AddDevice(sta3Dev);
3874
3875 Ptr<Node> interfererNode = CreateObject<Node>();
3878 m_phyInterferer->SetDevice(interfererDev);
3879 m_phyInterferer->SetChannel(spectrumChannel);
3880 m_phyInterferer->SetDutyCycle(1);
3881 interfererNode->AddDevice(interfererDev);
3882
3883 // Configure power attributes of all wifi devices
3884 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3885 for (auto& phy : phys)
3886 {
3887 phy->SetAttribute("TxGain", DoubleValue(1.0));
3888 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3889 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3890 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3891 phy->SetAttribute("RxGain", DoubleValue(2.0));
3892 // test assumes no rejection power for simplicity
3893 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3894 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3895 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3896 }
3897}
3898
3899void
3901{
3902 m_phyAp->Dispose();
3903 m_phyAp = nullptr;
3904 m_phySta1->Dispose();
3905 m_phySta1 = nullptr;
3906 m_phySta2->Dispose();
3907 m_phySta2 = nullptr;
3908 m_phySta3->Dispose();
3909 m_phySta3 = nullptr;
3911 m_phyInterferer = nullptr;
3912}
3913
3914void
3916{
3917 NS_LOG_INFO(log);
3918}
3919
3920void
3922 bool solicited,
3923 WifiPhyState expectedStateAtEnd,
3924 uint32_t expectedSuccessFromSta1,
3925 uint32_t expectedFailuresFromSta1,
3926 uint32_t expectedBytesFromSta1,
3927 uint32_t expectedSuccessFromSta2,
3928 uint32_t expectedFailuresFromSta2,
3929 uint32_t expectedBytesFromSta2,
3930 bool scheduleTxSta1,
3931 Time ulTimeDifference,
3932 WifiPhyState expectedStateBeforeEnd,
3933 TrigVectorInfo error)
3934{
3935 static uint64_t uid = 0;
3936
3937 // AP sends an SU packet preceding HE TB PPDUs
3940 this,
3941 0,
3942 50,
3943 ++uid,
3944 0);
3945 if (!solicited)
3946 {
3947 // UID of TB PPDUs will be different than the one of the preceding frame
3948 ++uid;
3949 }
3950 else
3951 {
3953 }
3954 // STA1 and STA2 send MU UL PPDUs addressed to AP
3957 m_apPhyStateListener.get());
3958 if (scheduleTxSta1)
3959 {
3960 Simulator::Schedule(delay,
3962 this,
3963 1,
3964 1,
3965 1000,
3966 uid,
3967 0,
3968 false);
3969 }
3970 Simulator::Schedule(delay + ulTimeDifference,
3972 this,
3973 2,
3974 2,
3975 1001,
3976 uid,
3977 0,
3978 false);
3979
3980 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3983 this,
3984 m_phyAp,
3985 expectedStateBeforeEnd);
3986 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3988 this,
3989 m_phyAp,
3990 expectedStateAtEnd);
3991 // TODO: add checks on TX stop for STAs
3992
3993 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3994 expectedFailuresFromSta2 >
3995 0)
3996 {
3997 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3998 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3999 // The expected time at which the reception is started corresponds to the time at which the
4000 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
4001 const Time expectedPayloadStart = delay + MicroSeconds(48);
4002 // The expected time at which the reception is terminated corresponds to the time at which
4003 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
4004 // received HE TB PPDU and the last received HE TB PPDU.
4005 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
4006 // At the end of the transmission, verify that a single RX start notification shall have
4007 // been notified when the reception of the first HE RB PPDU starts.
4008 Simulator::Schedule(expectedPayloadEnd,
4010 this,
4011 1,
4012 Simulator::Now() + expectedPayloadStart);
4013 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
4014 // notification shall have been notified when the reception of the last HE RB PPDU ends
4015 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
4017 this,
4018 1,
4019 Simulator::Now() + expectedPayloadEnd,
4020 isSuccess);
4021 }
4022
4023 delay += MilliSeconds(100);
4024 // Check reception state from STA 1
4025 Simulator::Schedule(delay,
4027 this,
4028 expectedSuccessFromSta1,
4029 expectedFailuresFromSta1,
4030 expectedBytesFromSta1);
4031 // Check reception state from STA 2
4032 Simulator::Schedule(delay,
4034 this,
4035 expectedSuccessFromSta2,
4036 expectedFailuresFromSta2,
4037 expectedBytesFromSta2);
4038 // Verify events data have been cleared
4040
4041 delay += MilliSeconds(100);
4043}
4044
4045void
4047 Watt_u rxPowerNonOfdmaRu1,
4048 Watt_u rxPowerNonOfdmaRu2,
4049 Watt_u rxPowerOfdmaRu1,
4050 Watt_u rxPowerOfdmaRu2)
4051{
4052 const auto detectionDuration = WifiPhy::GetPreambleDetectionDuration();
4053 const auto txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
4054 const auto txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
4055 const auto hePhy = DynamicCast<const OfdmaTestHePhy>(m_phyAp->GetHePhy());
4056 const auto nonOfdmaDuration = hePhy->CalculateNonHeDurationForHeTb(txVectorSta2);
4057 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonHeDurationForHeTb(txVectorSta1));
4058
4059 std::vector<Watt_u> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
4060 std::vector<WifiSpectrumBandInfo> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
4061 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
4062 std::vector<Watt_u> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
4063 std::vector<WifiSpectrumBandInfo> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
4064 hePhy->GetRuBandForRx(txVectorSta2, 2)};
4065
4066 for (uint8_t i = 0; i < 2; ++i)
4067 {
4068 /**
4069 * Perform checks at AP
4070 */
4071 // Check received power on non-OFDMA portion
4073 delay + detectionDuration +
4074 NanoSeconds(1), // just after beginning of portion (once event is stored)
4076 this,
4077 m_phyAp,
4078 nonOfdmaBand[i],
4079 rxPowerNonOfdma[i]);
4080 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4082 this,
4083 m_phyAp,
4084 nonOfdmaBand[i],
4085 rxPowerNonOfdma[i]);
4086 // Check received power on OFDMA portion
4087 Simulator::Schedule(delay + nonOfdmaDuration +
4088 NanoSeconds(1), // just after beginning of portion
4090 this,
4091 m_phyAp,
4092 ofdmaBand[i],
4093 rxPowerOfdma[i]);
4095 NanoSeconds(1), // just before end of portion
4097 this,
4098 m_phyAp,
4099 ofdmaBand[i],
4100 rxPowerOfdma[i]);
4101
4102 /**
4103 * Perform checks for non-transmitting STA (STA 3).
4104 * Cannot use CheckNonOfdmaRxPower method since current event may be reset if
4105 * preamble not detected (e.g. not on primary).
4106 */
4107 // Check received power on non-OFDMA portion
4109 delay + detectionDuration +
4110 NanoSeconds(1), // just after beginning of portion (once event is stored)
4112 this,
4113 m_phySta3,
4114 nonOfdmaBand[i],
4115 rxPowerNonOfdma[i]);
4116 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4118 this,
4119 m_phySta3,
4120 nonOfdmaBand[i],
4121 rxPowerNonOfdma[i]);
4122 // Check received power on OFDMA portion
4123 Simulator::Schedule(delay + nonOfdmaDuration +
4124 NanoSeconds(1), // just after beginning of portion
4126 this,
4127 m_phySta3,
4128 ofdmaBand[i],
4129 rxPowerOfdma[i]);
4131 NanoSeconds(1), // just before end of portion
4133 this,
4134 m_phySta3,
4135 ofdmaBand[i],
4136 rxPowerOfdma[i]);
4137 }
4138
4139 if (rxPowerOfdmaRu1 != Watt_u{0.0})
4140 {
4141 /**
4142 * Perform checks for transmitting STA (STA 2) to ensure it has correctly logged
4143 * power received from other transmitting STA (STA 1).
4144 * Cannot use CheckNonOfdmaRxPower method since current event not set.
4145 */
4146 const auto rxPowerNonOfdmaSta1Only =
4147 (m_channelWidth >= MHz_u{40})
4148 ? rxPowerNonOfdma[0]
4149 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4150 // Check received power on non-OFDMA portion
4152 delay + detectionDuration +
4153 NanoSeconds(1), // just after beginning of portion (once event is stored)
4155 this,
4156 m_phySta2,
4157 nonOfdmaBand[0],
4158 rxPowerNonOfdmaSta1Only);
4159 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4161 this,
4162 m_phySta2,
4163 nonOfdmaBand[0],
4164 rxPowerNonOfdmaSta1Only);
4165 // Check received power on OFDMA portion
4166 Simulator::Schedule(delay + nonOfdmaDuration +
4167 NanoSeconds(1), // just after beginning of portion
4169 this,
4170 m_phySta2,
4171 ofdmaBand[0],
4172 rxPowerOfdma[0]);
4174 NanoSeconds(1), // just before end of portion
4176 this,
4177 m_phySta2,
4178 ofdmaBand[0],
4179 rxPowerOfdma[0]);
4180 }
4181}
4182
4183void
4185{
4188 int64_t streamNumber = 0;
4189 m_phyAp->AssignStreams(streamNumber);
4190 m_phySta1->AssignStreams(streamNumber);
4191 m_phySta2->AssignStreams(streamNumber);
4192 m_phySta3->AssignStreams(streamNumber);
4193
4194 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
4199 ->number;
4200
4209
4210 Time delay;
4212 delay += Seconds(1);
4213
4214 /**
4215 * In all the following tests, 2 HE TB PPDUs of the same UL MU transmission
4216 * are sent on RU 1 for STA 1 and RU 2 for STA 2.
4217 * The difference between solicited and unsolicited lies in that their PPDU
4218 * ID correspond to the one of the immediately preceding HE SU PPDU (thus
4219 * mimicking trigger frame reception).
4220 */
4221
4222 //---------------------------------------------------------------------------
4223 // Verify that both solicited HE TB PPDUs have been corrected received
4224 Simulator::Schedule(delay,
4226 this,
4227 "Reception of solicited HE TB PPDUs");
4228 ScheduleTest(delay,
4229 true,
4230 WifiPhyState::IDLE,
4231 1,
4232 0,
4233 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4234 1,
4235 0,
4236 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4237 delay += Seconds(1);
4238
4239 //---------------------------------------------------------------------------
4240 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4241 // corrected received
4243 delay,
4245 this,
4246 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4247 ScheduleTest(delay,
4248 true,
4249 WifiPhyState::IDLE,
4250 1,
4251 0,
4252 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4253 1,
4254 0,
4255 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4256 true,
4257 NanoSeconds(100));
4258 delay += Seconds(1);
4259
4260 //---------------------------------------------------------------------------
4261 // Verify that no unsolicited HE TB PPDU is received
4262 Simulator::Schedule(delay,
4264 this,
4265 "Dropping of unsolicited HE TB PPDUs");
4266 ScheduleTest(delay,
4267 false,
4268 WifiPhyState::IDLE,
4269 0,
4270 0,
4271 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4272 0,
4273 0,
4274 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4275 true,
4276 Seconds(0),
4277 WifiPhyState::CCA_BUSY);
4278 delay += Seconds(1);
4279
4280 //---------------------------------------------------------------------------
4281 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4282 Simulator::Schedule(delay,
4284 this,
4285 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4286 ScheduleTest(delay,
4287 true,
4288 WifiPhyState::IDLE,
4289 0,
4290 0,
4291 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4292 0,
4293 0,
4294 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4295 true,
4296 Seconds(0),
4297 WifiPhyState::CCA_BUSY,
4299 delay += Seconds(1);
4300
4301 //---------------------------------------------------------------------------
4302 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4303 Simulator::Schedule(delay,
4305 this,
4306 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4307 ScheduleTest(delay,
4308 true,
4309 WifiPhyState::IDLE,
4310 0,
4311 0,
4312 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4313 0,
4314 0,
4315 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4316 true,
4317 Seconds(0),
4318 WifiPhyState::CCA_BUSY,
4319 UL_LENGTH);
4320 delay += Seconds(1);
4321
4322 //---------------------------------------------------------------------------
4323 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4324 Simulator::Schedule(delay,
4326 this,
4327 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4328 ScheduleTest(delay,
4329 true,
4330 WifiPhyState::IDLE,
4331 0,
4332 0,
4333 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4334 0,
4335 0,
4336 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4337 true,
4338 Seconds(0),
4339 WifiPhyState::CCA_BUSY,
4340 AID);
4341 delay += Seconds(1);
4342
4343 //---------------------------------------------------------------------------
4344 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4345 // impacted
4347 delay,
4349 this,
4350 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4351 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4352 BandInfo bandInfo;
4353 bandInfo.fc = MHzToHz(m_frequency - (m_channelWidth / 4));
4354 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
4355 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
4356 Bands bands;
4357 bands.push_back(bandInfo);
4358
4359 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4360 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4361 Watt_u interferencePower{0.1};
4362 *interferencePsdRu1 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
4363
4366 this,
4367 interferencePsdRu1,
4368 MilliSeconds(100));
4370 delay,
4371 true,
4372 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4373 // interference
4374 0,
4375 1,
4376 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4377 1,
4378 0,
4379 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4380 delay += Seconds(1);
4381
4382 //---------------------------------------------------------------------------
4383 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4384 // impacted
4386 delay,
4388 this,
4389 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4390 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4391 bandInfo.fc = MHzToHz(m_frequency + (m_channelWidth / 4));
4392 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 4);
4393 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 4);
4394 bands.clear();
4395 bands.push_back(bandInfo);
4396
4397 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4398 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4399 *interferencePsdRu2 = interferencePower / (MHzToHz(m_channelWidth / 2) * 20);
4400
4403 this,
4404 interferencePsdRu2,
4405 MilliSeconds(100));
4406 ScheduleTest(delay,
4407 true,
4408 (m_channelWidth >= MHz_u{40})
4409 ? WifiPhyState::IDLE
4410 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4411 // generated in its primary channel
4412 1,
4413 0,
4414 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4415 0,
4416 1,
4417 0); // Reception of the PSDU from STA 2 should have failed (since interference
4418 // occupies RU 2)
4419 delay += Seconds(1);
4420
4421 //---------------------------------------------------------------------------
4422 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4423 // been impacted
4424 Simulator::Schedule(delay,
4426 this,
4427 "Reception of solicited HE TB PPDUs with interference on the full band "
4428 "during PSDU reception");
4429 // A strong non-wifi interference is generated on the full band during PSDU reception
4430 bandInfo.fc = MHzToHz(m_frequency);
4431 bandInfo.fl = bandInfo.fc - MHzToHz(m_channelWidth / 2);
4432 bandInfo.fh = bandInfo.fc + MHzToHz(m_channelWidth / 2);
4433 bands.clear();
4434 bands.push_back(bandInfo);
4435
4436 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4437 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4438 *interferencePsdAll = interferencePower / (MHzToHz(m_channelWidth) * 20);
4439
4442 this,
4443 interferencePsdAll,
4444 MilliSeconds(100));
4446 delay,
4447 true,
4448 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4449 // interference
4450 0,
4451 1,
4452 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4453 0,
4454 1,
4455 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4456 // 2)
4457 delay += Seconds(1);
4458
4459 //---------------------------------------------------------------------------
4460 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4461 // solicited HE TB PPDUs have been impacted if they are on the same
4462 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4463 Simulator::Schedule(delay,
4465 this,
4466 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4467 "1 during PSDU reception");
4468 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4471 this,
4472 3,
4473 1,
4474 1002,
4475 1,
4476 0,
4477 false);
4478 // Expected figures from STA 2
4479 uint32_t succ;
4480 uint32_t fail;
4481 uint32_t bytes;
4482 if (m_channelWidth > MHz_u{20})
4483 {
4484 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4485 // interference from STA 3 on distinct 20 MHz channel)
4486 succ = 1;
4487 fail = 0;
4488 bytes = 1001;
4489 }
4490 else
4491 {
4492 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4493 // same 20 MHz channel)
4494 succ = 0;
4495 fail = 1;
4496 bytes = 0;
4497 }
4498 ScheduleTest(delay,
4499 true,
4500 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4501 // interference on measurement channel width
4502 0,
4503 1,
4504 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4505 // STA 3 on same 20 MHz channel)
4506 succ,
4507 fail,
4508 bytes);
4509 delay += Seconds(1);
4510
4511 //---------------------------------------------------------------------------
4512 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4513 // solicited HE TB PPDUs have been impacted if they are on the same
4514 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4515 Simulator::Schedule(delay,
4517 this,
4518 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4519 "2 during PSDU reception");
4520 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4523 this,
4524 3,
4525 2,
4526 1002,
4527 1,
4528 0,
4529 false);
4530 // Expected figures from STA 1
4531 if (m_channelWidth > MHz_u{20})
4532 {
4533 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4534 // interference from STA 3 on distinct 20 MHz channel)
4535 succ = 1;
4536 fail = 0;
4537 bytes = 1000;
4538 }
4539 else
4540 {
4541 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4542 // same 20 MHz channel)
4543 succ = 0;
4544 fail = 1;
4545 bytes = 0;
4546 }
4547 ScheduleTest(delay,
4548 true,
4549 (m_channelWidth >= MHz_u{40})
4550 ? WifiPhyState::IDLE
4551 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4552 // TB PPDU on primary channel
4553 succ,
4554 fail,
4555 bytes,
4556 0,
4557 1,
4558 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4559 // STA 3 on same 20 MHz channel)
4560 delay += Seconds(1);
4561
4562 //---------------------------------------------------------------------------
4563 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4564 // impacted
4566 delay,
4568 this,
4569 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4570 // One HE SU arrives at AP during the 400ns window
4571 Simulator::Schedule(delay + NanoSeconds(300),
4573 this,
4574 3,
4575 1002,
4576 1,
4577 0);
4579 delay,
4580 true,
4581 WifiPhyState::IDLE,
4582 0,
4583 1,
4584 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4585 0,
4586 1,
4587 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4588 delay += Seconds(1);
4589
4590 //---------------------------------------------------------------------------
4591 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4592 // received
4593 Simulator::Schedule(delay,
4595 this,
4596 "Reception of solicited HE TB PPDU only on RU 2");
4597 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4598 // otherwise
4601 this,
4602 m_phySta3,
4603 (m_channelWidth >= MHz_u{40})
4604 ? WifiPhyState::IDLE
4605 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4606 // IDLE if HE TB PPDU on primary channel
4607 ScheduleTest(delay,
4608 true,
4609 WifiPhyState::IDLE,
4610 0,
4611 0,
4612 0, // No transmission scheduled for STA 1
4613 1,
4614 0,
4615 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4616 false,
4617 Seconds(0),
4618 WifiPhyState::RX); // Measurement channel is total channel width
4619 delay += Seconds(1);
4620
4621 //---------------------------------------------------------------------------
4622 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4623 Simulator::Schedule(delay,
4625 this,
4626 "Measure power for reception of HE TB PPDU only on RU 2");
4627 auto rxPower = DbmToW(
4628 dBm_u{19}); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4630 (m_channelWidth >= MHz_u{40}) ? Watt_u{0.0} : rxPower,
4631 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4632 Watt_u{0.0},
4633 rxPower);
4634 ScheduleTest(delay,
4635 true,
4636 WifiPhyState::IDLE,
4637 0,
4638 0,
4639 0, // No transmission scheduled for STA 1
4640 1,
4641 0,
4642 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4643 false,
4644 Seconds(0),
4645 WifiPhyState::RX); // Measurement channel is total channel width
4646 delay += Seconds(1);
4647
4648 //---------------------------------------------------------------------------
4649 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4650 // limitation enforced
4652 delay,
4654 this,
4655 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4656 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4657 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4658 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4660 this,
4661 m_phySta2,
4662 dBm_per_MHz_u{3});
4663
4664 rxPower = (m_channelWidth > MHz_u{40})
4665 ? DbmToW(dBm_u{19})
4666 : DbmToW(dBm_u{18.0103}); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4667 // transmitted only on one 20 MHz channel
4668 auto rxPowerOfdma = rxPower;
4669 if (m_channelWidth <= MHz_u{40})
4670 {
4671 rxPowerOfdma =
4672 (m_channelWidth == MHz_u{20})
4673 ? DbmToW(dBm_u{14.0309}) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4674 : DbmToW(dBm_u{18.0103}); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4675 }
4677 (m_channelWidth >= MHz_u{40}) ? Watt_u{0.0} : rxPower,
4678 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4679 Watt_u{0.0},
4680 rxPowerOfdma);
4681
4682 // Reset PSD limitation once HE TB has been sent
4685 this,
4686 m_phySta2,
4687 dBm_per_MHz_u{100});
4688 ScheduleTest(delay,
4689 true,
4690 WifiPhyState::IDLE,
4691 0,
4692 0,
4693 0, // No transmission scheduled for STA 1
4694 1,
4695 0,
4696 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4697 false,
4698 Seconds(0),
4699 WifiPhyState::RX); // Measurement channel is total channel width
4700 delay += Seconds(1);
4701
4702 //---------------------------------------------------------------------------
4703 // Measure the power of 2 solicited HE TB PPDU from both STAs
4704 Simulator::Schedule(delay,
4706 this,
4707 "Measure power for reception of HE TB PPDU on both RUs");
4708 rxPower = DbmToW(
4709 dBm_u{19}); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4710 const auto rxPowerNonOfdma =
4711 (m_channelWidth >= MHz_u{40})
4712 ? rxPower
4713 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4714 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4715 ScheduleTest(delay,
4716 true,
4717 WifiPhyState::IDLE,
4718 1,
4719 0,
4720 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4721 1,
4722 0,
4723 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4724 delay += Seconds(1);
4725
4726 //---------------------------------------------------------------------------
4727 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4728 // ongoing)
4729 Simulator::Schedule(delay,
4731 this,
4732 "Reception of an HE TB PPDU from another BSS");
4733 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4735 Simulator::Schedule(delay + MilliSeconds(100),
4737 this,
4738 3,
4739 1,
4740 1002,
4741 1,
4742 2,
4743 false);
4744
4745 // Verify events data have been cleared
4746 Simulator::Schedule(delay + MilliSeconds(200),
4748 this);
4749
4751 delay += Seconds(1);
4752
4753 //---------------------------------------------------------------------------
4754 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4755 // corrected received
4757 delay,
4759 this,
4760 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4761 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4765 this,
4766 3,
4767 1,
4768 1002,
4769 1,
4770 2,
4771 true);
4772 ScheduleTest(delay,
4773 true,
4774 WifiPhyState::CCA_BUSY,
4775 1,
4776 0,
4777 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4778 1,
4779 0,
4780 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4781 true,
4782 NanoSeconds(200));
4783 delay += Seconds(1);
4784
4786}
4787
4788void
4790{
4791 m_frequency = MHz_u{5180};
4792 m_channelWidth = MHz_u{20};
4794 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4795 RunOne();
4796
4797 m_frequency = MHz_u{5190};
4798 m_channelWidth = MHz_u{40};
4800 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4801 RunOne();
4802
4803 m_frequency = MHz_u{5210};
4804 m_channelWidth = MHz_u{80};
4806 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4807 RunOne();
4808
4809 m_frequency = MHz_u{5250};
4810 m_channelWidth = MHz_u{160};
4812 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4813 RunOne();
4814
4816}
4817
4818/**
4819 * @ingroup wifi-test
4820 * @ingroup tests
4821 *
4822 * @brief PHY padding exclusion test
4823 */
4825{
4826 public:
4828 ~TestPhyPaddingExclusion() override;
4829
4830 private:
4831 void DoSetup() override;
4832 void DoTeardown() override;
4833 void DoRun() override;
4834
4835 /**
4836 * Send HE TB PPDU function
4837 * @param txStaId the ID of the TX STA
4838 * @param index the RU index used for the transmission
4839 * @param payloadSize the size of the payload in bytes
4840 * @param txDuration the duration of the PPDU
4841 */
4842 void SendHeTbPpdu(uint16_t txStaId,
4843 std::size_t index,
4844 std::size_t payloadSize,
4845 Time txDuration);
4846 /**
4847 * Set TRIGVECTOR for HE TB PPDU
4848 *
4849 * @param ppduDuration the duration of the HE TB PPDU
4850 */
4851 void SetTrigVector(Time ppduDuration);
4852
4853 /**
4854 * Generate interference function
4855 * @param interferencePsd the PSD of the interference to be generated
4856 * @param duration the duration of the interference
4857 */
4858 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4859 /**
4860 * Stop interference function
4861 */
4862 void StopInterference();
4863
4864 /**
4865 * Run one function
4866 */
4867 void RunOne();
4868
4869 /**
4870 * Check the received PSDUs from STA1
4871 * @param expectedSuccess the expected number of success
4872 * @param expectedFailures the expected number of failures
4873 * @param expectedBytes the expected number of bytes
4874 */
4875 void CheckRxFromSta1(uint32_t expectedSuccess,
4876 uint32_t expectedFailures,
4877 uint32_t expectedBytes);
4878
4879 /**
4880 * Check the received PSDUs from STA2
4881 * @param expectedSuccess the expected number of success
4882 * @param expectedFailures the expected number of failures
4883 * @param expectedBytes the expected number of bytes
4884 */
4885 void CheckRxFromSta2(uint32_t expectedSuccess,
4886 uint32_t expectedFailures,
4887 uint32_t expectedBytes);
4888
4889 /**
4890 * Verify all events are cleared at end of TX or RX
4891 */
4892 void VerifyEventsCleared();
4893
4894 /**
4895 * Check the PHY state
4896 * @param phy the PHY
4897 * @param expectedState the expected state of the PHY
4898 */
4899 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
4900 /// @copydoc CheckPhyState
4902
4903 /**
4904 * Reset function
4905 */
4906 void Reset();
4907
4908 /**
4909 * Receive success function
4910 * @param psdu the PSDU
4911 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
4912 * @param txVector the transmit vector
4913 * @param statusPerMpdu reception status per MPDU
4914 */
4916 RxSignalInfo rxSignalInfo,
4917 const WifiTxVector& txVector,
4918 const std::vector<bool>& statusPerMpdu);
4919
4920 /**
4921 * Receive failure function
4922 * @param psdu the PSDU
4923 */
4924 void RxFailure(Ptr<const WifiPsdu> psdu);
4925
4929
4931
4932 uint32_t m_countRxSuccessFromSta1; ///< count RX success from STA 1
4933 uint32_t m_countRxSuccessFromSta2; ///< count RX success from STA 2
4934 uint32_t m_countRxFailureFromSta1; ///< count RX failure from STA 1
4935 uint32_t m_countRxFailureFromSta2; ///< count RX failure from STA 2
4936 uint32_t m_countRxBytesFromSta1; ///< count RX bytes from STA 1
4937 uint32_t m_countRxBytesFromSta2; ///< count RX bytes from STA 2
4938};
4939
4941 : TestCase("PHY padding exclusion test"),
4942 m_countRxSuccessFromSta1(0),
4943 m_countRxSuccessFromSta2(0),
4944 m_countRxFailureFromSta1(0),
4945 m_countRxFailureFromSta2(0),
4946 m_countRxBytesFromSta1(0),
4947 m_countRxBytesFromSta2(0)
4948{
4949}
4950
4951void
4953 std::size_t index,
4954 std::size_t payloadSize,
4955 Time txDuration)
4956{
4957 WifiConstPsduMap psdus;
4958
4959 WifiTxVector txVector{HePhy::GetHeMcs7(),
4960 0,
4962 NanoSeconds(1600),
4963 1,
4964 1,
4965 0,
4967 false,
4968 false,
4969 true};
4970
4971 HeRu::RuSpec ru(RuType::RU_106_TONE, index, false);
4972 txVector.SetRu(ru, txStaId);
4973 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4974 txVector.SetNss(1, txStaId);
4975
4976 auto pkt = Create<Packet>(payloadSize);
4977 WifiMacHeader hdr;
4979 hdr.SetQosTid(0);
4980 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4981 std::ostringstream addr;
4982 addr << "00:00:00:00:00:0" << txStaId;
4983 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4984 hdr.SetSequenceNumber(1);
4985 auto psdu = Create<WifiPsdu>(pkt, hdr);
4986 psdus.insert(std::make_pair(txStaId, psdu));
4987
4989 if (txStaId == 1)
4990 {
4991 phy = m_phySta1;
4992 }
4993 else if (txStaId == 2)
4994 {
4995 phy = m_phySta2;
4996 }
4997
4998 txVector.SetLength(
4999 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
5000
5001 phy->SetPpduUid(0);
5002 phy->Send(psdus, txVector);
5003}
5004
5005void
5007{
5008 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
5009 m_phyInterferer->SetPeriod(duration);
5010 m_phyInterferer->Start();
5012}
5013
5014void
5019
5023
5024void
5026 RxSignalInfo rxSignalInfo,
5027 const WifiTxVector& txVector,
5028 const std::vector<bool>& /*statusPerMpdu*/)
5029{
5030 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
5031 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
5032 {
5034 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
5035 }
5036 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
5037 {
5039 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
5040 }
5041}
5042
5043void
5045{
5046 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
5047 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
5048 {
5050 }
5051 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
5052 {
5054 }
5055}
5056
5057void
5059 uint32_t expectedFailures,
5060 uint32_t expectedBytes)
5061{
5063 expectedSuccess,
5064 "The number of successfully received packets from STA 1 is not correct!");
5067 expectedFailures,
5068 "The number of unsuccessfuly received packets from STA 1 is not correct!");
5070 expectedBytes,
5071 "The number of bytes received from STA 1 is not correct!");
5072}
5073
5074void
5076 uint32_t expectedFailures,
5077 uint32_t expectedBytes)
5078{
5080 expectedSuccess,
5081 "The number of successfully received packets from STA 2 is not correct!");
5084 expectedFailures,
5085 "The number of unsuccessfuly received packets from STA 2 is not correct!");
5087 expectedBytes,
5088 "The number of bytes received from STA 2 is not correct!");
5089}
5090
5091void
5093{
5095 nullptr,
5096 "m_currentEvent for AP was not cleared");
5098 nullptr,
5099 "m_currentEvent for STA 1 was not cleared");
5101 nullptr,
5102 "m_currentEvent for STA 2 was not cleared");
5103}
5104
5105void
5107{
5108 // This is needed to make sure PHY state will be checked as the last event if a state change
5109 // occurred at the exact same time as the check
5111}
5112
5113void
5115{
5116 WifiPhyState currentState = phy->GetState()->GetState();
5117 NS_LOG_FUNCTION(this << currentState);
5118 NS_TEST_ASSERT_MSG_EQ(currentState,
5119 expectedState,
5120 "PHY State " << currentState << " does not match expected state "
5121 << expectedState << " at " << Simulator::Now());
5122}
5123
5124void
5137
5138void
5140{
5143 int64_t streamNumber = 0;
5144
5147 lossModel->SetFrequency(MHzToHz(DEFAULT_FREQUENCY));
5148 spectrumChannel->AddPropagationLossModel(lossModel);
5151 spectrumChannel->SetPropagationDelayModel(delayModel);
5152
5153 Ptr<Node> apNode = CreateObject<Node>();
5156 "Txop",
5157 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
5158 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5159 apDev->SetMac(apMac);
5162 apDev->SetHeConfiguration(heConfiguration);
5164 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5166 m_phyAp->SetErrorRateModel(apErrorModel);
5167 m_phyAp->SetDevice(apDev);
5168 m_phyAp->AddChannel(spectrumChannel);
5170 m_phyAp->AssignStreams(streamNumber);
5171 auto channelNum = WifiPhyOperatingChannel::FindFirst(0,
5176 ->number;
5177
5183 m_phyAp->SetMobility(apMobility);
5184 apDev->SetPhy(m_phyAp);
5185 apDev->SetStandard(WIFI_STANDARD_80211ax);
5186 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5187 apMac->SetWifiPhys({m_phyAp});
5188 apNode->AggregateObject(apMobility);
5189 apNode->AddDevice(apDev);
5190
5191 Ptr<Node> sta1Node = CreateObject<Node>();
5195 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5197 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5198 m_phySta1->SetDevice(sta1Dev);
5199 m_phySta1->AddChannel(spectrumChannel);
5201 m_phySta1->AssignStreams(streamNumber);
5205 m_phySta1->SetMobility(sta1Mobility);
5206 sta1Dev->SetPhy(m_phySta1);
5207 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
5208 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5209 sta1Node->AggregateObject(sta1Mobility);
5210 sta1Node->AddDevice(sta1Dev);
5211
5212 Ptr<Node> sta2Node = CreateObject<Node>();
5216 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5218 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5219 m_phySta2->SetDevice(sta2Dev);
5220 m_phySta2->AddChannel(spectrumChannel);
5222 m_phySta2->AssignStreams(streamNumber);
5226 m_phySta2->SetMobility(sta2Mobility);
5227 sta2Dev->SetPhy(m_phySta2);
5228 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
5229 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5230 sta2Node->AggregateObject(sta2Mobility);
5231 sta2Node->AddDevice(sta2Dev);
5232
5233 Ptr<Node> interfererNode = CreateObject<Node>();
5236 m_phyInterferer->SetDevice(interfererDev);
5237 m_phyInterferer->SetChannel(spectrumChannel);
5238 m_phyInterferer->SetDutyCycle(1);
5239 interfererNode->AddDevice(interfererDev);
5240}
5241
5242void
5244{
5245 m_phyAp->Dispose();
5246 m_phyAp = nullptr;
5247 m_phySta1->Dispose();
5248 m_phySta1 = nullptr;
5249 m_phySta2->Dispose();
5250 m_phySta2 = nullptr;
5252 m_phyInterferer = nullptr;
5253}
5254
5255void
5257{
5258 WifiTxVector trigVector{HePhy::GetHeMcs7(),
5259 0,
5261 NanoSeconds(1600),
5262 1,
5263 1,
5264 0,
5266 false,
5267 false,
5268 true};
5269 trigVector.SetRu(HeRu::RuSpec(RuType::RU_106_TONE, 1, false), 1);
5270 trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5271 trigVector.SetNss(1, 1);
5272 trigVector.SetRu(HeRu::RuSpec(RuType::RU_106_TONE, 2, false), 2);
5273 trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5274 trigVector.SetNss(1, 2);
5275 uint16_t length;
5276 std::tie(length, ppduDuration) =
5278 trigVector.SetLength(length);
5280 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5281}
5282
5283void
5285{
5286 Time expectedPpduDuration = NanoSeconds(292800);
5287 Time ppduWithPaddingDuration =
5288 expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5289
5291
5292 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5295 this,
5296 1,
5297 1,
5298 1000,
5299 ppduWithPaddingDuration);
5302 this,
5303 2,
5304 2,
5305 1001,
5306 ppduWithPaddingDuration);
5307
5308 // Set TRIGVECTOR on AP
5311 this,
5312 ppduWithPaddingDuration);
5313
5314 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5315 Simulator::Schedule(Seconds(1) + ppduWithPaddingDuration - NanoSeconds(1),
5317 this,
5318 m_phyAp,
5319 WifiPhyState::RX);
5320 Simulator::Schedule(Seconds(1) + ppduWithPaddingDuration,
5322 this,
5323 m_phyAp,
5324 WifiPhyState::IDLE);
5325
5326 // One PSDU of 1000 bytes should have been successfully received from STA 1
5328 // One PSDU of 1001 bytes should have been successfully received from STA 2
5330 // Verify events data have been cleared
5332
5334
5335 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5338 this,
5339 1,
5340 1,
5341 1000,
5342 ppduWithPaddingDuration);
5345 this,
5346 2,
5347 2,
5348 1001,
5349 ppduWithPaddingDuration);
5350
5351 // Set TRIGVECTOR on AP
5354 this,
5355 ppduWithPaddingDuration);
5356
5357 // A strong non-wifi interference is generated on RU 1 during padding reception
5358 BandInfo bandInfo;
5360 bandInfo.fl = bandInfo.fc - MHzToHz(DEFAULT_CHANNEL_WIDTH / 4);
5361 bandInfo.fh = bandInfo.fc + MHzToHz(DEFAULT_CHANNEL_WIDTH / 4);
5362 Bands bands;
5363 bands.push_back(bandInfo);
5364
5365 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5366 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5367 Watt_u interferencePower{0.1};
5368 *interferencePsdRu1 = interferencePower / (MHzToHz(DEFAULT_CHANNEL_WIDTH / 2) * 20);
5369
5370 Simulator::Schedule(Seconds(2) + MicroSeconds(50) + expectedPpduDuration,
5372 this,
5373 interferencePsdRu1,
5374 MilliSeconds(100));
5375
5376 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5377 // CCA_BUSY instead of IDLE due to the interference)
5378 Simulator::Schedule(Seconds(2) + ppduWithPaddingDuration - NanoSeconds(1),
5380 this,
5381 m_phyAp,
5382 WifiPhyState::RX);
5383 Simulator::Schedule(Seconds(2) + ppduWithPaddingDuration,
5385 this,
5386 m_phyAp,
5387 WifiPhyState::CCA_BUSY);
5388
5389 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5390 // occupies RU 1 after payload, during PHY padding)
5392 // One PSDU of 1001 bytes should have been successfully received from STA 2
5394 // Verify events data have been cleared
5396
5398
5400
5402}
5403
5404/**
5405 * @ingroup wifi-test
5406 * @ingroup tests
5407 *
5408 * @brief UL-OFDMA power control test
5409 */
5411{
5412 public:
5414 ~TestUlOfdmaPowerControl() override;
5415
5416 private:
5417 void DoSetup() override;
5418 void DoTeardown() override;
5419 void DoRun() override;
5420
5421 /**
5422 * Send a MU BAR through the AP to the STAs listed in the provided vector.
5423 *
5424 * @param staIds the vector of STA-IDs of STAs to address the MU-BAR to
5425 */
5426 void SendMuBar(std::vector<uint16_t> staIds);
5427
5428 /**
5429 * Send a QoS Data packet to the destination station in order
5430 * to set up a block Ack session (so that the MU-BAR may have a reply).
5431 *
5432 * @param destination the address of the destination station
5433 */
5434 void SetupBa(Address destination);
5435
5436 /**
5437 * Run one simulation with an optional BA session set up phase.
5438 *
5439 * @param setupBa true if BA session should be set up (i.e. upon first run),
5440 * false otherwise
5441 */
5442 void RunOne(bool setupBa);
5443
5444 /**
5445 * Replace the AP's callback on its PHY's ReceiveOkCallback
5446 * by the ReceiveOkCallbackAtAp method.
5447 */
5449
5450 /**
5451 * Receive OK callback function at AP.
5452 * This method will be plugged into the AP PHY's ReceiveOkCallback once the
5453 * block Ack session has been set up. This is done in the Reset function.
5454 * @param psdu the PSDU
5455 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
5456 * @param txVector the TXVECTOR used for the packet
5457 * @param statusPerMpdu reception status per MPDU
5458 */
5460 RxSignalInfo rxSignalInfo,
5461 const WifiTxVector& txVector,
5462 const std::vector<bool>& statusPerMpdu);
5463
5464 uint8_t m_bssColor; ///< BSS color
5465
5466 Ptr<WifiNetDevice> m_apDev; ///< network device of AP
5467 Ptr<WifiNetDevice> m_sta1Dev; ///< network device of STA 1
5468 Ptr<WifiNetDevice> m_sta2Dev; ///< network device of STA 2
5469
5471
5472 dBm_u m_txPowerAp; ///< transmit power of AP
5473 dBm_u m_txPowerStart; ///< minimum transmission power for STAs
5474 dBm_u m_txPowerEnd; ///< maximum transmission power for STAs
5475 uint8_t m_txPowerLevels; ///< number of transmission power levels for STAs
5476
5477 dBm_u m_requestedRssiSta1; ///< requested RSSI from STA 1 at AP for HE TB PPDUs
5478 dBm_u m_requestedRssiSta2; ///< requested RSSI from STA 2 at AP for HE TB PPDUs
5479
5480 dBm_u m_rssiSta1; ///< expected RSSI from STA 1 at AP for HE TB PPDUs
5481 dBm_u m_rssiSta2; ///< expected RSSI from STA 2 at AP for HE TB PPDUs
5482
5483 dB_u m_tol; ///< tolerance between received and expected RSSIs
5484};
5485
5487 : TestCase("UL-OFDMA power control test"),
5488 m_bssColor(1),
5489 m_txPowerAp(dBm_u{0}),
5490 m_txPowerStart(dBm_u{0}),
5491 m_txPowerEnd(dBm_u{0}),
5492 m_txPowerLevels(0),
5493 m_requestedRssiSta1(dBm_u{0}),
5494 m_requestedRssiSta2(dBm_u{0}),
5495 m_rssiSta1(dBm_u{0}),
5496 m_rssiSta2(dBm_u{0}),
5497 m_tol(dB_u{0.1})
5498{
5499}
5500
5502{
5503 m_phyAp = nullptr;
5504 m_apDev = nullptr;
5505 m_sta1Dev = nullptr;
5506 m_sta2Dev = nullptr;
5507}
5508
5509void
5511{
5512 // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5513 Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5514 m_apDev->Send(pkt, destination, 0);
5515}
5516
5517void
5518TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5519{
5520 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5521
5522 // Build MU-BAR trigger frame
5523 CtrlTriggerHeader muBar;
5524 muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5525 muBar.SetMoreTF(true);
5526 muBar.SetCsRequired(true);
5528 muBar.SetGiAndLtfType(NanoSeconds(1600), 2);
5529 muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5530 muBar.SetUlSpatialReuse(60500);
5531
5532 RuType ru = (staIds.size() == 1) ? RuType::RU_242_TONE : RuType::RU_106_TONE;
5533 std::size_t index = 1;
5534 int8_t ulTargetRssi = -40; // will be overwritten
5535 for (const auto& staId : staIds)
5536 {
5538 ui.SetAid12(staId);
5539 ui.SetRuAllocation(HeRu::RuSpec{ru, index, true});
5540 ui.SetUlFecCodingType(true);
5541 ui.SetUlMcs(7);
5542 ui.SetUlDcm(false);
5543 ui.SetSsAllocation(1, 1);
5544 if (staId == 1)
5545 {
5546 ulTargetRssi = m_requestedRssiSta1;
5547 }
5548 else if (staId == 2)
5549 {
5550 ulTargetRssi = m_requestedRssiSta2;
5551 }
5552 else
5553 {
5554 NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5555 }
5556 ui.SetUlTargetRssi(ulTargetRssi);
5557
5560 bar.SetTidInfo(0);
5561 bar.SetStartingSequence(4095);
5563
5564 ++index;
5565 }
5566
5567 WifiTxVector tbTxVector{muBar.GetHeTbTxVector(staIds.front())};
5569 tbTxVector,
5571 .first);
5572
5573 WifiConstPsduMap psdus;
5574 WifiTxVector txVector{HePhy::GetHeMcs7(),
5575 0,
5577 NanoSeconds(800),
5578 1,
5579 1,
5580 0,
5582 false,
5583 false,
5584 false,
5585 m_bssColor};
5586
5587 auto bar = Create<Packet>();
5588 bar->AddHeader(muBar);
5589
5590 auto receiver = Mac48Address::GetBroadcast();
5591 if (staIds.size() == 1)
5592 {
5593 const auto aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5594 if (staIds.front() == aidSta1)
5595 {
5596 receiver = Mac48Address::ConvertFrom(m_sta1Dev->GetAddress());
5597 }
5598 else
5599 {
5600 NS_ASSERT(staIds.front() ==
5601 DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5602 receiver = Mac48Address::ConvertFrom(m_sta2Dev->GetAddress());
5603 }
5604 }
5605
5606 WifiMacHeader hdr;
5608 hdr.SetAddr1(receiver);
5609 hdr.SetAddr2(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5610 hdr.SetAddr3(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5611 hdr.SetDsNotTo();
5612 hdr.SetDsFrom();
5613 hdr.SetNoRetry();
5614 hdr.SetNoMoreFragments();
5615 auto psdu = Create<WifiPsdu>(bar, hdr);
5616
5617 auto nav = m_apDev->GetPhy()->GetSifs();
5618 const auto staId = staIds.front(); // either will do
5619 nav += SpectrumWifiPhy::CalculateTxDuration(GetBlockAckSize(BlockAckType::COMPRESSED),
5620 tbTxVector,
5622 staId);
5623 psdu->SetDuration(nav);
5624 psdus.insert(std::make_pair(SU_STA_ID, psdu));
5625
5626 m_phyAp->Send(psdus, txVector);
5627}
5628
5629void
5631 RxSignalInfo rxSignalInfo,
5632 const WifiTxVector& txVector,
5633 const std::vector<bool>& /*statusPerMpdu*/)
5634{
5635 NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5636 const auto rssi = rxSignalInfo.rssi;
5637 NS_ASSERT(psdu->GetNMpdus() == 1);
5638 const auto& hdr = psdu->GetHeader(0);
5639 NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5640 if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5641 {
5643 rssi,
5644 m_rssiSta1,
5645 m_tol,
5646 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5647 << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5648 }
5649 else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5650 {
5652 rssi,
5653 m_rssiSta2,
5654 m_tol,
5655 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5656 << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5657 }
5658 else
5659 {
5660 NS_ABORT_MSG("The receiver address is unknown");
5661 }
5662}
5663
5664void
5666{
5667 // Now that BA session has been established we can plug our method
5668 m_phyAp->SetReceiveOkCallback(
5670}
5671
5672void
5674{
5675 auto apNode = CreateObject<Node>();
5676 NodeContainer staNodes;
5677 staNodes.Create(2);
5678
5679 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5681 spectrumChannel->AddPropagationLossModel(lossModel);
5683 spectrumChannel->SetPropagationDelayModel(delayModel);
5684
5685 SpectrumWifiPhyHelper spectrumPhy;
5686 spectrumPhy.SetChannel(spectrumChannel);
5687 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5688 spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5689
5690 WifiHelper wifi;
5691 wifi.SetStandard(WIFI_STANDARD_80211ax);
5692 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5693 "DataMode",
5694 StringValue("HeMcs7"),
5695 "ControlMode",
5696 StringValue("HeMcs7"));
5697
5698 WifiMacHelper mac;
5699 mac.SetType("ns3::StaWifiMac");
5700 auto staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5701 WifiHelper::AssignStreams(staDevs, 0);
5702 m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5704 m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5706
5707 // Set the beacon interval long enough so that associated STAs may not consider link lost when
5708 // beacon generation is disabled during the actual tests. Having such a long interval also
5709 // avoids bloating logs with beacons during the set up phase.
5710 mac.SetType("ns3::ApWifiMac",
5711 "BeaconGeneration",
5712 BooleanValue(true),
5713 "BeaconInterval",
5714 TimeValue(MicroSeconds(1024 * 600)));
5715 m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5717 m_apDev->GetHeConfiguration()->m_bssColor = m_bssColor;
5720 // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5721 // set up for both STAs
5722
5723 MobilityHelper mobility;
5724 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5725 auto positionAlloc = CreateObject<ListPositionAllocator>();
5726 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5727 positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5728 positionAlloc->Add(
5729 Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5730 mobility.SetPositionAllocator(positionAlloc);
5731
5732 mobility.Install(apNode);
5733 mobility.Install(staNodes);
5734
5735 lossModel->SetDefaultLoss(50.0);
5736 lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5737 staNodes.Get(1)->GetObject<MobilityModel>(),
5738 56.0,
5739 true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5740}
5741
5742void
5744{
5745 m_phyAp->Dispose();
5746 m_phyAp = nullptr;
5747 m_apDev->Dispose();
5748 m_apDev = nullptr;
5749 m_sta1Dev->Dispose();
5750 m_sta1Dev = nullptr;
5751 m_sta2Dev->Dispose();
5752 m_sta2Dev = nullptr;
5753}
5754
5755void
5757{
5760 int64_t streamNumber = 0;
5761
5762 auto phySta1 = m_sta1Dev->GetPhy();
5763 auto phySta2 = m_sta2Dev->GetPhy();
5764
5765 m_phyAp->AssignStreams(streamNumber);
5766 phySta1->AssignStreams(streamNumber);
5767 phySta2->AssignStreams(streamNumber);
5768
5769 m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5770 m_phyAp->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerAp));
5771 m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5772
5773 phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5774 phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5775 phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5776
5777 phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5778 phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5779 phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5780
5781 Time relativeStart{};
5782 if (setupBa)
5783 {
5784 // Set up BA for each station once the association phase has ended
5785 // so that a BA session is established when the MU-BAR is received.
5788 this,
5789 m_sta1Dev->GetAddress());
5792 this,
5793 m_sta2Dev->GetAddress());
5794 relativeStart = MilliSeconds(1000);
5795 }
5796 else
5797 {
5798 auto apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5799 NS_ASSERT(apMac);
5800 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5801 }
5802
5803 Simulator::Schedule(relativeStart,
5805 this);
5806
5807 {
5808 // Verify that the RSSI from STA 1 is consistent with what was requested
5809 std::vector<uint16_t> staIds{1};
5810 Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5811 }
5812
5813 {
5814 // Verify that the RSSI from STA 2 is consistent with what was requested
5815 std::vector<uint16_t> staIds{2};
5816 Simulator::Schedule(relativeStart + MilliSeconds(20),
5818 this,
5819 staIds);
5820 }
5821
5822 {
5823 // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5824 std::vector<uint16_t> staIds{1, 2};
5825 Simulator::Schedule(relativeStart + MilliSeconds(40),
5827 this,
5828 staIds);
5829 }
5830
5831 Simulator::Stop(relativeStart + MilliSeconds(100));
5833}
5834
5835void
5837{
5838 // Power configurations
5839 m_txPowerAp = dBm_u{20}; // so as to have -30 and -36 dBm at STA 1 and STA 2 resp., since path
5840 // loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5841 m_txPowerStart = dBm_u{15};
5842
5843 // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5846
5847 // Test single power level
5848 {
5849 // STA power configurations: 15 dBm only
5850 m_txPowerEnd = dBm_u{15};
5851 m_txPowerLevels = 1;
5852
5853 // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5854 // regardless of the estimated path loss.
5855 m_rssiSta1 = dBm_u{-35}; // 15 dBm - 50 dB
5856 m_rssiSta2 = dBm_u{-41}; // 15 dBm - 56 dB
5857
5858 RunOne(true);
5859 }
5860
5861 // Test 2 dBm granularity
5862 {
5863 // STA power configurations: [15:2:25] dBm
5864 m_txPowerEnd = dBm_u{25};
5865 m_txPowerLevels = 6;
5866
5867 // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5868 // requested
5869 m_rssiSta1 = dBm_u{-29}; // 21 dBm - 50 dB
5870 m_rssiSta2 = dBm_u{-35}; // 21 dBm - 50 dB
5871
5872 RunOne(false);
5873 }
5874
5875 // Test 1 dBm granularity
5876 {
5877 // STA power configurations: [15:1:25] dBm
5878 m_txPowerEnd = dBm_u{25};
5879 m_txPowerLevels = 11;
5880
5881 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5882 m_rssiSta1 = dBm_u{-30}; // 20 dBm - 50 dB
5883 m_rssiSta2 = dBm_u{-36}; // 20 dBm - 56 dB
5884
5885 RunOne(false);
5886 }
5887
5888 // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5889 {
5890 // STA power configurations: [15:1:25] dBm
5891 m_txPowerEnd = dBm_u{25};
5892 m_txPowerLevels = 11;
5893
5894 // Requested UL RSSIs
5896 dBm_u{-28}; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5897 m_requestedRssiSta2 = dBm_u{-37}; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5898
5899 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5900 m_rssiSta1 = dBm_u{-28}; // 22 dBm - 50 dB
5901 m_rssiSta2 = dBm_u{-37}; // 19 dBm - 56 dB
5902
5903 RunOne(false);
5904 }
5905
5907}
5908
5909/**
5910 * @ingroup wifi-test
5911 * @ingroup tests
5912 *
5913 * @brief wifi PHY OFDMA Test Suite
5914 */
5916{
5917 public:
5919};
5920
5922 : TestSuite("wifi-phy-ofdma", Type::UNIT)
5923{
5924 AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5925 AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::Duration::QUICK);
5926 AddTestCase(new TestUlOfdmaPpduUid, TestCase::Duration::QUICK);
5927 AddTestCase(new TestMultipleHeTbPreambles, TestCase::Duration::QUICK);
5928 AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::Duration::QUICK);
5929 AddTestCase(new TestPhyPaddingExclusion, TestCase::Duration::QUICK);
5930 AddTestCase(new TestUlOfdmaPowerControl, TestCase::Duration::QUICK);
5931}
5932
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_ofdmaTestHePhy
Pointer to HE PHY instance used for OFDMA test.
void StartTx(Ptr< const WifiPpdu > ppdu) override
void DoDispose() override
Destructor implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
void Reset()
Reset data upon end of TX or RX.
Definition wifi-phy.cc:1968
TracedCallback< uint64_t > m_phyTxPpduUidTrace
Callback providing UID of the PPDU that is about to be transmitted.
void DoInitialize() override
Initialize() implementation.
Time GetEnergyDuration(Watt_u energy, WifiSpectrumBandInfo band)
Wrapper to InterferenceHelper method.
HE PHY slightly modified so as to return a given STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
OfdmaTestHePhy(uint16_t staId)
Constructor.
void SetGlobalPpduUid(uint64_t uid)
Set the global PPDU UID counter.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
uint16_t m_staId
ID of the STA to which this PHY belongs to.
WifiSpectrumBandInfo GetNonOfdmaBand(const WifiTxVector &txVector, uint16_t staId) const
Get the band used to transmit the non-OFDMA part of an HE TB PPDU.
PHY listener for OFDMA tests.
OfdmaTestPhyListener()=default
void NotifyRxEndError() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
bool m_lastRxSuccess
flag whether last RX has been successful
void NotifyRxStart(Time duration) override
Time GetLastRxStartNotification() const
Return the time at which the last RX start notification has been received.
void NotifySwitchingStart(Time duration) override
void NotifyWakeup() override
Notify listeners that we woke up.
uint32_t m_notifyRxStart
count number of RX start notifications
void Reset()
Reset function.
Time m_lastRxEnd
last time a RX end notification has been received
Time m_lastRxStart
last time a RX start notification has been received
Time GetLastRxEndNotification() const
Return the time at which the last RX end notification has been received.
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &) override
uint32_t m_notifyRxEnd
count number of RX end notifications
bool IsLastRxSuccess() const
Return whether last RX has been successful.
void NotifySleep() override
Notify listeners that we went to sleep.
uint32_t GetNumRxEndNotifications() const
Return the number of RX end notifications that has been received since the last reset.
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyTxStart(Time duration, dBm_u txPower) override
uint32_t GetNumRxStartNotifications() const
Return the number of RX start notifications that has been received since the last reset.
void NotifyOff() override
Notify listeners that we went to switch off.
void NotifyOn() override
Notify listeners that we went to switch on.
DL-OFDMA PHY puncturing test.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void DoRun() override
Implementation to actually run this TestCase.
Time m_expectedPpduDuration20Mhz
expected duration to send MU PPDU on 20 MHz RU
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
void ResetResults()
Reset the results.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
void RunOne()
Run one function.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2, const std::vector< bool > &puncturedSubchannels)
Send MU-PPDU function.
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 2.
Time m_expectedPpduDuration40Mhz
expected duration to send MU PPDU on 40 MHz RU
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void StopInterference()
Stop interference function.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 1.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint8_t m_indexSubchannel
Index of the subchannel (starting from 0) that should contain an interference and be punctured during...
uint32_t m_countRxSuccessSta1
count RX success for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 2.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
void RunOne()
Run one function.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 1.
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Time m_expectedPpduDuration
expected duration to send MU PPDU
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void RxSuccessSta3(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 3.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
uint32_t m_countRxSuccessSta3
count RX success for STA 3
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
uint32_t m_countRxBytesSta3
count RX bytes for STA 3
void RxFailureSta3(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 3.
void StopInterference()
Stop interference function.
void ResetResults()
Reset the results.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxSuccessSta1
count RX success for STA 1
void CheckResultsSta3(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 3.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
Send MU-PPDU function.
UL-OFDMA multiple RX events test.
WifiTxVector m_trigVector
TRIGVECTOR.
void RxHeTbPpdu(uint64_t uid, uint16_t staId, Watt_u txPower, size_t payloadSize)
Receive HE TB PPDU function.
Ptr< OfdmaSpectrumWifiPhy > m_phy
Phy.
void RxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void CheckHeTbPreambles(size_t nEvents, std::vector< uint64_t > uids)
Check the received HE TB preambles.
uint64_t m_totalBytesDropped
total number of dropped bytes
void CheckBytesDropped(size_t expectedBytesDropped)
Check the number of bytes dropped.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
PHY padding exclusion test.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
void DoRun() override
Implementation to actually run this TestCase.
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
void SetTrigVector(Time ppduDuration)
Set TRIGVECTOR for HE TB PPDU.
void Reset()
Reset function.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
void StopInterference()
Stop interference function.
void RunOne()
Run one function.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void ScheduleTest(Time delay, bool solicited, WifiPhyState expectedStateAtEnd, uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1, uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2, bool scheduleTxSta1=true, Time ulTimeDifference=Seconds(0), WifiPhyState expectedStateBeforeEnd=WifiPhyState::RX, TrigVectorInfo error=NONE)
Schedule test to perform.
std::shared_ptr< OfdmaTestPhyListener > m_apPhyStateListener
listener for AP PHY state transitions
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId, std::size_t index, uint8_t bssColor) const
Get TXVECTOR for HE TB PPDU.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification)
Check the the number of RX start notifications at the AP as well as the last time a RX start has been...
TrigVectorInfo
Erroneous info included in a TRIGVECTOR.
void SetBssColor(Ptr< WifiPhy > phy, uint8_t bssColor)
Set the BSS color.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void LogScenario(std::string log) const
Log scenario description.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor, bool incrementUid)
Send HE TB PPDU function.
void DoRun() override
Implementation to actually run this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void StopInterference()
Stop interference function.
void CheckOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, Watt_u expectedRxPower)
Check the received power for the OFDMA part of the HE TB PPDUs over the given band.
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void SetPsdLimit(Ptr< WifiPhy > phy, dBm_per_MHz_u psdLimit)
Set the PSD limit.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
void RunOne()
Run one function.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void CheckApRxEnd(uint32_t expectedNotifications, Time expectedLastNotification, bool expectedSuccess)
Check the the number of RX end notifications at the AP as well as the last time a RX end has been not...
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
void CheckNonOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, Watt_u expectedRxPower)
Check the received power for the non-OFDMA of the HE TB PPDUs over the given band.
void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE SU PPDU function.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void SetTrigVector(uint8_t bssColor, TrigVectorInfo error)
Set TRIGVECTOR for HE TB PPDU.
void SchedulePowerMeasurementChecks(Time delay, Watt_u rxPowerNonOfdmaRu1, Watt_u rxPowerNonOfdmaRu2, Watt_u rxPowerOfdmaRu1, Watt_u rxPowerOfdmaRu2)
Schedule power measurement related checks.
Time m_expectedPpduDuration
expected duration to send MU PPDU
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
UL-OFDMA power control test.
dBm_u m_requestedRssiSta2
requested RSSI from STA 2 at AP for HE TB PPDUs
void DoRun() override
Implementation to actually run this TestCase.
Ptr< WifiNetDevice > m_sta2Dev
network device of STA 2
dBm_u m_rssiSta2
expected RSSI from STA 2 at AP for HE TB PPDUs
dBm_u m_txPowerEnd
maximum transmission power for STAs
dBm_u m_txPowerStart
minimum transmission power for STAs
void SetupBa(Address destination)
Send a QoS Data packet to the destination station in order to set up a block Ack session (so that the...
Ptr< WifiNetDevice > m_sta1Dev
network device of STA 1
dBm_u m_rssiSta1
expected RSSI from STA 1 at AP for HE TB PPDUs
Ptr< WifiNetDevice > m_apDev
network device of AP
dBm_u m_requestedRssiSta1
requested RSSI from STA 1 at AP for HE TB PPDUs
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void ReplaceReceiveOkCallbackOfAp()
Replace the AP's callback on its PHY's ReceiveOkCallback by the ReceiveOkCallbackAtAp method.
dBm_u m_txPowerAp
transmit power of AP
uint8_t m_txPowerLevels
number of transmission power levels for STAs
dB_u m_tol
tolerance between received and expected RSSIs
void RunOne(bool setupBa)
Run one simulation with an optional BA session set up phase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void ReceiveOkCallbackAtAp(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive OK callback function at AP.
void SendMuBar(std::vector< uint16_t > staIds)
Send a MU BAR through the AP to the STAs listed in the provided vector.
UL-OFDMA PPDU UID attribution test.
void TxPpduSta1(uint64_t uid)
Transmitted PPDU information function for STA 1.
void ResetPpduUid()
Reset the global PPDU UID counter in WifiPhy.
void CheckUid(uint16_t staId, uint64_t expectedUid)
Check the UID of the transmitted PPDU.
void TxPpduAp(uint64_t uid)
Transmitted PPDU information function for AP.
void TxPpduSta2(uint64_t uid)
Transmitted PPDU information function for STA 2.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
uint64_t m_ppduUidAp
UID of PPDU transmitted by AP.
uint64_t m_ppduUidSta1
UID of PPDU transmitted by STA1.
uint64_t m_ppduUidSta2
UID of PPDU transmitted by STA2.
void DoRun() override
Implementation to actually run this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu()
Send MU-PPDU toward both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendTbPpdu()
Send TB-PPDU from both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
void SendSuPpdu(uint16_t txStaId)
Send SU-PPDU function.
wifi PHY OFDMA Test Suite
a polymophic address class
Definition address.h:90
AttributeValue implementation for Boolean.
Definition boolean.h:26
Headers for BlockAckRequest.
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
Headers for Trigger frames.
CtrlTriggerUserInfoField & AddUserInfoField()
Append a new User Info field to this Trigger frame and return a non-const reference to it.
void SetApTxPower(int8_t power)
Set the AP TX Power subfield of the Common Info field.
WifiTxVector GetHeTbTxVector(uint16_t staId) const
Get the TX vector that the station with the given STA-ID will use to send the HE TB PPDU solicited by...
void SetType(TriggerFrameType type)
Set the Trigger frame type.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse subfield of the Common Info field.
void SetGiAndLtfType(Time guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
void SetMoreTF(bool more)
Set the More TF subfield of the Common Info field.
void SetUlBandwidth(MHz_u bw)
Set the bandwidth of the solicited HE TB PPDU.
User Info field of Trigger frames.
void SetAid12(uint16_t aid)
Set the AID12 subfield, which carries the 12 LSBs of the AID of the station for which this User Info ...
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
void SetUlMcs(uint8_t mcs)
Set the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
void SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader &bar)
Set the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlDcm(bool dcm)
Set the UL DCM subfield, which indicates whether or not DCM is used.
void SetSsAllocation(uint8_t startingSs, uint8_t nSs)
Set the SS Allocation subfield, which is present when the AID12 subfield is neither 0 nor 2045.
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
void SetRuAllocation(WifiRu::RuSpec ru)
Set the RU Allocation subfield according to the specified RU.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
PHY entity for HE (11ax)
Definition he-phy.h:58
static WifiMode GetHeMcs9()
Return MCS 9 from HE MCS values.
MHz_u GetNonOfdmaWidth(WifiRu::RuSpec ru) const
Get the width of the non-OFDMA portion of an HE TB PPDU.
Definition he-phy.cc:1047
static std::vector< WifiSpectrumBandIndices > ConvertHeRuSubcarriers(MHz_u bandWidth, MHz_u guardBandwidth, const std::vector< MHz_u > &centerFrequencies, MHz_u totalWidth, Hz_u subcarrierSpacing, SubcarrierRange subcarrierRange, uint8_t bandIndex=0)
Definition he-phy.cc:1822
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:566
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:262
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Definition he-ppdu.h:106
@ PSD_NON_HE_PORTION
Non-HE portion of an HE PPDU.
Definition he-ppdu.h:105
RU Specification.
Definition he-ru.h:37
static std::size_t GetIndexIn80MHzSegment(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the index of a given RU transmitted in a PPDU within its 80 MHz segment.
Definition he-ru.cc:475
static SubcarrierGroup GetSubcarrierGroup(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the subcarrier group of the RU having the given PHY index among all the RUs of the given type (nu...
Definition he-ru.cc:592
static bool GetPrimary80MHzFlag(MHz_u bw, RuType ruType, std::size_t phyIndex, uint8_t p20Index)
Get the primary 80 MHz flag of a given RU transmitted in a PPDU.
Definition he-ru.cc:462
an EUI-48 address
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
void Dispose()
Dispose of this Object.
Definition object.cc:247
MHz_u GetGuardBandwidth(MHz_u currentChannelWidth) const
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition phy-entity.h:948
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition phy-entity.cc:82
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition phy-entity.h:974
AttributeValue implementation for Pointer.
Ptr< T > Get() const
Definition pointer.h:223
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:595
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Make it easy to create and manage PHY objects for the spectrum model.
void SetChannel(const Ptr< SpectrumChannel > channel)
802.11 PHY layer model
void SetDevice(const Ptr< WifiNetDevice > device) override
Sets the device this PHY is associated with.
void StartRx(Ptr< SpectrumSignalParameters > rxParams, Ptr< const WifiSpectrumPhyInterface > interface)
Input method for delivering a signal from the spectrum channel and low-level PHY interface to this Sp...
void DoInitialize() override
Initialize() implementation.
MHz_u GetGuardBandwidth(MHz_u currentChannelWidth) const override
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
void DoDispose() override
Destructor implementation.
void StartTx(Ptr< const WifiPpdu > ppdu) override
Hold variables of type string.
Definition string.h:45
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
AttributeValue implementation for Time.
Definition nstime.h:1432
Forward calls to a chain of Callback.
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
Implements the IEEE 802.11 MAC header.
void SetNoMoreFragments()
Un-set the More Fragment bit in the Frame Control Field.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetDsFrom()
Set the From DS bit in the Frame Control field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetNoRetry()
Un-set the Retry bit in the Frame Control field.
create MAC layers for a ns3::WifiNetDevice.
void Set(std::string name, const AttributeValue &v)
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition wifi-phy.cc:679
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:1821
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition wifi-phy.cc:688
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > m_currentPreambleEvents
store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is be...
Definition wifi-phy.h:1361
Hz_u GetSubcarrierSpacing() const
Definition wifi-phy.cc:2388
std::tuple< uint8_t, MHz_u, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying a segment of an operating channel.
Definition wifi-phy.h:940
static Time GetPreambleDetectionDuration()
Definition wifi-phy.cc:1529
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition wifi-phy.cc:485
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition wifi-phy.cc:1010
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1588
virtual WifiSpectrumBandFrequencies ConvertIndicesToFrequencies(const WifiSpectrumBandIndices &indices) const =0
This is a helper function to convert start and stop indices to start and stop frequencies.
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition wifi-phy.h:1384
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition wifi-phy.cc:491
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition wifi-phy.cc:1070
Ptr< Event > m_currentEvent
Hold the current event.
Definition wifi-phy.h:1359
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:761
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition wifi-phy.h:1364
MHz_u GetChannelWidth() const
Definition wifi-phy.cc:1100
void SetOperatingChannel(const WifiPhyOperatingChannel &channel)
If the standard for this object has not been set yet, store the channel settings corresponding to the...
Definition wifi-phy.cc:1136
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition wifi-phy.cc:709
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition wifi-phy.cc:654
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition wifi-phy.h:1346
void SetReceiveOkCallback(RxOkCallback callback)
Definition wifi-phy.cc:479
void Reset()
Reset data upon end of TX or RX.
Definition wifi-phy.cc:1968
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition wifi-phy.cc:1082
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition wifi-phy.cc:776
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:2364
receive notifications about PHY events.
uint8_t GetPrimaryChannelIndex(MHz_u primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
std::vector< MHz_u > GetFrequencies() const
Return the center frequency per segment.
static ConstIterator FindFirst(uint8_t number, MHz_u frequency, MHz_u width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first frequency segment matching the specified parameters.
This objects implements the PHY state machine of the Wifi device.
static RuSpec FindOverlappingRu(MHz_u bw, RuSpec referenceRu, RuType searchedRuType)
Find the RU allocation of the given RU type overlapping the given reference RU allocation.
Definition wifi-ru.cc:226
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition wifi-ru.cc:78
static RuType GetRuType(RuSpec ru)
Get the type of a given RU.
Definition wifi-ru.cc:45
static std::size_t GetPhyIndex(RuSpec ru, MHz_u bw, uint8_t p20Index)
Get the RU PHY index.
Definition wifi-ru.cc:57
static Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(const std::vector< MHz_u > &centerFrequencies, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, const std::vector< WifiSpectrumBandIndices > &ru)
Create a transmit power spectral density corresponding to the OFDMA part of HE TB PPDUs for a given R...
static Ptr< SpectrumValue > CreateHeOfdmTxPowerSpectralDensity(MHz_u centerFrequency, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, dBr_u minInnerBand=dBr_u{-20}, dBr_u minOuterband=dBr_u{-28}, dBr_u lowestPoint=dBr_u{-40}, const std::vector< bool > &puncturedSubchannels={})
Create a transmit power spectral density corresponding to OFDM High Efficiency (HE) (802....
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
void SetRu(WifiRu::RuSpec ru, uint16_t staId)
Set the RU specification for the STA-ID.
WifiPreamble GetPreambleType() const
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
MHz_u GetChannelWidth() const
WifiRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition test.h:327
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPhyBand
Identifies the PHY band.
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Definition first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
WifiPhyState
The state of the PHY layer.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
std::vector< BandInfo > Bands
Container of BandInfo.
RuType
The different Resource Unit (RU) types.
Definition wifi-types.h:98
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
Definition wifi-utils.h:135
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_CTL_BACKRESP
@ WIFI_MAC_QOSDATA
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
Definition wifi-utils.cc:33
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
Definition wifi-utils.cc:60
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
Definition wifi-utils.h:110
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
std::vector< uint16_t > RuAllocation
9 bits RU_ALLOCATION per 20 MHz
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:78
dBm_u rssi
RSSI.
Definition wifi-types.h:80
WifiSpectrumBandInfo structure containing info about a spectrum band.
std::vector< WifiSpectrumBandIndices > indices
the start and stop indices for each segment of the band
static const MHz_u DEFAULT_FREQUENCY
static WifiPhyOfdmaTestSuite wifiPhyOfdmaTestSuite
the test suite
static const uint8_t DEFAULT_CHANNEL_NUMBER
static const WifiPhyBand DEFAULT_WIFI_BAND
static const MHz_u DEFAULT_CHANNEL_WIDTH
static const MHz_u DEFAULT_GUARD_WIDTH