A Discrete-Event Network Simulator
API
wifi-phy-ofdma-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 University of Washington
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
18  */
19 
20 #include "ns3/ap-wifi-mac.h"
21 #include "ns3/boolean.h"
22 #include "ns3/constant-position-mobility-model.h"
23 #include "ns3/ctrl-headers.h"
24 #include "ns3/double.h"
25 #include "ns3/he-configuration.h"
26 #include "ns3/he-phy.h"
27 #include "ns3/he-ppdu.h"
28 #include "ns3/interference-helper.h"
29 #include "ns3/log.h"
30 #include "ns3/mobility-helper.h"
31 #include "ns3/multi-model-spectrum-channel.h"
32 #include "ns3/nist-error-rate-model.h"
33 #include "ns3/node.h"
34 #include "ns3/non-communicating-net-device.h"
35 #include "ns3/pointer.h"
36 #include "ns3/rng-seed-manager.h"
37 #include "ns3/simulator.h"
38 #include "ns3/spectrum-wifi-helper.h"
39 #include "ns3/spectrum-wifi-phy.h"
40 #include "ns3/sta-wifi-mac.h"
41 #include "ns3/string.h"
42 #include "ns3/test.h"
43 #include "ns3/threshold-preamble-detection-model.h"
44 #include "ns3/waveform-generator.h"
45 #include "ns3/wifi-mac-header.h"
46 #include "ns3/wifi-net-device.h"
47 #include "ns3/wifi-phy-listener.h"
48 #include "ns3/wifi-psdu.h"
49 #include "ns3/wifi-spectrum-phy-interface.h"
50 #include "ns3/wifi-spectrum-signal-parameters.h"
51 #include "ns3/wifi-spectrum-value-helper.h"
52 #include "ns3/wifi-utils.h"
53 
54 #include <algorithm>
55 #include <iterator>
56 #include <memory>
57 
58 using namespace ns3;
59 
60 NS_LOG_COMPONENT_DEFINE("WifiPhyOfdmaTest");
61 
62 static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
63 static const uint32_t DEFAULT_FREQUENCY = 5180; // MHz
65 static const uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
66 static const uint16_t DEFAULT_GUARD_WIDTH =
67  DEFAULT_CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
68 
73 class OfdmaTestHePhy : public HePhy
74 {
75  public:
81  OfdmaTestHePhy(uint16_t staId);
82  ~OfdmaTestHePhy() override;
83 
91  uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
92 
98  void SetGlobalPpduUid(uint64_t uid);
99 
100  private:
101  uint16_t m_staId;
102 }; // class OfdmaTestHePhy
103 
105  : HePhy(),
106  m_staId(staId)
107 {
108 }
109 
111 {
112 }
113 
114 uint16_t
116 {
117  if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
118  {
119  return m_staId;
120  }
121  return HePhy::GetStaId(ppdu);
122 }
123 
124 void
126 {
127  m_globalPpduUid = uid;
128 }
129 
134 {
135  public:
140  static TypeId GetTypeId();
146  OfdmaSpectrumWifiPhy(uint16_t staId);
147  ~OfdmaSpectrumWifiPhy() override;
148 
149  void DoInitialize() override;
150  void DoDispose() override;
151 
152  using WifiPhy::Reset;
153  void StartTx(Ptr<const WifiPpdu> ppdu) override;
154 
160  typedef void (*TxPpduUidCallback)(uint64_t uid);
161 
167  void SetPpduUid(uint64_t uid);
168 
174  void SetTriggerFrameUid(uint64_t uid);
175 
179  std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
184 
195  Time GetEnergyDuration(double energyW, WifiSpectrumBandInfo band);
196 
200  Ptr<const HePhy> GetHePhy() const;
201 
202  private:
206 }; // class OfdmaSpectrumWifiPhy
207 
208 TypeId
210 {
211  static TypeId tid =
212  TypeId("ns3::OfdmaSpectrumWifiPhy")
214  .SetGroupName("Wifi")
215  .AddTraceSource("TxPpduUid",
216  "UID of the PPDU to be transmitted",
218  "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
219  return tid;
220 }
221 
223  : SpectrumWifiPhy()
224 {
225  m_ofdmTestHePhy = Create<OfdmaTestHePhy>(staId);
226  m_ofdmTestHePhy->SetOwner(this);
227 }
228 
230 {
231 }
232 
233 void
235 {
236  // Replace HE PHY instance with test instance
238  SpectrumWifiPhy::DoInitialize();
239 }
240 
241 void
243 {
244  m_ofdmTestHePhy = nullptr;
245  SpectrumWifiPhy::DoDispose();
246 }
247 
248 void
250 {
252  m_previouslyRxPpduUid = uid;
253 }
254 
255 void
257 {
258  m_previouslyRxPpduUid = uid;
259 }
260 
261 void
263 {
264  m_phyTxPpduUidTrace(ppdu->GetUid());
265  SpectrumWifiPhy::StartTx(ppdu);
266 }
267 
268 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
270 {
272 }
273 
276 {
277  return m_currentEvent;
278 }
279 
280 Time
282 {
283  return m_interference->GetEnergyDuration(energyW, band);
284 }
285 
288 {
289  return DynamicCast<const HePhy>(GetLatestPhyEntity());
290 }
291 
299 {
300  public:
302  ~TestDlOfdmaPhyTransmission() override;
303 
304  private:
305  void DoSetup() override;
306  void DoTeardown() override;
307  void DoRun() override;
308 
317  RxSignalInfo rxSignalInfo,
318  WifiTxVector txVector,
319  std::vector<bool> statusPerMpdu);
328  RxSignalInfo rxSignalInfo,
329  WifiTxVector txVector,
330  std::vector<bool> statusPerMpdu);
339  RxSignalInfo rxSignalInfo,
340  WifiTxVector txVector,
341  std::vector<bool> statusPerMpdu);
342 
358 
365  void CheckResultsSta1(uint32_t expectedRxSuccess,
366  uint32_t expectedRxFailure,
367  uint32_t expectedRxBytes);
374  void CheckResultsSta2(uint32_t expectedRxSuccess,
375  uint32_t expectedRxFailure,
376  uint32_t expectedRxBytes);
383  void CheckResultsSta3(uint32_t expectedRxSuccess,
384  uint32_t expectedRxFailure,
385  uint32_t expectedRxBytes);
386 
390  void ResetResults();
391 
397  void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
398 
404  void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
408  void StopInterference();
409 
413  void RunOne();
414 
427 
437 
443 
444  uint16_t m_frequency;
445  uint16_t m_channelWidth;
447 };
448 
450  : TestCase("DL-OFDMA PHY test"),
451  m_countRxSuccessSta1(0),
452  m_countRxSuccessSta2(0),
453  m_countRxSuccessSta3(0),
454  m_countRxFailureSta1(0),
455  m_countRxFailureSta2(0),
456  m_countRxFailureSta3(0),
457  m_countRxBytesSta1(0),
458  m_countRxBytesSta2(0),
459  m_countRxBytesSta3(0),
460  m_frequency(DEFAULT_FREQUENCY),
461  m_channelWidth(DEFAULT_CHANNEL_WIDTH),
462  m_expectedPpduDuration(NanoSeconds(306400))
463 {
464 }
465 
466 void
468 {
475  m_countRxBytesSta1 = 0;
476  m_countRxBytesSta2 = 0;
477  m_countRxBytesSta3 = 0;
478 }
479 
480 void
481 TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
482 {
483  NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
484  WifiConstPsduMap psdus;
485  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
486  0,
488  800,
489  1,
490  1,
491  0,
493  false,
494  false);
495  HeRu::RuType ruType = HeRu::RU_106_TONE;
496  if (m_channelWidth == 20)
497  {
498  ruType = HeRu::RU_106_TONE;
499  txVector.SetRuAllocation({96}, 0);
500  }
501  else if (m_channelWidth == 40)
502  {
503  ruType = HeRu::RU_242_TONE;
504  txVector.SetRuAllocation({192, 192}, 0);
505  }
506  else if (m_channelWidth == 80)
507  {
508  ruType = HeRu::RU_484_TONE;
509  txVector.SetRuAllocation({200, 200, 200, 200}, 0);
510  }
511  else if (m_channelWidth == 160)
512  {
513  ruType = HeRu::RU_996_TONE;
514  txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208}, 0);
515  }
516  else
517  {
518  NS_ASSERT_MSG(false, "Unsupported channel width");
519  }
520 
521  txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
522 
523  HeRu::RuSpec ru1(ruType, 1, true);
524  txVector.SetRu(ru1, rxStaId1);
525  txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
526  txVector.SetNss(1, rxStaId1);
527 
528  HeRu::RuSpec ru2(ruType, (m_channelWidth == 160 ? 1 : 2), m_channelWidth != 160);
529  txVector.SetRu(ru2, rxStaId2);
530  txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
531  txVector.SetNss(1, rxStaId2);
532 
533  Ptr<Packet> pkt1 = Create<Packet>(1000);
534  WifiMacHeader hdr1;
536  hdr1.SetQosTid(0);
537  hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
538  hdr1.SetSequenceNumber(1);
539  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
540  psdus.insert(std::make_pair(rxStaId1, psdu1));
541 
542  Ptr<Packet> pkt2 = Create<Packet>(1500);
543  WifiMacHeader hdr2;
545  hdr2.SetQosTid(0);
546  hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
547  hdr2.SetSequenceNumber(2);
548  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
549  psdus.insert(std::make_pair(rxStaId2, psdu2));
550 
551  m_phyAp->Send(psdus, txVector);
552 }
553 
554 void
556 {
557  m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
558  m_phyInterferer->SetPeriod(duration);
560  Simulator::Schedule(duration, &TestDlOfdmaPhyTransmission::StopInterference, this);
561 }
562 
563 void
565 {
567 }
568 
570 {
571 }
572 
573 void
575  RxSignalInfo rxSignalInfo,
576  WifiTxVector txVector,
577  std::vector<bool> /*statusPerMpdu*/)
578 {
579  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
581  m_countRxBytesSta1 += (psdu->GetSize() - 30);
582 }
583 
584 void
586  RxSignalInfo rxSignalInfo,
587  WifiTxVector txVector,
588  std::vector<bool> /*statusPerMpdu*/)
589 {
590  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
592  m_countRxBytesSta2 += (psdu->GetSize() - 30);
593 }
594 
595 void
597  RxSignalInfo rxSignalInfo,
598  WifiTxVector txVector,
599  std::vector<bool> /*statusPerMpdu*/)
600 {
601  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
603  m_countRxBytesSta3 += (psdu->GetSize() - 30);
604 }
605 
606 void
608 {
609  NS_LOG_FUNCTION(this << *psdu);
611 }
612 
613 void
615 {
616  NS_LOG_FUNCTION(this << *psdu);
618 }
619 
620 void
622 {
623  NS_LOG_FUNCTION(this << *psdu);
625 }
626 
627 void
629  uint32_t expectedRxFailure,
630  uint32_t expectedRxBytes)
631 {
633  expectedRxSuccess,
634  "The number of successfully received packets by STA 1 is not correct!");
636  expectedRxFailure,
637  "The number of unsuccessfuly received packets by STA 1 is not correct!");
639  expectedRxBytes,
640  "The number of bytes received by STA 1 is not correct!");
641 }
642 
643 void
645  uint32_t expectedRxFailure,
646  uint32_t expectedRxBytes)
647 {
649  expectedRxSuccess,
650  "The number of successfully received packets by STA 2 is not correct!");
652  expectedRxFailure,
653  "The number of unsuccessfuly received packets by STA 2 is not correct!");
655  expectedRxBytes,
656  "The number of bytes received by STA 2 is not correct!");
657 }
658 
659 void
661  uint32_t expectedRxFailure,
662  uint32_t expectedRxBytes)
663 {
665  expectedRxSuccess,
666  "The number of successfully received packets by STA 3 is not correct!");
668  expectedRxFailure,
669  "The number of unsuccessfuly received packets by STA 3 is not correct!");
671  expectedRxBytes,
672  "The number of bytes received by STA 3 is not correct!");
673 }
674 
675 void
677 {
678  // This is needed to make sure PHY state will be checked as the last event if a state change
679  // occurred at the exact same time as the check
680  Simulator::ScheduleNow(&TestDlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
681 }
682 
683 void
685  WifiPhyState expectedState)
686 {
687  WifiPhyState currentState;
688  PointerValue ptr;
689  phy->GetAttribute("State", ptr);
690  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
691  currentState = state->GetState();
692  NS_LOG_FUNCTION(this << currentState);
693  NS_TEST_ASSERT_MSG_EQ(currentState,
694  expectedState,
695  "PHY State " << currentState << " does not match expected state "
696  << expectedState << " at " << Simulator::Now());
697 }
698 
699 void
701 {
702  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
703  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
704  lossModel->SetFrequency(m_frequency * 1e6);
705  spectrumChannel->AddPropagationLossModel(lossModel);
707  CreateObject<ConstantSpeedPropagationDelayModel>();
708  spectrumChannel->SetPropagationDelayModel(delayModel);
709 
710  Ptr<Node> apNode = CreateObject<Node>();
711  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
712  m_phyAp = CreateObject<SpectrumWifiPhy>();
713  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
714  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
715  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
716  m_phyAp->SetErrorRateModel(apErrorModel);
717  m_phyAp->SetDevice(apDev);
718  m_phyAp->AddChannel(spectrumChannel);
720  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
721  m_phyAp->SetMobility(apMobility);
722  apDev->SetPhy(m_phyAp);
723  apNode->AggregateObject(apMobility);
724  apNode->AddDevice(apDev);
725 
726  Ptr<Node> sta1Node = CreateObject<Node>();
727  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
728  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
729  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
730  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
731  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
732  m_phySta1->SetErrorRateModel(sta1ErrorModel);
733  m_phySta1->SetDevice(sta1Dev);
734  m_phySta1->AddChannel(spectrumChannel);
739  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
740  m_phySta1->SetMobility(sta1Mobility);
741  sta1Dev->SetPhy(m_phySta1);
742  sta1Node->AggregateObject(sta1Mobility);
743  sta1Node->AddDevice(sta1Dev);
744 
745  Ptr<Node> sta2Node = CreateObject<Node>();
746  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
747  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
748  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
749  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
750  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
751  m_phySta2->SetErrorRateModel(sta2ErrorModel);
752  m_phySta2->SetDevice(sta2Dev);
753  m_phySta2->AddChannel(spectrumChannel);
758  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
759  m_phySta2->SetMobility(sta2Mobility);
760  sta2Dev->SetPhy(m_phySta2);
761  sta2Node->AggregateObject(sta2Mobility);
762  sta2Node->AddDevice(sta2Dev);
763 
764  Ptr<Node> sta3Node = CreateObject<Node>();
765  Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
766  m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
767  Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
768  m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
769  Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
770  m_phySta3->SetErrorRateModel(sta3ErrorModel);
771  m_phySta3->SetDevice(sta3Dev);
772  m_phySta3->AddChannel(spectrumChannel);
777  Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
778  m_phySta3->SetMobility(sta3Mobility);
779  sta3Dev->SetPhy(m_phySta3);
780  sta3Node->AggregateObject(sta3Mobility);
781  sta3Node->AddDevice(sta3Dev);
782 
783  Ptr<Node> interfererNode = CreateObject<Node>();
784  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
785  m_phyInterferer = CreateObject<WaveformGenerator>();
786  m_phyInterferer->SetDevice(interfererDev);
787  m_phyInterferer->SetChannel(spectrumChannel);
789  interfererNode->AddDevice(interfererDev);
790 }
791 
792 void
794 {
795  m_phyAp->Dispose();
796  m_phyAp = nullptr;
797  m_phySta1->Dispose();
798  m_phySta1 = nullptr;
799  m_phySta2->Dispose();
800  m_phySta2 = nullptr;
801  m_phySta3->Dispose();
802  m_phySta3 = nullptr;
804  m_phyInterferer = nullptr;
805 }
806 
807 void
809 {
810  RngSeedManager::SetSeed(1);
811  RngSeedManager::SetRun(1);
812  int64_t streamNumber = 0;
813  m_phyAp->AssignStreams(streamNumber);
814  m_phySta1->AssignStreams(streamNumber);
815  m_phySta2->AssignStreams(streamNumber);
816  m_phySta3->AssignStreams(streamNumber);
817 
818  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
819  m_frequency,
823 
832 
833  Simulator::Schedule(Seconds(0.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
834 
835  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
836  // Each STA should receive its PSDU.
837  Simulator::Schedule(Seconds(1.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
838 
839  // Since it takes m_expectedPpduDuration to transmit the PPDU,
840  // all 3 PHYs should be back to IDLE at the same time,
841  // even the PHY that has no PSDU addressed to it.
842  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
844  this,
845  m_phySta1,
847  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
849  this,
850  m_phySta2,
852  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
854  this,
855  m_phySta3,
857  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
859  this,
860  m_phySta1,
862  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
864  this,
865  m_phySta2,
867  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
869  this,
870  m_phySta3,
872 
873  // One PSDU of 1000 bytes should have been successfully received by STA 1
874  Simulator::Schedule(Seconds(1.1),
876  this,
877  1,
878  0,
879  1000);
880  // One PSDU of 1500 bytes should have been successfully received by STA 2
881  Simulator::Schedule(Seconds(1.1),
883  this,
884  1,
885  0,
886  1500);
887  // No PSDU should have been received by STA 3
888  Simulator::Schedule(Seconds(1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
889 
890  Simulator::Schedule(Seconds(1.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
891 
892  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
893  // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
894  // but should keep its PHY busy during all PPDU duration.
895  Simulator::Schedule(Seconds(2.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 3);
896 
897  // Since it takes m_expectedPpduDuration to transmit the PPDU,
898  // all 3 PHYs should be back to IDLE at the same time,
899  // even the PHY that has no PSDU addressed to it.
900  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
902  this,
903  m_phySta1,
905  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
907  this,
908  m_phySta2,
910  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
912  this,
913  m_phySta3,
915  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
917  this,
918  m_phySta1,
920  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
922  this,
923  m_phySta2,
925  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
927  this,
928  m_phySta3,
930 
931  // One PSDU of 1000 bytes should have been successfully received by STA 1
932  Simulator::Schedule(Seconds(2.1),
934  this,
935  1,
936  0,
937  1000);
938  // No PSDU should have been received by STA 2
939  Simulator::Schedule(Seconds(2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 0, 0);
940  // One PSDU of 1500 bytes should have been successfully received by STA 3
941  Simulator::Schedule(Seconds(2.1),
943  this,
944  1,
945  0,
946  1500);
947 
948  Simulator::Schedule(Seconds(2.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
949 
950  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
951  Simulator::Schedule(Seconds(3.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
952 
953  // A strong non-wifi interference is generated on RU 1 during PSDU reception
954  BandInfo bandInfo;
955  bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
956  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
957  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
958  Bands bands;
959  bands.push_back(bandInfo);
960 
961  Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
962  Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
963  double interferencePower = 0.1; // watts
964  *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
965 
966  Simulator::Schedule(Seconds(3.0) + MicroSeconds(50),
968  this,
969  interferencePsdRu1,
970  MilliSeconds(100));
971 
972  // Since it takes m_expectedPpduDuration to transmit the PPDU,
973  // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
974  // even the PHY that has no PSDU addressed to it.
975  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
977  this,
978  m_phySta1,
980  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
982  this,
983  m_phySta2,
985  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
987  this,
988  m_phySta3,
990  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
992  this,
993  m_phySta1,
995  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
997  this,
998  m_phySta2,
1000  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
1002  this,
1003  m_phySta3,
1005 
1006  // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1007  // occupies RU 1)
1008  Simulator::Schedule(Seconds(3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
1009  // One PSDU of 1500 bytes should have been successfully received by STA 2
1010  Simulator::Schedule(Seconds(3.1),
1012  this,
1013  1,
1014  0,
1015  1500);
1016  // No PSDU should have been received by STA3
1017  Simulator::Schedule(Seconds(3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1018 
1019  Simulator::Schedule(Seconds(3.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1020 
1021  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1022  Simulator::Schedule(Seconds(4.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
1023 
1024  // A strong non-wifi interference is generated on RU 2 during PSDU reception
1025  bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
1026  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
1027  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
1028  bands.clear();
1029  bands.push_back(bandInfo);
1030 
1031  Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1032  Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1033  *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
1034 
1035  Simulator::Schedule(Seconds(4.0) + MicroSeconds(50),
1037  this,
1038  interferencePsdRu2,
1039  MilliSeconds(100));
1040 
1041  // Since it takes m_expectedPpduDuration to transmit the PPDU,
1042  // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1043  // same time, even the PHY that has no PSDU addressed to it.
1044  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1046  this,
1047  m_phySta1,
1049  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1051  this,
1052  m_phySta2,
1054  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1056  this,
1057  m_phySta3,
1059  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1061  this,
1062  m_phySta1,
1064  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1066  this,
1067  m_phySta2,
1069  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1071  this,
1072  m_phySta3,
1074 
1075  // One PSDU of 1000 bytes should have been successfully received by STA 1
1076  Simulator::Schedule(Seconds(4.1),
1078  this,
1079  1,
1080  0,
1081  1000);
1082  // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1083  // occupies RU 2)
1084  Simulator::Schedule(Seconds(4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
1085  // No PSDU should have been received by STA3
1086  Simulator::Schedule(Seconds(4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1087 
1088  Simulator::Schedule(Seconds(4.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1089 
1090  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1091  Simulator::Schedule(Seconds(5.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
1092 
1093  // A strong non-wifi interference is generated on the full band during PSDU reception
1094  bandInfo.fc = m_frequency * 1e6;
1095  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
1096  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
1097  bands.clear();
1098  bands.push_back(bandInfo);
1099 
1100  Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1101  Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1102  *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
1103 
1104  Simulator::Schedule(Seconds(5.0) + MicroSeconds(50),
1106  this,
1107  interferencePsdAll,
1108  MilliSeconds(100));
1109 
1110  // Since it takes m_expectedPpduDuration to transmit the PPDU,
1111  // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1112  // even the PHY that has no PSDU addressed to it.
1113  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1115  this,
1116  m_phySta1,
1118  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1120  this,
1121  m_phySta2,
1123  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1125  this,
1126  m_phySta3,
1128  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1130  this,
1131  m_phySta1,
1133  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1135  this,
1136  m_phySta2,
1138  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1140  this,
1141  m_phySta3,
1143 
1144  // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1145  // occupies RU 1)
1146  Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
1147  // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1148  // occupies RU 2)
1149  Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
1150  // No PSDU should have been received by STA3
1151  Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1152 
1153  Simulator::Schedule(Seconds(5.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1154 
1155  Simulator::Run();
1156 }
1157 
1158 void
1160 {
1161  m_frequency = 5180;
1162  m_channelWidth = 20;
1164  RunOne();
1165 
1166  m_frequency = 5190;
1167  m_channelWidth = 40;
1169  RunOne();
1170 
1171  m_frequency = 5210;
1172  m_channelWidth = 80;
1174  RunOne();
1175 
1176  m_frequency = 5250;
1177  m_channelWidth = 160;
1179  RunOne();
1180 
1181  Simulator::Destroy();
1182 }
1183 
1191 {
1192  public:
1194 
1195  private:
1196  void DoSetup() override;
1197  void DoTeardown() override;
1198  void DoRun() override;
1199 
1208  RxSignalInfo rxSignalInfo,
1209  WifiTxVector txVector,
1210  const std::vector<bool> statusPerMpdu);
1211 
1220  RxSignalInfo rxSignalInfo,
1221  WifiTxVector txVector,
1222  std::vector<bool> statusPerMpdu);
1223 
1229 
1235 
1242  void CheckResultsSta1(uint32_t expectedRxSuccess,
1243  uint32_t expectedRxFailure,
1244  uint32_t expectedRxBytes);
1245 
1252  void CheckResultsSta2(uint32_t expectedRxSuccess,
1253  uint32_t expectedRxFailure,
1254  uint32_t expectedRxBytes);
1255 
1259  void ResetResults();
1260 
1268  void SendMuPpdu(uint16_t rxStaId1,
1269  uint16_t rxStaId2,
1270  const std::vector<bool>& puncturedSubchannels);
1271 
1277  void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1278 
1282  void StopInterference();
1283 
1287  void RunOne();
1288 
1295 
1302 
1309 
1314 
1315  uint16_t m_frequency;
1316  uint16_t m_channelWidth;
1317 
1320 
1323 };
1324 
1326  : TestCase("DL-OFDMA PHY puncturing test"),
1327  m_countRxSuccessSta1(0),
1328  m_countRxSuccessSta2(0),
1329  m_countRxFailureSta1(0),
1330  m_countRxFailureSta2(0),
1331  m_countRxBytesSta1(0),
1332  m_countRxBytesSta2(0),
1333  m_frequency(5210),
1334  m_channelWidth(80),
1335  m_indexSubchannel(0),
1336  m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1337  m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1338 {
1339 }
1340 
1341 void
1343 {
1348  m_countRxBytesSta1 = 0;
1349  m_countRxBytesSta2 = 0;
1350 }
1351 
1352 void
1354  uint16_t rxStaId2,
1355  const std::vector<bool>& puncturedSubchannels)
1356 {
1357  NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1358  WifiConstPsduMap psdus;
1359  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
1360  0,
1362  800,
1363  1,
1364  1,
1365  0,
1367  false,
1368  false);
1369 
1370  HeRu::RuType ruType =
1371  puncturedSubchannels.empty()
1372  ? HeRu::RU_484_TONE
1373  : (puncturedSubchannels.at(1) ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1374  HeRu::RuSpec ru1(ruType, 1, true);
1375  txVector.SetRu(ru1, rxStaId1);
1376  txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1377  txVector.SetNss(1, rxStaId1);
1378 
1379  ruType = puncturedSubchannels.empty()
1380  ? HeRu::RU_484_TONE
1381  : (puncturedSubchannels.at(1) ? HeRu::RU_484_TONE : HeRu::RU_242_TONE);
1382  HeRu::RuSpec ru2(ruType,
1383  ruType == HeRu::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1384  true);
1385  txVector.SetRu(ru2, rxStaId2);
1386  txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1387  txVector.SetNss(1, rxStaId2);
1388 
1389  std::vector<uint8_t> ruAlloc;
1390  if (puncturedSubchannels.empty())
1391  {
1392  std::fill_n(std::back_inserter(ruAlloc), 4, 200);
1393  }
1394  else
1395  {
1396  ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1397  ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
1398  ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1399  : (puncturedSubchannels.at(3) ? 192 : 200));
1400  ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1401  : (puncturedSubchannels.at(3) ? 113 : 200));
1402  }
1403 
1404  txVector.SetRuAllocation(ruAlloc, 0);
1405  txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1406 
1407  Ptr<Packet> pkt1 = Create<Packet>(1000);
1408  WifiMacHeader hdr1;
1409  hdr1.SetType(WIFI_MAC_QOSDATA);
1410  hdr1.SetQosTid(0);
1411  hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1412  hdr1.SetSequenceNumber(1);
1413  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1414  psdus.insert(std::make_pair(rxStaId1, psdu1));
1415 
1416  Ptr<Packet> pkt2 = Create<Packet>(1500);
1417  WifiMacHeader hdr2;
1418  hdr2.SetType(WIFI_MAC_QOSDATA);
1419  hdr2.SetQosTid(0);
1420  hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1421  hdr2.SetSequenceNumber(2);
1422  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1423  psdus.insert(std::make_pair(rxStaId2, psdu2));
1424 
1425  if (!puncturedSubchannels.empty())
1426  {
1427  txVector.SetInactiveSubchannels(puncturedSubchannels);
1428  }
1429 
1430  m_phyAp->Send(psdus, txVector);
1431 }
1432 
1433 void
1435 {
1436  NS_LOG_FUNCTION(this << duration);
1437  m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
1438  m_phyInterferer->SetPeriod(duration);
1440  Simulator::Schedule(duration, &TestDlOfdmaPhyPuncturing::StopInterference, this);
1441 }
1442 
1443 void
1445 {
1446  NS_LOG_FUNCTION(this);
1447  m_phyInterferer->Stop();
1448 }
1449 
1450 void
1452  RxSignalInfo rxSignalInfo,
1453  WifiTxVector txVector,
1454  std::vector<bool> /*statusPerMpdu*/)
1455 {
1456  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1458  m_countRxBytesSta1 += (psdu->GetSize() - 30);
1459 }
1460 
1461 void
1463  RxSignalInfo rxSignalInfo,
1464  WifiTxVector txVector,
1465  std::vector<bool> /*statusPerMpdu*/)
1466 {
1467  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1469  m_countRxBytesSta2 += (psdu->GetSize() - 30);
1470 }
1471 
1472 void
1474 {
1475  NS_LOG_FUNCTION(this << *psdu);
1477 }
1478 
1479 void
1481 {
1482  NS_LOG_FUNCTION(this << *psdu);
1484 }
1485 
1486 void
1488  uint32_t expectedRxFailure,
1489  uint32_t expectedRxBytes)
1490 {
1492  expectedRxSuccess,
1493  "The number of successfully received packets by STA 1 is not correct!");
1495  expectedRxFailure,
1496  "The number of unsuccessfuly received packets by STA 1 is not correct!");
1498  expectedRxBytes,
1499  "The number of bytes received by STA 1 is not correct!");
1500 }
1501 
1502 void
1504  uint32_t expectedRxFailure,
1505  uint32_t expectedRxBytes)
1506 {
1508  expectedRxSuccess,
1509  "The number of successfully received packets by STA 2 is not correct!");
1511  expectedRxFailure,
1512  "The number of unsuccessfuly received packets by STA 2 is not correct!");
1514  expectedRxBytes,
1515  "The number of bytes received by STA 2 is not correct!");
1516 }
1517 
1518 void
1520 {
1521  // This is needed to make sure PHY state will be checked as the last event if a state change
1522  // occurred at the exact same time as the check
1523  Simulator::ScheduleNow(&TestDlOfdmaPhyPuncturing::DoCheckPhyState, this, phy, expectedState);
1524 }
1525 
1526 void
1528 {
1529  WifiPhyState currentState;
1530  PointerValue ptr;
1531  phy->GetAttribute("State", ptr);
1532  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
1533  currentState = state->GetState();
1534  NS_LOG_FUNCTION(this << currentState);
1535  NS_TEST_ASSERT_MSG_EQ(currentState,
1536  expectedState,
1537  "PHY State " << currentState << " does not match expected state "
1538  << expectedState << " at " << Simulator::Now());
1539 }
1540 
1541 void
1543 {
1544  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1545  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1546  lossModel->SetFrequency(m_frequency * 1e6);
1547  spectrumChannel->AddPropagationLossModel(lossModel);
1549  CreateObject<ConstantSpeedPropagationDelayModel>();
1550  spectrumChannel->SetPropagationDelayModel(delayModel);
1551 
1552  Ptr<Node> apNode = CreateObject<Node>();
1553  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1554  m_phyAp = CreateObject<SpectrumWifiPhy>();
1555  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1556  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1557  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1558  m_phyAp->SetErrorRateModel(apErrorModel);
1559  m_phyAp->SetDevice(apDev);
1560  m_phyAp->AddChannel(spectrumChannel);
1562  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1563  m_phyAp->SetMobility(apMobility);
1564  apDev->SetPhy(m_phyAp);
1565  apNode->AggregateObject(apMobility);
1566  apNode->AddDevice(apDev);
1567 
1568  Ptr<Node> sta1Node = CreateObject<Node>();
1569  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1570  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1571  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1572  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1573  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1574  m_phySta1->SetErrorRateModel(sta1ErrorModel);
1575  m_phySta1->SetDevice(sta1Dev);
1576  m_phySta1->AddChannel(spectrumChannel);
1581  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1582  m_phySta1->SetMobility(sta1Mobility);
1583  sta1Dev->SetPhy(m_phySta1);
1584  sta1Node->AggregateObject(sta1Mobility);
1585  sta1Node->AddDevice(sta1Dev);
1586 
1587  Ptr<Node> sta2Node = CreateObject<Node>();
1588  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1589  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1590  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1591  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1592  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1593  m_phySta2->SetErrorRateModel(sta2ErrorModel);
1594  m_phySta2->SetDevice(sta2Dev);
1595  m_phySta2->AddChannel(spectrumChannel);
1600  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1601  m_phySta2->SetMobility(sta2Mobility);
1602  sta2Dev->SetPhy(m_phySta2);
1603  sta2Node->AggregateObject(sta2Mobility);
1604  sta2Node->AddDevice(sta2Dev);
1605 
1606  Ptr<Node> interfererNode = CreateObject<Node>();
1607  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
1608  m_phyInterferer = CreateObject<WaveformGenerator>();
1609  m_phyInterferer->SetDevice(interfererDev);
1610  m_phyInterferer->SetChannel(spectrumChannel);
1612  interfererNode->AddDevice(interfererDev);
1613 }
1614 
1615 void
1617 {
1618  m_phyAp->Dispose();
1619  m_phyAp = nullptr;
1620  m_phySta1->Dispose();
1621  m_phySta1 = nullptr;
1622  m_phySta2->Dispose();
1623  m_phySta2 = nullptr;
1625  m_phyInterferer = nullptr;
1626 }
1627 
1628 void
1630 {
1631  RngSeedManager::SetSeed(1);
1632  RngSeedManager::SetRun(1);
1633  int64_t streamNumber = 0;
1634  m_phyAp->AssignStreams(streamNumber);
1635  m_phySta1->AssignStreams(streamNumber);
1636  m_phySta2->AssignStreams(streamNumber);
1637 
1638  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1639  m_frequency,
1643 
1650 
1651  // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1652  // duration of the test run
1653  BandInfo bandInfo;
1654  bandInfo.fc = (m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20)) * 1e6;
1655  // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1656  // the border of another RU
1657  bandInfo.fl = bandInfo.fc - (5 * 1e6);
1658  bandInfo.fh = bandInfo.fc + (5 * 1e6);
1659  Bands bands;
1660  bands.push_back(bandInfo);
1661 
1662  Ptr<SpectrumModel> spectrumInterference = Create<SpectrumModel>(bands);
1663  Ptr<SpectrumValue> interferencePsd = Create<SpectrumValue>(spectrumInterference);
1664  double interferencePower = 0.1; // watts
1665  *interferencePsd = interferencePower / 10e6;
1666 
1667  Simulator::Schedule(Seconds(0.0),
1669  this,
1670  interferencePsd,
1671  Seconds(3));
1672 
1673  //---------------------------------------------------------------------------
1674  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1675  Simulator::Schedule(Seconds(1.0),
1677  this,
1678  1,
1679  2,
1680  std::vector<bool>{});
1681 
1682  // Since it takes m_expectedPpduDuration to transmit the PPDU,
1683  // both PHYs should be back to IDLE at the same time.
1684  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz - NanoSeconds(1),
1686  this,
1687  m_phySta1,
1689  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz - NanoSeconds(1),
1691  this,
1692  m_phySta2,
1694  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz,
1696  this,
1697  m_phySta1,
1699  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz,
1701  this,
1702  m_phySta2,
1704 
1705  if (m_indexSubchannel < 2) // interference in RU 1
1706  {
1707  // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1708  Simulator::Schedule(Seconds(1.1),
1710  this,
1711  0,
1712  1,
1713  0);
1714  // One PSDU of 1500 bytes should have been successfully received by STA 2
1715  Simulator::Schedule(Seconds(1.1),
1717  this,
1718  1,
1719  0,
1720  1500);
1721  }
1722  else // interference in RU 2
1723  {
1724  // One PSDU of 1000 bytes should have been successfully received by STA 1
1725  Simulator::Schedule(Seconds(1.1),
1727  this,
1728  1,
1729  0,
1730  1000);
1731  // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1732  Simulator::Schedule(Seconds(1.1),
1734  this,
1735  0,
1736  1,
1737  0);
1738  }
1739 
1740  Simulator::Schedule(Seconds(1.5), &TestDlOfdmaPhyPuncturing::ResetResults, this);
1741 
1742  //---------------------------------------------------------------------------
1743  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1744  // the punctured 20 MHz subchannel is the one that has interference
1745  std::vector<bool> puncturedSubchannels;
1746  for (std::size_t i = 0; i < (m_channelWidth / 20); ++i)
1747  {
1748  if (i == m_indexSubchannel)
1749  {
1750  puncturedSubchannels.push_back(true);
1751  }
1752  else
1753  {
1754  puncturedSubchannels.push_back(false);
1755  }
1756  }
1757  Simulator::Schedule(Seconds(2.0),
1759  this,
1760  1,
1761  2,
1762  puncturedSubchannels);
1763 
1764  // Since it takes m_expectedPpduDuration to transmit the PPDU,
1765  // both PHYs should be back to IDLE at the same time.
1766  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz - NanoSeconds(1),
1768  this,
1769  m_phySta1,
1771  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz - NanoSeconds(1),
1773  this,
1774  m_phySta2,
1776  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz,
1778  this,
1779  m_phySta1,
1781  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz,
1783  this,
1784  m_phySta2,
1786 
1787  // One PSDU of 1000 bytes should have been successfully received by STA 1
1788  Simulator::Schedule(Seconds(2.1),
1790  this,
1791  1,
1792  0,
1793  1000);
1794  // One PSDU of 1500 bytes should have been successfully received by STA 2
1795  Simulator::Schedule(Seconds(2.1),
1797  this,
1798  1,
1799  0,
1800  1500);
1801 
1802  Simulator::Schedule(Seconds(2.5), &TestDlOfdmaPhyPuncturing::ResetResults, this);
1803 
1804  Simulator::Run();
1805 }
1806 
1807 void
1809 {
1810  // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1811  // cannot be punctured
1812  for (auto index : {1, 2, 3})
1813  {
1814  m_indexSubchannel = index;
1815  RunOne();
1816  }
1817  Simulator::Destroy();
1818 }
1819 
1827 {
1828  public:
1830  ~TestUlOfdmaPpduUid() override;
1831 
1832  private:
1833  void DoSetup() override;
1834  void DoTeardown() override;
1835  void DoRun() override;
1836 
1841  void TxPpduAp(uint64_t uid);
1846  void TxPpduSta1(uint64_t uid);
1851  void TxPpduSta2(uint64_t uid);
1855  void ResetPpduUid();
1856 
1860  void SendMuPpdu();
1864  void SendTbPpdu();
1869  void SendSuPpdu(uint16_t txStaId);
1870 
1876  void CheckUid(uint16_t staId, uint64_t expectedUid);
1877 
1881 
1882  uint64_t m_ppduUidAp;
1883  uint64_t m_ppduUidSta1;
1884  uint64_t m_ppduUidSta2;
1885 };
1886 
1888  : TestCase("UL-OFDMA PPDU UID attribution test"),
1889  m_ppduUidAp(UINT64_MAX),
1890  m_ppduUidSta1(UINT64_MAX),
1891  m_ppduUidSta2(UINT64_MAX)
1892 {
1893 }
1894 
1896 {
1897 }
1898 
1899 void
1901 {
1902  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1903  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1904  lossModel->SetFrequency(DEFAULT_FREQUENCY);
1905  spectrumChannel->AddPropagationLossModel(lossModel);
1907  CreateObject<ConstantSpeedPropagationDelayModel>();
1908  spectrumChannel->SetPropagationDelayModel(delayModel);
1909 
1910  Ptr<Node> apNode = CreateObject<Node>();
1911  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1912  m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
1913  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1914  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1915  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1916  m_phyAp->SetErrorRateModel(apErrorModel);
1917  m_phyAp->AddChannel(spectrumChannel);
1919  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1926  m_phyAp->SetDevice(apDev);
1927  m_phyAp->TraceConnectWithoutContext("TxPpduUid",
1929  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1930  m_phyAp->SetMobility(apMobility);
1931  apDev->SetPhy(m_phyAp);
1932  apNode->AggregateObject(apMobility);
1933  apNode->AddDevice(apDev);
1935  apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1936 
1937  Ptr<Node> sta1Node = CreateObject<Node>();
1938  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1939  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1940  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1941  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1942  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1943  m_phySta1->SetErrorRateModel(sta1ErrorModel);
1944  m_phySta1->AddChannel(spectrumChannel);
1948  m_phySta1->SetDevice(sta1Dev);
1951  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1952  m_phySta1->SetMobility(sta1Mobility);
1953  sta1Dev->SetPhy(m_phySta1);
1954  sta1Node->AggregateObject(sta1Mobility);
1955  sta1Node->AddDevice(sta1Dev);
1956 
1957  Ptr<Node> sta2Node = CreateObject<Node>();
1958  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1959  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1960  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1961  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1962  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1963  m_phySta2->SetErrorRateModel(sta2ErrorModel);
1964  m_phySta2->AddChannel(spectrumChannel);
1968  m_phySta2->SetDevice(sta2Dev);
1971  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1972  m_phySta2->SetMobility(sta2Mobility);
1973  sta2Dev->SetPhy(m_phySta2);
1974  sta2Node->AggregateObject(sta2Mobility);
1975  sta2Node->AddDevice(sta2Dev);
1976 }
1977 
1978 void
1980 {
1981  m_phyAp->Dispose();
1982  m_phyAp = nullptr;
1983  m_phySta1->Dispose();
1984  m_phySta1 = nullptr;
1985  m_phySta2->Dispose();
1986  m_phySta2 = nullptr;
1987 }
1988 
1989 void
1990 TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
1991 {
1992  uint64_t uid;
1993  std::string device;
1994  switch (staId)
1995  {
1996  case 0:
1997  uid = m_ppduUidAp;
1998  device = "AP";
1999  break;
2000  case 1:
2001  uid = m_ppduUidSta1;
2002  device = "STA1";
2003  break;
2004  case 2:
2005  uid = m_ppduUidSta2;
2006  device = "STA2";
2007  break;
2008  default:
2009  NS_ABORT_MSG("Unexpected STA-ID");
2010  }
2012  expectedUid,
2013  "UID " << uid << " does not match expected one " << expectedUid << " for "
2014  << device << " at " << Simulator::Now());
2015 }
2016 
2017 void
2019 {
2020  NS_LOG_FUNCTION(this << uid);
2021  m_ppduUidAp = uid;
2022 }
2023 
2024 void
2026 {
2027  NS_LOG_FUNCTION(this << uid);
2028  m_ppduUidSta1 = uid;
2029 }
2030 
2031 void
2033 {
2034  NS_LOG_FUNCTION(this << uid);
2035  m_ppduUidSta2 = uid;
2036 }
2037 
2038 void
2040 {
2041  NS_LOG_FUNCTION(this);
2042  m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2043 }
2044 
2045 void
2047 {
2048  WifiConstPsduMap psdus;
2049  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2050  0,
2052  800,
2053  1,
2054  1,
2055  0,
2057  false,
2058  false);
2059 
2060  uint16_t rxStaId1 = 1;
2061  HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2062  txVector.SetRu(ru1, rxStaId1);
2063  txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2064  txVector.SetNss(1, rxStaId1);
2065 
2066  uint16_t rxStaId2 = 2;
2067  HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2068  txVector.SetRu(ru2, rxStaId2);
2069  txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2070  txVector.SetNss(1, rxStaId2);
2071  txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2072  txVector.SetRuAllocation({96}, 0);
2073 
2074  Ptr<Packet> pkt1 = Create<Packet>(1000);
2075  WifiMacHeader hdr1;
2076  hdr1.SetType(WIFI_MAC_QOSDATA);
2077  hdr1.SetQosTid(0);
2078  hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2079  hdr1.SetSequenceNumber(1);
2080  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2081  psdus.insert(std::make_pair(rxStaId1, psdu1));
2082 
2083  Ptr<Packet> pkt2 = Create<Packet>(1500);
2084  WifiMacHeader hdr2;
2085  hdr2.SetType(WIFI_MAC_QOSDATA);
2086  hdr2.SetQosTid(0);
2087  hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2088  hdr2.SetSequenceNumber(2);
2089  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2090  psdus.insert(std::make_pair(rxStaId2, psdu2));
2091 
2092  m_phyAp->Send(psdus, txVector);
2093 }
2094 
2095 void
2097 {
2098  WifiConstPsduMap psdus1;
2099  WifiConstPsduMap psdus2;
2100 
2101  WifiTxVector txVector1 = WifiTxVector(HePhy::GetHeMcs7(),
2102  0,
2104  1600,
2105  1,
2106  1,
2107  0,
2109  false,
2110  false);
2111  WifiTxVector txVector2 = txVector1;
2112  WifiTxVector trigVector = txVector2;
2113 
2114  uint16_t rxStaId1 = 1;
2115  HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2116  txVector1.SetRu(ru1, rxStaId1);
2117  txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2118  txVector1.SetNss(1, rxStaId1);
2119  trigVector.SetRu(ru1, rxStaId1);
2120  trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2121  trigVector.SetNss(1, rxStaId1);
2122 
2123  Ptr<Packet> pkt1 = Create<Packet>(1000);
2124  WifiMacHeader hdr1;
2125  hdr1.SetType(WIFI_MAC_QOSDATA);
2126  hdr1.SetQosTid(0);
2127  hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2128  hdr1.SetSequenceNumber(1);
2129  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2130  psdus1.insert(std::make_pair(rxStaId1, psdu1));
2131 
2132  uint16_t rxStaId2 = 2;
2133  HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, false);
2134  txVector2.SetRu(ru2, rxStaId2);
2135  txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2136  txVector2.SetNss(1, rxStaId2);
2137  trigVector.SetRu(ru2, rxStaId2);
2138  trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2139  trigVector.SetNss(1, rxStaId2);
2140 
2141  Ptr<Packet> pkt2 = Create<Packet>(1500);
2142  WifiMacHeader hdr2;
2143  hdr2.SetType(WIFI_MAC_QOSDATA);
2144  hdr2.SetQosTid(0);
2145  hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2146  hdr2.SetSequenceNumber(2);
2147  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2148  psdus2.insert(std::make_pair(rxStaId2, psdu2));
2149 
2150  Time txDuration1 = m_phySta1->CalculateTxDuration(psdu1->GetSize(),
2151  txVector1,
2152  m_phySta1->GetPhyBand(),
2153  rxStaId1);
2154  Time txDuration2 = m_phySta2->CalculateTxDuration(psdu2->GetSize(),
2155  txVector2,
2156  m_phySta1->GetPhyBand(),
2157  rxStaId2);
2158  Time txDuration = std::max(txDuration1, txDuration2);
2159 
2160  txVector1.SetLength(
2161  HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector1, m_phySta1->GetPhyBand())
2162  .first);
2163  txVector2.SetLength(
2164  HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector2, m_phySta2->GetPhyBand())
2165  .first);
2166 
2167  auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
2168  hePhyAp->SetTrigVector(trigVector, txDuration);
2169 
2170  m_phySta1->Send(psdus1, txVector1);
2171  m_phySta2->Send(psdus2, txVector2);
2172 }
2173 
2174 void
2176 {
2177  WifiConstPsduMap psdus;
2178  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2179  0,
2181  800,
2182  1,
2183  1,
2184  0,
2186  false,
2187  false);
2188 
2189  Ptr<Packet> pkt = Create<Packet>(1000);
2190  WifiMacHeader hdr;
2192  hdr.SetQosTid(0);
2193  hdr.SetAddr1(Mac48Address::GetBroadcast());
2194  hdr.SetSequenceNumber(1);
2195  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2196  psdus.insert(std::make_pair(SU_STA_ID, psdu));
2197 
2198  switch (txStaId)
2199  {
2200  case 0:
2201  m_phyAp->Send(psdus, txVector);
2202  break;
2203  case 1:
2204  m_phySta1->Send(psdus, txVector);
2205  break;
2206  case 2:
2207  m_phySta2->Send(psdus, txVector);
2208  break;
2209  default:
2210  NS_ABORT_MSG("Unexpected STA-ID");
2211  }
2212 }
2213 
2214 void
2216 {
2217  RngSeedManager::SetSeed(1);
2218  RngSeedManager::SetRun(1);
2219  int64_t streamNumber = 0;
2220  m_phyAp->AssignStreams(streamNumber);
2221  m_phySta1->AssignStreams(streamNumber);
2222  m_phySta2->AssignStreams(streamNumber);
2223 
2224  // Reset PPDU UID so as not to be dependent on previously executed test cases,
2225  // since global attribute will be changed).
2226  ResetPpduUid();
2227 
2228  // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2229  // PPDU UID should be equal to 0 (the first counter value).
2230  Simulator::Schedule(Seconds(1.0), &TestUlOfdmaPpduUid::SendMuPpdu, this);
2231  Simulator::Schedule(Seconds(1.0), &TestUlOfdmaPpduUid::CheckUid, this, 0, 0);
2232 
2233  // Send HE SU PPDU from AP.
2234  // PPDU UID should be incremented since this is a new PPDU.
2235  Simulator::Schedule(Seconds(1.1), &TestUlOfdmaPpduUid::SendSuPpdu, this, 0);
2236  Simulator::Schedule(Seconds(1.1), &TestUlOfdmaPpduUid::CheckUid, this, 0, 1);
2237 
2238  // Send HE TB PPDU from STAs to AP.
2239  // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2240  // preceding correctly received PPDU (which normally contains the trigger frame).
2241  Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::SendTbPpdu, this);
2242  Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::CheckUid, this, 1, 1);
2243  Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::CheckUid, this, 2, 1);
2244 
2245  // Send HE SU PPDU from STA1.
2246  // PPDU UID should be incremented since this is a new PPDU.
2247  Simulator::Schedule(Seconds(1.2), &TestUlOfdmaPpduUid::SendSuPpdu, this, 1);
2248  Simulator::Schedule(Seconds(1.2), &TestUlOfdmaPpduUid::CheckUid, this, 1, 2);
2249 
2250  Simulator::Run();
2251  Simulator::Destroy();
2252 }
2253 
2261 {
2262  public:
2264  ~TestMultipleHeTbPreambles() override;
2265 
2266  private:
2267  void DoSetup() override;
2268  void DoTeardown() override;
2269  void DoRun() override;
2270 
2280  void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize);
2281 
2296 
2303 
2307  void Reset();
2308 
2314  void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2315 
2320  void CheckBytesDropped(size_t expectedBytesDropped);
2321 
2323 
2326 };
2327 
2329  : TestCase("UL-OFDMA multiple RX events test"),
2330  m_totalBytesDropped(0),
2331  m_trigVector(HePhy::GetHeMcs7(),
2332  0,
2334  1600,
2335  1,
2336  1,
2337  0,
2339  false,
2340  false)
2341 {
2342 }
2343 
2345 {
2346 }
2347 
2348 void
2350 {
2351  NS_LOG_FUNCTION(this);
2352  m_totalBytesDropped = 0;
2353  // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2354  m_phy->Reset();
2355  m_trigVector.GetHeMuUserInfoMap().clear();
2356 }
2357 
2358 void
2360 {
2361  NS_LOG_FUNCTION(this << p << reason);
2362  m_totalBytesDropped += (p->GetSize() - 30);
2363 }
2364 
2365 void
2366 TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2367 {
2368  auto events = m_phy->GetCurrentPreambleEvents();
2369  NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2370  for (const auto& uid : uids)
2371  {
2372  auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2373  auto it = events.find(pair);
2374  bool found = (it != events.end());
2375  NS_TEST_ASSERT_MSG_EQ(found,
2376  true,
2377  "HE TB PPDU with UID " << uid << " has not been received!");
2378  }
2379 }
2380 
2381 void
2383 {
2385  expectedBytesDropped,
2386  "The number of dropped bytes is not correct!");
2387 }
2388 
2389 void
2391  uint16_t staId,
2392  double txPowerWatts,
2393  size_t payloadSize)
2394 {
2395  WifiConstPsduMap psdus;
2396  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2397  0,
2399  1600,
2400  1,
2401  1,
2402  0,
2404  false,
2405  false);
2406 
2407  HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2408  txVector.SetRu(ru, staId);
2409  txVector.SetMode(HePhy::GetHeMcs7(), staId);
2410  txVector.SetNss(1, staId);
2411 
2412  m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2413 
2414  Ptr<Packet> pkt = Create<Packet>(payloadSize);
2415  WifiMacHeader hdr;
2417  hdr.SetQosTid(0);
2418  hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2419  hdr.SetSequenceNumber(1);
2420  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2421  psdus.insert(std::make_pair(staId, psdu));
2422 
2423  Time ppduDuration =
2424  m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand(), staId);
2425  Ptr<HePpdu> ppdu = Create<HePpdu>(psdus,
2426  txVector,
2428  ppduDuration,
2429  uid,
2430  HePpdu::PSD_NON_HE_PORTION);
2431 
2432  // Send non-OFDMA part
2433  Time nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonHeDurationForHeTb(txVector);
2434  uint32_t centerFrequency = m_phy->GetHePhy()->GetCenterFrequencyForNonHePart(txVector, staId);
2435  uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2436  uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
2437  Ptr<SpectrumValue> rxPsd = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(
2438  centerFrequency,
2439  channelWidth,
2440  txPowerWatts,
2441  m_phy->GetGuardBandwidth(channelWidth));
2442  Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters>();
2443  rxParams->psd = rxPsd;
2444  rxParams->txPhy = nullptr;
2445  rxParams->duration = nonOfdmaDuration;
2446  rxParams->ppdu = ppdu;
2447 
2448  uint16_t length;
2449  std::tie(length, ppduDuration) =
2450  HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, txVector, m_phy->GetPhyBand());
2451  txVector.SetLength(length);
2452  m_trigVector.SetLength(length);
2453  auto hePhy = DynamicCast<HePhy>(m_phy->GetLatestPhyEntity());
2454  hePhy->SetTrigVector(m_trigVector, ppduDuration);
2455  ppdu->ResetTxVector();
2456  m_phy->StartRx(rxParams, nullptr);
2457 
2458  // Schedule OFDMA part
2459  Ptr<HePpdu> ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2460  ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2461  const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2462  Ptr<SpectrumValue> rxPsdOfdma =
2463  WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity(DEFAULT_FREQUENCY,
2465  txPowerWatts,
2467  band.indices);
2468  Ptr<WifiSpectrumSignalParameters> rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2469  rxParamsOfdma->psd = rxPsd;
2470  rxParamsOfdma->txPhy = nullptr;
2471  rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2472  rxParamsOfdma->ppdu = ppduOfdma;
2473  Simulator::Schedule(nonOfdmaDuration,
2475  this,
2476  rxParamsOfdma);
2477 }
2478 
2479 void
2481 {
2482  Simulator::ScheduleNow(&TestMultipleHeTbPreambles::DoRxHeTbPpduOfdmaPart, this, rxParamsOfdma);
2483 }
2484 
2485 void
2487 {
2488  // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2489  // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2490  // OFDMA part is scheduled after end of HE-SIG-A decoding.
2491  m_phy->StartRx(rxParamsOfdma, nullptr);
2492 }
2493 
2494 void
2496 {
2497  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
2498  Ptr<Node> node = CreateObject<Node>();
2499  Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
2501  m_phy = CreateObject<OfdmaSpectrumWifiPhy>(0);
2502  Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2503  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2504  Ptr<ApWifiMac> mac = CreateObject<ApWifiMac>();
2505  mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2506  dev->SetMac(mac);
2507  m_phy->SetInterferenceHelper(interferenceHelper);
2508  m_phy->SetErrorRateModel(error);
2509  m_phy->AddChannel(spectrumChannel);
2514  0});
2515  m_phy->TraceConnectWithoutContext("PhyRxDrop",
2517  m_phy->SetDevice(dev);
2518  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2519  CreateObject<ThresholdPreambleDetectionModel>();
2520  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2521  preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2522  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2523  Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
2524  heConfiguration->SetMaxTbPpduDelay(NanoSeconds(400));
2525  dev->SetHeConfiguration(heConfiguration);
2526  dev->SetPhy(m_phy);
2527  node->AddDevice(dev);
2528 }
2529 
2530 void
2532 {
2533  m_phy->Dispose();
2534  m_phy = nullptr;
2535 }
2536 
2537 void
2539 {
2540  RngSeedManager::SetSeed(1);
2541  RngSeedManager::SetRun(1);
2542  int64_t streamNumber = 0;
2543  m_phy->AssignStreams(streamNumber);
2544 
2545  double txPowerWatts = 0.01;
2546 
2547  {
2548  // Verify a single UL MU transmission with two stations belonging to the same BSS
2549  std::vector<uint64_t> uids{0};
2550  Simulator::Schedule(Seconds(1),
2552  this,
2553  uids[0],
2554  1,
2555  txPowerWatts,
2556  1001);
2557  Simulator::Schedule(Seconds(1) + NanoSeconds(100),
2559  this,
2560  uids[0],
2561  2,
2562  txPowerWatts,
2563  1002);
2564  // Check that we received a single UL MU transmission with the corresponding UID
2565  Simulator::Schedule(Seconds(1.0) + MicroSeconds(1),
2567  this,
2568  1,
2569  uids);
2570  Simulator::Schedule(Seconds(1.5), &TestMultipleHeTbPreambles::Reset, this);
2571  }
2572 
2573  {
2574  // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2575  // the second transmission arrives during the preamble detection window and with half the
2576  // power of the first transmission.
2577  std::vector<uint64_t> uids{1, 2};
2578  Simulator::Schedule(Seconds(2),
2580  this,
2581  uids[0],
2582  1,
2583  txPowerWatts,
2584  1001);
2585  Simulator::Schedule(Seconds(2) + NanoSeconds(100),
2587  this,
2588  uids[0],
2589  2,
2590  txPowerWatts,
2591  1002);
2592  Simulator::Schedule(Seconds(2) + NanoSeconds(200),
2594  this,
2595  uids[1],
2596  1,
2597  txPowerWatts / 2,
2598  1003);
2599  Simulator::Schedule(Seconds(2) + NanoSeconds(300),
2601  this,
2602  uids[1],
2603  2,
2604  txPowerWatts / 2,
2605  1004);
2606  // Check that we received the correct reception of 2 UL MU transmissions with the
2607  // corresponding UIDs
2608  Simulator::Schedule(Seconds(2.0) + MicroSeconds(1),
2610  this,
2611  2,
2612  uids);
2613  Simulator::Schedule(Seconds(2.5), &TestMultipleHeTbPreambles::Reset, this);
2614  // TODO: verify PPDUs from second UL MU transmission are dropped
2615  }
2616 
2617  {
2618  // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2619  // the second transmission arrives during the preamble detection window and with twice the
2620  // power of the first transmission.
2621  std::vector<uint64_t> uids{3, 4};
2622  Simulator::Schedule(Seconds(3),
2624  this,
2625  uids[0],
2626  1,
2627  txPowerWatts / 2,
2628  1001);
2629  Simulator::Schedule(Seconds(3) + NanoSeconds(100),
2631  this,
2632  uids[0],
2633  2,
2634  txPowerWatts / 2,
2635  1002);
2636  Simulator::Schedule(Seconds(3) + NanoSeconds(200),
2638  this,
2639  uids[1],
2640  1,
2641  txPowerWatts,
2642  1003);
2643  Simulator::Schedule(Seconds(3) + NanoSeconds(300),
2645  this,
2646  uids[1],
2647  2,
2648  txPowerWatts,
2649  1004);
2650  // Check that we received the correct reception of 2 UL MU transmissions with the
2651  // corresponding UIDs
2652  Simulator::Schedule(Seconds(3.0) + MicroSeconds(1),
2654  this,
2655  2,
2656  uids);
2657  Simulator::Schedule(Seconds(3.5), &TestMultipleHeTbPreambles::Reset, this);
2658  // TODO: verify PPDUs from first UL MU transmission are dropped
2659  }
2660 
2661  {
2662  // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2663  // the second transmission arrives during PHY header reception and with the same power as
2664  // the first transmission.
2665  std::vector<uint64_t> uids{5, 6};
2666  Simulator::Schedule(Seconds(4),
2668  this,
2669  uids[0],
2670  1,
2671  txPowerWatts,
2672  1001);
2673  Simulator::Schedule(Seconds(4) + NanoSeconds(100),
2675  this,
2676  uids[0],
2677  2,
2678  txPowerWatts,
2679  1002);
2680  Simulator::Schedule(Seconds(4) + MicroSeconds(5),
2682  this,
2683  uids[1],
2684  1,
2685  txPowerWatts,
2686  1003);
2687  Simulator::Schedule(Seconds(4) + MicroSeconds(5) + NanoSeconds(100),
2689  this,
2690  uids[1],
2691  2,
2692  txPowerWatts,
2693  1004);
2694  // Check that we received the correct reception of the first UL MU transmission with the
2695  // corresponding UID (second one dropped)
2696  Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
2698  this,
2699  1,
2700  std::vector<uint64_t>{uids[0]});
2701  // The packets of the second UL MU transmission should have been dropped
2702  Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
2704  this,
2705  1003 + 1004);
2706  Simulator::Schedule(Seconds(4.5), &TestMultipleHeTbPreambles::Reset, this);
2707  }
2708 
2709  {
2710  // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2711  // BSS, where the second transmission arrives during payload reception and with the same
2712  // power as the first transmission.
2713  std::vector<uint64_t> uids{7, 8};
2714  Simulator::Schedule(Seconds(5),
2716  this,
2717  uids[0],
2718  1,
2719  txPowerWatts,
2720  1001);
2721  Simulator::Schedule(Seconds(5) + NanoSeconds(100),
2723  this,
2724  uids[0],
2725  2,
2726  txPowerWatts,
2727  1002);
2728  Simulator::Schedule(Seconds(5) + MicroSeconds(50),
2730  this,
2731  uids[1],
2732  1,
2733  txPowerWatts,
2734  1003);
2735  Simulator::Schedule(Seconds(5) + MicroSeconds(50) + NanoSeconds(100),
2737  this,
2738  uids[1],
2739  2,
2740  txPowerWatts,
2741  1004);
2742  // Check that we received the correct reception of the first UL MU transmission with the
2743  // corresponding UID (second one dropped)
2744  Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
2746  this,
2747  1,
2748  std::vector<uint64_t>{uids[0]});
2749  // The packets of the second UL MU transmission should have been dropped
2750  Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
2752  this,
2753  1003 + 1004);
2754  Simulator::Schedule(Seconds(5.5), &TestMultipleHeTbPreambles::Reset, this);
2755  }
2756 
2757  {
2758  // Verify the correct reception of a single UL MU transmission with two stations belonging
2759  // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2760  // the configured delay spread of 400ns
2761  std::vector<uint64_t> uids{9};
2762  Simulator::Schedule(Seconds(6),
2764  this,
2765  uids[0],
2766  1,
2767  txPowerWatts,
2768  1001);
2769  Simulator::Schedule(Seconds(6) + NanoSeconds(500),
2771  this,
2772  uids[0],
2773  2,
2774  txPowerWatts,
2775  1002);
2776  // Check that we received a single UL MU transmission with the corresponding UID
2777  Simulator::Schedule(Seconds(6.0) + MicroSeconds(1),
2779  this,
2780  1,
2781  uids);
2782  // The first packet of 1001 bytes should be dropped because preamble is not detected after
2783  // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2784  // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2785  // second packet of 1002 bytes is dropped as well.
2786  Simulator::Schedule(Seconds(6.0) + MicroSeconds(5),
2788  this,
2789  1001 + 1002);
2790  Simulator::Schedule(Seconds(6.5), &TestMultipleHeTbPreambles::Reset, this);
2791  }
2792 
2793  Simulator::Run();
2794  Simulator::Destroy();
2795 }
2796 
2804 {
2805  public:
2807 
2808  void NotifyRxStart(Time duration) override
2809  {
2810  NS_LOG_FUNCTION(this << duration);
2812  ++m_notifyRxStart;
2813  m_lastRxSuccess = false;
2814  }
2815 
2816  void NotifyRxEndOk() override
2817  {
2818  NS_LOG_FUNCTION(this);
2820  ++m_notifyRxEnd;
2821  m_lastRxSuccess = true;
2822  }
2823 
2824  void NotifyRxEndError() override
2825  {
2826  NS_LOG_FUNCTION(this);
2828  ++m_notifyRxEnd;
2829  m_lastRxSuccess = false;
2830  }
2831 
2832  void NotifyTxStart(Time duration, double txPowerDbm) override
2833  {
2834  NS_LOG_FUNCTION(this << duration << txPowerDbm);
2835  }
2836 
2837  void NotifyCcaBusyStart(Time duration,
2838  WifiChannelListType channelType,
2839  const std::vector<Time>& /*per20MhzDurations*/) override
2840  {
2841  NS_LOG_FUNCTION(this << duration << channelType);
2842  }
2843 
2844  void NotifySwitchingStart(Time duration) override
2845  {
2846  }
2847 
2848  void NotifySleep() override
2849  {
2850  }
2851 
2852  void NotifyOff() override
2853  {
2854  }
2855 
2856  void NotifyWakeup() override
2857  {
2858  }
2859 
2860  void NotifyOn() override
2861  {
2862  }
2863 
2867  void Reset()
2868  {
2869  m_notifyRxStart = 0;
2870  m_notifyRxEnd = 0;
2871  m_lastRxStart = Seconds(0);
2872  m_lastRxEnd = Seconds(0);
2873  m_lastRxSuccess = false;
2874  }
2875 
2881  {
2882  return m_notifyRxStart;
2883  }
2884 
2889  uint32_t GetNumRxEndNotifications() const
2890  {
2891  return m_notifyRxEnd;
2892  }
2893 
2899  {
2900  return m_lastRxStart;
2901  }
2902 
2908  {
2909  return m_lastRxEnd;
2910  }
2911 
2916  bool IsLastRxSuccess() const
2917  {
2918  return m_lastRxSuccess;
2919  }
2920 
2921  private:
2922  uint32_t m_notifyRxStart{0};
2923  uint32_t m_notifyRxEnd{0};
2926  bool m_lastRxSuccess{false};
2927 };
2928 
2936 {
2937  public:
2942  {
2943  NONE = 0,
2947  };
2948 
2950  ~TestUlOfdmaPhyTransmission() override;
2951 
2952  private:
2953  void DoSetup() override;
2954  void DoTeardown() override;
2955  void DoRun() override;
2956 
2964  WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2965  std::size_t index,
2966  uint8_t bssColor) const;
2973  void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2983  void SendHeTbPpdu(uint16_t txStaId,
2984  std::size_t index,
2985  std::size_t payloadSize,
2986  uint64_t uid,
2987  uint8_t bssColor,
2988  bool incrementUid);
2989 
2997  void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
2998 
3004  void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3005 
3011  void SetPsdLimit(Ptr<WifiPhy> phy, double psdLimit);
3012 
3018  void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3022  void StopInterference();
3023 
3027  void RunOne();
3028 
3035  void CheckRxFromSta1(uint32_t expectedSuccess,
3036  uint32_t expectedFailures,
3037  uint32_t expectedBytes);
3038 
3045  void CheckRxFromSta2(uint32_t expectedSuccess,
3046  uint32_t expectedFailures,
3047  uint32_t expectedBytes);
3048 
3056  WifiSpectrumBandInfo band,
3057  double expectedRxPower);
3065  WifiSpectrumBandInfo band,
3066  double expectedRxPower);
3067 
3071  void VerifyEventsCleared();
3072 
3081 
3088  void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3096  void CheckApRxEnd(uint32_t expectedNotifications,
3097  Time expectedLastNotification,
3098  bool expectedSuccess);
3099 
3103  void Reset();
3104 
3112  void RxSuccess(Ptr<const WifiPsdu> psdu,
3113  RxSignalInfo rxSignalInfo,
3114  WifiTxVector txVector,
3115  std::vector<bool> statusPerMpdu);
3116 
3121  void RxFailure(Ptr<const WifiPsdu> psdu);
3122 
3143  void ScheduleTest(Time delay,
3144  bool solicited,
3145  WifiPhyState expectedStateAtEnd,
3146  uint32_t expectedSuccessFromSta1,
3147  uint32_t expectedFailuresFromSta1,
3148  uint32_t expectedBytesFromSta1,
3149  uint32_t expectedSuccessFromSta2,
3150  uint32_t expectedFailuresFromSta2,
3151  uint32_t expectedBytesFromSta2,
3152  bool scheduleTxSta1 = true,
3153  Time ulTimeDifference = Seconds(0),
3154  WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3155  TrigVectorInfo error = NONE);
3156 
3167  double rxPowerNonOfdmaRu1,
3168  double rxPowerNonOfdmaRu2,
3169  double rxPowerOfdmaRu1,
3170  double rxPowerOfdmaRu2);
3176  void LogScenario(std::string log) const;
3177 
3182 
3183  std::shared_ptr<OfdmaTestPhyListener>
3185 
3187 
3194 
3195  uint16_t m_frequency;
3196  uint16_t m_channelWidth;
3198 };
3199 
3201  : TestCase("UL-OFDMA PHY test"),
3202  m_countRxSuccessFromSta1(0),
3203  m_countRxSuccessFromSta2(0),
3204  m_countRxFailureFromSta1(0),
3205  m_countRxFailureFromSta2(0),
3206  m_countRxBytesFromSta1(0),
3207  m_countRxBytesFromSta2(0),
3208  m_frequency(DEFAULT_FREQUENCY),
3209  m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3210  m_expectedPpduDuration(NanoSeconds(271200))
3211 {
3212 }
3213 
3214 void
3216  std::size_t payloadSize,
3217  uint64_t uid,
3218  uint8_t bssColor)
3219 {
3220  NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3221  WifiConstPsduMap psdus;
3222 
3223  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
3224  0,
3226  800,
3227  1,
3228  1,
3229  0,
3231  false,
3232  false,
3233  false,
3234  bssColor);
3235 
3236  Ptr<Packet> pkt = Create<Packet>(payloadSize);
3237  WifiMacHeader hdr;
3239  hdr.SetQosTid(0);
3240  hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3241  std::ostringstream addr;
3242  addr << "00:00:00:00:00:0" << txStaId;
3243  hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3244  hdr.SetSequenceNumber(1);
3245  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3246  psdus.insert(std::make_pair(SU_STA_ID, psdu));
3247 
3249  if (txStaId == 1)
3250  {
3251  phy = m_phySta1;
3252  }
3253  else if (txStaId == 2)
3254  {
3255  phy = m_phySta2;
3256  }
3257  else if (txStaId == 3)
3258  {
3259  phy = m_phySta3;
3260  }
3261  else if (txStaId == 0)
3262  {
3263  phy = m_phyAp;
3264  }
3265  phy->SetPpduUid(uid);
3266  phy->Send(psdus, txVector);
3267 }
3268 
3271  std::size_t index,
3272  uint8_t bssColor) const
3273 {
3274  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
3275  0,
3277  1600,
3278  1,
3279  1,
3280  0,
3282  false,
3283  false,
3284  false,
3285  bssColor);
3286 
3287  HeRu::RuType ruType = HeRu::RU_106_TONE;
3288  if (m_channelWidth == 20)
3289  {
3290  ruType = HeRu::RU_106_TONE;
3291  }
3292  else if (m_channelWidth == 40)
3293  {
3294  ruType = HeRu::RU_242_TONE;
3295  }
3296  else if (m_channelWidth == 80)
3297  {
3298  ruType = HeRu::RU_484_TONE;
3299  }
3300  else if (m_channelWidth == 160)
3301  {
3302  ruType = HeRu::RU_996_TONE;
3303  }
3304  else
3305  {
3306  NS_ASSERT_MSG(false, "Unsupported channel width");
3307  }
3308 
3309  bool primary80MHz = true;
3310  if (m_channelWidth == 160 && index == 2)
3311  {
3312  primary80MHz = false;
3313  index = 1;
3314  }
3315  HeRu::RuSpec ru(ruType, index, primary80MHz);
3316  txVector.SetRu(ru, txStaId);
3317  txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3318  txVector.SetNss(1, txStaId);
3319  return txVector;
3320 }
3321 
3322 void
3324 {
3325  uint16_t channelWidth = m_channelWidth;
3326  if (error == CHANNEL_WIDTH)
3327  {
3328  channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
3329  }
3330 
3331  WifiTxVector txVector(HePhy::GetHeMcs7(),
3332  0,
3334  1600,
3335  1,
3336  1,
3337  0,
3338  channelWidth,
3339  false,
3340  false,
3341  false,
3342  bssColor);
3343 
3344  HeRu::RuType ruType = HeRu::RU_106_TONE;
3345  if (channelWidth == 20)
3346  {
3347  ruType = HeRu::RU_106_TONE;
3348  }
3349  else if (channelWidth == 40)
3350  {
3351  ruType = HeRu::RU_242_TONE;
3352  }
3353  else if (channelWidth == 80)
3354  {
3355  ruType = HeRu::RU_484_TONE;
3356  }
3357  else if (channelWidth == 160)
3358  {
3359  ruType = HeRu::RU_996_TONE;
3360  }
3361  else
3362  {
3363  NS_ASSERT_MSG(false, "Unsupported channel width");
3364  }
3365 
3366  uint16_t aid1 = (error == AID ? 3 : 1);
3367  uint16_t aid2 = (error == AID ? 4 : 2);
3368 
3369  HeRu::RuSpec ru1(ruType, 1, true);
3370  txVector.SetRu(ru1, aid1);
3371  txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3372  txVector.SetNss(1, aid1);
3373 
3374  HeRu::RuSpec ru2(ruType, (channelWidth == 160 ? 1 : 2), (channelWidth != 160));
3375  txVector.SetRu(ru2, aid2);
3376  txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3377  txVector.SetNss(1, aid2);
3378 
3379  uint16_t length;
3380  std::tie(length, m_expectedPpduDuration) =
3381  HePhy::ConvertHeTbPpduDurationToLSigLength(m_expectedPpduDuration,
3382  txVector,
3383  m_phyAp->GetPhyBand());
3384  if (error == UL_LENGTH)
3385  {
3386  ++length;
3387  }
3388  txVector.SetLength(length);
3389  auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
3390  hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3391 }
3392 
3393 void
3395  std::size_t index,
3396  std::size_t payloadSize,
3397  uint64_t uid,
3398  uint8_t bssColor,
3399  bool incrementUid)
3400 {
3401  NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3402  WifiConstPsduMap psdus;
3403 
3404  if (incrementUid)
3405  {
3406  ++uid;
3407  }
3408 
3409  WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3410  Ptr<Packet> pkt = Create<Packet>(payloadSize);
3411  WifiMacHeader hdr;
3413  hdr.SetQosTid(0);
3414  hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3415  std::ostringstream addr;
3416  addr << "00:00:00:00:00:0" << txStaId;
3417  hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3418  hdr.SetSequenceNumber(1);
3419  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3420  psdus.insert(std::make_pair(txStaId, psdu));
3421 
3423  if (txStaId == 1)
3424  {
3425  phy = m_phySta1;
3426  }
3427  else if (txStaId == 2)
3428  {
3429  phy = m_phySta2;
3430  }
3431  else if (txStaId == 3)
3432  {
3433  phy = m_phySta3;
3434  }
3435 
3436  Time txDuration =
3437  phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
3438  txVector.SetLength(
3439  HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3440 
3441  phy->SetPpduUid(uid);
3442  phy->Send(psdus, txVector);
3443 }
3444 
3445 void
3447 {
3448  NS_LOG_FUNCTION(this << duration);
3449  m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
3450  m_phyInterferer->SetPeriod(duration);
3452  Simulator::Schedule(duration, &TestUlOfdmaPhyTransmission::StopInterference, this);
3453 }
3454 
3455 void
3457 {
3458  m_phyInterferer->Stop();
3459 }
3460 
3462 {
3463 }
3464 
3465 void
3467  RxSignalInfo rxSignalInfo,
3468  WifiTxVector txVector,
3469  std::vector<bool> /*statusPerMpdu*/)
3470 {
3471  NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3472  if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3473  {
3475  m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3476  }
3477  else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3478  {
3480  m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3481  }
3482 }
3483 
3484 void
3486 {
3487  NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3488  if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3489  {
3491  }
3492  else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3493  {
3495  }
3496 }
3497 
3498 void
3500  uint32_t expectedFailures,
3501  uint32_t expectedBytes)
3502 {
3504  expectedSuccess,
3505  "The number of successfully received packets from STA 1 is not correct!");
3508  expectedFailures,
3509  "The number of unsuccessfuly received packets from STA 1 is not correct!");
3511  expectedBytes,
3512  "The number of bytes received from STA 1 is not correct!");
3513 }
3514 
3515 void
3517  uint32_t expectedFailures,
3518  uint32_t expectedBytes)
3519 {
3521  expectedSuccess,
3522  "The number of successfully received packets from STA 2 is not correct!");
3525  expectedFailures,
3526  "The number of unsuccessfuly received packets from STA 2 is not correct!");
3528  expectedBytes,
3529  "The number of bytes received from STA 2 is not correct!");
3530 }
3531 
3532 void
3534  WifiSpectrumBandInfo band,
3535  double expectedRxPower)
3536 {
3537  Ptr<Event> event = phy->GetCurrentEvent();
3538  NS_ASSERT(event);
3539  auto rxPower = event->GetRxPowerW(band);
3540  NS_LOG_FUNCTION(this << band << expectedRxPower << rxPower);
3541  // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3542  NS_TEST_ASSERT_MSG_EQ_TOL(rxPower,
3543  expectedRxPower,
3544  5e-3,
3545  "RX power " << rxPower << " over (" << band
3546  << ") does not match expected power " << expectedRxPower
3547  << " at " << Simulator::Now());
3548 }
3549 
3550 void
3552  WifiSpectrumBandInfo band,
3553  double expectedRxPower)
3554 {
3560  NS_LOG_FUNCTION(this << band << expectedRxPower);
3561  double step = 5e-3;
3562  if (expectedRxPower > 0.0)
3563  {
3565  phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3566  true,
3567  "At least " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3568  << Simulator::Now());
3570  phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3571  false,
3572  "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3573  << Simulator::Now());
3574  }
3575  else
3576  {
3578  phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3579  false,
3580  "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3581  << Simulator::Now());
3582  }
3583 }
3584 
3585 void
3587 {
3589  nullptr,
3590  "m_currentEvent for AP was not cleared");
3592  nullptr,
3593  "m_currentEvent for STA 1 was not cleared");
3595  nullptr,
3596  "m_currentEvent for STA 2 was not cleared");
3597 }
3598 
3599 void
3601 {
3602  // This is needed to make sure PHY state will be checked as the last event if a state change
3603  // occurred at the exact same time as the check
3604  Simulator::ScheduleNow(&TestUlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
3605 }
3606 
3607 void
3609  WifiPhyState expectedState)
3610 {
3611  WifiPhyState currentState;
3612  PointerValue ptr;
3613  phy->GetAttribute("State", ptr);
3614  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
3615  currentState = state->GetState();
3616  NS_LOG_FUNCTION(this << currentState);
3617  NS_TEST_ASSERT_MSG_EQ(currentState,
3618  expectedState,
3619  "PHY State " << currentState << " does not match expected state "
3620  << expectedState << " at " << Simulator::Now());
3621 }
3622 
3623 void
3624 TestUlOfdmaPhyTransmission::CheckApRxStart(uint32_t expectedNotifications,
3625  Time expectedLastNotification)
3626 {
3627  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxStartNotifications(),
3628  expectedNotifications,
3629  "Number of RX start notifications "
3630  << m_apPhyStateListener->GetNumRxStartNotifications()
3631  << " does not match expected count " << expectedNotifications
3632  << " for AP at " << Simulator::Now());
3633  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxStartNotification(),
3634  expectedLastNotification,
3635  "Last time RX start notification has been received "
3636  << m_apPhyStateListener->GetLastRxStartNotification()
3637  << " does not match expected time " << expectedLastNotification
3638  << " for AP at " << Simulator::Now());
3639 }
3640 
3641 void
3642 TestUlOfdmaPhyTransmission::CheckApRxEnd(uint32_t expectedNotifications,
3643  Time expectedLastNotification,
3644  bool expectedSuccess)
3645 {
3646  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxEndNotifications(),
3647  expectedNotifications,
3648  "Number of RX end notifications "
3649  << m_apPhyStateListener->GetNumRxEndNotifications()
3650  << " does not match expected count " << expectedNotifications
3651  << " for AP at " << Simulator::Now());
3652  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxEndNotification(),
3653  expectedLastNotification,
3654  "Last time RX end notification has been received "
3655  << m_apPhyStateListener->GetLastRxEndNotification()
3656  << " does not match expected time " << expectedLastNotification
3657  << " for AP at " << Simulator::Now());
3658  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->IsLastRxSuccess(),
3659  expectedSuccess,
3660  "Last time RX end notification indicated a "
3661  << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3662  << " but expected a " << (expectedSuccess ? "success" : "failure")
3663  << " for AP at " << Simulator::Now());
3664 }
3665 
3666 void
3668 {
3675  m_phySta1->SetPpduUid(0);
3678  SetBssColor(m_phyAp, 0);
3679  m_apPhyStateListener->Reset();
3680 }
3681 
3682 void
3684 {
3685  Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3686  Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3687  heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3688 }
3689 
3690 void
3692 {
3693  NS_LOG_FUNCTION(this << phy << psdLimit);
3694  phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3695 }
3696 
3697 void
3699 {
3700  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
3701  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
3702  lossModel->SetFrequency(m_frequency);
3703  spectrumChannel->AddPropagationLossModel(lossModel);
3705  CreateObject<ConstantSpeedPropagationDelayModel>();
3706  spectrumChannel->SetPropagationDelayModel(delayModel);
3707 
3708  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3709  CreateObject<ThresholdPreambleDetectionModel>();
3710  preambleDetectionModel->SetAttribute(
3711  "MinimumRssi",
3712  DoubleValue(
3713  -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3714  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3715 
3716  Ptr<Node> apNode = CreateObject<Node>();
3717  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
3719  Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
3720  apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3721  apDev->SetMac(apMac);
3722  m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
3723  Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
3724  apDev->SetHeConfiguration(heConfiguration);
3725  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
3726  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3727  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
3728  m_phyAp->SetErrorRateModel(apErrorModel);
3729  m_phyAp->SetDevice(apDev);
3730  m_phyAp->AddChannel(spectrumChannel);
3734  m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3735  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
3736  m_phyAp->SetMobility(apMobility);
3737  m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3739  apDev->SetPhy(m_phyAp);
3740  apMac->SetWifiPhys({m_phyAp});
3741  apNode->AggregateObject(apMobility);
3742  apNode->AddDevice(apDev);
3743 
3744  Ptr<Node> sta1Node = CreateObject<Node>();
3745  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
3747  sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3748  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
3749  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
3750  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3751  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
3752  m_phySta1->SetErrorRateModel(sta1ErrorModel);
3753  m_phySta1->SetDevice(sta1Dev);
3754  m_phySta1->AddChannel(spectrumChannel);
3756  m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3757  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
3758  m_phySta1->SetMobility(sta1Mobility);
3759  sta1Dev->SetPhy(m_phySta1);
3760  sta1Node->AggregateObject(sta1Mobility);
3761  sta1Node->AddDevice(sta1Dev);
3762 
3763  Ptr<Node> sta2Node = CreateObject<Node>();
3764  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
3766  sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3767  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
3768  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
3769  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3770  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
3771  m_phySta2->SetErrorRateModel(sta2ErrorModel);
3772  m_phySta2->SetDevice(sta2Dev);
3773  m_phySta2->AddChannel(spectrumChannel);
3775  m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3776  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
3777  m_phySta2->SetMobility(sta2Mobility);
3778  sta2Dev->SetPhy(m_phySta2);
3779  sta2Node->AggregateObject(sta2Mobility);
3780  sta2Node->AddDevice(sta2Dev);
3781 
3782  Ptr<Node> sta3Node = CreateObject<Node>();
3783  Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
3785  sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3786  m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
3787  Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
3788  m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3789  Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
3790  m_phySta3->SetErrorRateModel(sta3ErrorModel);
3791  m_phySta3->SetDevice(sta3Dev);
3792  m_phySta3->AddChannel(spectrumChannel);
3794  m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3795  Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
3796  m_phySta3->SetMobility(sta3Mobility);
3797  sta3Dev->SetPhy(m_phySta3);
3798  sta3Node->AggregateObject(sta3Mobility);
3799  sta3Node->AddDevice(sta3Dev);
3800 
3801  Ptr<Node> interfererNode = CreateObject<Node>();
3802  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
3803  m_phyInterferer = CreateObject<WaveformGenerator>();
3804  m_phyInterferer->SetDevice(interfererDev);
3805  m_phyInterferer->SetChannel(spectrumChannel);
3807  interfererNode->AddDevice(interfererDev);
3808 
3809  // Configure power attributes of all wifi devices
3810  std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3811  for (auto& phy : phys)
3812  {
3813  phy->SetAttribute("TxGain", DoubleValue(1.0));
3814  phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3815  phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3816  phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3817  phy->SetAttribute("RxGain", DoubleValue(2.0));
3818  // test assumes no rejection power for simplicity
3819  phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3820  phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3821  phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3822  }
3823 }
3824 
3825 void
3827 {
3828  m_phyAp->Dispose();
3829  m_phyAp = nullptr;
3830  m_phySta1->Dispose();
3831  m_phySta1 = nullptr;
3832  m_phySta2->Dispose();
3833  m_phySta2 = nullptr;
3834  m_phySta3->Dispose();
3835  m_phySta3 = nullptr;
3837  m_phyInterferer = nullptr;
3838 }
3839 
3840 void
3842 {
3843  NS_LOG_INFO(log);
3844 }
3845 
3846 void
3848  bool solicited,
3849  WifiPhyState expectedStateAtEnd,
3850  uint32_t expectedSuccessFromSta1,
3851  uint32_t expectedFailuresFromSta1,
3852  uint32_t expectedBytesFromSta1,
3853  uint32_t expectedSuccessFromSta2,
3854  uint32_t expectedFailuresFromSta2,
3855  uint32_t expectedBytesFromSta2,
3856  bool scheduleTxSta1,
3857  Time ulTimeDifference,
3858  WifiPhyState expectedStateBeforeEnd,
3859  TrigVectorInfo error)
3860 {
3861  static uint64_t uid = 0;
3862 
3863  // AP sends an SU packet preceding HE TB PPDUs
3864  Simulator::Schedule(delay - MilliSeconds(10),
3866  this,
3867  0,
3868  50,
3869  ++uid,
3870  0);
3871  if (!solicited)
3872  {
3873  // UID of TB PPDUs will be different than the one of the preceding frame
3874  ++uid;
3875  }
3876  else
3877  {
3878  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetTrigVector, this, 0, error);
3879  }
3880  // STA1 and STA2 send MU UL PPDUs addressed to AP
3881  Simulator::Schedule(delay - MilliSeconds(1),
3883  m_apPhyStateListener.get());
3884  if (scheduleTxSta1)
3885  {
3886  Simulator::Schedule(delay,
3888  this,
3889  1,
3890  1,
3891  1000,
3892  uid,
3893  0,
3894  false);
3895  }
3896  Simulator::Schedule(delay + ulTimeDifference,
3898  this,
3899  2,
3900  2,
3901  1001,
3902  uid,
3903  0,
3904  false);
3905 
3906  // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3907  Simulator::Schedule(delay + m_expectedPpduDuration - NanoSeconds(1),
3909  this,
3910  m_phyAp,
3911  expectedStateBeforeEnd);
3912  Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3914  this,
3915  m_phyAp,
3916  expectedStateAtEnd);
3917  // TODO: add checks on TX stop for STAs
3918 
3919  if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3920  expectedFailuresFromSta2 >
3921  0)
3922  {
3923  // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3924  const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3925  // The expected time at which the reception is started corresponds to the time at which the
3926  // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3927  const Time expectedPayloadStart = delay + MicroSeconds(48);
3928  // The expected time at which the reception is terminated corresponds to the time at which
3929  // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3930  // received HE TB PPDU and the last received HE TB PPDU.
3931  const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3932  // At the end of the transmission, verify that a single RX start notification shall have
3933  // been notified when the reception of the first HE RB PPDU starts.
3934  Simulator::Schedule(expectedPayloadEnd,
3936  this,
3937  1,
3938  Simulator::Now() + expectedPayloadStart);
3939  // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3940  // notification shall have been notified when the reception of the last HE RB PPDU ends
3941  Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3943  this,
3944  1,
3945  Simulator::Now() + expectedPayloadEnd,
3946  isSuccess);
3947  }
3948 
3949  delay += MilliSeconds(100);
3950  // Check reception state from STA 1
3951  Simulator::Schedule(delay,
3953  this,
3954  expectedSuccessFromSta1,
3955  expectedFailuresFromSta1,
3956  expectedBytesFromSta1);
3957  // Check reception state from STA 2
3958  Simulator::Schedule(delay,
3960  this,
3961  expectedSuccessFromSta2,
3962  expectedFailuresFromSta2,
3963  expectedBytesFromSta2);
3964  // Verify events data have been cleared
3965  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::VerifyEventsCleared, this);
3966 
3967  delay += MilliSeconds(100);
3968  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::Reset, this);
3969 }
3970 
3971 void
3973  double rxPowerNonOfdmaRu1,
3974  double rxPowerNonOfdmaRu2,
3975  double rxPowerOfdmaRu1,
3976  double rxPowerOfdmaRu2)
3977 {
3978  Time detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3979  WifiTxVector txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3980  WifiTxVector txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3981  Ptr<const HePhy> hePhy = m_phyAp->GetHePhy();
3982  Time nonOfdmaDuration = hePhy->CalculateNonHeDurationForHeTb(txVectorSta2);
3983  NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonHeDurationForHeTb(txVectorSta1));
3984 
3985  std::vector<double> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3986  std::vector<WifiSpectrumBandInfo> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3987  hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
3988  std::vector<double> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
3989  std::vector<WifiSpectrumBandInfo> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
3990  hePhy->GetRuBandForRx(txVectorSta2, 2)};
3991 
3992  for (uint8_t i = 0; i < 2; ++i)
3993  {
3997  // Check received power on non-OFDMA portion
3998  Simulator::Schedule(
3999  delay + detectionDuration +
4000  NanoSeconds(1), // just after beginning of portion (once event is stored)
4002  this,
4003  m_phyAp,
4004  nonOfdmaBand[i],
4005  rxPowerNonOfdma[i]);
4006  Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4008  this,
4009  m_phyAp,
4010  nonOfdmaBand[i],
4011  rxPowerNonOfdma[i]);
4012  // Check received power on OFDMA portion
4013  Simulator::Schedule(delay + nonOfdmaDuration +
4014  NanoSeconds(1), // just after beginning of portion
4016  this,
4017  m_phyAp,
4018  ofdmaBand[i],
4019  rxPowerOfdma[i]);
4020  Simulator::Schedule(delay + m_expectedPpduDuration -
4021  NanoSeconds(1), // just before end of portion
4023  this,
4024  m_phyAp,
4025  ofdmaBand[i],
4026  rxPowerOfdma[i]);
4027 
4033  // Check received power on non-OFDMA portion
4034  Simulator::Schedule(
4035  delay + detectionDuration +
4036  NanoSeconds(1), // just after beginning of portion (once event is stored)
4038  this,
4039  m_phySta3,
4040  nonOfdmaBand[i],
4041  rxPowerNonOfdma[i]);
4042  Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4044  this,
4045  m_phySta3,
4046  nonOfdmaBand[i],
4047  rxPowerNonOfdma[i]);
4048  // Check received power on OFDMA portion
4049  Simulator::Schedule(delay + nonOfdmaDuration +
4050  NanoSeconds(1), // just after beginning of portion
4052  this,
4053  m_phySta3,
4054  ofdmaBand[i],
4055  rxPowerOfdma[i]);
4056  Simulator::Schedule(delay + m_expectedPpduDuration -
4057  NanoSeconds(1), // just before end of portion
4059  this,
4060  m_phySta3,
4061  ofdmaBand[i],
4062  rxPowerOfdma[i]);
4063  }
4064 
4065  if (rxPowerOfdmaRu1 != 0.0)
4066  {
4072  double rxPowerNonOfdmaSta1Only =
4073  (m_channelWidth >= 40)
4074  ? rxPowerNonOfdma[0]
4075  : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4076  // Check received power on non-OFDMA portion
4077  Simulator::Schedule(
4078  delay + detectionDuration +
4079  NanoSeconds(1), // just after beginning of portion (once event is stored)
4081  this,
4082  m_phySta2,
4083  nonOfdmaBand[0],
4084  rxPowerNonOfdmaSta1Only);
4085  Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4087  this,
4088  m_phySta2,
4089  nonOfdmaBand[0],
4090  rxPowerNonOfdmaSta1Only);
4091  // Check received power on OFDMA portion
4092  Simulator::Schedule(delay + nonOfdmaDuration +
4093  NanoSeconds(1), // just after beginning of portion
4095  this,
4096  m_phySta2,
4097  ofdmaBand[0],
4098  rxPowerOfdma[0]);
4099  Simulator::Schedule(delay + m_expectedPpduDuration -
4100  NanoSeconds(1), // just before end of portion
4102  this,
4103  m_phySta2,
4104  ofdmaBand[0],
4105  rxPowerOfdma[0]);
4106  }
4107 }
4108 
4109 void
4111 {
4112  RngSeedManager::SetSeed(1);
4113  RngSeedManager::SetRun(1);
4114  int64_t streamNumber = 0;
4115  m_phyAp->AssignStreams(streamNumber);
4116  m_phySta1->AssignStreams(streamNumber);
4117  m_phySta2->AssignStreams(streamNumber);
4118  m_phySta3->AssignStreams(streamNumber);
4119 
4120  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
4121  m_frequency,
4125 
4134 
4135  Time delay = Seconds(0.0);
4136  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::Reset, this);
4137  delay += Seconds(1.0);
4138 
4147  //---------------------------------------------------------------------------
4148  // Verify that both solicited HE TB PPDUs have been corrected received
4149  Simulator::Schedule(delay,
4151  this,
4152  "Reception of solicited HE TB PPDUs");
4153  ScheduleTest(delay,
4154  true,
4156  1,
4157  0,
4158  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4159  1,
4160  0,
4161  1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4162  delay += Seconds(1.0);
4163 
4164  //---------------------------------------------------------------------------
4165  // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4166  // corrected received
4167  Simulator::Schedule(
4168  delay,
4170  this,
4171  "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4172  ScheduleTest(delay,
4173  true,
4175  1,
4176  0,
4177  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4178  1,
4179  0,
4180  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4181  true,
4182  NanoSeconds(100));
4183  delay += Seconds(1.0);
4184 
4185  //---------------------------------------------------------------------------
4186  // Verify that no unsolicited HE TB PPDU is received
4187  Simulator::Schedule(delay,
4189  this,
4190  "Dropping of unsolicited HE TB PPDUs");
4191  ScheduleTest(delay,
4192  false,
4194  0,
4195  0,
4196  0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4197  0,
4198  0,
4199  0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4200  true,
4201  Seconds(0),
4203  delay += Seconds(1.0);
4204 
4205  //---------------------------------------------------------------------------
4206  // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4207  Simulator::Schedule(delay,
4209  this,
4210  "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4211  ScheduleTest(delay,
4212  true,
4214  0,
4215  0,
4216  0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4217  0,
4218  0,
4219  0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4220  true,
4221  Seconds(0),
4223  CHANNEL_WIDTH);
4224  delay += Seconds(1.0);
4225 
4226  //---------------------------------------------------------------------------
4227  // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4228  Simulator::Schedule(delay,
4230  this,
4231  "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4232  ScheduleTest(delay,
4233  true,
4235  0,
4236  0,
4237  0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4238  0,
4239  0,
4240  0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4241  true,
4242  Seconds(0),
4244  UL_LENGTH);
4245  delay += Seconds(1.0);
4246 
4247  //---------------------------------------------------------------------------
4248  // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4249  Simulator::Schedule(delay,
4251  this,
4252  "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4253  ScheduleTest(delay,
4254  true,
4256  0,
4257  0,
4258  0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4259  0,
4260  0,
4261  0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4262  true,
4263  Seconds(0),
4265  AID);
4266  delay += Seconds(1.0);
4267 
4268  //---------------------------------------------------------------------------
4269  // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4270  // impacted
4271  Simulator::Schedule(
4272  delay,
4274  this,
4275  "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4276  // A strong non-wifi interference is generated on RU 1 during PSDU reception
4277  BandInfo bandInfo;
4278  bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
4279  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4280  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4281  Bands bands;
4282  bands.push_back(bandInfo);
4283 
4284  Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4285  Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4286  double interferencePower = 0.1; // watts
4287  *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
4288 
4289  Simulator::Schedule(delay + MicroSeconds(50),
4291  this,
4292  interferencePsdRu1,
4293  MilliSeconds(100));
4294  ScheduleTest(
4295  delay,
4296  true,
4297  WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4298  // interference
4299  0,
4300  1,
4301  0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4302  1,
4303  0,
4304  1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4305  delay += Seconds(1.0);
4306 
4307  //---------------------------------------------------------------------------
4308  // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4309  // impacted
4310  Simulator::Schedule(
4311  delay,
4313  this,
4314  "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4315  // A strong non-wifi interference is generated on RU 2 during PSDU reception
4316  bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
4317  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4318  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4319  bands.clear();
4320  bands.push_back(bandInfo);
4321 
4322  Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4323  Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4324  *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
4325 
4326  Simulator::Schedule(delay + MicroSeconds(50),
4328  this,
4329  interferencePsdRu2,
4330  MilliSeconds(100));
4331  ScheduleTest(delay,
4332  true,
4333  (m_channelWidth >= 40)
4335  : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4336  // generated in its primary channel
4337  1,
4338  0,
4339  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4340  0,
4341  1,
4342  0); // Reception of the PSDU from STA 2 should have failed (since interference
4343  // occupies RU 2)
4344  delay += Seconds(1.0);
4345 
4346  //---------------------------------------------------------------------------
4347  // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4348  // been impacted
4349  Simulator::Schedule(delay,
4351  this,
4352  "Reception of solicited HE TB PPDUs with interference on the full band "
4353  "during PSDU reception");
4354  // A strong non-wifi interference is generated on the full band during PSDU reception
4355  bandInfo.fc = m_frequency * 1e6;
4356  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
4357  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
4358  bands.clear();
4359  bands.push_back(bandInfo);
4360 
4361  Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4362  Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4363  *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
4364 
4365  Simulator::Schedule(delay + MicroSeconds(50),
4367  this,
4368  interferencePsdAll,
4369  MilliSeconds(100));
4370  ScheduleTest(
4371  delay,
4372  true,
4373  WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4374  // interference
4375  0,
4376  1,
4377  0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4378  0,
4379  1,
4380  0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4381  // 2)
4382  delay += Seconds(1.0);
4383 
4384  //---------------------------------------------------------------------------
4385  // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4386  // solicited HE TB PPDUs have been impacted if they are on the same
4387  // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4388  Simulator::Schedule(delay,
4390  this,
4391  "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4392  "1 during PSDU reception");
4393  // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4394  Simulator::Schedule(delay + MicroSeconds(50),
4396  this,
4397  3,
4398  1,
4399  1002,
4400  1,
4401  0,
4402  false);
4403  // Expected figures from STA 2
4404  uint32_t succ;
4405  uint32_t fail;
4406  uint32_t bytes;
4407  if (m_channelWidth > 20)
4408  {
4409  // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4410  // interference from STA 3 on distinct 20 MHz channel)
4411  succ = 1;
4412  fail = 0;
4413  bytes = 1001;
4414  }
4415  else
4416  {
4417  // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4418  // same 20 MHz channel)
4419  succ = 0;
4420  fail = 1;
4421  bytes = 0;
4422  }
4423  ScheduleTest(delay,
4424  true,
4425  WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4426  // interference on measurement channel width
4427  0,
4428  1,
4429  0, // Reception of the PSDU from STA 1 should have failed (since interference from
4430  // STA 3 on same 20 MHz channel)
4431  succ,
4432  fail,
4433  bytes);
4434  delay += Seconds(1.0);
4435 
4436  //---------------------------------------------------------------------------
4437  // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4438  // solicited HE TB PPDUs have been impacted if they are on the same
4439  // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4440  Simulator::Schedule(delay,
4442  this,
4443  "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4444  "2 during PSDU reception");
4445  // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4446  Simulator::Schedule(delay + MicroSeconds(50),
4448  this,
4449  3,
4450  2,
4451  1002,
4452  1,
4453  0,
4454  false);
4455  // Expected figures from STA 1
4456  if (m_channelWidth > 20)
4457  {
4458  // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4459  // interference from STA 3 on distinct 20 MHz channel)
4460  succ = 1;
4461  fail = 0;
4462  bytes = 1000;
4463  }
4464  else
4465  {
4466  // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4467  // same 20 MHz channel)
4468  succ = 0;
4469  fail = 1;
4470  bytes = 0;
4471  }
4472  ScheduleTest(delay,
4473  true,
4474  (m_channelWidth >= 40)
4476  : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4477  // TB PPDU on primary channel
4478  succ,
4479  fail,
4480  bytes,
4481  0,
4482  1,
4483  0); // Reception of the PSDU from STA 2 should have failed (since interference from
4484  // STA 3 on same 20 MHz channel)
4485  delay += Seconds(1.0);
4486 
4487  //---------------------------------------------------------------------------
4488  // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4489  // impacted
4490  Simulator::Schedule(
4491  delay,
4493  this,
4494  "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4495  // One HE SU arrives at AP during the 400ns window
4496  Simulator::Schedule(delay + NanoSeconds(300),
4498  this,
4499  3,
4500  1002,
4501  1,
4502  0);
4503  ScheduleTest(
4504  delay,
4505  true,
4507  0,
4508  1,
4509  0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4510  0,
4511  1,
4512  0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4513  delay += Seconds(1.0);
4514 
4515  //---------------------------------------------------------------------------
4516  // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4517  // received
4518  Simulator::Schedule(delay,
4520  this,
4521  "Reception of solicited HE TB PPDU only on RU 2");
4522  // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4523  // otherwise
4524  Simulator::Schedule(delay + m_expectedPpduDuration - NanoSeconds(1),
4526  this,
4527  m_phySta3,
4528  (m_channelWidth >= 40)
4530  : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4531  // IDLE if HE TB PPDU on primary channel
4532  ScheduleTest(delay,
4533  true,
4535  0,
4536  0,
4537  0, // No transmission scheduled for STA 1
4538  1,
4539  0,
4540  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4541  false,
4542  Seconds(0),
4543  WifiPhyState::RX); // Measurement channel is total channel width
4544  delay += Seconds(1.0);
4545 
4546  //---------------------------------------------------------------------------
4547  // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4548  Simulator::Schedule(delay,
4550  this,
4551  "Measure power for reception of HE TB PPDU only on RU 2");
4552  double rxPower =
4553  DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4555  (m_channelWidth >= 40) ? 0.0 : rxPower,
4556  rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4557  0.0,
4558  rxPower);
4559  ScheduleTest(delay,
4560  true,
4562  0,
4563  0,
4564  0, // No transmission scheduled for STA 1
4565  1,
4566  0,
4567  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4568  false,
4569  Seconds(0),
4570  WifiPhyState::RX); // Measurement channel is total channel width
4571  delay += Seconds(1.0);
4572 
4573  //---------------------------------------------------------------------------
4574  // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4575  // limitation enforced
4576  Simulator::Schedule(
4577  delay,
4579  this,
4580  "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4581  // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4582  // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4583  Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4585  this,
4586  m_phySta2,
4587  3.0);
4588 
4589  rxPower = (m_channelWidth > 40)
4590  ? DbmToW(19)
4591  : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4592  // transmitted only on one 20 MHz channel
4593  double rxPowerOfdma = rxPower;
4594  if (m_channelWidth <= 40)
4595  {
4596  rxPowerOfdma = (m_channelWidth == 20)
4597  ? DbmToW(14.0309) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4598  : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4599  }
4601  (m_channelWidth >= 40) ? 0.0 : rxPower,
4602  rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4603  0.0,
4604  rxPowerOfdma);
4605 
4606  // Reset PSD limitation once HE TB has been sent
4607  Simulator::Schedule(delay + m_expectedPpduDuration,
4609  this,
4610  m_phySta2,
4611  100.0);
4612  ScheduleTest(delay,
4613  true,
4615  0,
4616  0,
4617  0, // No transmission scheduled for STA 1
4618  1,
4619  0,
4620  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4621  false,
4622  Seconds(0),
4623  WifiPhyState::RX); // Measurement channel is total channel width
4624  delay += Seconds(1.0);
4625 
4626  //---------------------------------------------------------------------------
4627  // Measure the power of 2 solicited HE TB PPDU from both STAs
4628  Simulator::Schedule(delay,
4630  this,
4631  "Measure power for reception of HE TB PPDU on both RUs");
4632  rxPower = DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4633  double rxPowerNonOfdma = (m_channelWidth >= 40)
4634  ? rxPower
4635  : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4636  SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4637  ScheduleTest(delay,
4638  true,
4640  1,
4641  0,
4642  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4643  1,
4644  0,
4645  1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4646  delay += Seconds(1.0);
4647 
4648  //---------------------------------------------------------------------------
4649  // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4650  // ongoing)
4651  Simulator::Schedule(delay,
4653  this,
4654  "Reception of an HE TB PPDU from another BSS");
4655  // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4656  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
4657  Simulator::Schedule(delay + MilliSeconds(100),
4659  this,
4660  3,
4661  1,
4662  1002,
4663  1,
4664  2,
4665  false);
4666 
4667  // Verify events data have been cleared
4668  Simulator::Schedule(delay + MilliSeconds(200),
4670  this);
4671 
4672  Simulator::Schedule(delay + MilliSeconds(500), &TestUlOfdmaPhyTransmission::Reset, this);
4673  delay += Seconds(1.0);
4674 
4675  //---------------------------------------------------------------------------
4676  // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4677  // corrected received
4678  Simulator::Schedule(
4679  delay,
4681  this,
4682  "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4683  "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4684  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
4685  Simulator::Schedule(delay + m_expectedPpduDuration + NanoSeconds(100),
4687  this,
4688  3,
4689  1,
4690  1002,
4691  1,
4692  2,
4693  true);
4694  ScheduleTest(delay,
4695  true,
4697  1,
4698  0,
4699  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4700  1,
4701  0,
4702  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4703  true,
4704  NanoSeconds(200));
4705  delay += Seconds(1.0);
4706 
4707  Simulator::Run();
4708 }
4709 
4710 void
4712 {
4713  m_frequency = 5180;
4714  m_channelWidth = 20;
4716  NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4717  RunOne();
4718 
4719  m_frequency = 5190;
4720  m_channelWidth = 40;
4722  NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4723  RunOne();
4724 
4725  m_frequency = 5210;
4726  m_channelWidth = 80;
4728  NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4729  RunOne();
4730 
4731  m_frequency = 5250;
4732  m_channelWidth = 160;
4734  NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4735  RunOne();
4736 
4737  Simulator::Destroy();
4738 }
4739 
4747 {
4748  public:
4750  ~TestPhyPaddingExclusion() override;
4751 
4752  private:
4753  void DoSetup() override;
4754  void DoTeardown() override;
4755  void DoRun() override;
4756 
4764  void SendHeTbPpdu(uint16_t txStaId,
4765  std::size_t index,
4766  std::size_t payloadSize,
4767  Time txDuration);
4773  void SetTrigVector(Time ppduDuration);
4774 
4780  void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4784  void StopInterference();
4785 
4789  void RunOne();
4790 
4797  void CheckRxFromSta1(uint32_t expectedSuccess,
4798  uint32_t expectedFailures,
4799  uint32_t expectedBytes);
4800 
4807  void CheckRxFromSta2(uint32_t expectedSuccess,
4808  uint32_t expectedFailures,
4809  uint32_t expectedBytes);
4810 
4814  void VerifyEventsCleared();
4815 
4824 
4828  void Reset();
4829 
4837  void RxSuccess(Ptr<const WifiPsdu> psdu,
4838  RxSignalInfo rxSignalInfo,
4839  WifiTxVector txVector,
4840  std::vector<bool> statusPerMpdu);
4841 
4846  void RxFailure(Ptr<const WifiPsdu> psdu);
4847 
4851 
4853 
4860 };
4861 
4863  : TestCase("PHY padding exclusion test"),
4864  m_countRxSuccessFromSta1(0),
4865  m_countRxSuccessFromSta2(0),
4866  m_countRxFailureFromSta1(0),
4867  m_countRxFailureFromSta2(0),
4868  m_countRxBytesFromSta1(0),
4869  m_countRxBytesFromSta2(0)
4870 {
4871 }
4872 
4873 void
4875  std::size_t index,
4876  std::size_t payloadSize,
4877  Time txDuration)
4878 {
4879  WifiConstPsduMap psdus;
4880 
4881  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
4882  0,
4884  1600,
4885  1,
4886  1,
4887  0,
4889  false,
4890  false,
4891  true);
4892 
4893  HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4894  txVector.SetRu(ru, txStaId);
4895  txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4896  txVector.SetNss(1, txStaId);
4897 
4898  Ptr<Packet> pkt = Create<Packet>(payloadSize);
4899  WifiMacHeader hdr;
4901  hdr.SetQosTid(0);
4902  hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4903  std::ostringstream addr;
4904  addr << "00:00:00:00:00:0" << txStaId;
4905  hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4906  hdr.SetSequenceNumber(1);
4907  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4908  psdus.insert(std::make_pair(txStaId, psdu));
4909 
4911  if (txStaId == 1)
4912  {
4913  phy = m_phySta1;
4914  }
4915  else if (txStaId == 2)
4916  {
4917  phy = m_phySta2;
4918  }
4919 
4920  txVector.SetLength(
4921  HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4922 
4923  phy->SetPpduUid(0);
4924  phy->Send(psdus, txVector);
4925 }
4926 
4927 void
4929 {
4930  m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
4931  m_phyInterferer->SetPeriod(duration);
4933  Simulator::Schedule(duration, &TestPhyPaddingExclusion::StopInterference, this);
4934 }
4935 
4936 void
4938 {
4939  m_phyInterferer->Stop();
4940 }
4941 
4943 {
4944 }
4945 
4946 void
4948  RxSignalInfo rxSignalInfo,
4949  WifiTxVector txVector,
4950  std::vector<bool> /*statusPerMpdu*/)
4951 {
4952  NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
4953  if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4954  {
4956  m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
4957  }
4958  else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4959  {
4961  m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
4962  }
4963 }
4964 
4965 void
4967 {
4968  NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
4969  if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4970  {
4972  }
4973  else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4974  {
4976  }
4977 }
4978 
4979 void
4981  uint32_t expectedFailures,
4982  uint32_t expectedBytes)
4983 {
4985  expectedSuccess,
4986  "The number of successfully received packets from STA 1 is not correct!");
4989  expectedFailures,
4990  "The number of unsuccessfuly received packets from STA 1 is not correct!");
4992  expectedBytes,
4993  "The number of bytes received from STA 1 is not correct!");
4994 }
4995 
4996 void
4998  uint32_t expectedFailures,
4999  uint32_t expectedBytes)
5000 {
5002  expectedSuccess,
5003  "The number of successfully received packets from STA 2 is not correct!");
5006  expectedFailures,
5007  "The number of unsuccessfuly received packets from STA 2 is not correct!");
5009  expectedBytes,
5010  "The number of bytes received from STA 2 is not correct!");
5011 }
5012 
5013 void
5015 {
5017  nullptr,
5018  "m_currentEvent for AP was not cleared");
5020  nullptr,
5021  "m_currentEvent for STA 1 was not cleared");
5023  nullptr,
5024  "m_currentEvent for STA 2 was not cleared");
5025 }
5026 
5027 void
5029 {
5030  // This is needed to make sure PHY state will be checked as the last event if a state change
5031  // occurred at the exact same time as the check
5032  Simulator::ScheduleNow(&TestPhyPaddingExclusion::DoCheckPhyState, this, phy, expectedState);
5033 }
5034 
5035 void
5037 {
5038  WifiPhyState currentState = phy->GetState()->GetState();
5039  NS_LOG_FUNCTION(this << currentState);
5040  NS_TEST_ASSERT_MSG_EQ(currentState,
5041  expectedState,
5042  "PHY State " << currentState << " does not match expected state "
5043  << expectedState << " at " << Simulator::Now());
5044 }
5045 
5046 void
5048 {
5055  m_phySta1->SetPpduUid(0);
5058 }
5059 
5060 void
5062 {
5063  RngSeedManager::SetSeed(1);
5064  RngSeedManager::SetRun(1);
5065  int64_t streamNumber = 0;
5066 
5067  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5068  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
5069  lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
5070  spectrumChannel->AddPropagationLossModel(lossModel);
5072  CreateObject<ConstantSpeedPropagationDelayModel>();
5073  spectrumChannel->SetPropagationDelayModel(delayModel);
5074 
5075  Ptr<Node> apNode = CreateObject<Node>();
5076  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
5077  Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
5078  apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5079  apDev->SetMac(apMac);
5080  m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
5081  Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
5082  apDev->SetHeConfiguration(heConfiguration);
5083  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
5084  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5085  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
5086  m_phyAp->SetErrorRateModel(apErrorModel);
5087  m_phyAp->SetDevice(apDev);
5088  m_phyAp->AddChannel(spectrumChannel);
5090  m_phyAp->AssignStreams(streamNumber);
5091  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
5096 
5101  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
5102  m_phyAp->SetMobility(apMobility);
5103  apDev->SetPhy(m_phyAp);
5105  apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5106  apMac->SetWifiPhys({m_phyAp});
5107  apNode->AggregateObject(apMobility);
5108  apNode->AddDevice(apDev);
5109 
5110  Ptr<Node> sta1Node = CreateObject<Node>();
5111  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
5112  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
5113  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
5114  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5115  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
5116  m_phySta1->SetErrorRateModel(sta1ErrorModel);
5117  m_phySta1->SetDevice(sta1Dev);
5118  m_phySta1->AddChannel(spectrumChannel);
5120  m_phySta1->AssignStreams(streamNumber);
5123  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
5124  m_phySta1->SetMobility(sta1Mobility);
5125  sta1Dev->SetPhy(m_phySta1);
5127  sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5128  sta1Node->AggregateObject(sta1Mobility);
5129  sta1Node->AddDevice(sta1Dev);
5130 
5131  Ptr<Node> sta2Node = CreateObject<Node>();
5132  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
5133  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
5134  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
5135  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5136  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
5137  m_phySta2->SetErrorRateModel(sta2ErrorModel);
5138  m_phySta2->SetDevice(sta2Dev);
5139  m_phySta2->AddChannel(spectrumChannel);
5141  m_phySta2->AssignStreams(streamNumber);
5144  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
5145  m_phySta2->SetMobility(sta2Mobility);
5146  sta2Dev->SetPhy(m_phySta2);
5148  sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5149  sta2Node->AggregateObject(sta2Mobility);
5150  sta2Node->AddDevice(sta2Dev);
5151 
5152  Ptr<Node> interfererNode = CreateObject<Node>();
5153  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
5154  m_phyInterferer = CreateObject<WaveformGenerator>();
5155  m_phyInterferer->SetDevice(interfererDev);
5156  m_phyInterferer->SetChannel(spectrumChannel);
5158  interfererNode->AddDevice(interfererDev);
5159 }
5160 
5161 void
5163 {
5164  m_phyAp->Dispose();
5165  m_phyAp = nullptr;
5166  m_phySta1->Dispose();
5167  m_phySta1 = nullptr;
5168  m_phySta2->Dispose();
5169  m_phySta2 = nullptr;
5171  m_phyInterferer = nullptr;
5172 }
5173 
5174 void
5176 {
5177  WifiTxVector trigVector(HePhy::GetHeMcs7(),
5178  0,
5180  1600,
5181  1,
5182  1,
5183  0,
5185  false,
5186  false,
5187  true);
5188  trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5189  trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5190  trigVector.SetNss(1, 1);
5191  trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5192  trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5193  trigVector.SetNss(1, 2);
5194  uint16_t length;
5195  std::tie(length, ppduDuration) =
5196  HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, trigVector, m_phyAp->GetPhyBand());
5197  trigVector.SetLength(length);
5198  auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
5199  hePhyAp->SetTrigVector(trigVector, ppduDuration);
5200 }
5201 
5202 void
5204 {
5205  Time expectedPpduDuration = NanoSeconds(292800);
5206  Time ppduWithPaddingDuration =
5207  expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5208 
5209  Simulator::Schedule(Seconds(0.0), &TestPhyPaddingExclusion::Reset, this);
5210 
5211  // STA1 and STA2 send MU UL PPDUs addressed to AP:
5212  Simulator::Schedule(Seconds(1.0),
5214  this,
5215  1,
5216  1,
5217  1000,
5218  ppduWithPaddingDuration);
5219  Simulator::Schedule(Seconds(1.0),
5221  this,
5222  2,
5223  2,
5224  1001,
5225  ppduWithPaddingDuration);
5226 
5227  // Set TRIGVECTOR on AP
5228  Simulator::Schedule(Seconds(1.0),
5230  this,
5231  ppduWithPaddingDuration);
5232 
5233  // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5234  Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration - NanoSeconds(1),
5236  this,
5237  m_phyAp,
5239  Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration,
5241  this,
5242  m_phyAp,
5244 
5245  // One PSDU of 1000 bytes should have been successfully received from STA 1
5246  Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
5247  // One PSDU of 1001 bytes should have been successfully received from STA 2
5248  Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
5249  // Verify events data have been cleared
5250  Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
5251 
5252  Simulator::Schedule(Seconds(1.5), &TestPhyPaddingExclusion::Reset, this);
5253 
5254  // STA1 and STA2 send MU UL PPDUs addressed to AP:
5255  Simulator::Schedule(Seconds(2.0),
5257  this,
5258  1,
5259  1,
5260  1000,
5261  ppduWithPaddingDuration);
5262  Simulator::Schedule(Seconds(2.0),
5264  this,
5265  2,
5266  2,
5267  1001,
5268  ppduWithPaddingDuration);
5269 
5270  // Set TRIGVECTOR on AP
5271  Simulator::Schedule(Seconds(2.0),
5273  this,
5274  ppduWithPaddingDuration);
5275 
5276  // A strong non-wifi interference is generated on RU 1 during padding reception
5277  BandInfo bandInfo;
5278  bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
5279  bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5280  bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5281  Bands bands;
5282  bands.push_back(bandInfo);
5283 
5284  Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5285  Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5286  double interferencePower = 0.1; // watts
5287  *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
5288 
5289  Simulator::Schedule(Seconds(2.0) + MicroSeconds(50) + expectedPpduDuration,
5291  this,
5292  interferencePsdRu1,
5293  MilliSeconds(100));
5294 
5295  // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5296  // CCA_BUSY instead of IDLE due to the interference)
5297  Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration - NanoSeconds(1),
5299  this,
5300  m_phyAp,
5302  Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration,
5304  this,
5305  m_phyAp,
5307 
5308  // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5309  // occupies RU 1 after payload, during PHY padding)
5310  Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
5311  // One PSDU of 1001 bytes should have been successfully received from STA 2
5312  Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
5313  // Verify events data have been cleared
5314  Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
5315 
5316  Simulator::Schedule(Seconds(2.5), &TestPhyPaddingExclusion::Reset, this);
5317 
5318  Simulator::Run();
5319 
5320  Simulator::Destroy();
5321 }
5322 
5330 {
5331  public:
5333  ~TestUlOfdmaPowerControl() override;
5334 
5335  private:
5336  void DoSetup() override;
5337  void DoTeardown() override;
5338  void DoRun() override;
5339 
5345  void SendMuBar(std::vector<uint16_t> staIds);
5346 
5353  void SetupBa(Address destination);
5354 
5361  void RunOne(bool setupBa);
5362 
5368 
5379  RxSignalInfo rxSignalInfo,
5380  WifiTxVector txVector,
5381  std::vector<bool> statusPerMpdu);
5382 
5383  uint8_t m_bssColor;
5384 
5388 
5390 
5391  double m_txPowerAp;
5393  double m_txPowerEnd;
5395 
5398 
5399  double m_rssiSta1;
5400  double m_rssiSta2;
5401 
5402  double m_tol;
5403 };
5404 
5406  : TestCase("UL-OFDMA power control test"),
5407  m_bssColor(1),
5408  m_txPowerAp(0),
5409  m_txPowerStart(0),
5410  m_txPowerEnd(0),
5411  m_txPowerLevels(0),
5412  m_requestedRssiSta1(0),
5413  m_requestedRssiSta2(0),
5414  m_rssiSta1(0),
5415  m_rssiSta2(0),
5416  m_tol(0.1)
5417 {
5418 }
5419 
5421 {
5422  m_phyAp = nullptr;
5423  m_apDev = nullptr;
5424  m_sta1Dev = nullptr;
5425  m_sta2Dev = nullptr;
5426 }
5427 
5428 void
5430 {
5431  // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5432  Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5433  m_apDev->Send(pkt, destination, 0);
5434 }
5435 
5436 void
5437 TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5438 {
5439  NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5440 
5441  // Build MU-BAR trigger frame
5442  CtrlTriggerHeader muBar;
5443  muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5444  muBar.SetMoreTF(true);
5445  muBar.SetCsRequired(true);
5447  muBar.SetGiAndLtfType(1600, 2);
5448  muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5449  muBar.SetUlSpatialReuse(60500);
5450 
5451  HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5452  std::size_t index = 1;
5453  int8_t ulTargetRssi = -40; // will be overwritten
5454  for (const auto& staId : staIds)
5455  {
5457  ui.SetAid12(staId);
5458  ui.SetRuAllocation({ru, index, true});
5459  ui.SetUlFecCodingType(true);
5460  ui.SetUlMcs(7);
5461  ui.SetUlDcm(false);
5462  ui.SetSsAllocation(1, 1);
5463  if (staId == 1)
5464  {
5465  ulTargetRssi = m_requestedRssiSta1;
5466  }
5467  else if (staId == 2)
5468  {
5469  ulTargetRssi = m_requestedRssiSta2;
5470  }
5471  else
5472  {
5473  NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5474  }
5475  ui.SetUlTargetRssi(ulTargetRssi);
5476 
5478  bar.SetType(BlockAckReqType::COMPRESSED);
5479  bar.SetTidInfo(0);
5480  bar.SetStartingSequence(4095);
5482 
5483  ++index;
5484  }
5485 
5486  WifiTxVector tbTxVector = muBar.GetHeTbTxVector(staIds.front());
5487  muBar.SetUlLength(HePhy::ConvertHeTbPpduDurationToLSigLength(MicroSeconds(128),
5488  tbTxVector,
5490  .first);
5491 
5492  WifiConstPsduMap psdus;
5493  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
5494  0,
5496  800,
5497  1,
5498  1,
5499  0,
5501  false,
5502  false,
5503  false,
5504  m_bssColor);
5505 
5506  Ptr<Packet> bar = Create<Packet>();
5507  bar->AddHeader(muBar);
5508 
5509  Mac48Address receiver = Mac48Address::GetBroadcast();
5510  if (staIds.size() == 1)
5511  {
5512  uint16_t aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5513  if (staIds.front() == aidSta1)
5514  {
5515  receiver = Mac48Address::ConvertFrom(m_sta1Dev->GetAddress());
5516  }
5517  else
5518  {
5519  NS_ASSERT(staIds.front() ==
5520  DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5521  receiver = Mac48Address::ConvertFrom(m_sta2Dev->GetAddress());
5522  }
5523  }
5524 
5525  WifiMacHeader hdr;
5527  hdr.SetAddr1(receiver);
5528  hdr.SetAddr2(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5529  hdr.SetAddr3(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5530  hdr.SetDsNotTo();
5531  hdr.SetDsFrom();
5532  hdr.SetNoRetry();
5533  hdr.SetNoMoreFragments();
5534  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(bar, hdr);
5535 
5536  Time nav = m_apDev->GetPhy()->GetSifs();
5537  uint16_t staId = staIds.front(); // either will do
5538  nav += m_phyAp->CalculateTxDuration(GetBlockAckSize(BlockAckType::COMPRESSED),
5539  tbTxVector,
5541  staId);
5542  psdu->SetDuration(nav);
5543  psdus.insert(std::make_pair(SU_STA_ID, psdu));
5544 
5545  m_phyAp->Send(psdus, txVector);
5546 }
5547 
5548 void
5550  RxSignalInfo rxSignalInfo,
5551  WifiTxVector txVector,
5552  std::vector<bool> /*statusPerMpdu*/)
5553 {
5554  NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5555  double rssi = rxSignalInfo.rssi;
5556  NS_ASSERT(psdu->GetNMpdus() == 1);
5557  WifiMacHeader hdr = psdu->GetHeader(0);
5558  NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5559  if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5560  {
5562  rssi,
5563  m_rssiSta1,
5564  m_tol,
5565  "The obtained RSSI from STA 1 at AP is different from the expected one ("
5566  << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5567  }
5568  else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5569  {
5571  rssi,
5572  m_rssiSta2,
5573  m_tol,
5574  "The obtained RSSI from STA 2 at AP is different from the expected one ("
5575  << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5576  }
5577  else
5578  {
5579  NS_ABORT_MSG("The receiver address is unknown");
5580  }
5581 }
5582 
5583 void
5585 {
5586  // Now that BA session has been established we can plug our method
5589 }
5590 
5591 void
5593 {
5594  Ptr<Node> apNode = CreateObject<Node>();
5595  NodeContainer staNodes;
5596  staNodes.Create(2);
5597 
5598  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5599  Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel>();
5600  spectrumChannel->AddPropagationLossModel(lossModel);
5602  CreateObject<ConstantSpeedPropagationDelayModel>();
5603  spectrumChannel->SetPropagationDelayModel(delayModel);
5604 
5605  SpectrumWifiPhyHelper spectrumPhy;
5606  spectrumPhy.SetChannel(spectrumChannel);
5607  spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5608  spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5609 
5610  WifiHelper wifi;
5611  wifi.SetStandard(WIFI_STANDARD_80211ax);
5612  wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5613  "DataMode",
5614  StringValue("HeMcs7"),
5615  "ControlMode",
5616  StringValue("HeMcs7"));
5617 
5619  mac.SetType("ns3::StaWifiMac");
5620  NetDeviceContainer staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5621  wifi.AssignStreams(staDevs, 0);
5622  m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5624  m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5626 
5627  // Set the beacon interval long enough so that associated STAs may not consider link lost when
5628  // beacon generation is disabled during the actual tests. Having such a long interval also
5629  // avoids bloating logs with beacons during the set up phase.
5630  mac.SetType("ns3::ApWifiMac",
5631  "BeaconGeneration",
5632  BooleanValue(true),
5633  "BeaconInterval",
5634  TimeValue(MicroSeconds(1024 * 600)));
5635  m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5636  NS_ASSERT(m_apDev);
5637  m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5638  m_phyAp = DynamicCast<SpectrumWifiPhy>(m_apDev->GetPhy());
5639  NS_ASSERT(m_phyAp);
5640  // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5641  // set up for both STAs
5642 
5644  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5645  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
5646  positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5647  positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5648  positionAlloc->Add(
5649  Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5650  mobility.SetPositionAllocator(positionAlloc);
5651 
5652  mobility.Install(apNode);
5653  mobility.Install(staNodes);
5654 
5655  lossModel->SetDefaultLoss(50.0);
5656  lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5657  staNodes.Get(1)->GetObject<MobilityModel>(),
5658  56.0,
5659  true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5660 }
5661 
5662 void
5664 {
5665  m_phyAp->Dispose();
5666  m_phyAp = nullptr;
5667  m_apDev->Dispose();
5668  m_apDev = nullptr;
5669  m_sta1Dev->Dispose();
5670  m_sta1Dev = nullptr;
5671  m_sta2Dev->Dispose();
5672  m_sta2Dev = nullptr;
5673 }
5674 
5675 void
5677 {
5678  RngSeedManager::SetSeed(1);
5679  RngSeedManager::SetRun(1);
5680  int64_t streamNumber = 0;
5681 
5682  Ptr<WifiPhy> phySta1 = m_sta1Dev->GetPhy();
5683  Ptr<WifiPhy> phySta2 = m_sta2Dev->GetPhy();
5684 
5685  m_phyAp->AssignStreams(streamNumber);
5686  phySta1->AssignStreams(streamNumber);
5687  phySta2->AssignStreams(streamNumber);
5688 
5689  m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5690  m_phyAp->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerAp));
5691  m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5692 
5693  phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5694  phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5695  phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5696 
5697  phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5698  phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5699  phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5700 
5701  Time relativeStart = MilliSeconds(0);
5702  if (setupBa)
5703  {
5704  // Set up BA for each station once the association phase has ended
5705  // so that a BA session is established when the MU-BAR is received.
5706  Simulator::Schedule(MilliSeconds(800),
5708  this,
5709  m_sta1Dev->GetAddress());
5710  Simulator::Schedule(MilliSeconds(850),
5712  this,
5713  m_sta2Dev->GetAddress());
5714  relativeStart = MilliSeconds(1000);
5715  }
5716  else
5717  {
5718  Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5719  NS_ASSERT(apMac);
5720  apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5721  }
5722 
5723  Simulator::Schedule(relativeStart,
5725  this);
5726 
5727  {
5728  // Verify that the RSSI from STA 1 is consistent with what was requested
5729  std::vector<uint16_t> staIds{1};
5730  Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5731  }
5732 
5733  {
5734  // Verify that the RSSI from STA 2 is consistent with what was requested
5735  std::vector<uint16_t> staIds{2};
5736  Simulator::Schedule(relativeStart + MilliSeconds(20),
5738  this,
5739  staIds);
5740  }
5741 
5742  {
5743  // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5744  std::vector<uint16_t> staIds{1, 2};
5745  Simulator::Schedule(relativeStart + MilliSeconds(40),
5747  this,
5748  staIds);
5749  }
5750 
5751  Simulator::Stop(relativeStart + MilliSeconds(100));
5752  Simulator::Run();
5753 }
5754 
5755 void
5757 {
5758  // Power configurations
5759  m_txPowerAp = 20; // dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
5760  // since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5761  m_txPowerStart = 15; // dBm
5762 
5763  // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5764  m_requestedRssiSta1 = -30.0;
5765  m_requestedRssiSta2 = -36.0;
5766 
5767  // Test single power level
5768  {
5769  // STA power configurations: 15 dBm only
5770  m_txPowerEnd = 15;
5771  m_txPowerLevels = 1;
5772 
5773  // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5774  // regardless of the estimated path loss.
5775  m_rssiSta1 = -35.0; // 15 dBm - 50 dB
5776  m_rssiSta2 = -41.0; // 15 dBm - 56 dB
5777 
5778  RunOne(true);
5779  }
5780 
5781  // Test 2 dBm granularity
5782  {
5783  // STA power configurations: [15:2:25] dBm
5784  m_txPowerEnd = 25;
5785  m_txPowerLevels = 6;
5786 
5787  // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5788  // requested
5789  m_rssiSta1 = -29.0; // 21 dBm - 50 dB
5790  m_rssiSta2 = -35.0; // 21 dBm - 50 dB
5791 
5792  RunOne(false);
5793  }
5794 
5795  // Test 1 dBm granularity
5796  {
5797  // STA power configurations: [15:1:25] dBm
5798  m_txPowerEnd = 25;
5799  m_txPowerLevels = 11;
5800 
5801  // Expected UL RSSIs, considering that we can correctly tune the transmit power
5802  m_rssiSta1 = -30.0; // 20 dBm - 50 dB
5803  m_rssiSta2 = -36.0; // 20 dBm - 56 dB
5804 
5805  RunOne(false);
5806  }
5807 
5808  // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5809  {
5810  // STA power configurations: [15:1:25] dBm
5811  m_txPowerEnd = 25;
5812  m_txPowerLevels = 11;
5813 
5814  // Requested UL RSSIs
5815  m_requestedRssiSta1 = -28.0; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5816  m_requestedRssiSta2 = -37.0; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5817 
5818  // Expected UL RSSIs, considering that we can correctly tune the transmit power
5819  m_rssiSta1 = -28.0; // 22 dBm - 50 dB
5820  m_rssiSta2 = -37.0; // 19 dBm - 56 dB
5821 
5822  RunOne(false);
5823  }
5824 
5825  Simulator::Destroy();
5826 }
5827 
5835 {
5836  public:
5838 };
5839 
5841  : TestSuite("wifi-phy-ofdma", UNIT)
5842 {
5843  AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::QUICK);
5844  AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::QUICK);
5845  AddTestCase(new TestUlOfdmaPpduUid, TestCase::QUICK);
5846  AddTestCase(new TestMultipleHeTbPreambles, TestCase::QUICK);
5847  AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::QUICK);
5848  AddTestCase(new TestPhyPaddingExclusion, TestCase::QUICK);
5849  AddTestCase(new TestUlOfdmaPowerControl, TestCase::QUICK);
5850 }
5851 
#define max(a, b)
Definition: 80211b.c:42
SpectrumWifiPhy used for testing OFDMA.
void SetTriggerFrameUid(uint64_t uid)
Since we assume trigger frame was previously received from AP, this is used to set its UID.
Ptr< const HePhy > GetHePhy() const
void(* TxPpduUidCallback)(uint64_t uid)
TracedCallback signature for UID of transmitted PPDU.
void SetPpduUid(uint64_t uid)
Set the global PPDU UID counter.
static TypeId GetTypeId()
Get the type ID.
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents()
Ptr< OfdmaTestHePhy > m_ofdmTestHePhy
Pointer to HE PHY instance used for OFDMA test.
Ptr< Event > GetCurrentEvent()
void StartTx(Ptr< const WifiPpdu > ppdu) override
void DoDispose() override
Destructor implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
Time GetEnergyDuration(double energyW, WifiSpectrumBandInfo band)
Wrapper to InterferenceHelper method.
TracedCallback< uint64_t > m_phyTxPpduUidTrace
Callback providing UID of the PPDU that is about to be transmitted.
void DoInitialize() override
Initialize() implementation.
HE PHY slightly modified so as to return a given STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
OfdmaTestHePhy(uint16_t staId)
Constructor.
~OfdmaTestHePhy() override
void SetGlobalPpduUid(uint64_t uid)
Set the global PPDU UID counter.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
uint16_t m_staId
ID of the STA to which this PHY belongs to.
PHY listener for OFDMA tests.
OfdmaTestPhyListener()=default
void NotifyRxEndError() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyTxStart(Time duration, double txPowerDbm) override
bool m_lastRxSuccess
flag whether last RX has been successful
void NotifyRxStart(Time duration) override
Time GetLastRxStartNotification() const
Return the time at which the last RX start notification has been received.
void NotifySwitchingStart(Time duration) override
void NotifyWakeup() override
Notify listeners that we woke up.
uint32_t m_notifyRxStart
count number of RX start notifications
void Reset()
Reset function.
Time m_lastRxEnd
last time a RX end notification has been received
Time m_lastRxStart
last time a RX start notification has been received
Time GetLastRxEndNotification() const
Return the time at which the last RX end notification has been received.
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &) override
uint32_t m_notifyRxEnd
count number of RX end notifications
bool IsLastRxSuccess() const
Return whether last RX has been successful.
void NotifySleep() override
Notify listeners that we went to sleep.
uint32_t GetNumRxEndNotifications() const
Return the number of RX end notifications that has been received since the last reset.
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
uint32_t GetNumRxStartNotifications() const
Return the number of RX start notifications that has been received since the last reset.
void NotifyOff() override
Notify listeners that we went to switch off.
void NotifyOn() override
Notify listeners that we went to switch on.
DL-OFDMA PHY puncturing test.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void DoRun() override
Implementation to actually run this TestCase.
Time m_expectedPpduDuration20Mhz
expected duration to send MU PPDU on 20 MHz RU
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
void ResetResults()
Reset the results.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
void RunOne()
Run one function.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2, const std::vector< bool > &puncturedSubchannels)
Send MU-PPDU function.
uint16_t m_frequency
frequency in MHz
uint16_t m_channelWidth
channel width in MHz
uint32_t m_countRxFailureSta1
count RX failure for STA 1
Time m_expectedPpduDuration40Mhz
expected duration to send MU PPDU on 40 MHz RU
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void StopInterference()
Stop interference function.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint8_t m_indexSubchannel
Index of the subchannel (starting from 0) that should contain an interference and be punctured during...
uint32_t m_countRxSuccessSta1
count RX success for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, const std::vector< bool > statusPerMpdu)
Receive success function for STA 1.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
uint16_t m_frequency
frequency in MHz
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint16_t m_channelWidth
channel width in MHz
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
void RunOne()
Run one function.
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Time m_expectedPpduDuration
expected duration to send MU PPDU
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 1.
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
void RxSuccessSta3(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 3.
uint32_t m_countRxSuccessSta3
count RX success for STA 3
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
uint32_t m_countRxBytesSta3
count RX bytes for STA 3
void RxFailureSta3(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 3.
void StopInterference()
Stop interference function.
void ResetResults()
Reset the results.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxSuccessSta1
count RX success for STA 1
void CheckResultsSta3(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 3.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
Send MU-PPDU function.
UL-OFDMA multiple RX events test.
WifiTxVector m_trigVector
TRIGVECTOR.
Ptr< OfdmaSpectrumWifiPhy > m_phy
Phy.
void RxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void CheckHeTbPreambles(size_t nEvents, std::vector< uint64_t > uids)
Check the received HE TB preambles.
void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize)
Receive HE TB PPDU function.
uint64_t m_totalBytesDropped
total number of dropped bytes
void CheckBytesDropped(size_t expectedBytesDropped)
Check the number of bytes dropped.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
PHY padding exclusion test.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
void DoRun() override
Implementation to actually run this TestCase.
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
void SetTrigVector(Time ppduDuration)
Set TRIGVECTOR for HE TB PPDU.
void Reset()
Reset function.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
void StopInterference()
Stop interference function.
void RunOne()
Run one function.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void ScheduleTest(Time delay, bool solicited, WifiPhyState expectedStateAtEnd, uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1, uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2, bool scheduleTxSta1=true, Time ulTimeDifference=Seconds(0), WifiPhyState expectedStateBeforeEnd=WifiPhyState::RX, TrigVectorInfo error=NONE)
Schedule test to perform.
std::shared_ptr< OfdmaTestPhyListener > m_apPhyStateListener
listener for AP PHY state transitions
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId, std::size_t index, uint8_t bssColor) const
Get TXVECTOR for HE TB PPDU.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
uint16_t m_frequency
frequency in MHz
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification)
Check the the number of RX start notifications at the AP as well as the last time a RX start has been...
TrigVectorInfo
Erroneous info included in a TRIGVECTOR.
void SchedulePowerMeasurementChecks(Time delay, double rxPowerNonOfdmaRu1, double rxPowerNonOfdmaRu2, double rxPowerOfdmaRu1, double rxPowerOfdmaRu2)
Schedule power measurement related checks.
void SetBssColor(Ptr< WifiPhy > phy, uint8_t bssColor)
Set the BSS color.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void LogScenario(std::string log) const
Log scenario description.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor, bool incrementUid)
Send HE TB PPDU function.
void SetPsdLimit(Ptr< WifiPhy > phy, double psdLimit)
Set the PSD limit.
void DoRun() override
Implementation to actually run this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void StopInterference()
Stop interference function.
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void CheckNonOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, double expectedRxPower)
Check the received power for the non-OFDMA of the HE TB PPDUs over the given band.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
void RunOne()
Run one function.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void CheckApRxEnd(uint32_t expectedNotifications, Time expectedLastNotification, bool expectedSuccess)
Check the the number of RX end notifications at the AP as well as the last time a RX end has been not...
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
void CheckOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, double expectedRxPower)
Check the received power for the OFDMA part of the HE TB PPDUs over the given band.
uint16_t m_channelWidth
channel width in MHz
void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE SU PPDU function.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void SetTrigVector(uint8_t bssColor, TrigVectorInfo error)
Set TRIGVECTOR for HE TB PPDU.
Time m_expectedPpduDuration
expected duration to send MU PPDU
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
UL-OFDMA power control test.
double m_requestedRssiSta1
requested RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
double m_txPowerStart
minimum transmission power (in dBm) for STAs
void DoRun() override
Implementation to actually run this TestCase.
double m_rssiSta2
expected RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
Ptr< WifiNetDevice > m_sta2Dev
network device of STA 2
double m_txPowerEnd
maximum transmission power (in dBm) for STAs
void SetupBa(Address destination)
Send a QoS Data packet to the destination station in order to set up a block Ack session (so that the...
Ptr< WifiNetDevice > m_sta1Dev
network device of STA 1
double m_tol
tolerance (in dB) between received and expected RSSIs
Ptr< WifiNetDevice > m_apDev
network device of AP
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void ReceiveOkCallbackAtAp(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive OK callback function at AP.
void ReplaceReceiveOkCallbackOfAp()
Replace the AP's callback on its PHY's ReceiveOkCallback by the ReceiveOkCallbackAtAp method.
double m_rssiSta1
expected RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
uint8_t m_txPowerLevels
number of transmission power levels for STAs
double m_requestedRssiSta2
requested RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
double m_txPowerAp
transmit power (in dBm) of AP
void RunOne(bool setupBa)
Run one simulation with an optional BA session set up phase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void SendMuBar(std::vector< uint16_t > staIds)
Send a MU BAR through the AP to the STAs listed in the provided vector.
UL-OFDMA PPDU UID attribution test.
void TxPpduSta1(uint64_t uid)
Transmitted PPDU information function for STA 1.
void ResetPpduUid()
Reset the global PPDU UID counter in WifiPhy.
void CheckUid(uint16_t staId, uint64_t expectedUid)
Check the UID of the transmitted PPDU.
void TxPpduAp(uint64_t uid)
Transmitted PPDU information function for AP.
void TxPpduSta2(uint64_t uid)
Transmitted PPDU information function for STA 2.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
uint64_t m_ppduUidAp
UID of PPDU transmitted by AP.
uint64_t m_ppduUidSta1
UID of PPDU transmitted by STA1.
uint64_t m_ppduUidSta2
UID of PPDU transmitted by STA2.
void DoRun() override
Implementation to actually run this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu()
Send MU-PPDU toward both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendTbPpdu()
Send TB-PPDU from both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
void SendSuPpdu(uint16_t txStaId)
Send SU-PPDU function.
wifi PHY OFDMA Test Suite
a polymophic address class
Definition: address.h:101
Headers for BlockAckRequest.
Definition: ctrl-headers.h:52
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
Headers for Trigger frames.
Definition: ctrl-headers.h:942
CtrlTriggerUserInfoField & AddUserInfoField()
Append a new User Info field to this Trigger frame and return a non-const reference to it.
void SetApTxPower(int8_t power)
Set the AP TX Power subfield of the Common Info field.
WifiTxVector GetHeTbTxVector(uint16_t staId) const
Get the TX vector that the station with the given STA-ID will use to send the HE TB PPDU solicited by...
void SetUlBandwidth(uint16_t bw)
Set the bandwidth of the solicited HE TB PPDU.
void SetType(TriggerFrameType type)
Set the Trigger frame type.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
void SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse subfield of the Common Info field.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
void SetMoreTF(bool more)
Set the More TF subfield of the Common Info field.
User Info field of Trigger frames.
Definition: ctrl-headers.h:590
void SetAid12(uint16_t aid)
Set the AID12 subfield, which carries the 12 LSBs of the AID of the station for which this User Info ...
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
void SetUlMcs(uint8_t mcs)
Set the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
void SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader &bar)
Set the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlDcm(bool dcm)
Set the UL DCM subfield, which indicates whether or not DCM is used.
void SetSsAllocation(uint8_t startingSs, uint8_t nSs)
Set the SS Allocation subfield, which is present when the AID12 subfield is neither 0 nor 2045.
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
void SetRuAllocation(HeRu::RuSpec ru)
Set the RU Allocation subfield according to the specified RU.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
PHY entity for HE (11ax)
Definition: he-phy.h:68
RU Specification.
Definition: he-ru.h:66
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:454
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
an EUI-48 address
Definition: mac48-address.h:46
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:138
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:315
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:204
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:259
void Dispose()
Dispose of this Object.
Definition: object.cc:219
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:89
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:1005
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:202
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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 AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const override
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
void SetDevice(Ptr< NetDevice > d) override
Set the associated NetDevice instance.
void SetChannel(Ptr< SpectrumChannel > c) override
Set the channel attached to this device.
virtual void Start()
Start the waveform generator.
void SetTxPowerSpectralDensity(Ptr< SpectrumValue > txs)
Set the Power Spectral Density used for outgoing waveforms.
void SetDutyCycle(double value)
void SetPeriod(Time period)
Set the period according to which the WaveformGenerator switches on and off.
virtual void Stop()
Stop the waveform generator.
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
Implements the IEEE 802.11 MAC header.
virtual WifiMacType GetType() const
Return the type (WifiMacType)
void SetNoMoreFragments()
Un-set the More Fragment bit in the Frame Control Field.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetDsFrom()
Set the From DS bit in the Frame Control field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetNoRetry()
Un-set the Retry bit in the Frame Control field.
create MAC layers for a ns3::WifiNetDevice.
virtual void SetWifiPhys(const std::vector< Ptr< WifiPhy >> &phys)
Definition: wifi-mac.cc:1146
void SetMac(const Ptr< WifiMac > mac)
void SetHeConfiguration(Ptr< HeConfiguration > heConfiguration)
Ptr< WifiMac > GetMac() const
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Ptr< HeConfiguration > GetHeConfiguration() const
void SetStandard(WifiStandard standard)
Set the Wifi standard.
Ptr< WifiPhy > GetPhy() const
void SetPhy(const Ptr< WifiPhy > phy)
Address GetAddress() const override
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:163
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
Definition: wifi-helper.h:550
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:631
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:1720
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:639
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:1275
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:781
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:455
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:961
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1507
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1298
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition: wifi-phy.cc:461
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:1098
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1021
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1273
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:711
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1278
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:659
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:891
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:619
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1260
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:449
void Reset()
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1854
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1033
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition: wifi-phy.cc:726
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:2227
receive notifications about PHY events.
This objects implements the PHY state machine of the Wifi device.
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:279
Mac48Address GetAddr2() const
Get the Transmitter Address (TA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:128
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:273
void SetDuration(Time duration)
Set the Duration/ID field on all the MPDUs.
Definition: wifi-psdu.cc:168
std::size_t GetNMpdus() const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:327
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetRuAllocation(const RuAllocation &ruAlloc, uint8_t p20Index)
Set RU_ALLOCATION field.
void SetInactiveSubchannels(const std::vector< bool > &inactiveSubchannels)
Set the 20 MHz subchannels that are punctured.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetRu(HeRu::RuSpec ru, uint16_t staId)
Set the RU specification for the STA-ID.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
void Reset()
Reset the initial value of every attribute as well as the value of every global to what they were bef...
Definition: config.cc:855
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
#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:144
#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:337
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
std::vector< BandInfo > Bands
Container of BandInfo.
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_CTL_BACKRESP
@ WIFI_MAC_QOSDATA
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
Definition: wifi-utils.cc:66
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
mac
Definition: third.py:92
wifi
Definition: third.py:95
mobility
Definition: third.py:105
phy
Definition: third.py:89
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
double rssi
RSSI in dBm.
Definition: phy-entity.h:71
WifiSpectrumBandInfo structure containing info about a spectrum band.
static const uint16_t DEFAULT_CHANNEL_WIDTH
static WifiPhyOfdmaTestSuite wifiPhyOfdmaTestSuite
the test suite
static const uint8_t DEFAULT_CHANNEL_NUMBER
static const WifiPhyBand DEFAULT_WIFI_BAND
static const uint16_t DEFAULT_GUARD_WIDTH
static const uint32_t DEFAULT_FREQUENCY
WifiPhyState
The state of the PHY layer.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ RX
The PHY layer is receiving a packet.
@ IDLE
The PHY layer is IDLE.