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-signal-parameters.h"
50 #include "ns3/wifi-spectrum-value-helper.h"
51 #include "ns3/wifi-utils.h"
52 
53 #include <algorithm>
54 #include <iterator>
55 #include <memory>
56 
57 using namespace ns3;
58 
59 NS_LOG_COMPONENT_DEFINE("WifiPhyOfdmaTest");
60 
61 static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
62 static const uint32_t DEFAULT_FREQUENCY = 5180; // MHz
64 static const uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
65 static const uint16_t DEFAULT_GUARD_WIDTH =
66  DEFAULT_CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
67 
72 class OfdmaTestHePhy : public HePhy
73 {
74  public:
80  OfdmaTestHePhy(uint16_t staId);
81  ~OfdmaTestHePhy() override;
82 
90  uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
91 
97  void SetGlobalPpduUid(uint64_t uid);
98 
99  private:
100  uint16_t m_staId;
101 }; // class OfdmaTestHePhy
102 
104  : HePhy(),
105  m_staId(staId)
106 {
107 }
108 
110 {
111 }
112 
113 uint16_t
115 {
116  if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
117  {
118  return m_staId;
119  }
120  return HePhy::GetStaId(ppdu);
121 }
122 
123 void
125 {
126  m_globalPpduUid = uid;
127 }
128 
133 {
134  public:
139  static TypeId GetTypeId();
145  OfdmaSpectrumWifiPhy(uint16_t staId);
146  ~OfdmaSpectrumWifiPhy() override;
147 
148  void DoInitialize() override;
149  void DoDispose() override;
150 
151  using WifiPhy::Reset;
152  void StartTx(Ptr<const WifiPpdu> ppdu) override;
153 
159  typedef void (*TxPpduUidCallback)(uint64_t uid);
160 
166  void SetPpduUid(uint64_t uid);
167 
173  void SetTriggerFrameUid(uint64_t uid);
174 
178  std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
183 
194  Time GetEnergyDuration(double energyW, WifiSpectrumBand band);
195 
199  Ptr<const HePhy> GetHePhy() const;
200 
201  private:
205 }; // class OfdmaSpectrumWifiPhy
206 
207 TypeId
209 {
210  static TypeId tid =
211  TypeId("ns3::OfdmaSpectrumWifiPhy")
213  .SetGroupName("Wifi")
214  .AddTraceSource("TxPpduUid",
215  "UID of the PPDU to be transmitted",
217  "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
218  return tid;
219 }
220 
222  : SpectrumWifiPhy()
223 {
224  m_ofdmTestHePhy = Create<OfdmaTestHePhy>(staId);
225  m_ofdmTestHePhy->SetOwner(this);
226 }
227 
229 {
230 }
231 
232 void
234 {
235  // Replace HE PHY instance with test instance
237  SpectrumWifiPhy::DoInitialize();
238 }
239 
240 void
242 {
243  m_ofdmTestHePhy = nullptr;
244  SpectrumWifiPhy::DoDispose();
245 }
246 
247 void
249 {
251  m_previouslyRxPpduUid = uid;
252 }
253 
254 void
256 {
257  m_previouslyRxPpduUid = uid;
258 }
259 
260 void
262 {
263  m_phyTxPpduUidTrace(ppdu->GetUid());
264  SpectrumWifiPhy::StartTx(ppdu);
265 }
266 
267 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
269 {
271 }
272 
275 {
276  return m_currentEvent;
277 }
278 
279 Time
281 {
282  return m_interference->GetEnergyDuration(energyW, band);
283 }
284 
287 {
288  return DynamicCast<const HePhy>(GetLatestPhyEntity());
289 }
290 
298 {
299  public:
301  ~TestDlOfdmaPhyTransmission() override;
302 
303  private:
304  void DoSetup() override;
305  void DoTeardown() override;
306  void DoRun() override;
307 
316  RxSignalInfo rxSignalInfo,
317  WifiTxVector txVector,
318  std::vector<bool> statusPerMpdu);
327  RxSignalInfo rxSignalInfo,
328  WifiTxVector txVector,
329  std::vector<bool> statusPerMpdu);
338  RxSignalInfo rxSignalInfo,
339  WifiTxVector txVector,
340  std::vector<bool> statusPerMpdu);
341 
357 
364  void CheckResultsSta1(uint32_t expectedRxSuccess,
365  uint32_t expectedRxFailure,
366  uint32_t expectedRxBytes);
373  void CheckResultsSta2(uint32_t expectedRxSuccess,
374  uint32_t expectedRxFailure,
375  uint32_t expectedRxBytes);
382  void CheckResultsSta3(uint32_t expectedRxSuccess,
383  uint32_t expectedRxFailure,
384  uint32_t expectedRxBytes);
385 
389  void ResetResults();
390 
396  void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
397 
403  void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
407  void StopInterference();
408 
412  void RunOne();
413 
426 
436 
442 
443  uint16_t m_frequency;
444  uint16_t m_channelWidth;
446 };
447 
449  : TestCase("DL-OFDMA PHY test"),
450  m_countRxSuccessSta1(0),
451  m_countRxSuccessSta2(0),
452  m_countRxSuccessSta3(0),
453  m_countRxFailureSta1(0),
454  m_countRxFailureSta2(0),
455  m_countRxFailureSta3(0),
456  m_countRxBytesSta1(0),
457  m_countRxBytesSta2(0),
458  m_countRxBytesSta3(0),
459  m_frequency(DEFAULT_FREQUENCY),
460  m_channelWidth(DEFAULT_CHANNEL_WIDTH),
461  m_expectedPpduDuration(NanoSeconds(306400))
462 {
463 }
464 
465 void
467 {
474  m_countRxBytesSta1 = 0;
475  m_countRxBytesSta2 = 0;
476  m_countRxBytesSta3 = 0;
477 }
478 
479 void
480 TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
481 {
482  NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
483  WifiConstPsduMap psdus;
484  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
485  0,
487  800,
488  1,
489  1,
490  0,
492  false,
493  false);
494  HeRu::RuType ruType = HeRu::RU_106_TONE;
495  if (m_channelWidth == 20)
496  {
497  ruType = HeRu::RU_106_TONE;
498  txVector.SetRuAllocation({96});
499  }
500  else if (m_channelWidth == 40)
501  {
502  ruType = HeRu::RU_242_TONE;
503  txVector.SetRuAllocation({192, 192});
504  }
505  else if (m_channelWidth == 80)
506  {
507  ruType = HeRu::RU_484_TONE;
508  txVector.SetRuAllocation({200, 200, 200, 200});
509  }
510  else if (m_channelWidth == 160)
511  {
512  ruType = HeRu::RU_996_TONE;
513  txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208});
514  }
515  else
516  {
517  NS_ASSERT_MSG(false, "Unsupported channel width");
518  }
519 
520  txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
521 
522  HeRu::RuSpec ru1(ruType, 1, true);
523  txVector.SetRu(ru1, rxStaId1);
524  txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
525  txVector.SetNss(1, rxStaId1);
526 
527  HeRu::RuSpec ru2(ruType, (m_channelWidth == 160 ? 1 : 2), m_channelWidth != 160);
528  txVector.SetRu(ru2, rxStaId2);
529  txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
530  txVector.SetNss(1, rxStaId2);
531 
532  Ptr<Packet> pkt1 = Create<Packet>(1000);
533  WifiMacHeader hdr1;
535  hdr1.SetQosTid(0);
536  hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
537  hdr1.SetSequenceNumber(1);
538  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
539  psdus.insert(std::make_pair(rxStaId1, psdu1));
540 
541  Ptr<Packet> pkt2 = Create<Packet>(1500);
542  WifiMacHeader hdr2;
544  hdr2.SetQosTid(0);
545  hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
546  hdr2.SetSequenceNumber(2);
547  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
548  psdus.insert(std::make_pair(rxStaId2, psdu2));
549 
550  m_phyAp->Send(psdus, txVector);
551 }
552 
553 void
555 {
556  m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
557  m_phyInterferer->SetPeriod(duration);
559  Simulator::Schedule(duration, &TestDlOfdmaPhyTransmission::StopInterference, this);
560 }
561 
562 void
564 {
566 }
567 
569 {
570 }
571 
572 void
574  RxSignalInfo rxSignalInfo,
575  WifiTxVector txVector,
576  std::vector<bool> /*statusPerMpdu*/)
577 {
578  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
580  m_countRxBytesSta1 += (psdu->GetSize() - 30);
581 }
582 
583 void
585  RxSignalInfo rxSignalInfo,
586  WifiTxVector txVector,
587  std::vector<bool> /*statusPerMpdu*/)
588 {
589  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
591  m_countRxBytesSta2 += (psdu->GetSize() - 30);
592 }
593 
594 void
596  RxSignalInfo rxSignalInfo,
597  WifiTxVector txVector,
598  std::vector<bool> /*statusPerMpdu*/)
599 {
600  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
602  m_countRxBytesSta3 += (psdu->GetSize() - 30);
603 }
604 
605 void
607 {
608  NS_LOG_FUNCTION(this << *psdu);
610 }
611 
612 void
614 {
615  NS_LOG_FUNCTION(this << *psdu);
617 }
618 
619 void
621 {
622  NS_LOG_FUNCTION(this << *psdu);
624 }
625 
626 void
628  uint32_t expectedRxFailure,
629  uint32_t expectedRxBytes)
630 {
632  expectedRxSuccess,
633  "The number of successfully received packets by STA 1 is not correct!");
635  expectedRxFailure,
636  "The number of unsuccessfuly received packets by STA 1 is not correct!");
638  expectedRxBytes,
639  "The number of bytes received by STA 1 is not correct!");
640 }
641 
642 void
644  uint32_t expectedRxFailure,
645  uint32_t expectedRxBytes)
646 {
648  expectedRxSuccess,
649  "The number of successfully received packets by STA 2 is not correct!");
651  expectedRxFailure,
652  "The number of unsuccessfuly received packets by STA 2 is not correct!");
654  expectedRxBytes,
655  "The number of bytes received by STA 2 is not correct!");
656 }
657 
658 void
660  uint32_t expectedRxFailure,
661  uint32_t expectedRxBytes)
662 {
664  expectedRxSuccess,
665  "The number of successfully received packets by STA 3 is not correct!");
667  expectedRxFailure,
668  "The number of unsuccessfuly received packets by STA 3 is not correct!");
670  expectedRxBytes,
671  "The number of bytes received by STA 3 is not correct!");
672 }
673 
674 void
676 {
677  // This is needed to make sure PHY state will be checked as the last event if a state change
678  // occurred at the exact same time as the check
679  Simulator::ScheduleNow(&TestDlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
680 }
681 
682 void
684  WifiPhyState expectedState)
685 {
686  WifiPhyState currentState;
687  PointerValue ptr;
688  phy->GetAttribute("State", ptr);
689  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
690  currentState = state->GetState();
691  NS_LOG_FUNCTION(this << currentState);
692  NS_TEST_ASSERT_MSG_EQ(currentState,
693  expectedState,
694  "PHY State " << currentState << " does not match expected state "
695  << expectedState << " at " << Simulator::Now());
696 }
697 
698 void
700 {
701  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
702  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
703  lossModel->SetFrequency(m_frequency * 1e6);
704  spectrumChannel->AddPropagationLossModel(lossModel);
706  CreateObject<ConstantSpeedPropagationDelayModel>();
707  spectrumChannel->SetPropagationDelayModel(delayModel);
708 
709  Ptr<Node> apNode = CreateObject<Node>();
710  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
711  m_phyAp = CreateObject<SpectrumWifiPhy>();
714  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
715  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
716  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
717  m_phyAp->SetErrorRateModel(apErrorModel);
718  m_phyAp->SetDevice(apDev);
719  m_phyAp->SetChannel(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);
731  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
732  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
733  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
734  m_phySta1->SetErrorRateModel(sta1ErrorModel);
735  m_phySta1->SetDevice(sta1Dev);
736  m_phySta1->SetChannel(spectrumChannel);
740  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
741  m_phySta1->SetMobility(sta1Mobility);
742  sta1Dev->SetPhy(m_phySta1);
743  sta1Node->AggregateObject(sta1Mobility);
744  sta1Node->AddDevice(sta1Dev);
745 
746  Ptr<Node> sta2Node = CreateObject<Node>();
747  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
748  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
751  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
752  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
753  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
754  m_phySta2->SetErrorRateModel(sta2ErrorModel);
755  m_phySta2->SetDevice(sta2Dev);
756  m_phySta2->SetChannel(spectrumChannel);
760  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
761  m_phySta2->SetMobility(sta2Mobility);
762  sta2Dev->SetPhy(m_phySta2);
763  sta2Node->AggregateObject(sta2Mobility);
764  sta2Node->AddDevice(sta2Dev);
765 
766  Ptr<Node> sta3Node = CreateObject<Node>();
767  Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
768  m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
771  Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
772  m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
773  Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
774  m_phySta3->SetErrorRateModel(sta3ErrorModel);
775  m_phySta3->SetDevice(sta3Dev);
776  m_phySta3->SetChannel(spectrumChannel);
780  Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
781  m_phySta3->SetMobility(sta3Mobility);
782  sta3Dev->SetPhy(m_phySta3);
783  sta3Node->AggregateObject(sta3Mobility);
784  sta3Node->AddDevice(sta3Dev);
785 
786  Ptr<Node> interfererNode = CreateObject<Node>();
787  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
788  m_phyInterferer = CreateObject<WaveformGenerator>();
789  m_phyInterferer->SetDevice(interfererDev);
790  m_phyInterferer->SetChannel(spectrumChannel);
792  interfererNode->AddDevice(interfererDev);
793 }
794 
795 void
797 {
798  m_phyAp->Dispose();
799  m_phyAp = nullptr;
800  m_phySta1->Dispose();
801  m_phySta1 = nullptr;
802  m_phySta2->Dispose();
803  m_phySta2 = nullptr;
804  m_phySta3->Dispose();
805  m_phySta3 = nullptr;
807  m_phyInterferer = nullptr;
808 }
809 
810 void
812 {
813  RngSeedManager::SetSeed(1);
814  RngSeedManager::SetRun(1);
815  int64_t streamNumber = 0;
816  m_phyAp->AssignStreams(streamNumber);
817  m_phySta1->AssignStreams(streamNumber);
818  m_phySta2->AssignStreams(streamNumber);
819  m_phySta3->AssignStreams(streamNumber);
820 
821  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
822  m_frequency,
826 
835 
836  Simulator::Schedule(Seconds(0.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
837 
838  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
839  // Each STA should receive its PSDU.
840  Simulator::Schedule(Seconds(1.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
841 
842  // Since it takes m_expectedPpduDuration to transmit the PPDU,
843  // all 3 PHYs should be back to IDLE at the same time,
844  // even the PHY that has no PSDU addressed to it.
845  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
847  this,
848  m_phySta1,
850  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
852  this,
853  m_phySta2,
855  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
857  this,
858  m_phySta3,
860  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
862  this,
863  m_phySta1,
865  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
867  this,
868  m_phySta2,
870  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
872  this,
873  m_phySta3,
875 
876  // One PSDU of 1000 bytes should have been successfully received by STA 1
877  Simulator::Schedule(Seconds(1.1),
879  this,
880  1,
881  0,
882  1000);
883  // One PSDU of 1500 bytes should have been successfully received by STA 2
884  Simulator::Schedule(Seconds(1.1),
886  this,
887  1,
888  0,
889  1500);
890  // No PSDU should have been received by STA 3
891  Simulator::Schedule(Seconds(1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
892 
893  Simulator::Schedule(Seconds(1.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
894 
895  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
896  // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
897  // but should keep its PHY busy during all PPDU duration.
898  Simulator::Schedule(Seconds(2.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 3);
899 
900  // Since it takes m_expectedPpduDuration to transmit the PPDU,
901  // all 3 PHYs should be back to IDLE at the same time,
902  // even the PHY that has no PSDU addressed to it.
903  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
905  this,
906  m_phySta1,
908  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
910  this,
911  m_phySta2,
913  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
915  this,
916  m_phySta3,
918  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
920  this,
921  m_phySta1,
923  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
925  this,
926  m_phySta2,
928  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
930  this,
931  m_phySta3,
933 
934  // One PSDU of 1000 bytes should have been successfully received by STA 1
935  Simulator::Schedule(Seconds(2.1),
937  this,
938  1,
939  0,
940  1000);
941  // No PSDU should have been received by STA 2
942  Simulator::Schedule(Seconds(2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 0, 0);
943  // One PSDU of 1500 bytes should have been successfully received by STA 3
944  Simulator::Schedule(Seconds(2.1),
946  this,
947  1,
948  0,
949  1500);
950 
951  Simulator::Schedule(Seconds(2.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
952 
953  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
954  Simulator::Schedule(Seconds(3.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
955 
956  // A strong non-wifi interference is generated on RU 1 during PSDU reception
957  BandInfo bandInfo;
958  bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
959  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
960  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
961  Bands bands;
962  bands.push_back(bandInfo);
963 
964  Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
965  Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
966  double interferencePower = 0.1; // watts
967  *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
968 
969  Simulator::Schedule(Seconds(3.0) + MicroSeconds(50),
971  this,
972  interferencePsdRu1,
973  MilliSeconds(100));
974 
975  // Since it takes m_expectedPpduDuration to transmit the PPDU,
976  // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
977  // even the PHY that has no PSDU addressed to it.
978  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
980  this,
981  m_phySta1,
983  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
985  this,
986  m_phySta2,
988  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
990  this,
991  m_phySta3,
993  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
995  this,
996  m_phySta1,
998  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
1000  this,
1001  m_phySta2,
1003  Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
1005  this,
1006  m_phySta3,
1008 
1009  // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1010  // occupies RU 1)
1011  Simulator::Schedule(Seconds(3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
1012  // One PSDU of 1500 bytes should have been successfully received by STA 2
1013  Simulator::Schedule(Seconds(3.1),
1015  this,
1016  1,
1017  0,
1018  1500);
1019  // No PSDU should have been received by STA3
1020  Simulator::Schedule(Seconds(3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1021 
1022  Simulator::Schedule(Seconds(3.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1023 
1024  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1025  Simulator::Schedule(Seconds(4.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
1026 
1027  // A strong non-wifi interference is generated on RU 2 during PSDU reception
1028  bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
1029  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
1030  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
1031  bands.clear();
1032  bands.push_back(bandInfo);
1033 
1034  Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1035  Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1036  *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
1037 
1038  Simulator::Schedule(Seconds(4.0) + MicroSeconds(50),
1040  this,
1041  interferencePsdRu2,
1042  MilliSeconds(100));
1043 
1044  // Since it takes m_expectedPpduDuration to transmit the PPDU,
1045  // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1046  // same time, even the PHY that has no PSDU addressed to it.
1047  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1049  this,
1050  m_phySta1,
1052  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1054  this,
1055  m_phySta2,
1057  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1059  this,
1060  m_phySta3,
1062  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1064  this,
1065  m_phySta1,
1067  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1069  this,
1070  m_phySta2,
1072  Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1074  this,
1075  m_phySta3,
1077 
1078  // One PSDU of 1000 bytes should have been successfully received by STA 1
1079  Simulator::Schedule(Seconds(4.1),
1081  this,
1082  1,
1083  0,
1084  1000);
1085  // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1086  // occupies RU 2)
1087  Simulator::Schedule(Seconds(4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
1088  // No PSDU should have been received by STA3
1089  Simulator::Schedule(Seconds(4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1090 
1091  Simulator::Schedule(Seconds(4.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1092 
1093  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1094  Simulator::Schedule(Seconds(5.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
1095 
1096  // A strong non-wifi interference is generated on the full band during PSDU reception
1097  bandInfo.fc = m_frequency * 1e6;
1098  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
1099  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
1100  bands.clear();
1101  bands.push_back(bandInfo);
1102 
1103  Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1104  Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1105  *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
1106 
1107  Simulator::Schedule(Seconds(5.0) + MicroSeconds(50),
1109  this,
1110  interferencePsdAll,
1111  MilliSeconds(100));
1112 
1113  // Since it takes m_expectedPpduDuration to transmit the PPDU,
1114  // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1115  // even the PHY that has no PSDU addressed to it.
1116  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1118  this,
1119  m_phySta1,
1121  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1123  this,
1124  m_phySta2,
1126  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1128  this,
1129  m_phySta3,
1131  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1133  this,
1134  m_phySta1,
1136  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1138  this,
1139  m_phySta2,
1141  Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1143  this,
1144  m_phySta3,
1146 
1147  // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1148  // occupies RU 1)
1149  Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
1150  // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1151  // occupies RU 2)
1152  Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
1153  // No PSDU should have been received by STA3
1154  Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1155 
1156  Simulator::Schedule(Seconds(5.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1157 
1158  Simulator::Run();
1159 }
1160 
1161 void
1163 {
1164  m_frequency = 5180;
1165  m_channelWidth = 20;
1167  RunOne();
1168 
1169  m_frequency = 5190;
1170  m_channelWidth = 40;
1172  RunOne();
1173 
1174  m_frequency = 5210;
1175  m_channelWidth = 80;
1177  RunOne();
1178 
1179  m_frequency = 5250;
1180  m_channelWidth = 160;
1182  RunOne();
1183 
1184  Simulator::Destroy();
1185 }
1186 
1194 {
1195  public:
1197 
1198  private:
1199  void DoSetup() override;
1200  void DoTeardown() override;
1201  void DoRun() override;
1202 
1211  RxSignalInfo rxSignalInfo,
1212  WifiTxVector txVector,
1213  const std::vector<bool> statusPerMpdu);
1214 
1223  RxSignalInfo rxSignalInfo,
1224  WifiTxVector txVector,
1225  std::vector<bool> statusPerMpdu);
1226 
1232 
1238 
1245  void CheckResultsSta1(uint32_t expectedRxSuccess,
1246  uint32_t expectedRxFailure,
1247  uint32_t expectedRxBytes);
1248 
1255  void CheckResultsSta2(uint32_t expectedRxSuccess,
1256  uint32_t expectedRxFailure,
1257  uint32_t expectedRxBytes);
1258 
1262  void ResetResults();
1263 
1271  void SendMuPpdu(uint16_t rxStaId1,
1272  uint16_t rxStaId2,
1273  const std::vector<bool>& puncturedSubchannels);
1274 
1280  void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1281 
1285  void StopInterference();
1286 
1290  void RunOne();
1291 
1298 
1305 
1312 
1317 
1318  uint16_t m_frequency;
1319  uint16_t m_channelWidth;
1320 
1323 
1326 };
1327 
1329  : TestCase("DL-OFDMA PHY puncturing test"),
1330  m_countRxSuccessSta1(0),
1331  m_countRxSuccessSta2(0),
1332  m_countRxFailureSta1(0),
1333  m_countRxFailureSta2(0),
1334  m_countRxBytesSta1(0),
1335  m_countRxBytesSta2(0),
1336  m_frequency(5210),
1337  m_channelWidth(80),
1338  m_indexSubchannel(0),
1339  m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1340  m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1341 {
1342 }
1343 
1344 void
1346 {
1351  m_countRxBytesSta1 = 0;
1352  m_countRxBytesSta2 = 0;
1353 }
1354 
1355 void
1357  uint16_t rxStaId2,
1358  const std::vector<bool>& puncturedSubchannels)
1359 {
1360  NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1361  WifiConstPsduMap psdus;
1362  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
1363  0,
1365  800,
1366  1,
1367  1,
1368  0,
1370  false,
1371  false);
1372 
1373  HeRu::RuType ruType =
1374  puncturedSubchannels.empty()
1375  ? HeRu::RU_484_TONE
1376  : (puncturedSubchannels.at(1) ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1377  HeRu::RuSpec ru1(ruType, 1, true);
1378  txVector.SetRu(ru1, rxStaId1);
1379  txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1380  txVector.SetNss(1, rxStaId1);
1381 
1382  ruType = puncturedSubchannels.empty()
1383  ? HeRu::RU_484_TONE
1384  : (puncturedSubchannels.at(1) ? HeRu::RU_484_TONE : HeRu::RU_242_TONE);
1385  HeRu::RuSpec ru2(ruType,
1386  ruType == HeRu::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1387  true);
1388  txVector.SetRu(ru2, rxStaId2);
1389  txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1390  txVector.SetNss(1, rxStaId2);
1391 
1392  std::vector<uint8_t> ruAlloc;
1393  if (puncturedSubchannels.empty())
1394  {
1395  std::fill_n(std::back_inserter(ruAlloc), 4, 200);
1396  }
1397  else
1398  {
1399  ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1400  ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
1401  ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1402  : (puncturedSubchannels.at(3) ? 192 : 200));
1403  ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1404  : (puncturedSubchannels.at(3) ? 113 : 200));
1405  }
1406 
1407  txVector.SetRuAllocation(ruAlloc);
1408  txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1409 
1410  Ptr<Packet> pkt1 = Create<Packet>(1000);
1411  WifiMacHeader hdr1;
1412  hdr1.SetType(WIFI_MAC_QOSDATA);
1413  hdr1.SetQosTid(0);
1414  hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1415  hdr1.SetSequenceNumber(1);
1416  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1417  psdus.insert(std::make_pair(rxStaId1, psdu1));
1418 
1419  Ptr<Packet> pkt2 = Create<Packet>(1500);
1420  WifiMacHeader hdr2;
1421  hdr2.SetType(WIFI_MAC_QOSDATA);
1422  hdr2.SetQosTid(0);
1423  hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1424  hdr2.SetSequenceNumber(2);
1425  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1426  psdus.insert(std::make_pair(rxStaId2, psdu2));
1427 
1428  if (!puncturedSubchannels.empty())
1429  {
1430  txVector.SetInactiveSubchannels(puncturedSubchannels);
1431  }
1432 
1433  m_phyAp->Send(psdus, txVector);
1434 }
1435 
1436 void
1438 {
1439  NS_LOG_FUNCTION(this << duration);
1440  m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
1441  m_phyInterferer->SetPeriod(duration);
1443  Simulator::Schedule(duration, &TestDlOfdmaPhyPuncturing::StopInterference, this);
1444 }
1445 
1446 void
1448 {
1449  NS_LOG_FUNCTION(this);
1450  m_phyInterferer->Stop();
1451 }
1452 
1453 void
1455  RxSignalInfo rxSignalInfo,
1456  WifiTxVector txVector,
1457  std::vector<bool> /*statusPerMpdu*/)
1458 {
1459  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1461  m_countRxBytesSta1 += (psdu->GetSize() - 30);
1462 }
1463 
1464 void
1466  RxSignalInfo rxSignalInfo,
1467  WifiTxVector txVector,
1468  std::vector<bool> /*statusPerMpdu*/)
1469 {
1470  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1472  m_countRxBytesSta2 += (psdu->GetSize() - 30);
1473 }
1474 
1475 void
1477 {
1478  NS_LOG_FUNCTION(this << *psdu);
1480 }
1481 
1482 void
1484 {
1485  NS_LOG_FUNCTION(this << *psdu);
1487 }
1488 
1489 void
1491  uint32_t expectedRxFailure,
1492  uint32_t expectedRxBytes)
1493 {
1495  expectedRxSuccess,
1496  "The number of successfully received packets by STA 1 is not correct!");
1498  expectedRxFailure,
1499  "The number of unsuccessfuly received packets by STA 1 is not correct!");
1501  expectedRxBytes,
1502  "The number of bytes received by STA 1 is not correct!");
1503 }
1504 
1505 void
1507  uint32_t expectedRxFailure,
1508  uint32_t expectedRxBytes)
1509 {
1511  expectedRxSuccess,
1512  "The number of successfully received packets by STA 2 is not correct!");
1514  expectedRxFailure,
1515  "The number of unsuccessfuly received packets by STA 2 is not correct!");
1517  expectedRxBytes,
1518  "The number of bytes received by STA 2 is not correct!");
1519 }
1520 
1521 void
1523 {
1524  // This is needed to make sure PHY state will be checked as the last event if a state change
1525  // occurred at the exact same time as the check
1526  Simulator::ScheduleNow(&TestDlOfdmaPhyPuncturing::DoCheckPhyState, this, phy, expectedState);
1527 }
1528 
1529 void
1531 {
1532  WifiPhyState currentState;
1533  PointerValue ptr;
1534  phy->GetAttribute("State", ptr);
1535  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
1536  currentState = state->GetState();
1537  NS_LOG_FUNCTION(this << currentState);
1538  NS_TEST_ASSERT_MSG_EQ(currentState,
1539  expectedState,
1540  "PHY State " << currentState << " does not match expected state "
1541  << expectedState << " at " << Simulator::Now());
1542 }
1543 
1544 void
1546 {
1547  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1548  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1549  lossModel->SetFrequency(m_frequency * 1e6);
1550  spectrumChannel->AddPropagationLossModel(lossModel);
1552  CreateObject<ConstantSpeedPropagationDelayModel>();
1553  spectrumChannel->SetPropagationDelayModel(delayModel);
1554 
1555  Ptr<Node> apNode = CreateObject<Node>();
1556  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1557  m_phyAp = CreateObject<SpectrumWifiPhy>();
1560  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1561  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1562  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1563  m_phyAp->SetErrorRateModel(apErrorModel);
1564  m_phyAp->SetDevice(apDev);
1565  m_phyAp->SetChannel(spectrumChannel);
1566  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1567  m_phyAp->SetMobility(apMobility);
1568  apDev->SetPhy(m_phyAp);
1569  apNode->AggregateObject(apMobility);
1570  apNode->AddDevice(apDev);
1571 
1572  Ptr<Node> sta1Node = CreateObject<Node>();
1573  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1574  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1577  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1578  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1579  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1580  m_phySta1->SetErrorRateModel(sta1ErrorModel);
1581  m_phySta1->SetDevice(sta1Dev);
1582  m_phySta1->SetChannel(spectrumChannel);
1586  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1587  m_phySta1->SetMobility(sta1Mobility);
1588  sta1Dev->SetPhy(m_phySta1);
1589  sta1Node->AggregateObject(sta1Mobility);
1590  sta1Node->AddDevice(sta1Dev);
1591 
1592  Ptr<Node> sta2Node = CreateObject<Node>();
1593  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1594  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1597  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1598  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1599  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1600  m_phySta2->SetErrorRateModel(sta2ErrorModel);
1601  m_phySta2->SetDevice(sta2Dev);
1602  m_phySta2->SetChannel(spectrumChannel);
1606  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1607  m_phySta2->SetMobility(sta2Mobility);
1608  sta2Dev->SetPhy(m_phySta2);
1609  sta2Node->AggregateObject(sta2Mobility);
1610  sta2Node->AddDevice(sta2Dev);
1611 
1612  Ptr<Node> interfererNode = CreateObject<Node>();
1613  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
1614  m_phyInterferer = CreateObject<WaveformGenerator>();
1615  m_phyInterferer->SetDevice(interfererDev);
1616  m_phyInterferer->SetChannel(spectrumChannel);
1618  interfererNode->AddDevice(interfererDev);
1619 }
1620 
1621 void
1623 {
1624  m_phyAp->Dispose();
1625  m_phyAp = nullptr;
1626  m_phySta1->Dispose();
1627  m_phySta1 = nullptr;
1628  m_phySta2->Dispose();
1629  m_phySta2 = nullptr;
1631  m_phyInterferer = nullptr;
1632 }
1633 
1634 void
1636 {
1637  RngSeedManager::SetSeed(1);
1638  RngSeedManager::SetRun(1);
1639  int64_t streamNumber = 0;
1640  m_phyAp->AssignStreams(streamNumber);
1641  m_phySta1->AssignStreams(streamNumber);
1642  m_phySta2->AssignStreams(streamNumber);
1643 
1644  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1645  m_frequency,
1649 
1656 
1657  // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1658  // duration of the test run
1659  BandInfo bandInfo;
1660  bandInfo.fc = (m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20)) * 1e6;
1661  // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1662  // the border of another RU
1663  bandInfo.fl = bandInfo.fc - (5 * 1e6);
1664  bandInfo.fh = bandInfo.fc + (5 * 1e6);
1665  Bands bands;
1666  bands.push_back(bandInfo);
1667 
1668  Ptr<SpectrumModel> spectrumInterference = Create<SpectrumModel>(bands);
1669  Ptr<SpectrumValue> interferencePsd = Create<SpectrumValue>(spectrumInterference);
1670  double interferencePower = 0.1; // watts
1671  *interferencePsd = interferencePower / 10e6;
1672 
1673  Simulator::Schedule(Seconds(0.0),
1675  this,
1676  interferencePsd,
1677  Seconds(3));
1678 
1679  //---------------------------------------------------------------------------
1680  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1681  Simulator::Schedule(Seconds(1.0),
1683  this,
1684  1,
1685  2,
1686  std::vector<bool>{});
1687 
1688  // Since it takes m_expectedPpduDuration to transmit the PPDU,
1689  // both PHYs should be back to IDLE at the same time.
1690  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz - NanoSeconds(1),
1692  this,
1693  m_phySta1,
1695  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz - NanoSeconds(1),
1697  this,
1698  m_phySta2,
1700  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz,
1702  this,
1703  m_phySta1,
1705  Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz,
1707  this,
1708  m_phySta2,
1710 
1711  if (m_indexSubchannel < 2) // interference in RU 1
1712  {
1713  // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1714  Simulator::Schedule(Seconds(1.1),
1716  this,
1717  0,
1718  1,
1719  0);
1720  // One PSDU of 1500 bytes should have been successfully received by STA 2
1721  Simulator::Schedule(Seconds(1.1),
1723  this,
1724  1,
1725  0,
1726  1500);
1727  }
1728  else // interference in RU 2
1729  {
1730  // One PSDU of 1000 bytes should have been successfully received by STA 1
1731  Simulator::Schedule(Seconds(1.1),
1733  this,
1734  1,
1735  0,
1736  1000);
1737  // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1738  Simulator::Schedule(Seconds(1.1),
1740  this,
1741  0,
1742  1,
1743  0);
1744  }
1745 
1746  Simulator::Schedule(Seconds(1.5), &TestDlOfdmaPhyPuncturing::ResetResults, this);
1747 
1748  //---------------------------------------------------------------------------
1749  // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1750  // the punctured 20 MHz subchannel is the one that has interference
1751  std::vector<bool> puncturedSubchannels;
1752  for (std::size_t i = 0; i < (m_channelWidth / 20); ++i)
1753  {
1754  if (i == m_indexSubchannel)
1755  {
1756  puncturedSubchannels.push_back(true);
1757  }
1758  else
1759  {
1760  puncturedSubchannels.push_back(false);
1761  }
1762  }
1763  Simulator::Schedule(Seconds(2.0),
1765  this,
1766  1,
1767  2,
1768  puncturedSubchannels);
1769 
1770  // Since it takes m_expectedPpduDuration to transmit the PPDU,
1771  // both PHYs should be back to IDLE at the same time.
1772  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz - NanoSeconds(1),
1774  this,
1775  m_phySta1,
1777  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz - NanoSeconds(1),
1779  this,
1780  m_phySta2,
1782  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz,
1784  this,
1785  m_phySta1,
1787  Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz,
1789  this,
1790  m_phySta2,
1792 
1793  // One PSDU of 1000 bytes should have been successfully received by STA 1
1794  Simulator::Schedule(Seconds(2.1),
1796  this,
1797  1,
1798  0,
1799  1000);
1800  // One PSDU of 1500 bytes should have been successfully received by STA 2
1801  Simulator::Schedule(Seconds(2.1),
1803  this,
1804  1,
1805  0,
1806  1500);
1807 
1808  Simulator::Schedule(Seconds(2.5), &TestDlOfdmaPhyPuncturing::ResetResults, this);
1809 
1810  Simulator::Run();
1811 }
1812 
1813 void
1815 {
1816  // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1817  // cannot be punctured
1818  for (auto index : {1, 2, 3})
1819  {
1820  m_indexSubchannel = index;
1821  RunOne();
1822  }
1823  Simulator::Destroy();
1824 }
1825 
1833 {
1834  public:
1836  ~TestUlOfdmaPpduUid() override;
1837 
1838  private:
1839  void DoSetup() override;
1840  void DoTeardown() override;
1841  void DoRun() override;
1842 
1847  void TxPpduAp(uint64_t uid);
1852  void TxPpduSta1(uint64_t uid);
1857  void TxPpduSta2(uint64_t uid);
1861  void ResetPpduUid();
1862 
1866  void SendMuPpdu();
1870  void SendTbPpdu();
1875  void SendSuPpdu(uint16_t txStaId);
1876 
1882  void CheckUid(uint16_t staId, uint64_t expectedUid);
1883 
1887 
1888  uint64_t m_ppduUidAp;
1889  uint64_t m_ppduUidSta1;
1890  uint64_t m_ppduUidSta2;
1891 };
1892 
1894  : TestCase("UL-OFDMA PPDU UID attribution test"),
1895  m_ppduUidAp(UINT64_MAX),
1896  m_ppduUidSta1(UINT64_MAX),
1897  m_ppduUidSta2(UINT64_MAX)
1898 {
1899 }
1900 
1902 {
1903 }
1904 
1905 void
1907 {
1908  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1909  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1910  lossModel->SetFrequency(DEFAULT_FREQUENCY);
1911  spectrumChannel->AddPropagationLossModel(lossModel);
1913  CreateObject<ConstantSpeedPropagationDelayModel>();
1914  spectrumChannel->SetPropagationDelayModel(delayModel);
1915 
1916  Ptr<Node> apNode = CreateObject<Node>();
1917  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1918  m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
1921  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1922  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1923  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1924  m_phyAp->SetErrorRateModel(apErrorModel);
1925  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1932  m_phyAp->SetDevice(apDev);
1933  m_phyAp->SetChannel(spectrumChannel);
1934  m_phyAp->TraceConnectWithoutContext("TxPpduUid",
1936  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1937  m_phyAp->SetMobility(apMobility);
1938  apDev->SetPhy(m_phyAp);
1939  apNode->AggregateObject(apMobility);
1940  apNode->AddDevice(apDev);
1942  apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1943 
1944  Ptr<Node> sta1Node = CreateObject<Node>();
1945  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1946  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1949  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1950  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1951  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1952  m_phySta1->SetErrorRateModel(sta1ErrorModel);
1955  m_phySta1->SetDevice(sta1Dev);
1956  m_phySta1->SetChannel(spectrumChannel);
1959  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1960  m_phySta1->SetMobility(sta1Mobility);
1961  sta1Dev->SetPhy(m_phySta1);
1962  sta1Node->AggregateObject(sta1Mobility);
1963  sta1Node->AddDevice(sta1Dev);
1964 
1965  Ptr<Node> sta2Node = CreateObject<Node>();
1966  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1967  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1970  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1971  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1972  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1973  m_phySta2->SetErrorRateModel(sta2ErrorModel);
1976  m_phySta2->SetDevice(sta2Dev);
1977  m_phySta2->SetChannel(spectrumChannel);
1980  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1981  m_phySta2->SetMobility(sta2Mobility);
1982  sta2Dev->SetPhy(m_phySta2);
1983  sta2Node->AggregateObject(sta2Mobility);
1984  sta2Node->AddDevice(sta2Dev);
1985 }
1986 
1987 void
1989 {
1990  m_phyAp->Dispose();
1991  m_phyAp = nullptr;
1992  m_phySta1->Dispose();
1993  m_phySta1 = nullptr;
1994  m_phySta2->Dispose();
1995  m_phySta2 = nullptr;
1996 }
1997 
1998 void
1999 TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
2000 {
2001  uint64_t uid;
2002  std::string device;
2003  switch (staId)
2004  {
2005  case 0:
2006  uid = m_ppduUidAp;
2007  device = "AP";
2008  break;
2009  case 1:
2010  uid = m_ppduUidSta1;
2011  device = "STA1";
2012  break;
2013  case 2:
2014  uid = m_ppduUidSta2;
2015  device = "STA2";
2016  break;
2017  default:
2018  NS_ABORT_MSG("Unexpected STA-ID");
2019  }
2021  expectedUid,
2022  "UID " << uid << " does not match expected one " << expectedUid << " for "
2023  << device << " at " << Simulator::Now());
2024 }
2025 
2026 void
2028 {
2029  NS_LOG_FUNCTION(this << uid);
2030  m_ppduUidAp = uid;
2031 }
2032 
2033 void
2035 {
2036  NS_LOG_FUNCTION(this << uid);
2037  m_ppduUidSta1 = uid;
2038 }
2039 
2040 void
2042 {
2043  NS_LOG_FUNCTION(this << uid);
2044  m_ppduUidSta2 = uid;
2045 }
2046 
2047 void
2049 {
2050  NS_LOG_FUNCTION(this);
2051  m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2052 }
2053 
2054 void
2056 {
2057  WifiConstPsduMap psdus;
2058  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2059  0,
2061  800,
2062  1,
2063  1,
2064  0,
2066  false,
2067  false);
2068 
2069  uint16_t rxStaId1 = 1;
2070  HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2071  txVector.SetRu(ru1, rxStaId1);
2072  txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2073  txVector.SetNss(1, rxStaId1);
2074 
2075  uint16_t rxStaId2 = 2;
2076  HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2077  txVector.SetRu(ru2, rxStaId2);
2078  txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2079  txVector.SetNss(1, rxStaId2);
2080  txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2081  txVector.SetRuAllocation({96});
2082 
2083  Ptr<Packet> pkt1 = Create<Packet>(1000);
2084  WifiMacHeader hdr1;
2085  hdr1.SetType(WIFI_MAC_QOSDATA);
2086  hdr1.SetQosTid(0);
2087  hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2088  hdr1.SetSequenceNumber(1);
2089  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2090  psdus.insert(std::make_pair(rxStaId1, psdu1));
2091 
2092  Ptr<Packet> pkt2 = Create<Packet>(1500);
2093  WifiMacHeader hdr2;
2094  hdr2.SetType(WIFI_MAC_QOSDATA);
2095  hdr2.SetQosTid(0);
2096  hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2097  hdr2.SetSequenceNumber(2);
2098  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2099  psdus.insert(std::make_pair(rxStaId2, psdu2));
2100 
2101  m_phyAp->Send(psdus, txVector);
2102 }
2103 
2104 void
2106 {
2107  WifiConstPsduMap psdus1;
2108  WifiConstPsduMap psdus2;
2109 
2110  WifiTxVector txVector1 = WifiTxVector(HePhy::GetHeMcs7(),
2111  0,
2113  1600,
2114  1,
2115  1,
2116  0,
2118  false,
2119  false);
2120  WifiTxVector txVector2 = txVector1;
2121  WifiTxVector trigVector = txVector2;
2122 
2123  uint16_t rxStaId1 = 1;
2124  HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2125  txVector1.SetRu(ru1, rxStaId1);
2126  txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2127  txVector1.SetNss(1, rxStaId1);
2128  trigVector.SetRu(ru1, rxStaId1);
2129  trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2130  trigVector.SetNss(1, rxStaId1);
2131 
2132  Ptr<Packet> pkt1 = Create<Packet>(1000);
2133  WifiMacHeader hdr1;
2134  hdr1.SetType(WIFI_MAC_QOSDATA);
2135  hdr1.SetQosTid(0);
2136  hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2137  hdr1.SetSequenceNumber(1);
2138  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2139  psdus1.insert(std::make_pair(rxStaId1, psdu1));
2140 
2141  uint16_t rxStaId2 = 2;
2142  HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, false);
2143  txVector2.SetRu(ru2, rxStaId2);
2144  txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2145  txVector2.SetNss(1, rxStaId2);
2146  trigVector.SetRu(ru2, rxStaId2);
2147  trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2148  trigVector.SetNss(1, rxStaId2);
2149 
2150  Ptr<Packet> pkt2 = Create<Packet>(1500);
2151  WifiMacHeader hdr2;
2152  hdr2.SetType(WIFI_MAC_QOSDATA);
2153  hdr2.SetQosTid(0);
2154  hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2155  hdr2.SetSequenceNumber(2);
2156  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2157  psdus2.insert(std::make_pair(rxStaId2, psdu2));
2158 
2159  Time txDuration1 = m_phySta1->CalculateTxDuration(psdu1->GetSize(),
2160  txVector1,
2161  m_phySta1->GetPhyBand(),
2162  rxStaId1);
2163  Time txDuration2 = m_phySta2->CalculateTxDuration(psdu2->GetSize(),
2164  txVector2,
2165  m_phySta1->GetPhyBand(),
2166  rxStaId2);
2167  Time txDuration = std::max(txDuration1, txDuration2);
2168 
2169  txVector1.SetLength(
2170  HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector1, m_phySta1->GetPhyBand())
2171  .first);
2172  txVector2.SetLength(
2173  HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector2, m_phySta2->GetPhyBand())
2174  .first);
2175 
2176  auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
2177  hePhyAp->SetTrigVector(trigVector, txDuration);
2178 
2179  m_phySta1->Send(psdus1, txVector1);
2180  m_phySta2->Send(psdus2, txVector2);
2181 }
2182 
2183 void
2185 {
2186  WifiConstPsduMap psdus;
2187  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2188  0,
2190  800,
2191  1,
2192  1,
2193  0,
2195  false,
2196  false);
2197 
2198  Ptr<Packet> pkt = Create<Packet>(1000);
2199  WifiMacHeader hdr;
2201  hdr.SetQosTid(0);
2202  hdr.SetAddr1(Mac48Address::GetBroadcast());
2203  hdr.SetSequenceNumber(1);
2204  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2205  psdus.insert(std::make_pair(SU_STA_ID, psdu));
2206 
2207  switch (txStaId)
2208  {
2209  case 0:
2210  m_phyAp->Send(psdus, txVector);
2211  break;
2212  case 1:
2213  m_phySta1->Send(psdus, txVector);
2214  break;
2215  case 2:
2216  m_phySta2->Send(psdus, txVector);
2217  break;
2218  default:
2219  NS_ABORT_MSG("Unexpected STA-ID");
2220  }
2221 }
2222 
2223 void
2225 {
2226  RngSeedManager::SetSeed(1);
2227  RngSeedManager::SetRun(1);
2228  int64_t streamNumber = 0;
2229  m_phyAp->AssignStreams(streamNumber);
2230  m_phySta1->AssignStreams(streamNumber);
2231  m_phySta2->AssignStreams(streamNumber);
2232 
2233  // Reset PPDU UID so as not to be dependent on previously executed test cases,
2234  // since global attribute will be changed).
2235  ResetPpduUid();
2236 
2237  // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2238  // PPDU UID should be equal to 0 (the first counter value).
2239  Simulator::Schedule(Seconds(1.0), &TestUlOfdmaPpduUid::SendMuPpdu, this);
2240  Simulator::Schedule(Seconds(1.0), &TestUlOfdmaPpduUid::CheckUid, this, 0, 0);
2241 
2242  // Send HE SU PPDU from AP.
2243  // PPDU UID should be incremented since this is a new PPDU.
2244  Simulator::Schedule(Seconds(1.1), &TestUlOfdmaPpduUid::SendSuPpdu, this, 0);
2245  Simulator::Schedule(Seconds(1.1), &TestUlOfdmaPpduUid::CheckUid, this, 0, 1);
2246 
2247  // Send HE TB PPDU from STAs to AP.
2248  // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2249  // preceding correctly received PPDU (which normally contains the trigger frame).
2250  Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::SendTbPpdu, this);
2251  Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::CheckUid, this, 1, 1);
2252  Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::CheckUid, this, 2, 1);
2253 
2254  // Send HE SU PPDU from STA1.
2255  // PPDU UID should be incremented since this is a new PPDU.
2256  Simulator::Schedule(Seconds(1.2), &TestUlOfdmaPpduUid::SendSuPpdu, this, 1);
2257  Simulator::Schedule(Seconds(1.2), &TestUlOfdmaPpduUid::CheckUid, this, 1, 2);
2258 
2259  Simulator::Run();
2260  Simulator::Destroy();
2261 }
2262 
2270 {
2271  public:
2273  ~TestMultipleHeTbPreambles() override;
2274 
2275  private:
2276  void DoSetup() override;
2277  void DoTeardown() override;
2278  void DoRun() override;
2279 
2289  void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize);
2290 
2305 
2312 
2316  void Reset();
2317 
2323  void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2324 
2329  void CheckBytesDropped(size_t expectedBytesDropped);
2330 
2332 
2335 };
2336 
2338  : TestCase("UL-OFDMA multiple RX events test"),
2339  m_totalBytesDropped(0),
2340  m_trigVector(HePhy::GetHeMcs7(),
2341  0,
2343  1600,
2344  1,
2345  1,
2346  0,
2348  false,
2349  false)
2350 {
2351 }
2352 
2354 {
2355 }
2356 
2357 void
2359 {
2360  NS_LOG_FUNCTION(this);
2361  m_totalBytesDropped = 0;
2362  // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2363  m_phy->Reset();
2364  m_trigVector.GetHeMuUserInfoMap().clear();
2365 }
2366 
2367 void
2369 {
2370  NS_LOG_FUNCTION(this << p << reason);
2371  m_totalBytesDropped += (p->GetSize() - 30);
2372 }
2373 
2374 void
2375 TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2376 {
2377  auto events = m_phy->GetCurrentPreambleEvents();
2378  NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2379  for (const auto& uid : uids)
2380  {
2381  auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2382  auto it = events.find(pair);
2383  bool found = (it != events.end());
2384  NS_TEST_ASSERT_MSG_EQ(found,
2385  true,
2386  "HE TB PPDU with UID " << uid << " has not been received!");
2387  }
2388 }
2389 
2390 void
2392 {
2394  expectedBytesDropped,
2395  "The number of dropped bytes is not correct!");
2396 }
2397 
2398 void
2400  uint16_t staId,
2401  double txPowerWatts,
2402  size_t payloadSize)
2403 {
2404  WifiConstPsduMap psdus;
2405  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2406  0,
2408  1600,
2409  1,
2410  1,
2411  0,
2413  false,
2414  false);
2415 
2416  HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2417  txVector.SetRu(ru, staId);
2418  txVector.SetMode(HePhy::GetHeMcs7(), staId);
2419  txVector.SetNss(1, staId);
2420 
2421  m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2422 
2423  Ptr<Packet> pkt = Create<Packet>(payloadSize);
2424  WifiMacHeader hdr;
2426  hdr.SetQosTid(0);
2427  hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2428  hdr.SetSequenceNumber(1);
2429  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2430  psdus.insert(std::make_pair(staId, psdu));
2431 
2432  Time ppduDuration =
2433  m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand(), staId);
2434  Ptr<HePpdu> ppdu = Create<HePpdu>(psdus,
2435  txVector,
2437  ppduDuration,
2439  uid,
2440  HePpdu::PSD_NON_HE_PORTION);
2441 
2442  // Send non-OFDMA part
2443  Time nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonOfdmaDurationForHeTb(txVector);
2444  uint32_t centerFrequency =
2445  m_phy->GetHePhy()->GetCenterFrequencyForNonOfdmaPart(txVector, staId);
2446  uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2447  uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
2448  Ptr<SpectrumValue> rxPsd = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(
2449  centerFrequency,
2450  channelWidth,
2451  txPowerWatts,
2452  m_phy->GetGuardBandwidth(channelWidth));
2453  Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters>();
2454  rxParams->psd = rxPsd;
2455  rxParams->txPhy = nullptr;
2456  rxParams->duration = nonOfdmaDuration;
2457  rxParams->ppdu = ppdu;
2458  rxParams->txWidth = channelWidth;
2459 
2460  uint16_t length;
2461  std::tie(length, ppduDuration) =
2462  HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, txVector, m_phy->GetPhyBand());
2463  txVector.SetLength(length);
2464  m_trigVector.SetLength(length);
2465  auto hePhy = DynamicCast<HePhy>(m_phy->GetLatestPhyEntity());
2466  hePhy->SetTrigVector(m_trigVector, ppduDuration);
2467  ppdu->ResetTxVector();
2468  m_phy->StartRx(rxParams);
2469 
2470  // Schedule OFDMA part
2471  Ptr<HePpdu> ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2472  ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2473  WifiSpectrumBand band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2474  Ptr<SpectrumValue> rxPsdOfdma =
2475  WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity(DEFAULT_FREQUENCY,
2477  txPowerWatts,
2479  band);
2480  Ptr<WifiSpectrumSignalParameters> rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2481  rxParamsOfdma->psd = rxPsd;
2482  rxParamsOfdma->txPhy = nullptr;
2483  rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2484  rxParamsOfdma->ppdu = ppduOfdma;
2485  rxParamsOfdma->txWidth = DEFAULT_CHANNEL_WIDTH;
2486  Simulator::Schedule(nonOfdmaDuration,
2488  this,
2489  rxParamsOfdma);
2490 }
2491 
2492 void
2494 {
2495  Simulator::ScheduleNow(&TestMultipleHeTbPreambles::DoRxHeTbPpduOfdmaPart, this, rxParamsOfdma);
2496 }
2497 
2498 void
2500 {
2501  // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2502  // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2503  // OFDMA part is scheduled after end of HE-SIG-A decoding.
2504  m_phy->StartRx(rxParamsOfdma);
2505 }
2506 
2507 void
2509 {
2510  Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
2512  m_phy = CreateObject<OfdmaSpectrumWifiPhy>(0);
2514  Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2515  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2516  Ptr<ApWifiMac> mac = CreateObject<ApWifiMac>();
2517  mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2518  dev->SetMac(mac);
2519  m_phy->SetInterferenceHelper(interferenceHelper);
2520  m_phy->SetErrorRateModel(error);
2524  0});
2525  m_phy->TraceConnectWithoutContext("PhyRxDrop",
2527  m_phy->SetDevice(dev);
2528  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2529  CreateObject<ThresholdPreambleDetectionModel>();
2530  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2531  preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2532  m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2533  Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
2534  heConfiguration->SetMaxTbPpduDelay(NanoSeconds(400));
2535  dev->SetHeConfiguration(heConfiguration);
2536 }
2537 
2538 void
2540 {
2541  m_phy->Dispose();
2542  m_phy = nullptr;
2543 }
2544 
2545 void
2547 {
2548  RngSeedManager::SetSeed(1);
2549  RngSeedManager::SetRun(1);
2550  int64_t streamNumber = 0;
2551  m_phy->AssignStreams(streamNumber);
2552 
2553  double txPowerWatts = 0.01;
2554 
2555  {
2556  // Verify a single UL MU transmission with two stations belonging to the same BSS
2557  std::vector<uint64_t> uids{0};
2558  Simulator::Schedule(Seconds(1),
2560  this,
2561  uids[0],
2562  1,
2563  txPowerWatts,
2564  1001);
2565  Simulator::Schedule(Seconds(1) + NanoSeconds(100),
2567  this,
2568  uids[0],
2569  2,
2570  txPowerWatts,
2571  1002);
2572  // Check that we received a single UL MU transmission with the corresponding UID
2573  Simulator::Schedule(Seconds(1.0) + MicroSeconds(1),
2575  this,
2576  1,
2577  uids);
2578  Simulator::Schedule(Seconds(1.5), &TestMultipleHeTbPreambles::Reset, this);
2579  }
2580 
2581  {
2582  // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2583  // the second transmission arrives during the preamble detection window and with half the
2584  // power of the first transmission.
2585  std::vector<uint64_t> uids{1, 2};
2586  Simulator::Schedule(Seconds(2),
2588  this,
2589  uids[0],
2590  1,
2591  txPowerWatts,
2592  1001);
2593  Simulator::Schedule(Seconds(2) + NanoSeconds(100),
2595  this,
2596  uids[0],
2597  2,
2598  txPowerWatts,
2599  1002);
2600  Simulator::Schedule(Seconds(2) + NanoSeconds(200),
2602  this,
2603  uids[1],
2604  1,
2605  txPowerWatts / 2,
2606  1003);
2607  Simulator::Schedule(Seconds(2) + NanoSeconds(300),
2609  this,
2610  uids[1],
2611  2,
2612  txPowerWatts / 2,
2613  1004);
2614  // Check that we received the correct reception of 2 UL MU transmissions with the
2615  // corresponding UIDs
2616  Simulator::Schedule(Seconds(2.0) + MicroSeconds(1),
2618  this,
2619  2,
2620  uids);
2621  Simulator::Schedule(Seconds(2.5), &TestMultipleHeTbPreambles::Reset, this);
2622  // TODO: verify PPDUs from second UL MU transmission are dropped
2623  }
2624 
2625  {
2626  // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2627  // the second transmission arrives during the preamble detection window and with twice the
2628  // power of the first transmission.
2629  std::vector<uint64_t> uids{3, 4};
2630  Simulator::Schedule(Seconds(3),
2632  this,
2633  uids[0],
2634  1,
2635  txPowerWatts / 2,
2636  1001);
2637  Simulator::Schedule(Seconds(3) + NanoSeconds(100),
2639  this,
2640  uids[0],
2641  2,
2642  txPowerWatts / 2,
2643  1002);
2644  Simulator::Schedule(Seconds(3) + NanoSeconds(200),
2646  this,
2647  uids[1],
2648  1,
2649  txPowerWatts,
2650  1003);
2651  Simulator::Schedule(Seconds(3) + NanoSeconds(300),
2653  this,
2654  uids[1],
2655  2,
2656  txPowerWatts,
2657  1004);
2658  // Check that we received the correct reception of 2 UL MU transmissions with the
2659  // corresponding UIDs
2660  Simulator::Schedule(Seconds(3.0) + MicroSeconds(1),
2662  this,
2663  2,
2664  uids);
2665  Simulator::Schedule(Seconds(3.5), &TestMultipleHeTbPreambles::Reset, this);
2666  // TODO: verify PPDUs from first UL MU transmission are dropped
2667  }
2668 
2669  {
2670  // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2671  // the second transmission arrives during PHY header reception and with the same power as
2672  // the first transmission.
2673  std::vector<uint64_t> uids{5, 6};
2674  Simulator::Schedule(Seconds(4),
2676  this,
2677  uids[0],
2678  1,
2679  txPowerWatts,
2680  1001);
2681  Simulator::Schedule(Seconds(4) + NanoSeconds(100),
2683  this,
2684  uids[0],
2685  2,
2686  txPowerWatts,
2687  1002);
2688  Simulator::Schedule(Seconds(4) + MicroSeconds(5),
2690  this,
2691  uids[1],
2692  1,
2693  txPowerWatts,
2694  1003);
2695  Simulator::Schedule(Seconds(4) + MicroSeconds(5) + NanoSeconds(100),
2697  this,
2698  uids[1],
2699  2,
2700  txPowerWatts,
2701  1004);
2702  // Check that we received the correct reception of the first UL MU transmission with the
2703  // corresponding UID (second one dropped)
2704  Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
2706  this,
2707  1,
2708  std::vector<uint64_t>{uids[0]});
2709  // The packets of the second UL MU transmission should have been dropped
2710  Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
2712  this,
2713  1003 + 1004);
2714  Simulator::Schedule(Seconds(4.5), &TestMultipleHeTbPreambles::Reset, this);
2715  }
2716 
2717  {
2718  // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2719  // BSS, where the second transmission arrives during payload reception and with the same
2720  // power as the first transmission.
2721  std::vector<uint64_t> uids{7, 8};
2722  Simulator::Schedule(Seconds(5),
2724  this,
2725  uids[0],
2726  1,
2727  txPowerWatts,
2728  1001);
2729  Simulator::Schedule(Seconds(5) + NanoSeconds(100),
2731  this,
2732  uids[0],
2733  2,
2734  txPowerWatts,
2735  1002);
2736  Simulator::Schedule(Seconds(5) + MicroSeconds(50),
2738  this,
2739  uids[1],
2740  1,
2741  txPowerWatts,
2742  1003);
2743  Simulator::Schedule(Seconds(5) + MicroSeconds(50) + NanoSeconds(100),
2745  this,
2746  uids[1],
2747  2,
2748  txPowerWatts,
2749  1004);
2750  // Check that we received the correct reception of the first UL MU transmission with the
2751  // corresponding UID (second one dropped)
2752  Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
2754  this,
2755  1,
2756  std::vector<uint64_t>{uids[0]});
2757  // The packets of the second UL MU transmission should have been dropped
2758  Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
2760  this,
2761  1003 + 1004);
2762  Simulator::Schedule(Seconds(5.5), &TestMultipleHeTbPreambles::Reset, this);
2763  }
2764 
2765  {
2766  // Verify the correct reception of a single UL MU transmission with two stations belonging
2767  // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2768  // the configured delay spread of 400ns
2769  std::vector<uint64_t> uids{9};
2770  Simulator::Schedule(Seconds(6),
2772  this,
2773  uids[0],
2774  1,
2775  txPowerWatts,
2776  1001);
2777  Simulator::Schedule(Seconds(6) + NanoSeconds(500),
2779  this,
2780  uids[0],
2781  2,
2782  txPowerWatts,
2783  1002);
2784  // Check that we received a single UL MU transmission with the corresponding UID
2785  Simulator::Schedule(Seconds(6.0) + MicroSeconds(1),
2787  this,
2788  1,
2789  uids);
2790  // The first packet of 1001 bytes should be dropped because preamble is not detected after
2791  // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2792  // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2793  // second packet of 1002 bytes is dropped as well.
2794  Simulator::Schedule(Seconds(6.0) + MicroSeconds(5),
2796  this,
2797  1001 + 1002);
2798  Simulator::Schedule(Seconds(6.5), &TestMultipleHeTbPreambles::Reset, this);
2799  }
2800 
2801  Simulator::Run();
2802  Simulator::Destroy();
2803 }
2804 
2812 {
2813  public:
2815 
2816  void NotifyRxStart(Time duration) override
2817  {
2818  NS_LOG_FUNCTION(this << duration);
2820  ++m_notifyRxStart;
2821  m_lastRxSuccess = false;
2822  }
2823 
2824  void NotifyRxEndOk() override
2825  {
2826  NS_LOG_FUNCTION(this);
2828  ++m_notifyRxEnd;
2829  m_lastRxSuccess = true;
2830  }
2831 
2832  void NotifyRxEndError() override
2833  {
2834  NS_LOG_FUNCTION(this);
2836  ++m_notifyRxEnd;
2837  m_lastRxSuccess = false;
2838  }
2839 
2840  void NotifyTxStart(Time duration, double txPowerDbm) override
2841  {
2842  NS_LOG_FUNCTION(this << duration << txPowerDbm);
2843  }
2844 
2845  void NotifyCcaBusyStart(Time duration,
2846  WifiChannelListType channelType,
2847  const std::vector<Time>& /*per20MhzDurations*/) override
2848  {
2849  NS_LOG_FUNCTION(this << duration << channelType);
2850  }
2851 
2852  void NotifySwitchingStart(Time duration) override
2853  {
2854  }
2855 
2856  void NotifySleep() override
2857  {
2858  }
2859 
2860  void NotifyOff() override
2861  {
2862  }
2863 
2864  void NotifyWakeup() override
2865  {
2866  }
2867 
2868  void NotifyOn() override
2869  {
2870  }
2871 
2875  void Reset()
2876  {
2877  m_notifyRxStart = 0;
2878  m_notifyRxEnd = 0;
2879  m_lastRxStart = Seconds(0);
2880  m_lastRxEnd = Seconds(0);
2881  m_lastRxSuccess = false;
2882  }
2883 
2889  {
2890  return m_notifyRxStart;
2891  }
2892 
2897  uint32_t GetNumRxEndNotifications() const
2898  {
2899  return m_notifyRxEnd;
2900  }
2901 
2907  {
2908  return m_lastRxStart;
2909  }
2910 
2916  {
2917  return m_lastRxEnd;
2918  }
2919 
2924  bool IsLastRxSuccess() const
2925  {
2926  return m_lastRxSuccess;
2927  }
2928 
2929  private:
2930  uint32_t m_notifyRxStart{0};
2931  uint32_t m_notifyRxEnd{0};
2934  bool m_lastRxSuccess{false};
2935 };
2936 
2944 {
2945  public:
2950  {
2951  NONE = 0,
2955  };
2956 
2958  ~TestUlOfdmaPhyTransmission() override;
2959 
2960  private:
2961  void DoSetup() override;
2962  void DoTeardown() override;
2963  void DoRun() override;
2964 
2972  WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2973  std::size_t index,
2974  uint8_t bssColor) const;
2981  void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2991  void SendHeTbPpdu(uint16_t txStaId,
2992  std::size_t index,
2993  std::size_t payloadSize,
2994  uint64_t uid,
2995  uint8_t bssColor,
2996  bool incrementUid);
2997 
3005  void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
3006 
3012  void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3013 
3019  void SetPsdLimit(Ptr<WifiPhy> phy, double psdLimit);
3020 
3026  void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3030  void StopInterference();
3031 
3035  void RunOne();
3036 
3043  void CheckRxFromSta1(uint32_t expectedSuccess,
3044  uint32_t expectedFailures,
3045  uint32_t expectedBytes);
3046 
3053  void CheckRxFromSta2(uint32_t expectedSuccess,
3054  uint32_t expectedFailures,
3055  uint32_t expectedBytes);
3056 
3064  WifiSpectrumBand band,
3065  double expectedRxPower);
3073  WifiSpectrumBand band,
3074  double expectedRxPower);
3075 
3079  void VerifyEventsCleared();
3080 
3089 
3096  void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3104  void CheckApRxEnd(uint32_t expectedNotifications,
3105  Time expectedLastNotification,
3106  bool expectedSuccess);
3107 
3111  void Reset();
3112 
3120  void RxSuccess(Ptr<const WifiPsdu> psdu,
3121  RxSignalInfo rxSignalInfo,
3122  WifiTxVector txVector,
3123  std::vector<bool> statusPerMpdu);
3124 
3129  void RxFailure(Ptr<const WifiPsdu> psdu);
3130 
3151  void ScheduleTest(Time delay,
3152  bool solicited,
3153  WifiPhyState expectedStateAtEnd,
3154  uint32_t expectedSuccessFromSta1,
3155  uint32_t expectedFailuresFromSta1,
3156  uint32_t expectedBytesFromSta1,
3157  uint32_t expectedSuccessFromSta2,
3158  uint32_t expectedFailuresFromSta2,
3159  uint32_t expectedBytesFromSta2,
3160  bool scheduleTxSta1 = true,
3161  Time ulTimeDifference = Seconds(0),
3162  WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3163  TrigVectorInfo error = NONE);
3164 
3175  double rxPowerNonOfdmaRu1,
3176  double rxPowerNonOfdmaRu2,
3177  double rxPowerOfdmaRu1,
3178  double rxPowerOfdmaRu2);
3184  void LogScenario(std::string log) const;
3185 
3190 
3191  std::unique_ptr<OfdmaTestPhyListener>
3193 
3195 
3202 
3203  uint16_t m_frequency;
3204  uint16_t m_channelWidth;
3206 };
3207 
3209  : TestCase("UL-OFDMA PHY test"),
3210  m_countRxSuccessFromSta1(0),
3211  m_countRxSuccessFromSta2(0),
3212  m_countRxFailureFromSta1(0),
3213  m_countRxFailureFromSta2(0),
3214  m_countRxBytesFromSta1(0),
3215  m_countRxBytesFromSta2(0),
3216  m_frequency(DEFAULT_FREQUENCY),
3217  m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3218  m_expectedPpduDuration(NanoSeconds(271200))
3219 {
3220 }
3221 
3222 void
3224  std::size_t payloadSize,
3225  uint64_t uid,
3226  uint8_t bssColor)
3227 {
3228  NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3229  WifiConstPsduMap psdus;
3230 
3231  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
3232  0,
3234  800,
3235  1,
3236  1,
3237  0,
3239  false,
3240  false,
3241  false,
3242  bssColor);
3243 
3244  Ptr<Packet> pkt = Create<Packet>(payloadSize);
3245  WifiMacHeader hdr;
3247  hdr.SetQosTid(0);
3248  hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3249  std::ostringstream addr;
3250  addr << "00:00:00:00:00:0" << txStaId;
3251  hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3252  hdr.SetSequenceNumber(1);
3253  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3254  psdus.insert(std::make_pair(SU_STA_ID, psdu));
3255 
3257  if (txStaId == 1)
3258  {
3259  phy = m_phySta1;
3260  }
3261  else if (txStaId == 2)
3262  {
3263  phy = m_phySta2;
3264  }
3265  else if (txStaId == 3)
3266  {
3267  phy = m_phySta3;
3268  }
3269  else if (txStaId == 0)
3270  {
3271  phy = m_phyAp;
3272  }
3273  phy->SetPpduUid(uid);
3274  phy->Send(psdus, txVector);
3275 }
3276 
3279  std::size_t index,
3280  uint8_t bssColor) const
3281 {
3282  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
3283  0,
3285  1600,
3286  1,
3287  1,
3288  0,
3290  false,
3291  false,
3292  false,
3293  bssColor);
3294 
3295  HeRu::RuType ruType = HeRu::RU_106_TONE;
3296  if (m_channelWidth == 20)
3297  {
3298  ruType = HeRu::RU_106_TONE;
3299  }
3300  else if (m_channelWidth == 40)
3301  {
3302  ruType = HeRu::RU_242_TONE;
3303  }
3304  else if (m_channelWidth == 80)
3305  {
3306  ruType = HeRu::RU_484_TONE;
3307  }
3308  else if (m_channelWidth == 160)
3309  {
3310  ruType = HeRu::RU_996_TONE;
3311  }
3312  else
3313  {
3314  NS_ASSERT_MSG(false, "Unsupported channel width");
3315  }
3316 
3317  bool primary80MHz = true;
3318  if (m_channelWidth == 160 && index == 2)
3319  {
3320  primary80MHz = false;
3321  index = 1;
3322  }
3323  HeRu::RuSpec ru(ruType, index, primary80MHz);
3324  txVector.SetRu(ru, txStaId);
3325  txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3326  txVector.SetNss(1, txStaId);
3327  return txVector;
3328 }
3329 
3330 void
3332 {
3333  uint16_t channelWidth = m_channelWidth;
3334  if (error == CHANNEL_WIDTH)
3335  {
3336  channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
3337  }
3338 
3339  WifiTxVector txVector(HePhy::GetHeMcs7(),
3340  0,
3342  1600,
3343  1,
3344  1,
3345  0,
3346  channelWidth,
3347  false,
3348  false,
3349  false,
3350  bssColor);
3351 
3352  HeRu::RuType ruType = HeRu::RU_106_TONE;
3353  if (channelWidth == 20)
3354  {
3355  ruType = HeRu::RU_106_TONE;
3356  }
3357  else if (channelWidth == 40)
3358  {
3359  ruType = HeRu::RU_242_TONE;
3360  }
3361  else if (channelWidth == 80)
3362  {
3363  ruType = HeRu::RU_484_TONE;
3364  }
3365  else if (channelWidth == 160)
3366  {
3367  ruType = HeRu::RU_996_TONE;
3368  }
3369  else
3370  {
3371  NS_ASSERT_MSG(false, "Unsupported channel width");
3372  }
3373 
3374  uint16_t aid1 = (error == AID ? 3 : 1);
3375  uint16_t aid2 = (error == AID ? 4 : 2);
3376 
3377  HeRu::RuSpec ru1(ruType, 1, true);
3378  txVector.SetRu(ru1, aid1);
3379  txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3380  txVector.SetNss(1, aid1);
3381 
3382  HeRu::RuSpec ru2(ruType, (channelWidth == 160 ? 1 : 2), (channelWidth == 160 ? false : true));
3383  txVector.SetRu(ru2, aid2);
3384  txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3385  txVector.SetNss(1, aid2);
3386 
3387  uint16_t length;
3388  std::tie(length, m_expectedPpduDuration) =
3389  HePhy::ConvertHeTbPpduDurationToLSigLength(m_expectedPpduDuration,
3390  txVector,
3391  m_phyAp->GetPhyBand());
3392  if (error == UL_LENGTH)
3393  {
3394  ++length;
3395  }
3396  txVector.SetLength(length);
3397  auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
3398  hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3399 }
3400 
3401 void
3403  std::size_t index,
3404  std::size_t payloadSize,
3405  uint64_t uid,
3406  uint8_t bssColor,
3407  bool incrementUid)
3408 {
3409  NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3410  WifiConstPsduMap psdus;
3411 
3412  if (incrementUid)
3413  {
3414  ++uid;
3415  }
3416 
3417  WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3418  Ptr<Packet> pkt = Create<Packet>(payloadSize);
3419  WifiMacHeader hdr;
3421  hdr.SetQosTid(0);
3422  hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3423  std::ostringstream addr;
3424  addr << "00:00:00:00:00:0" << txStaId;
3425  hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3426  hdr.SetSequenceNumber(1);
3427  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3428  psdus.insert(std::make_pair(txStaId, psdu));
3429 
3431  if (txStaId == 1)
3432  {
3433  phy = m_phySta1;
3434  }
3435  else if (txStaId == 2)
3436  {
3437  phy = m_phySta2;
3438  }
3439  else if (txStaId == 3)
3440  {
3441  phy = m_phySta3;
3442  }
3443 
3444  Time txDuration =
3445  phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
3446  txVector.SetLength(
3447  HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3448 
3449  phy->SetPpduUid(uid);
3450  phy->Send(psdus, txVector);
3451 }
3452 
3453 void
3455 {
3456  NS_LOG_FUNCTION(this << duration);
3457  m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
3458  m_phyInterferer->SetPeriod(duration);
3460  Simulator::Schedule(duration, &TestUlOfdmaPhyTransmission::StopInterference, this);
3461 }
3462 
3463 void
3465 {
3466  m_phyInterferer->Stop();
3467 }
3468 
3470 {
3471 }
3472 
3473 void
3475  RxSignalInfo rxSignalInfo,
3476  WifiTxVector txVector,
3477  std::vector<bool> /*statusPerMpdu*/)
3478 {
3479  NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3480  if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3481  {
3483  m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3484  }
3485  else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3486  {
3488  m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3489  }
3490 }
3491 
3492 void
3494 {
3495  NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3496  if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3497  {
3499  }
3500  else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3501  {
3503  }
3504 }
3505 
3506 void
3508  uint32_t expectedFailures,
3509  uint32_t expectedBytes)
3510 {
3512  expectedSuccess,
3513  "The number of successfully received packets from STA 1 is not correct!");
3516  expectedFailures,
3517  "The number of unsuccessfuly received packets from STA 1 is not correct!");
3519  expectedBytes,
3520  "The number of bytes received from STA 1 is not correct!");
3521 }
3522 
3523 void
3525  uint32_t expectedFailures,
3526  uint32_t expectedBytes)
3527 {
3529  expectedSuccess,
3530  "The number of successfully received packets from STA 2 is not correct!");
3533  expectedFailures,
3534  "The number of unsuccessfuly received packets from STA 2 is not correct!");
3536  expectedBytes,
3537  "The number of bytes received from STA 2 is not correct!");
3538 }
3539 
3540 void
3542  WifiSpectrumBand band,
3543  double expectedRxPower)
3544 {
3545  Ptr<Event> event = phy->GetCurrentEvent();
3546  NS_ASSERT(event);
3547  double rxPower = event->GetRxPowerW(band);
3548  NS_LOG_FUNCTION(this << band.first << band.second << expectedRxPower << rxPower);
3549  // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3550  NS_TEST_ASSERT_MSG_EQ_TOL(rxPower,
3551  expectedRxPower,
3552  5e-3,
3553  "RX power " << rxPower << " over (" << band.first << ", "
3554  << band.second << ") does not match expected power "
3555  << expectedRxPower << " at " << Simulator::Now());
3556 }
3557 
3558 void
3560  WifiSpectrumBand band,
3561  double expectedRxPower)
3562 {
3568  NS_LOG_FUNCTION(this << band.first << band.second << expectedRxPower);
3569  double step = 5e-3;
3570  if (expectedRxPower > 0.0)
3571  {
3573  phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3574  true,
3575  "At least " << expectedRxPower << " W expected for OFDMA part over (" << band.first
3576  << ", " << band.second << ") at " << Simulator::Now());
3578  phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3579  false,
3580  "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first
3581  << ", " << band.second << ") at " << Simulator::Now());
3582  }
3583  else
3584  {
3586  phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3587  false,
3588  "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first
3589  << ", " << band.second << ") at " << Simulator::Now());
3590  }
3591 }
3592 
3593 void
3595 {
3597  nullptr,
3598  "m_currentEvent for AP was not cleared");
3600  nullptr,
3601  "m_currentEvent for STA 1 was not cleared");
3603  nullptr,
3604  "m_currentEvent for STA 2 was not cleared");
3605 }
3606 
3607 void
3609 {
3610  // This is needed to make sure PHY state will be checked as the last event if a state change
3611  // occurred at the exact same time as the check
3612  Simulator::ScheduleNow(&TestUlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
3613 }
3614 
3615 void
3617  WifiPhyState expectedState)
3618 {
3619  WifiPhyState currentState;
3620  PointerValue ptr;
3621  phy->GetAttribute("State", ptr);
3622  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
3623  currentState = state->GetState();
3624  NS_LOG_FUNCTION(this << currentState);
3625  NS_TEST_ASSERT_MSG_EQ(currentState,
3626  expectedState,
3627  "PHY State " << currentState << " does not match expected state "
3628  << expectedState << " at " << Simulator::Now());
3629 }
3630 
3631 void
3632 TestUlOfdmaPhyTransmission::CheckApRxStart(uint32_t expectedNotifications,
3633  Time expectedLastNotification)
3634 {
3635  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxStartNotifications(),
3636  expectedNotifications,
3637  "Number of RX start notifications "
3638  << m_apPhyStateListener->GetNumRxStartNotifications()
3639  << " does not match expected count " << expectedNotifications
3640  << " for AP at " << Simulator::Now());
3641  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxStartNotification(),
3642  expectedLastNotification,
3643  "Last time RX start notification has been received "
3644  << m_apPhyStateListener->GetLastRxStartNotification()
3645  << " does not match expected time " << expectedLastNotification
3646  << " for AP at " << Simulator::Now());
3647 }
3648 
3649 void
3650 TestUlOfdmaPhyTransmission::CheckApRxEnd(uint32_t expectedNotifications,
3651  Time expectedLastNotification,
3652  bool expectedSuccess)
3653 {
3654  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxEndNotifications(),
3655  expectedNotifications,
3656  "Number of RX end notifications "
3657  << m_apPhyStateListener->GetNumRxEndNotifications()
3658  << " does not match expected count " << expectedNotifications
3659  << " for AP at " << Simulator::Now());
3660  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxEndNotification(),
3661  expectedLastNotification,
3662  "Last time RX end notification has been received "
3663  << m_apPhyStateListener->GetLastRxEndNotification()
3664  << " does not match expected time " << expectedLastNotification
3665  << " for AP at " << Simulator::Now());
3666  NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->IsLastRxSuccess(),
3667  expectedSuccess,
3668  "Last time RX end notification indicated a "
3669  << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3670  << " but expected a " << (expectedSuccess ? "success" : "failure")
3671  << " for AP at " << Simulator::Now());
3672 }
3673 
3674 void
3676 {
3683  m_phySta1->SetPpduUid(0);
3686  SetBssColor(m_phyAp, 0);
3687  m_apPhyStateListener->Reset();
3688 }
3689 
3690 void
3692 {
3693  Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3694  Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3695  heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3696 }
3697 
3698 void
3700 {
3701  NS_LOG_FUNCTION(this << phy << psdLimit);
3702  phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3703 }
3704 
3705 void
3707 {
3708  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
3709  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
3710  lossModel->SetFrequency(m_frequency);
3711  spectrumChannel->AddPropagationLossModel(lossModel);
3713  CreateObject<ConstantSpeedPropagationDelayModel>();
3714  spectrumChannel->SetPropagationDelayModel(delayModel);
3715 
3716  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3717  CreateObject<ThresholdPreambleDetectionModel>();
3718  preambleDetectionModel->SetAttribute(
3719  "MinimumRssi",
3720  DoubleValue(
3721  -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3722  preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3723 
3724  Ptr<Node> apNode = CreateObject<Node>();
3725  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
3727  Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
3728  apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3729  apDev->SetMac(apMac);
3730  m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
3733  Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
3734  apDev->SetHeConfiguration(heConfiguration);
3735  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
3736  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3737  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
3738  m_phyAp->SetErrorRateModel(apErrorModel);
3739  m_phyAp->SetDevice(apDev);
3740  m_phyAp->SetChannel(spectrumChannel);
3743  m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3744  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
3745  m_phyAp->SetMobility(apMobility);
3746  m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3748  apDev->SetPhy(m_phyAp);
3749  apMac->SetWifiPhys({m_phyAp});
3750  apNode->AggregateObject(apMobility);
3751  apNode->AddDevice(apDev);
3752 
3753  Ptr<Node> sta1Node = CreateObject<Node>();
3754  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
3756  sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3757  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
3760  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
3761  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3762  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
3763  m_phySta1->SetErrorRateModel(sta1ErrorModel);
3764  m_phySta1->SetDevice(sta1Dev);
3765  m_phySta1->SetChannel(spectrumChannel);
3766  m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3767  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
3768  m_phySta1->SetMobility(sta1Mobility);
3769  sta1Dev->SetPhy(m_phySta1);
3770  sta1Node->AggregateObject(sta1Mobility);
3771  sta1Node->AddDevice(sta1Dev);
3772 
3773  Ptr<Node> sta2Node = CreateObject<Node>();
3774  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
3776  sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3777  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
3780  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
3781  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3782  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
3783  m_phySta2->SetErrorRateModel(sta2ErrorModel);
3784  m_phySta2->SetDevice(sta2Dev);
3785  m_phySta2->SetChannel(spectrumChannel);
3786  m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3787  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
3788  m_phySta2->SetMobility(sta2Mobility);
3789  sta2Dev->SetPhy(m_phySta2);
3790  sta2Node->AggregateObject(sta2Mobility);
3791  sta2Node->AddDevice(sta2Dev);
3792 
3793  Ptr<Node> sta3Node = CreateObject<Node>();
3794  Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
3796  sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3797  m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
3800  Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
3801  m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3802  Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
3803  m_phySta3->SetErrorRateModel(sta3ErrorModel);
3804  m_phySta3->SetDevice(sta3Dev);
3805  m_phySta3->SetChannel(spectrumChannel);
3806  m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3807  Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
3808  m_phySta3->SetMobility(sta3Mobility);
3809  sta3Dev->SetPhy(m_phySta3);
3810  sta3Node->AggregateObject(sta3Mobility);
3811  sta3Node->AddDevice(sta3Dev);
3812 
3813  Ptr<Node> interfererNode = CreateObject<Node>();
3814  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
3815  m_phyInterferer = CreateObject<WaveformGenerator>();
3816  m_phyInterferer->SetDevice(interfererDev);
3817  m_phyInterferer->SetChannel(spectrumChannel);
3819  interfererNode->AddDevice(interfererDev);
3820 
3821  // Configure power attributes of all wifi devices
3822  std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3823  for (auto& phy : phys)
3824  {
3825  phy->SetAttribute("TxGain", DoubleValue(1.0));
3826  phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3827  phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3828  phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3829  phy->SetAttribute("RxGain", DoubleValue(2.0));
3830  // test assumes no rejection power for simplicity
3831  phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3832  phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3833  phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3834  }
3835 }
3836 
3837 void
3839 {
3840  m_phyAp->Dispose();
3841  m_phyAp = nullptr;
3842  m_phySta1->Dispose();
3843  m_phySta1 = nullptr;
3844  m_phySta2->Dispose();
3845  m_phySta2 = nullptr;
3846  m_phySta3->Dispose();
3847  m_phySta3 = nullptr;
3849  m_phyInterferer = nullptr;
3850 }
3851 
3852 void
3854 {
3855  NS_LOG_INFO(log);
3856 }
3857 
3858 void
3860  bool solicited,
3861  WifiPhyState expectedStateAtEnd,
3862  uint32_t expectedSuccessFromSta1,
3863  uint32_t expectedFailuresFromSta1,
3864  uint32_t expectedBytesFromSta1,
3865  uint32_t expectedSuccessFromSta2,
3866  uint32_t expectedFailuresFromSta2,
3867  uint32_t expectedBytesFromSta2,
3868  bool scheduleTxSta1,
3869  Time ulTimeDifference,
3870  WifiPhyState expectedStateBeforeEnd,
3871  TrigVectorInfo error)
3872 {
3873  static uint64_t uid = 0;
3874 
3875  // AP sends an SU packet preceding HE TB PPDUs
3876  Simulator::Schedule(delay - MilliSeconds(10),
3878  this,
3879  0,
3880  50,
3881  ++uid,
3882  0);
3883  if (!solicited)
3884  {
3885  // UID of TB PPDUs will be different than the one of the preceding frame
3886  ++uid;
3887  }
3888  else
3889  {
3890  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetTrigVector, this, 0, error);
3891  }
3892  // STA1 and STA2 send MU UL PPDUs addressed to AP
3893  Simulator::Schedule(delay - MilliSeconds(1),
3895  m_apPhyStateListener.get());
3896  if (scheduleTxSta1)
3897  {
3898  Simulator::Schedule(delay,
3900  this,
3901  1,
3902  1,
3903  1000,
3904  uid,
3905  0,
3906  false);
3907  }
3908  Simulator::Schedule(delay + ulTimeDifference,
3910  this,
3911  2,
3912  2,
3913  1001,
3914  uid,
3915  0,
3916  false);
3917 
3918  // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3919  Simulator::Schedule(delay + m_expectedPpduDuration - NanoSeconds(1),
3921  this,
3922  m_phyAp,
3923  expectedStateBeforeEnd);
3924  Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3926  this,
3927  m_phyAp,
3928  expectedStateAtEnd);
3929  // TODO: add checks on TX stop for STAs
3930 
3931  if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3932  expectedFailuresFromSta2 >
3933  0)
3934  {
3935  // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3936  const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3937  // The expected time at which the reception is started corresponds to the time at which the
3938  // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3939  const Time expectedPayloadStart = delay + MicroSeconds(48);
3940  // The expected time at which the reception is terminated corresponds to the time at which
3941  // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3942  // received HE TB PPDU and the last received HE TB PPDU.
3943  const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3944  // At the end of the transmission, verify that a single RX start notification shall have
3945  // been notified when the reception of the first HE RB PPDU starts.
3946  Simulator::Schedule(expectedPayloadEnd,
3948  this,
3949  1,
3950  Simulator::Now() + expectedPayloadStart);
3951  // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3952  // notification shall have been notified when the reception of the last HE RB PPDU ends
3953  Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3955  this,
3956  1,
3957  Simulator::Now() + expectedPayloadEnd,
3958  isSuccess);
3959  }
3960 
3961  delay += MilliSeconds(100);
3962  // Check reception state from STA 1
3963  Simulator::Schedule(delay,
3965  this,
3966  expectedSuccessFromSta1,
3967  expectedFailuresFromSta1,
3968  expectedBytesFromSta1);
3969  // Check reception state from STA 2
3970  Simulator::Schedule(delay,
3972  this,
3973  expectedSuccessFromSta2,
3974  expectedFailuresFromSta2,
3975  expectedBytesFromSta2);
3976  // Verify events data have been cleared
3977  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::VerifyEventsCleared, this);
3978 
3979  delay += MilliSeconds(100);
3980  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::Reset, this);
3981 }
3982 
3983 void
3985  double rxPowerNonOfdmaRu1,
3986  double rxPowerNonOfdmaRu2,
3987  double rxPowerOfdmaRu1,
3988  double rxPowerOfdmaRu2)
3989 {
3990  Time detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3991  WifiTxVector txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3992  WifiTxVector txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3993  Ptr<const HePhy> hePhy = m_phyAp->GetHePhy();
3994  Time nonOfdmaDuration = hePhy->CalculateNonOfdmaDurationForHeTb(txVectorSta2);
3995  NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonOfdmaDurationForHeTb(txVectorSta1));
3996 
3997  std::vector<double> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3998  std::vector<WifiSpectrumBand> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3999  hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
4000  std::vector<double> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
4001  std::vector<WifiSpectrumBand> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
4002  hePhy->GetRuBandForRx(txVectorSta2, 2)};
4003 
4004  for (uint8_t i = 0; i < 2; ++i)
4005  {
4009  // Check received power on non-OFDMA portion
4010  Simulator::Schedule(
4011  delay + detectionDuration +
4012  NanoSeconds(1), // just after beginning of portion (once event is stored)
4014  this,
4015  m_phyAp,
4016  nonOfdmaBand[i],
4017  rxPowerNonOfdma[i]);
4018  Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4020  this,
4021  m_phyAp,
4022  nonOfdmaBand[i],
4023  rxPowerNonOfdma[i]);
4024  // Check received power on OFDMA portion
4025  Simulator::Schedule(delay + nonOfdmaDuration +
4026  NanoSeconds(1), // just after beginning of portion
4028  this,
4029  m_phyAp,
4030  ofdmaBand[i],
4031  rxPowerOfdma[i]);
4032  Simulator::Schedule(delay + m_expectedPpduDuration -
4033  NanoSeconds(1), // just before end of portion
4035  this,
4036  m_phyAp,
4037  ofdmaBand[i],
4038  rxPowerOfdma[i]);
4039 
4045  // Check received power on non-OFDMA portion
4046  Simulator::Schedule(
4047  delay + detectionDuration +
4048  NanoSeconds(1), // just after beginning of portion (once event is stored)
4050  this,
4051  m_phySta3,
4052  nonOfdmaBand[i],
4053  rxPowerNonOfdma[i]);
4054  Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4056  this,
4057  m_phySta3,
4058  nonOfdmaBand[i],
4059  rxPowerNonOfdma[i]);
4060  // Check received power on OFDMA portion
4061  Simulator::Schedule(delay + nonOfdmaDuration +
4062  NanoSeconds(1), // just after beginning of portion
4064  this,
4065  m_phySta3,
4066  ofdmaBand[i],
4067  rxPowerOfdma[i]);
4068  Simulator::Schedule(delay + m_expectedPpduDuration -
4069  NanoSeconds(1), // just before end of portion
4071  this,
4072  m_phySta3,
4073  ofdmaBand[i],
4074  rxPowerOfdma[i]);
4075  }
4076 
4077  if (rxPowerOfdmaRu1 != 0.0)
4078  {
4084  double rxPowerNonOfdmaSta1Only =
4085  (m_channelWidth >= 40)
4086  ? rxPowerNonOfdma[0]
4087  : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4088  // Check received power on non-OFDMA portion
4089  Simulator::Schedule(
4090  delay + detectionDuration +
4091  NanoSeconds(1), // just after beginning of portion (once event is stored)
4093  this,
4094  m_phySta2,
4095  nonOfdmaBand[0],
4096  rxPowerNonOfdmaSta1Only);
4097  Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4099  this,
4100  m_phySta2,
4101  nonOfdmaBand[0],
4102  rxPowerNonOfdmaSta1Only);
4103  // Check received power on OFDMA portion
4104  Simulator::Schedule(delay + nonOfdmaDuration +
4105  NanoSeconds(1), // just after beginning of portion
4107  this,
4108  m_phySta2,
4109  ofdmaBand[0],
4110  rxPowerOfdma[0]);
4111  Simulator::Schedule(delay + m_expectedPpduDuration -
4112  NanoSeconds(1), // just before end of portion
4114  this,
4115  m_phySta2,
4116  ofdmaBand[0],
4117  rxPowerOfdma[0]);
4118  }
4119 }
4120 
4121 void
4123 {
4124  RngSeedManager::SetSeed(1);
4125  RngSeedManager::SetRun(1);
4126  int64_t streamNumber = 0;
4127  m_phyAp->AssignStreams(streamNumber);
4128  m_phySta1->AssignStreams(streamNumber);
4129  m_phySta2->AssignStreams(streamNumber);
4130  m_phySta3->AssignStreams(streamNumber);
4131 
4132  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
4133  m_frequency,
4137 
4146 
4147  Time delay = Seconds(0.0);
4148  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::Reset, this);
4149  delay += Seconds(1.0);
4150 
4159  //---------------------------------------------------------------------------
4160  // Verify that both solicited HE TB PPDUs have been corrected received
4161  Simulator::Schedule(delay,
4163  this,
4164  "Reception of solicited HE TB PPDUs");
4165  ScheduleTest(delay,
4166  true,
4168  1,
4169  0,
4170  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4171  1,
4172  0,
4173  1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4174  delay += Seconds(1.0);
4175 
4176  //---------------------------------------------------------------------------
4177  // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4178  // corrected received
4179  Simulator::Schedule(
4180  delay,
4182  this,
4183  "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4184  ScheduleTest(delay,
4185  true,
4187  1,
4188  0,
4189  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4190  1,
4191  0,
4192  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4193  true,
4194  NanoSeconds(100));
4195  delay += Seconds(1.0);
4196 
4197  //---------------------------------------------------------------------------
4198  // Verify that no unsolicited HE TB PPDU is received
4199  Simulator::Schedule(delay,
4201  this,
4202  "Dropping of unsolicited HE TB PPDUs");
4203  ScheduleTest(delay,
4204  false,
4206  0,
4207  0,
4208  0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4209  0,
4210  0,
4211  0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4212  true,
4213  Seconds(0),
4215  delay += Seconds(1.0);
4216 
4217  //---------------------------------------------------------------------------
4218  // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4219  Simulator::Schedule(delay,
4221  this,
4222  "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4223  ScheduleTest(delay,
4224  true,
4226  0,
4227  0,
4228  0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4229  0,
4230  0,
4231  0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4232  true,
4233  Seconds(0),
4235  CHANNEL_WIDTH);
4236  delay += Seconds(1.0);
4237 
4238  //---------------------------------------------------------------------------
4239  // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4240  Simulator::Schedule(delay,
4242  this,
4243  "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4244  ScheduleTest(delay,
4245  true,
4247  0,
4248  0,
4249  0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4250  0,
4251  0,
4252  0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4253  true,
4254  Seconds(0),
4256  UL_LENGTH);
4257  delay += Seconds(1.0);
4258 
4259  //---------------------------------------------------------------------------
4260  // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4261  Simulator::Schedule(delay,
4263  this,
4264  "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4265  ScheduleTest(delay,
4266  true,
4268  0,
4269  0,
4270  0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4271  0,
4272  0,
4273  0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4274  true,
4275  Seconds(0),
4277  AID);
4278  delay += Seconds(1.0);
4279 
4280  //---------------------------------------------------------------------------
4281  // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4282  // impacted
4283  Simulator::Schedule(
4284  delay,
4286  this,
4287  "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4288  // A strong non-wifi interference is generated on RU 1 during PSDU reception
4289  BandInfo bandInfo;
4290  bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
4291  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4292  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4293  Bands bands;
4294  bands.push_back(bandInfo);
4295 
4296  Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4297  Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4298  double interferencePower = 0.1; // watts
4299  *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
4300 
4301  Simulator::Schedule(delay + MicroSeconds(50),
4303  this,
4304  interferencePsdRu1,
4305  MilliSeconds(100));
4306  ScheduleTest(
4307  delay,
4308  true,
4309  WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4310  // interference
4311  0,
4312  1,
4313  0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4314  1,
4315  0,
4316  1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4317  delay += Seconds(1.0);
4318 
4319  //---------------------------------------------------------------------------
4320  // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4321  // impacted
4322  Simulator::Schedule(
4323  delay,
4325  this,
4326  "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4327  // A strong non-wifi interference is generated on RU 2 during PSDU reception
4328  bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
4329  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4330  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4331  bands.clear();
4332  bands.push_back(bandInfo);
4333 
4334  Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4335  Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4336  *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
4337 
4338  Simulator::Schedule(delay + MicroSeconds(50),
4340  this,
4341  interferencePsdRu2,
4342  MilliSeconds(100));
4343  ScheduleTest(delay,
4344  true,
4345  (m_channelWidth >= 40)
4347  : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4348  // generated in its primary channel
4349  1,
4350  0,
4351  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4352  0,
4353  1,
4354  0); // Reception of the PSDU from STA 2 should have failed (since interference
4355  // occupies RU 2)
4356  delay += Seconds(1.0);
4357 
4358  //---------------------------------------------------------------------------
4359  // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4360  // been impacted
4361  Simulator::Schedule(delay,
4363  this,
4364  "Reception of solicited HE TB PPDUs with interference on the full band "
4365  "during PSDU reception");
4366  // A strong non-wifi interference is generated on the full band during PSDU reception
4367  bandInfo.fc = m_frequency * 1e6;
4368  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
4369  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
4370  bands.clear();
4371  bands.push_back(bandInfo);
4372 
4373  Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4374  Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4375  *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
4376 
4377  Simulator::Schedule(delay + MicroSeconds(50),
4379  this,
4380  interferencePsdAll,
4381  MilliSeconds(100));
4382  ScheduleTest(
4383  delay,
4384  true,
4385  WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4386  // interference
4387  0,
4388  1,
4389  0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4390  0,
4391  1,
4392  0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4393  // 2)
4394  delay += Seconds(1.0);
4395 
4396  //---------------------------------------------------------------------------
4397  // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4398  // solicited HE TB PPDUs have been impacted if they are on the same
4399  // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4400  Simulator::Schedule(delay,
4402  this,
4403  "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4404  "1 during PSDU reception");
4405  // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4406  Simulator::Schedule(delay + MicroSeconds(50),
4408  this,
4409  3,
4410  1,
4411  1002,
4412  1,
4413  0,
4414  false);
4415  // Expected figures from STA 2
4416  uint32_t succ;
4417  uint32_t fail;
4418  uint32_t bytes;
4419  if (m_channelWidth > 20)
4420  {
4421  // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4422  // interference from STA 3 on distinct 20 MHz channel)
4423  succ = 1;
4424  fail = 0;
4425  bytes = 1001;
4426  }
4427  else
4428  {
4429  // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4430  // same 20 MHz channel)
4431  succ = 0;
4432  fail = 1;
4433  bytes = 0;
4434  }
4435  ScheduleTest(delay,
4436  true,
4437  WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4438  // interference on measurement channel width
4439  0,
4440  1,
4441  0, // Reception of the PSDU from STA 1 should have failed (since interference from
4442  // STA 3 on same 20 MHz channel)
4443  succ,
4444  fail,
4445  bytes);
4446  delay += Seconds(1.0);
4447 
4448  //---------------------------------------------------------------------------
4449  // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4450  // solicited HE TB PPDUs have been impacted if they are on the same
4451  // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4452  Simulator::Schedule(delay,
4454  this,
4455  "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4456  "2 during PSDU reception");
4457  // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4458  Simulator::Schedule(delay + MicroSeconds(50),
4460  this,
4461  3,
4462  2,
4463  1002,
4464  1,
4465  0,
4466  false);
4467  // Expected figures from STA 1
4468  if (m_channelWidth > 20)
4469  {
4470  // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4471  // interference from STA 3 on distinct 20 MHz channel)
4472  succ = 1;
4473  fail = 0;
4474  bytes = 1000;
4475  }
4476  else
4477  {
4478  // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4479  // same 20 MHz channel)
4480  succ = 0;
4481  fail = 1;
4482  bytes = 0;
4483  }
4484  ScheduleTest(delay,
4485  true,
4486  (m_channelWidth >= 40)
4488  : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4489  // TB PPDU on primary channel
4490  succ,
4491  fail,
4492  bytes,
4493  0,
4494  1,
4495  0); // Reception of the PSDU from STA 2 should have failed (since interference from
4496  // STA 3 on same 20 MHz channel)
4497  delay += Seconds(1.0);
4498 
4499  //---------------------------------------------------------------------------
4500  // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4501  // impacted
4502  Simulator::Schedule(
4503  delay,
4505  this,
4506  "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4507  // One HE SU arrives at AP during the 400ns window
4508  Simulator::Schedule(delay + NanoSeconds(300),
4510  this,
4511  3,
4512  1002,
4513  1,
4514  0);
4515  ScheduleTest(
4516  delay,
4517  true,
4519  0,
4520  1,
4521  0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4522  0,
4523  1,
4524  0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4525  delay += Seconds(1.0);
4526 
4527  //---------------------------------------------------------------------------
4528  // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4529  // received
4530  Simulator::Schedule(delay,
4532  this,
4533  "Reception of solicited HE TB PPDU only on RU 2");
4534  // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4535  // otherwise
4536  Simulator::Schedule(delay + m_expectedPpduDuration - NanoSeconds(1),
4538  this,
4539  m_phySta3,
4540  (m_channelWidth >= 40)
4542  : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4543  // IDLE if HE TB PPDU on primary channel
4544  ScheduleTest(delay,
4545  true,
4547  0,
4548  0,
4549  0, // No transmission scheduled for STA 1
4550  1,
4551  0,
4552  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4553  false,
4554  Seconds(0),
4555  WifiPhyState::RX); // Measurement channel is total channel width
4556  delay += Seconds(1.0);
4557 
4558  //---------------------------------------------------------------------------
4559  // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4560  Simulator::Schedule(delay,
4562  this,
4563  "Measure power for reception of HE TB PPDU only on RU 2");
4564  double rxPower =
4565  DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4567  (m_channelWidth >= 40) ? 0.0 : rxPower,
4568  rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4569  0.0,
4570  rxPower);
4571  ScheduleTest(delay,
4572  true,
4574  0,
4575  0,
4576  0, // No transmission scheduled for STA 1
4577  1,
4578  0,
4579  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4580  false,
4581  Seconds(0),
4582  WifiPhyState::RX); // Measurement channel is total channel width
4583  delay += Seconds(1.0);
4584 
4585  //---------------------------------------------------------------------------
4586  // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4587  // limitation enforced
4588  Simulator::Schedule(
4589  delay,
4591  this,
4592  "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4593  // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4594  // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4595  Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4597  this,
4598  m_phySta2,
4599  3.0);
4600 
4601  rxPower = (m_channelWidth > 40)
4602  ? DbmToW(19)
4603  : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4604  // transmitted only on one 20 MHz channel
4605  double rxPowerOfdma = rxPower;
4606  if (m_channelWidth <= 40)
4607  {
4608  rxPowerOfdma = (m_channelWidth == 20)
4609  ? DbmToW(14.0309) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4610  : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4611  }
4613  (m_channelWidth >= 40) ? 0.0 : rxPower,
4614  rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4615  0.0,
4616  rxPowerOfdma);
4617 
4618  // Reset PSD limitation once HE TB has been sent
4619  Simulator::Schedule(delay + m_expectedPpduDuration,
4621  this,
4622  m_phySta2,
4623  100.0);
4624  ScheduleTest(delay,
4625  true,
4627  0,
4628  0,
4629  0, // No transmission scheduled for STA 1
4630  1,
4631  0,
4632  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4633  false,
4634  Seconds(0),
4635  WifiPhyState::RX); // Measurement channel is total channel width
4636  delay += Seconds(1.0);
4637 
4638  //---------------------------------------------------------------------------
4639  // Measure the power of 2 solicited HE TB PPDU from both STAs
4640  Simulator::Schedule(delay,
4642  this,
4643  "Measure power for reception of HE TB PPDU on both RUs");
4644  rxPower = DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4645  double rxPowerNonOfdma = (m_channelWidth >= 40)
4646  ? rxPower
4647  : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4648  SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4649  ScheduleTest(delay,
4650  true,
4652  1,
4653  0,
4654  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4655  1,
4656  0,
4657  1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4658  delay += Seconds(1.0);
4659 
4660  //---------------------------------------------------------------------------
4661  // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4662  // ongoing)
4663  Simulator::Schedule(delay,
4665  this,
4666  "Reception of an HE TB PPDU from another BSS");
4667  // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4668  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
4669  Simulator::Schedule(delay + MilliSeconds(100),
4671  this,
4672  3,
4673  1,
4674  1002,
4675  1,
4676  2,
4677  false);
4678 
4679  // Verify events data have been cleared
4680  Simulator::Schedule(delay + MilliSeconds(200),
4682  this);
4683 
4684  Simulator::Schedule(delay + MilliSeconds(500), &TestUlOfdmaPhyTransmission::Reset, this);
4685  delay += Seconds(1.0);
4686 
4687  //---------------------------------------------------------------------------
4688  // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4689  // corrected received
4690  Simulator::Schedule(
4691  delay,
4693  this,
4694  "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4695  "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4696  Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
4697  Simulator::Schedule(delay + m_expectedPpduDuration + NanoSeconds(100),
4699  this,
4700  3,
4701  1,
4702  1002,
4703  1,
4704  2,
4705  true);
4706  ScheduleTest(delay,
4707  true,
4709  1,
4710  0,
4711  1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4712  1,
4713  0,
4714  1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4715  true,
4716  NanoSeconds(200));
4717  delay += Seconds(1.0);
4718 
4719  Simulator::Run();
4720 }
4721 
4722 void
4724 {
4725  m_frequency = 5180;
4726  m_channelWidth = 20;
4728  NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4729  RunOne();
4730 
4731  m_frequency = 5190;
4732  m_channelWidth = 40;
4734  NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4735  RunOne();
4736 
4737  m_frequency = 5210;
4738  m_channelWidth = 80;
4740  NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4741  RunOne();
4742 
4743  m_frequency = 5250;
4744  m_channelWidth = 160;
4746  NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4747  RunOne();
4748 
4749  Simulator::Destroy();
4750 }
4751 
4759 {
4760  public:
4762  ~TestPhyPaddingExclusion() override;
4763 
4764  private:
4765  void DoSetup() override;
4766  void DoTeardown() override;
4767  void DoRun() override;
4768 
4776  void SendHeTbPpdu(uint16_t txStaId,
4777  std::size_t index,
4778  std::size_t payloadSize,
4779  Time txDuration);
4785  void SetTrigVector(Time ppduDuration);
4786 
4792  void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4796  void StopInterference();
4797 
4801  void RunOne();
4802 
4809  void CheckRxFromSta1(uint32_t expectedSuccess,
4810  uint32_t expectedFailures,
4811  uint32_t expectedBytes);
4812 
4819  void CheckRxFromSta2(uint32_t expectedSuccess,
4820  uint32_t expectedFailures,
4821  uint32_t expectedBytes);
4822 
4826  void VerifyEventsCleared();
4827 
4836 
4840  void Reset();
4841 
4849  void RxSuccess(Ptr<const WifiPsdu> psdu,
4850  RxSignalInfo rxSignalInfo,
4851  WifiTxVector txVector,
4852  std::vector<bool> statusPerMpdu);
4853 
4858  void RxFailure(Ptr<const WifiPsdu> psdu);
4859 
4863 
4865 
4872 };
4873 
4875  : TestCase("PHY padding exclusion test"),
4876  m_countRxSuccessFromSta1(0),
4877  m_countRxSuccessFromSta2(0),
4878  m_countRxFailureFromSta1(0),
4879  m_countRxFailureFromSta2(0),
4880  m_countRxBytesFromSta1(0),
4881  m_countRxBytesFromSta2(0)
4882 {
4883 }
4884 
4885 void
4887  std::size_t index,
4888  std::size_t payloadSize,
4889  Time txDuration)
4890 {
4891  WifiConstPsduMap psdus;
4892 
4893  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
4894  0,
4896  1600,
4897  1,
4898  1,
4899  0,
4901  false,
4902  false,
4903  1);
4904 
4905  HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4906  txVector.SetRu(ru, txStaId);
4907  txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4908  txVector.SetNss(1, txStaId);
4909 
4910  Ptr<Packet> pkt = Create<Packet>(payloadSize);
4911  WifiMacHeader hdr;
4913  hdr.SetQosTid(0);
4914  hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4915  std::ostringstream addr;
4916  addr << "00:00:00:00:00:0" << txStaId;
4917  hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4918  hdr.SetSequenceNumber(1);
4919  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4920  psdus.insert(std::make_pair(txStaId, psdu));
4921 
4923  if (txStaId == 1)
4924  {
4925  phy = m_phySta1;
4926  }
4927  else if (txStaId == 2)
4928  {
4929  phy = m_phySta2;
4930  }
4931 
4932  txVector.SetLength(
4933  HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4934 
4935  phy->SetPpduUid(0);
4936  phy->Send(psdus, txVector);
4937 }
4938 
4939 void
4941 {
4942  m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
4943  m_phyInterferer->SetPeriod(duration);
4945  Simulator::Schedule(duration, &TestPhyPaddingExclusion::StopInterference, this);
4946 }
4947 
4948 void
4950 {
4951  m_phyInterferer->Stop();
4952 }
4953 
4955 {
4956 }
4957 
4958 void
4960  RxSignalInfo rxSignalInfo,
4961  WifiTxVector txVector,
4962  std::vector<bool> /*statusPerMpdu*/)
4963 {
4964  NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
4965  if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4966  {
4968  m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
4969  }
4970  else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4971  {
4973  m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
4974  }
4975 }
4976 
4977 void
4979 {
4980  NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
4981  if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4982  {
4984  }
4985  else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4986  {
4988  }
4989 }
4990 
4991 void
4993  uint32_t expectedFailures,
4994  uint32_t expectedBytes)
4995 {
4997  expectedSuccess,
4998  "The number of successfully received packets from STA 1 is not correct!");
5001  expectedFailures,
5002  "The number of unsuccessfuly received packets from STA 1 is not correct!");
5004  expectedBytes,
5005  "The number of bytes received from STA 1 is not correct!");
5006 }
5007 
5008 void
5010  uint32_t expectedFailures,
5011  uint32_t expectedBytes)
5012 {
5014  expectedSuccess,
5015  "The number of successfully received packets from STA 2 is not correct!");
5018  expectedFailures,
5019  "The number of unsuccessfuly received packets from STA 2 is not correct!");
5021  expectedBytes,
5022  "The number of bytes received from STA 2 is not correct!");
5023 }
5024 
5025 void
5027 {
5029  nullptr,
5030  "m_currentEvent for AP was not cleared");
5032  nullptr,
5033  "m_currentEvent for STA 1 was not cleared");
5035  nullptr,
5036  "m_currentEvent for STA 2 was not cleared");
5037 }
5038 
5039 void
5041 {
5042  // This is needed to make sure PHY state will be checked as the last event if a state change
5043  // occurred at the exact same time as the check
5044  Simulator::ScheduleNow(&TestPhyPaddingExclusion::DoCheckPhyState, this, phy, expectedState);
5045 }
5046 
5047 void
5049 {
5050  WifiPhyState currentState = phy->GetState()->GetState();
5051  NS_LOG_FUNCTION(this << currentState);
5052  NS_TEST_ASSERT_MSG_EQ(currentState,
5053  expectedState,
5054  "PHY State " << currentState << " does not match expected state "
5055  << expectedState << " at " << Simulator::Now());
5056 }
5057 
5058 void
5060 {
5067  m_phySta1->SetPpduUid(0);
5070 }
5071 
5072 void
5074 {
5075  RngSeedManager::SetSeed(1);
5076  RngSeedManager::SetRun(1);
5077  int64_t streamNumber = 0;
5078 
5079  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5080  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
5081  lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
5082  spectrumChannel->AddPropagationLossModel(lossModel);
5084  CreateObject<ConstantSpeedPropagationDelayModel>();
5085  spectrumChannel->SetPropagationDelayModel(delayModel);
5086 
5087  Ptr<Node> apNode = CreateObject<Node>();
5088  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
5089  Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
5090  apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5091  apDev->SetMac(apMac);
5092  m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
5095  Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
5096  apDev->SetHeConfiguration(heConfiguration);
5097  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
5098  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5099  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
5100  m_phyAp->SetErrorRateModel(apErrorModel);
5101  m_phyAp->SetDevice(apDev);
5102  m_phyAp->SetChannel(spectrumChannel);
5103  m_phyAp->AssignStreams(streamNumber);
5104  auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
5109 
5114  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
5115  m_phyAp->SetMobility(apMobility);
5116  apDev->SetPhy(m_phyAp);
5118  apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5119  apMac->SetWifiPhys({m_phyAp});
5120  apNode->AggregateObject(apMobility);
5121  apNode->AddDevice(apDev);
5122 
5123  Ptr<Node> sta1Node = CreateObject<Node>();
5124  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
5125  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
5128  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
5129  m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5130  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
5131  m_phySta1->SetErrorRateModel(sta1ErrorModel);
5132  m_phySta1->SetDevice(sta1Dev);
5133  m_phySta1->SetChannel(spectrumChannel);
5134  m_phySta1->AssignStreams(streamNumber);
5137  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
5138  m_phySta1->SetMobility(sta1Mobility);
5139  sta1Dev->SetPhy(m_phySta1);
5141  sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5142  sta1Node->AggregateObject(sta1Mobility);
5143  sta1Node->AddDevice(sta1Dev);
5144 
5145  Ptr<Node> sta2Node = CreateObject<Node>();
5146  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
5147  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
5150  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
5151  m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5152  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
5153  m_phySta2->SetErrorRateModel(sta2ErrorModel);
5154  m_phySta2->SetDevice(sta2Dev);
5155  m_phySta2->SetChannel(spectrumChannel);
5156  m_phySta2->AssignStreams(streamNumber);
5159  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
5160  m_phySta2->SetMobility(sta2Mobility);
5161  sta2Dev->SetPhy(m_phySta2);
5163  sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5164  sta2Node->AggregateObject(sta2Mobility);
5165  sta2Node->AddDevice(sta2Dev);
5166 
5167  Ptr<Node> interfererNode = CreateObject<Node>();
5168  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
5169  m_phyInterferer = CreateObject<WaveformGenerator>();
5170  m_phyInterferer->SetDevice(interfererDev);
5171  m_phyInterferer->SetChannel(spectrumChannel);
5173  interfererNode->AddDevice(interfererDev);
5174 }
5175 
5176 void
5178 {
5179  m_phyAp->Dispose();
5180  m_phyAp = nullptr;
5181  m_phySta1->Dispose();
5182  m_phySta1 = nullptr;
5183  m_phySta2->Dispose();
5184  m_phySta2 = nullptr;
5186  m_phyInterferer = nullptr;
5187 }
5188 
5189 void
5191 {
5192  WifiTxVector trigVector(HePhy::GetHeMcs7(),
5193  0,
5195  1600,
5196  1,
5197  1,
5198  0,
5200  false,
5201  false,
5202  1);
5203  trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5204  trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5205  trigVector.SetNss(1, 1);
5206  trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5207  trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5208  trigVector.SetNss(1, 2);
5209  uint16_t length;
5210  std::tie(length, ppduDuration) =
5211  HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, trigVector, m_phyAp->GetPhyBand());
5212  trigVector.SetLength(length);
5213  auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
5214  hePhyAp->SetTrigVector(trigVector, ppduDuration);
5215 }
5216 
5217 void
5219 {
5220  Time expectedPpduDuration = NanoSeconds(292800);
5221  Time ppduWithPaddingDuration =
5222  expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5223 
5224  Simulator::Schedule(Seconds(0.0), &TestPhyPaddingExclusion::Reset, this);
5225 
5226  // STA1 and STA2 send MU UL PPDUs addressed to AP:
5227  Simulator::Schedule(Seconds(1.0),
5229  this,
5230  1,
5231  1,
5232  1000,
5233  ppduWithPaddingDuration);
5234  Simulator::Schedule(Seconds(1.0),
5236  this,
5237  2,
5238  2,
5239  1001,
5240  ppduWithPaddingDuration);
5241 
5242  // Set TRIGVECTOR on AP
5243  Simulator::Schedule(Seconds(1.0),
5245  this,
5246  ppduWithPaddingDuration);
5247 
5248  // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5249  Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration - NanoSeconds(1),
5251  this,
5252  m_phyAp,
5254  Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration,
5256  this,
5257  m_phyAp,
5259 
5260  // One PSDU of 1000 bytes should have been successfully received from STA 1
5261  Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
5262  // One PSDU of 1001 bytes should have been successfully received from STA 2
5263  Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
5264  // Verify events data have been cleared
5265  Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
5266 
5267  Simulator::Schedule(Seconds(1.5), &TestPhyPaddingExclusion::Reset, this);
5268 
5269  // STA1 and STA2 send MU UL PPDUs addressed to AP:
5270  Simulator::Schedule(Seconds(2.0),
5272  this,
5273  1,
5274  1,
5275  1000,
5276  ppduWithPaddingDuration);
5277  Simulator::Schedule(Seconds(2.0),
5279  this,
5280  2,
5281  2,
5282  1001,
5283  ppduWithPaddingDuration);
5284 
5285  // Set TRIGVECTOR on AP
5286  Simulator::Schedule(Seconds(2.0),
5288  this,
5289  ppduWithPaddingDuration);
5290 
5291  // A strong non-wifi interference is generated on RU 1 during padding reception
5292  BandInfo bandInfo;
5293  bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
5294  bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5295  bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5296  Bands bands;
5297  bands.push_back(bandInfo);
5298 
5299  Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5300  Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5301  double interferencePower = 0.1; // watts
5302  *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
5303 
5304  Simulator::Schedule(Seconds(2.0) + MicroSeconds(50) + expectedPpduDuration,
5306  this,
5307  interferencePsdRu1,
5308  MilliSeconds(100));
5309 
5310  // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5311  // CCA_BUSY instead of IDLE due to the interference)
5312  Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration - NanoSeconds(1),
5314  this,
5315  m_phyAp,
5317  Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration,
5319  this,
5320  m_phyAp,
5322 
5323  // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5324  // occupies RU 1 after payload, during PHY padding)
5325  Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
5326  // One PSDU of 1001 bytes should have been successfully received from STA 2
5327  Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
5328  // Verify events data have been cleared
5329  Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
5330 
5331  Simulator::Schedule(Seconds(2.5), &TestPhyPaddingExclusion::Reset, this);
5332 
5333  Simulator::Run();
5334 
5335  Simulator::Destroy();
5336 }
5337 
5345 {
5346  public:
5348  ~TestUlOfdmaPowerControl() override;
5349 
5350  private:
5351  void DoSetup() override;
5352  void DoTeardown() override;
5353  void DoRun() override;
5354 
5360  void SendMuBar(std::vector<uint16_t> staIds);
5361 
5368  void SetupBa(Address destination);
5369 
5376  void RunOne(bool setupBa);
5377 
5383 
5394  RxSignalInfo rxSignalInfo,
5395  WifiTxVector txVector,
5396  std::vector<bool> statusPerMpdu);
5397 
5398  uint8_t m_bssColor;
5399 
5403 
5405 
5406  double m_txPowerAp;
5408  double m_txPowerEnd;
5410 
5413 
5414  double m_rssiSta1;
5415  double m_rssiSta2;
5416 
5417  double m_tol;
5418 };
5419 
5421  : TestCase("UL-OFDMA power control test"),
5422  m_bssColor(1),
5423  m_txPowerAp(0),
5424  m_txPowerStart(0),
5425  m_txPowerEnd(0),
5426  m_txPowerLevels(0),
5427  m_requestedRssiSta1(0),
5428  m_requestedRssiSta2(0),
5429  m_rssiSta1(0),
5430  m_rssiSta2(0),
5431  m_tol(0.1)
5432 {
5433 }
5434 
5436 {
5437  m_phyAp = nullptr;
5438  m_apDev = nullptr;
5439  m_sta1Dev = nullptr;
5440  m_sta2Dev = nullptr;
5441 }
5442 
5443 void
5445 {
5446  // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5447  Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5448  m_apDev->Send(pkt, destination, 0);
5449 }
5450 
5451 void
5452 TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5453 {
5454  NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5455 
5456  // Build MU-BAR trigger frame
5457  CtrlTriggerHeader muBar;
5458  muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5459  muBar.SetMoreTF(true);
5460  muBar.SetCsRequired(true);
5462  muBar.SetGiAndLtfType(1600, 2);
5463  muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5464  muBar.SetUlSpatialReuse(60500);
5465 
5466  HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5467  std::size_t index = 1;
5468  int8_t ulTargetRssi = -40; // will be overwritten
5469  for (const auto& staId : staIds)
5470  {
5472  ui.SetAid12(staId);
5473  ui.SetRuAllocation({ru, index, true});
5474  ui.SetUlFecCodingType(true);
5475  ui.SetUlMcs(7);
5476  ui.SetUlDcm(false);
5477  ui.SetSsAllocation(1, 1);
5478  if (staId == 1)
5479  {
5480  ulTargetRssi = m_requestedRssiSta1;
5481  }
5482  else if (staId == 2)
5483  {
5484  ulTargetRssi = m_requestedRssiSta2;
5485  }
5486  else
5487  {
5488  NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5489  }
5490  ui.SetUlTargetRssi(ulTargetRssi);
5491 
5493  bar.SetType(BlockAckReqType::COMPRESSED);
5494  bar.SetTidInfo(0);
5495  bar.SetStartingSequence(4095);
5497 
5498  ++index;
5499  }
5500 
5501  WifiTxVector tbTxVector = muBar.GetHeTbTxVector(staIds.front());
5502  muBar.SetUlLength(HePhy::ConvertHeTbPpduDurationToLSigLength(MicroSeconds(128),
5503  tbTxVector,
5505  .first);
5506 
5507  WifiConstPsduMap psdus;
5508  WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
5509  0,
5511  800,
5512  1,
5513  1,
5514  0,
5516  false,
5517  false,
5518  false,
5519  m_bssColor);
5520 
5521  Ptr<Packet> bar = Create<Packet>();
5522  bar->AddHeader(muBar);
5523 
5524  Mac48Address receiver = Mac48Address::GetBroadcast();
5525  if (staIds.size() == 1)
5526  {
5527  uint16_t aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5528  if (staIds.front() == aidSta1)
5529  {
5530  receiver = Mac48Address::ConvertFrom(m_sta1Dev->GetAddress());
5531  }
5532  else
5533  {
5534  NS_ASSERT(staIds.front() ==
5535  DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5536  receiver = Mac48Address::ConvertFrom(m_sta2Dev->GetAddress());
5537  }
5538  }
5539 
5540  WifiMacHeader hdr;
5542  hdr.SetAddr1(receiver);
5543  hdr.SetAddr2(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5544  hdr.SetAddr3(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5545  hdr.SetDsNotTo();
5546  hdr.SetDsFrom();
5547  hdr.SetNoRetry();
5548  hdr.SetNoMoreFragments();
5549  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(bar, hdr);
5550 
5551  Time nav = m_apDev->GetPhy()->GetSifs();
5552  uint16_t staId = staIds.front(); // either will do
5553  nav += m_phyAp->CalculateTxDuration(GetBlockAckSize(BlockAckType::COMPRESSED),
5554  tbTxVector,
5556  staId);
5557  psdu->SetDuration(nav);
5558  psdus.insert(std::make_pair(SU_STA_ID, psdu));
5559 
5560  m_phyAp->Send(psdus, txVector);
5561 }
5562 
5563 void
5565  RxSignalInfo rxSignalInfo,
5566  WifiTxVector txVector,
5567  std::vector<bool> /*statusPerMpdu*/)
5568 {
5569  NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5570  double rssi = rxSignalInfo.rssi;
5571  NS_ASSERT(psdu->GetNMpdus() == 1);
5572  WifiMacHeader hdr = psdu->GetHeader(0);
5573  NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5574  if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5575  {
5577  rssi,
5578  m_rssiSta1,
5579  m_tol,
5580  "The obtained RSSI from STA 1 at AP is different from the expected one ("
5581  << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5582  }
5583  else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5584  {
5586  rssi,
5587  m_rssiSta2,
5588  m_tol,
5589  "The obtained RSSI from STA 2 at AP is different from the expected one ("
5590  << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5591  }
5592  else
5593  {
5594  NS_ABORT_MSG("The receiver address is unknown");
5595  }
5596 }
5597 
5598 void
5600 {
5601  // Now that BA session has been established we can plug our method
5604 }
5605 
5606 void
5608 {
5609  Ptr<Node> apNode = CreateObject<Node>();
5610  NodeContainer staNodes;
5611  staNodes.Create(2);
5612 
5613  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5614  Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel>();
5615  spectrumChannel->AddPropagationLossModel(lossModel);
5617  CreateObject<ConstantSpeedPropagationDelayModel>();
5618  spectrumChannel->SetPropagationDelayModel(delayModel);
5619 
5620  SpectrumWifiPhyHelper spectrumPhy;
5621  spectrumPhy.SetChannel(spectrumChannel);
5622  spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5623  spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5624 
5625  WifiHelper wifi;
5626  wifi.SetStandard(WIFI_STANDARD_80211ax);
5627  wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5628  "DataMode",
5629  StringValue("HeMcs7"),
5630  "ControlMode",
5631  StringValue("HeMcs7"));
5632 
5634  mac.SetType("ns3::StaWifiMac");
5635  NetDeviceContainer staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5636  wifi.AssignStreams(staDevs, 0);
5637  m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5639  m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5641 
5642  // Set the beacon interval long enough so that associated STAs may not consider link lost when
5643  // beacon generation is disabled during the actual tests. Having such a long interval also
5644  // avoids bloating logs with beacons during the set up phase.
5645  mac.SetType("ns3::ApWifiMac",
5646  "BeaconGeneration",
5647  BooleanValue(true),
5648  "BeaconInterval",
5649  TimeValue(MicroSeconds(1024 * 600)));
5650  m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5651  NS_ASSERT(m_apDev);
5652  m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5653  m_phyAp = DynamicCast<SpectrumWifiPhy>(m_apDev->GetPhy());
5654  NS_ASSERT(m_phyAp);
5655  // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5656  // set up for both STAs
5657 
5659  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5660  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
5661  positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5662  positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5663  positionAlloc->Add(
5664  Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5665  mobility.SetPositionAllocator(positionAlloc);
5666 
5667  mobility.Install(apNode);
5668  mobility.Install(staNodes);
5669 
5670  lossModel->SetDefaultLoss(50.0);
5671  lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5672  staNodes.Get(1)->GetObject<MobilityModel>(),
5673  56.0,
5674  true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5675 }
5676 
5677 void
5679 {
5680  m_phyAp->Dispose();
5681  m_phyAp = nullptr;
5682  m_apDev->Dispose();
5683  m_apDev = nullptr;
5684  m_sta1Dev->Dispose();
5685  m_sta1Dev = nullptr;
5686  m_sta2Dev->Dispose();
5687  m_sta2Dev = nullptr;
5688 }
5689 
5690 void
5692 {
5693  RngSeedManager::SetSeed(1);
5694  RngSeedManager::SetRun(1);
5695  int64_t streamNumber = 0;
5696 
5697  Ptr<WifiPhy> phySta1 = m_sta1Dev->GetPhy();
5698  Ptr<WifiPhy> phySta2 = m_sta2Dev->GetPhy();
5699 
5700  m_phyAp->AssignStreams(streamNumber);
5701  phySta1->AssignStreams(streamNumber);
5702  phySta2->AssignStreams(streamNumber);
5703 
5704  m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5705  m_phyAp->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerAp));
5706  m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5707 
5708  phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5709  phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5710  phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5711 
5712  phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5713  phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5714  phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5715 
5716  Time relativeStart = MilliSeconds(0);
5717  if (setupBa)
5718  {
5719  // Set up BA for each station once the association phase has ended
5720  // so that a BA session is established when the MU-BAR is received.
5721  Simulator::Schedule(MilliSeconds(800),
5723  this,
5724  m_sta1Dev->GetAddress());
5725  Simulator::Schedule(MilliSeconds(850),
5727  this,
5728  m_sta2Dev->GetAddress());
5729  relativeStart = MilliSeconds(1000);
5730  }
5731  else
5732  {
5733  Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5734  NS_ASSERT(apMac);
5735  apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5736  }
5737 
5738  Simulator::Schedule(relativeStart,
5740  this);
5741 
5742  {
5743  // Verify that the RSSI from STA 1 is consistent with what was requested
5744  std::vector<uint16_t> staIds{1};
5745  Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5746  }
5747 
5748  {
5749  // Verify that the RSSI from STA 2 is consistent with what was requested
5750  std::vector<uint16_t> staIds{2};
5751  Simulator::Schedule(relativeStart + MilliSeconds(20),
5753  this,
5754  staIds);
5755  }
5756 
5757  {
5758  // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5759  std::vector<uint16_t> staIds{1, 2};
5760  Simulator::Schedule(relativeStart + MilliSeconds(40),
5762  this,
5763  staIds);
5764  }
5765 
5766  Simulator::Stop(relativeStart + MilliSeconds(100));
5767  Simulator::Run();
5768 }
5769 
5770 void
5772 {
5773  // Power configurations
5774  m_txPowerAp = 20; // dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
5775  // since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5776  m_txPowerStart = 15; // dBm
5777 
5778  // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5779  m_requestedRssiSta1 = -30.0;
5780  m_requestedRssiSta2 = -36.0;
5781 
5782  // Test single power level
5783  {
5784  // STA power configurations: 15 dBm only
5785  m_txPowerEnd = 15;
5786  m_txPowerLevels = 1;
5787 
5788  // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5789  // regardless of the estimated path loss.
5790  m_rssiSta1 = -35.0; // 15 dBm - 50 dB
5791  m_rssiSta2 = -41.0; // 15 dBm - 56 dB
5792 
5793  RunOne(true);
5794  }
5795 
5796  // Test 2 dBm granularity
5797  {
5798  // STA power configurations: [15:2:25] dBm
5799  m_txPowerEnd = 25;
5800  m_txPowerLevels = 6;
5801 
5802  // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5803  // requested
5804  m_rssiSta1 = -29.0; // 21 dBm - 50 dB
5805  m_rssiSta2 = -35.0; // 21 dBm - 50 dB
5806 
5807  RunOne(false);
5808  }
5809 
5810  // Test 1 dBm granularity
5811  {
5812  // STA power configurations: [15:1:25] dBm
5813  m_txPowerEnd = 25;
5814  m_txPowerLevels = 11;
5815 
5816  // Expected UL RSSIs, considering that we can correctly tune the transmit power
5817  m_rssiSta1 = -30.0; // 20 dBm - 50 dB
5818  m_rssiSta2 = -36.0; // 20 dBm - 56 dB
5819 
5820  RunOne(false);
5821  }
5822 
5823  // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5824  {
5825  // STA power configurations: [15:1:25] dBm
5826  m_txPowerEnd = 25;
5827  m_txPowerLevels = 11;
5828 
5829  // Requested UL RSSIs
5830  m_requestedRssiSta1 = -28.0; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5831  m_requestedRssiSta2 = -37.0; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5832 
5833  // Expected UL RSSIs, considering that we can correctly tune the transmit power
5834  m_rssiSta1 = -28.0; // 22 dBm - 50 dB
5835  m_rssiSta2 = -37.0; // 19 dBm - 56 dB
5836 
5837  RunOne(false);
5838  }
5839 
5840  Simulator::Destroy();
5841 }
5842 
5850 {
5851  public:
5853 };
5854 
5856  : TestSuite("wifi-phy-ofdma", UNIT)
5857 {
5858  AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::QUICK);
5859  AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::QUICK);
5860  AddTestCase(new TestUlOfdmaPpduUid, TestCase::QUICK);
5861  AddTestCase(new TestMultipleHeTbPreambles, TestCase::QUICK);
5862  AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::QUICK);
5863  AddTestCase(new TestPhyPaddingExclusion, TestCase::QUICK);
5864  AddTestCase(new TestUlOfdmaPowerControl, TestCase::QUICK);
5865 }
5866 
#define max(a, b)
Definition: 80211b.c:43
SpectrumWifiPhy used for testing OFDMA.
Time GetEnergyDuration(double energyW, WifiSpectrumBand band)
Wrapper to InterferenceHelper method.
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.
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.
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 CheckOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBand band, double expectedRxPower)
Check the received power for the OFDMA part of the HE TB PPDUs over the given band.
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
std::unique_ptr< OfdmaTestPhyListener > m_apPhyStateListener
listener for AP PHY state transitions
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 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 CheckNonOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBand band, double expectedRxPower)
Check the received power for the non-OFDMA of the HE TB PPDUs over the given band.
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.
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:100
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAckRequest.
Definition: ctrl-headers.h:52
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
Headers for Trigger frames.
Definition: ctrl-headers.h:945
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:435
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:311
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:200
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:863
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:987
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:206
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Make it easy to create and manage PHY objects for the spectrum model.
void SetChannel(Ptr< SpectrumChannel > channel)
802.11 PHY layer model
void SetChannel(const Ptr< SpectrumChannel > channel)
Set the SpectrumChannel this SpectrumWifiPhy is to be connected to.
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const override
void StartRx(Ptr< SpectrumSignalParameters > rxParams)
Input method for delivering a signal from the spectrum channel and low-level PHY interface to this Sp...
void CreateWifiSpectrumPhyInterface(Ptr< NetDevice > device)
Method to encapsulate the creation of the WifiSpectrumPhyInterface object (used to bind the WifiSpect...
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:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1423
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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:325
Implements the IEEE 802.11 MAC header.
WifiMacType GetType() const
Return the type (enum 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.
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:925
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:551
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:624
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:1693
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:632
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:1221
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:774
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:448
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:941
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1480
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1244
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:1062
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:996
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1219
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:704
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1224
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:600
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:652
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:612
void RegisterListener(WifiPhyListener *listener)
Definition: wifi-phy.cc:454
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1206
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:442
void Reset()
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1804
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:870
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition: wifi-phy.cc:719
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:2184
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 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.
void SetRuAllocation(const RuAllocation &ruAlloc)
Set RU Allocation of SIG-B common field.
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:856
#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:296
#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:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
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:707
std::pair< uint32_t, uint32_t > WifiSpectrumBand
typedef for a pair of start and stop sub-band indexes
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
mac
Definition: third.py:85
wifi
Definition: third.py:88
mobility
Definition: third.py:96
phy
Definition: third.py:82
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:70
double rssi
RSSI in dBm.
Definition: phy-entity.h:72
#define SU_STA_ID
Definition: wifi-mode.h:34
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.