A Discrete-Event Network Simulator
API
wifi-phy-ofdma-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2019 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
19  */
20 
21 #include "ns3/log.h"
22 #include "ns3/test.h"
23 #include "ns3/node.h"
24 #include "ns3/pointer.h"
25 #include "ns3/string.h"
26 #include "ns3/double.h"
27 #include "ns3/boolean.h"
28 #include "ns3/simulator.h"
29 #include "ns3/rng-seed-manager.h"
30 #include "ns3/constant-position-mobility-model.h"
31 #include "ns3/wifi-spectrum-signal-parameters.h"
32 #include "ns3/wifi-spectrum-value-helper.h"
33 #include "ns3/multi-model-spectrum-channel.h"
34 #include "ns3/spectrum-wifi-phy.h"
35 #include "ns3/nist-error-rate-model.h"
36 #include "ns3/interference-helper.h"
37 #include "ns3/wifi-mac-header.h"
38 #include "ns3/wifi-net-device.h"
39 #include "ns3/wifi-psdu.h"
40 #include "ns3/he-ppdu.h"
41 #include "ns3/wifi-utils.h"
42 #include "ns3/ap-wifi-mac.h"
43 #include "ns3/sta-wifi-mac.h"
44 #include "ns3/he-configuration.h"
45 #include "ns3/ctrl-headers.h"
46 #include "ns3/threshold-preamble-detection-model.h"
47 #include "ns3/he-phy.h"
48 #include "ns3/waveform-generator.h"
49 #include "ns3/non-communicating-net-device.h"
50 #include "ns3/spectrum-wifi-helper.h"
51 #include "ns3/mobility-helper.h"
52 
53 using namespace ns3;
54 
55 NS_LOG_COMPONENT_DEFINE ("WifiPhyOfdmaTest");
56 
57 static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
58 static const uint32_t DEFAULT_FREQUENCY = 5180; // MHz
60 static const uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
61 static const uint16_t DEFAULT_GUARD_WIDTH = DEFAULT_CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
62 
67 class OfdmaTestHePhy : public HePhy
68 {
69 public:
75  OfdmaTestHePhy (uint16_t staId);
76  virtual ~OfdmaTestHePhy ();
77 
85  uint16_t GetStaId (const Ptr<const WifiPpdu> ppdu) const override;
86 
92  void SetGlobalPpduUid (uint64_t uid);
93 
94 private:
95  uint16_t m_staId;
96 }; //class OfdmaTestHePhy
97 
99  : HePhy (),
100  m_staId (staId)
101 {
102 }
103 
105 {
106 }
107 
108 uint16_t
110 {
111  if (ppdu->GetType () == WIFI_PPDU_TYPE_DL_MU)
112  {
113  return m_staId;
114  }
115  return HePhy::GetStaId (ppdu);
116 }
117 
118 void
120 {
121  m_globalPpduUid = uid;
122 }
123 
128 {
129 public:
134  static TypeId GetTypeId (void);
140  OfdmaSpectrumWifiPhy (uint16_t staId);
141  virtual ~OfdmaSpectrumWifiPhy ();
142 
143  void DoInitialize (void) override;
144  void DoDispose (void) override;
145 
146  using WifiPhy::Reset;
147 
153  typedef void (*TxPpduUidCallback)(uint64_t uid);
154 
158  void StartTx (Ptr<WifiPpdu> ppdu) override;
163  uint16_t GetGuardBandwidth (uint16_t currentChannelWidth) const override;
164 
170  void SetPpduUid (uint64_t uid);
171 
177  void SetTriggerFrameUid (uint64_t uid);
178 
182  std::map <std::pair<uint64_t, WifiPreamble>, Ptr<Event> > & GetCurrentPreambleEvents (void);
187 
198  Time GetEnergyDuration (double energyW, WifiSpectrumBand band);
199 
203  Ptr<const HePhy> GetHePhy (void) const;
204 
205 private:
208 }; //class OfdmaSpectrumWifiPhy
209 
210 TypeId
212 {
213  static TypeId tid = TypeId ("ns3::OfdmaSpectrumWifiPhy")
215  .SetGroupName ("Wifi")
216  .AddTraceSource ("TxPpduUid",
217  "UID of the PPDU to be transmitted",
219  "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback")
220  ;
221  return tid;
222 }
223 
225  : SpectrumWifiPhy ()
226 {
227  m_ofdmTestHePhy = Create<OfdmaTestHePhy> (staId);
228  m_ofdmTestHePhy->SetOwner (this);
229 }
230 
232 {
233 }
234 
235 void
237 {
238  //Replace HE PHY instance with test instance
240  SpectrumWifiPhy::DoInitialize ();
241 }
242 
243 void
245 {
246  m_ofdmTestHePhy = 0;
247  SpectrumWifiPhy::DoDispose ();
248 }
249 
250 void
252 {
254  m_previouslyRxPpduUid = uid;
255 }
256 
257 void
259 {
260  m_previouslyRxPpduUid = uid;
261 }
262 
263 void
265 {
266  m_phyTxPpduUidTrace (ppdu->GetUid ());
267  SpectrumWifiPhy::StartTx (ppdu);
268 }
269 
270 std::map <std::pair<uint64_t, WifiPreamble>, Ptr<Event> > &
272 {
274 }
275 
276 uint16_t
277 OfdmaSpectrumWifiPhy::GetGuardBandwidth (uint16_t currentChannelWidth) const
278 {
279  // return a small enough value to avoid having too much out of band transmission
280  // knowing that slopes are not configurable yet.
281  return 1;
282 }
283 
286 {
287  return m_currentEvent;
288 }
289 
290 Time
292 {
293  return m_interference->GetEnergyDuration (energyW, band);
294 }
295 
298 {
299  return DynamicCast<const HePhy> (GetPhyEntity (WIFI_MOD_CLASS_HE));
300 }
301 
309 {
310 public:
312  virtual ~TestDlOfdmaPhyTransmission ();
313 
314 private:
315  void DoSetup (void) override;
316  void DoTeardown (void) override;
317  void DoRun (void) override;
318 
326  void RxSuccessSta1 (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
327  WifiTxVector txVector, std::vector<bool> statusPerMpdu);
335  void RxSuccessSta2 (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
336  WifiTxVector txVector, std::vector<bool> statusPerMpdu);
344  void RxSuccessSta3 (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
345  WifiTxVector txVector, std::vector<bool> statusPerMpdu);
346 
351  void RxFailureSta1 (Ptr<WifiPsdu> psdu);
356  void RxFailureSta2 (Ptr<WifiPsdu> psdu);
361  void RxFailureSta3 (Ptr<WifiPsdu> psdu);
362 
369  void CheckResultsSta1 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes);
376  void CheckResultsSta2 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes);
383  void CheckResultsSta3 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes);
384 
388  void ResetResults ();
389 
395  void SendMuPpdu (uint16_t rxStaId1, uint16_t rxStaId2);
396 
402  void GenerateInterference (Ptr<SpectrumValue> interferencePsd, Time duration);
406  void StopInterference (void);
407 
411  void RunOne ();
412 
425 
435 
441 
442  uint16_t m_frequency;
443  uint16_t m_channelWidth;
445 };
446 
448  : TestCase ("DL-OFDMA PHY test"),
449  m_countRxSuccessSta1 (0),
450  m_countRxSuccessSta2 (0),
451  m_countRxSuccessSta3 (0),
452  m_countRxFailureSta1 (0),
453  m_countRxFailureSta2 (0),
454  m_countRxFailureSta3 (0),
455  m_countRxBytesSta1 (0),
456  m_countRxBytesSta2 (0),
457  m_countRxBytesSta3 (0),
458  m_frequency (DEFAULT_FREQUENCY),
459  m_channelWidth (DEFAULT_CHANNEL_WIDTH),
460  m_expectedPpduDuration (NanoSeconds (306400))
461 {
462 }
463 
464 void
466 {
473  m_countRxBytesSta1 = 0;
474  m_countRxBytesSta2 = 0;
475  m_countRxBytesSta3 = 0;
476 }
477 
478 void
479 TestDlOfdmaPhyTransmission::SendMuPpdu (uint16_t rxStaId1, uint16_t rxStaId2)
480 {
481  NS_LOG_FUNCTION (this << rxStaId1 << rxStaId2);
482  WifiConstPsduMap psdus;
483  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_MU, 800, 1, 1, 0, m_channelWidth, false, false);
484  HeRu::RuType ruType = HeRu::RU_106_TONE;
485  if (m_channelWidth == 20)
486  {
487  ruType = HeRu::RU_106_TONE;
488  }
489  else if (m_channelWidth == 40)
490  {
491  ruType = HeRu::RU_242_TONE;
492  }
493  else if (m_channelWidth == 80)
494  {
495  ruType = HeRu::RU_484_TONE;
496  }
497  else if (m_channelWidth == 160)
498  {
499  ruType = HeRu::RU_996_TONE;
500  }
501  else
502  {
503  NS_ASSERT_MSG (false, "Unsupported channel width");
504  }
505 
506  HeRu::RuSpec ru1 (ruType, 1, true);
507  txVector.SetRu (ru1, rxStaId1);
508  txVector.SetMode (HePhy::GetHeMcs7 (), rxStaId1);
509  txVector.SetNss (1, rxStaId1);
510 
511  HeRu::RuSpec ru2 (ruType, (m_channelWidth == 160 ? 1 : 2), m_channelWidth != 160);
512  txVector.SetRu (ru2, rxStaId2);
513  txVector.SetMode (HePhy::GetHeMcs9 (), rxStaId2);
514  txVector.SetNss (1, rxStaId2);
515 
516  Ptr<Packet> pkt1 = Create<Packet> (1000);
517  WifiMacHeader hdr1;
518  hdr1.SetType (WIFI_MAC_QOSDATA);
519  hdr1.SetQosTid (0);
520  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:01"));
521  hdr1.SetSequenceNumber (1);
522  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu> (pkt1, hdr1);
523  psdus.insert (std::make_pair (rxStaId1, psdu1));
524 
525  Ptr<Packet> pkt2 = Create<Packet> (1500);
526  WifiMacHeader hdr2;
527  hdr2.SetType (WIFI_MAC_QOSDATA);
528  hdr2.SetQosTid (0);
529  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
530  hdr2.SetSequenceNumber (2);
531  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu> (pkt2, hdr2);
532  psdus.insert (std::make_pair (rxStaId2, psdu2));
533 
534  m_phyAp->Send (psdus, txVector);
535 }
536 
537 void
539 {
540  m_phyInterferer->SetTxPowerSpectralDensity (interferencePsd);
541  m_phyInterferer->SetPeriod (duration);
543  Simulator::Schedule (duration, &TestDlOfdmaPhyTransmission::StopInterference, this);
544 }
545 
546 void
548 {
550 }
551 
553 {
554 }
555 
556 void
558  WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
559 {
560  NS_LOG_FUNCTION (this << *psdu << rxSignalInfo << txVector);
562  m_countRxBytesSta1 += (psdu->GetSize () - 30);
563 }
564 
565 void
567  WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
568 {
569  NS_LOG_FUNCTION (this << *psdu << rxSignalInfo << txVector);
571  m_countRxBytesSta2 += (psdu->GetSize () - 30);
572 }
573 
574 void
576  WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
577 {
578  NS_LOG_FUNCTION (this << *psdu << rxSignalInfo << txVector);
580  m_countRxBytesSta3 += (psdu->GetSize () - 30);
581 }
582 
583 void
585 {
586  NS_LOG_FUNCTION (this << *psdu);
588 }
589 
590 void
592 {
593  NS_LOG_FUNCTION (this << *psdu);
595 }
596 
597 void
599 {
600  NS_LOG_FUNCTION (this << *psdu);
602 }
603 
604 void
605 TestDlOfdmaPhyTransmission::CheckResultsSta1 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
606 {
607  NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessSta1, expectedRxSuccess, "The number of successfully received packets by STA 1 is not correct!");
608  NS_TEST_ASSERT_MSG_EQ (m_countRxFailureSta1, expectedRxFailure, "The number of unsuccessfully received packets by STA 1 is not correct!");
609  NS_TEST_ASSERT_MSG_EQ (m_countRxBytesSta1, expectedRxBytes, "The number of bytes received by STA 1 is not correct!");
610 }
611 
612 void
613 TestDlOfdmaPhyTransmission::CheckResultsSta2 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
614 {
615  NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessSta2, expectedRxSuccess, "The number of successfully received packets by STA 2 is not correct!");
616  NS_TEST_ASSERT_MSG_EQ (m_countRxFailureSta2, expectedRxFailure, "The number of unsuccessfully received packets by STA 2 is not correct!");
617  NS_TEST_ASSERT_MSG_EQ (m_countRxBytesSta2, expectedRxBytes, "The number of bytes received by STA 2 is not correct!");
618 }
619 
620 void
621 TestDlOfdmaPhyTransmission::CheckResultsSta3 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
622 {
623  NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessSta3, expectedRxSuccess, "The number of successfully received packets by STA 3 is not correct!");
624  NS_TEST_ASSERT_MSG_EQ (m_countRxFailureSta3, expectedRxFailure, "The number of unsuccessfully received packets by STA 3 is not correct!");
625  NS_TEST_ASSERT_MSG_EQ (m_countRxBytesSta3, expectedRxBytes, "The number of bytes received by STA 3 is not correct!");
626 }
627 
628 void
630 {
631  //This is needed to make sure PHY state will be checked as the last event if a state change occured at the exact same time as the check
632  Simulator::ScheduleNow (&TestDlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
633 }
634 
635 void
637 {
638  WifiPhyState currentState;
639  PointerValue ptr;
640  phy->GetAttribute ("State", ptr);
641  Ptr <WifiPhyStateHelper> state = DynamicCast <WifiPhyStateHelper> (ptr.Get<WifiPhyStateHelper> ());
642  currentState = state->GetState ();
643  NS_LOG_FUNCTION (this << currentState);
644  NS_TEST_ASSERT_MSG_EQ (currentState, expectedState, "PHY State " << currentState << " does not match expected state " << expectedState << " at " << Simulator::Now ());
645 }
646 
647 void
649 {
650  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
651  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
652  lossModel->SetFrequency (m_frequency * 1e6);
653  spectrumChannel->AddPropagationLossModel (lossModel);
654  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
655  spectrumChannel->SetPropagationDelayModel (delayModel);
656 
657  Ptr<Node> apNode = CreateObject<Node> ();
658  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice> ();
659  m_phyAp = CreateObject<SpectrumWifiPhy> ();
662  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper> ();
663  m_phyAp->SetInterferenceHelper (apInterferenceHelper);
664  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel> ();
665  m_phyAp->SetErrorRateModel (apErrorModel);
666  m_phyAp->SetDevice (apDev);
667  m_phyAp->SetChannel (spectrumChannel);
668  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel> ();
669  m_phyAp->SetMobility (apMobility);
670  apDev->SetPhy (m_phyAp);
671  apNode->AggregateObject (apMobility);
672  apNode->AddDevice (apDev);
673 
674  Ptr<Node> sta1Node = CreateObject<Node> ();
675  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice> ();
676  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy> (1);
679  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper> ();
680  m_phySta1->SetInterferenceHelper (sta1InterferenceHelper);
681  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel> ();
682  m_phySta1->SetErrorRateModel (sta1ErrorModel);
683  m_phySta1->SetDevice (sta1Dev);
684  m_phySta1->SetChannel (spectrumChannel);
687  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel> ();
688  m_phySta1->SetMobility (sta1Mobility);
689  sta1Dev->SetPhy (m_phySta1);
690  sta1Node->AggregateObject (sta1Mobility);
691  sta1Node->AddDevice (sta1Dev);
692 
693  Ptr<Node> sta2Node = CreateObject<Node> ();
694  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice> ();
695  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy> (2);
698  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper> ();
699  m_phySta2->SetInterferenceHelper (sta2InterferenceHelper);
700  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel> ();
701  m_phySta2->SetErrorRateModel (sta2ErrorModel);
702  m_phySta2->SetDevice (sta2Dev);
703  m_phySta2->SetChannel (spectrumChannel);
706  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel> ();
707  m_phySta2->SetMobility (sta2Mobility);
708  sta2Dev->SetPhy (m_phySta2);
709  sta2Node->AggregateObject (sta2Mobility);
710  sta2Node->AddDevice (sta2Dev);
711 
712  Ptr<Node> sta3Node = CreateObject<Node> ();
713  Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice> ();
714  m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy> (3);
717  Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper> ();
718  m_phySta3->SetInterferenceHelper (sta3InterferenceHelper);
719  Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel> ();
720  m_phySta3->SetErrorRateModel (sta3ErrorModel);
721  m_phySta3->SetDevice (sta3Dev);
722  m_phySta3->SetChannel (spectrumChannel);
725  Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel> ();
726  m_phySta3->SetMobility (sta3Mobility);
727  sta3Dev->SetPhy (m_phySta3);
728  sta3Node->AggregateObject (sta3Mobility);
729  sta3Node->AddDevice (sta3Dev);
730 
731  Ptr<Node> interfererNode = CreateObject<Node> ();
732  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice> ();
733  m_phyInterferer = CreateObject<WaveformGenerator> ();
734  m_phyInterferer->SetDevice (interfererDev);
735  m_phyInterferer->SetChannel (spectrumChannel);
737  interfererNode->AddDevice (interfererDev);
738 }
739 
740 void
742 {
743  m_phyAp->Dispose ();
744  m_phyAp = 0;
745  m_phySta1->Dispose ();
746  m_phySta1 = 0;
747  m_phySta2->Dispose ();
748  m_phySta2 = 0;
749  m_phySta3->Dispose ();
750  m_phySta3 = 0;
752  m_phyInterferer = 0;
753 }
754 
755 void
757 {
758  RngSeedManager::SetSeed (1);
759  RngSeedManager::SetRun (1);
760  int64_t streamNumber = 0;
761  m_phyAp->AssignStreams (streamNumber);
762  m_phySta1->AssignStreams (streamNumber);
763  m_phySta2->AssignStreams (streamNumber);
764  m_phySta3->AssignStreams (streamNumber);
765 
766  auto channelNum = std::get<0> (*WifiPhyOperatingChannel::FindFirst (0, m_frequency, m_channelWidth,
769 
771  (int)(WIFI_PHY_BAND_5GHZ), 0});
773  (int)(WIFI_PHY_BAND_5GHZ), 0});
775  (int)(WIFI_PHY_BAND_5GHZ), 0});
777  (int)(WIFI_PHY_BAND_5GHZ), 0});
778 
779  Simulator::Schedule (Seconds (0.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
780 
781  //Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
782  //Each STA should receive its PSDU.
783  Simulator::Schedule (Seconds (1.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
784 
785  //Since it takes m_expectedPpduDuration to transmit the PPDU,
786  //all 3 PHYs should be back to IDLE at the same time,
787  //even the PHY that has no PSDU addressed to it.
794 
795  //One PSDU of 1000 bytes should have been successfully received by STA 1
796  Simulator::Schedule (Seconds (1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 1, 0, 1000);
797  //One PSDU of 1500 bytes should have been successfully received by STA 2
798  Simulator::Schedule (Seconds (1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 1, 0, 1500);
799  //No PSDU should have been received by STA 3
800  Simulator::Schedule (Seconds (1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
801 
802  Simulator::Schedule (Seconds (1.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
803 
804  //Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
805  //STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
806  //but should keep its PHY busy during all PPDU duration.
807  Simulator::Schedule (Seconds (2.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 3);
808 
809  //Since it takes m_expectedPpduDuration to transmit the PPDU,
810  //all 3 PHYs should be back to IDLE at the same time,
811  //even the PHY that has no PSDU addressed to it.
818 
819  //One PSDU of 1000 bytes should have been successfully received by STA 1
820  Simulator::Schedule (Seconds (2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 1, 0, 1000);
821  //No PSDU should have been received by STA 2
822  Simulator::Schedule (Seconds (2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 0, 0);
823  //One PSDU of 1500 bytes should have been successfully received by STA 3
824  Simulator::Schedule (Seconds (2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 1, 0, 1500);
825 
826  Simulator::Schedule (Seconds (2.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
827 
828  //Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
829  Simulator::Schedule (Seconds (3.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
830 
831  //A strong non-wifi interference is generated on RU 1 during PSDU reception
832  BandInfo bandInfo;
833  bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
834  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
835  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
836  Bands bands;
837  bands.push_back (bandInfo);
838 
839  Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel> (bands);
840  Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue> (SpectrumInterferenceRu1);
841  double interferencePower = 0.1; //watts
842  *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
843 
844  Simulator::Schedule (Seconds (3.0) + MicroSeconds (50), &TestDlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdRu1, MilliSeconds (100));
845 
846  //Since it takes m_expectedPpduDuration to transmit the PPDU,
847  //both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
848  //even the PHY that has no PSDU addressed to it.
855 
856  //One PSDU of 1000 bytes should have been unsuccessfully received by STA 1 (since interference occupies RU 1)
857  Simulator::Schedule (Seconds (3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
858  //One PSDU of 1500 bytes should have been successfully received by STA 2
859  Simulator::Schedule (Seconds (3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 1, 0, 1500);
860  //No PSDU should have been received by STA3
861  Simulator::Schedule (Seconds (3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
862 
863  Simulator::Schedule (Seconds (3.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
864 
865  //Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
866  Simulator::Schedule (Seconds (4.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
867 
868  //A strong non-wifi interference is generated on RU 2 during PSDU reception
869  bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
870  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
871  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
872  bands.clear ();
873  bands.push_back (bandInfo);
874 
875  Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel> (bands);
876  Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue> (SpectrumInterferenceRu2);
877  *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
878 
879  Simulator::Schedule (Seconds (4.0) + MicroSeconds (50), &TestDlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdRu2, MilliSeconds (100));
880 
881  //Since it takes m_expectedPpduDuration to transmit the PPDU,
882  //both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the same time,
883  //even the PHY that has no PSDU addressed to it.
890 
891  //One PSDU of 1000 bytes should have been successfully received by STA 1
892  Simulator::Schedule (Seconds (4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 1, 0, 1000);
893  //One PSDU of 1500 bytes should have been unsuccessfully received by STA 2 (since interference occupies RU 2)
894  Simulator::Schedule (Seconds (4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
895  //No PSDU should have been received by STA3
896  Simulator::Schedule (Seconds (4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
897 
898  Simulator::Schedule (Seconds (4.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
899 
900  //Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
901  Simulator::Schedule (Seconds (5.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
902 
903  //A strong non-wifi interference is generated on the full band during PSDU reception
904  bandInfo.fc = m_frequency * 1e6;
905  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
906  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
907  bands.clear ();
908  bands.push_back (bandInfo);
909 
910  Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel> (bands);
911  Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue> (SpectrumInterferenceAll);
912  *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
913 
914  Simulator::Schedule (Seconds (5.0) + MicroSeconds (50), &TestDlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdAll, MilliSeconds (100));
915 
916  //Since it takes m_expectedPpduDuration to transmit the PPDU,
917  //both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
918  //even the PHY that has no PSDU addressed to it.
925 
926  //One PSDU of 1000 bytes should have been unsuccessfully received by STA 1 (since interference occupies RU 1)
927  Simulator::Schedule (Seconds (5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
928  //One PSDU of 1500 bytes should have been unsuccessfully received by STA 2 (since interference occupies RU 2)
929  Simulator::Schedule (Seconds (5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
930  //No PSDU should have been received by STA3
931  Simulator::Schedule (Seconds (5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
932 
933  Simulator::Schedule (Seconds (5.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
934 
935  Simulator::Run ();
936 }
937 
938 void
940 {
941  m_frequency = 5180;
942  m_channelWidth = 20;
944  RunOne ();
945 
946  m_frequency = 5190;
947  m_channelWidth = 40;
949  RunOne ();
950 
951  m_frequency = 5210;
952  m_channelWidth = 80;
954  RunOne ();
955 
956  m_frequency = 5250;
957  m_channelWidth = 160;
959  RunOne ();
960 
961  Simulator::Destroy ();
962 }
963 
964 
972 {
973 public:
975  virtual ~TestUlOfdmaPpduUid ();
976 
977 private:
978  void DoSetup (void) override;
979  void DoTeardown (void) override;
980  void DoRun (void) override;
981 
986  void TxPpduAp (uint64_t uid);
991  void TxPpduSta1 (uint64_t uid);
996  void TxPpduSta2 (uint64_t uid);
1000  void ResetPpduUid (void);
1001 
1005  void SendMuPpdu (void);
1009  void SendTbPpdu (void);
1014  void SendSuPpdu (uint16_t txStaId);
1015 
1021  void CheckUid (uint16_t staId, uint64_t expectedUid);
1022 
1026 
1027  uint64_t m_ppduUidAp;
1028  uint64_t m_ppduUidSta1;
1029  uint64_t m_ppduUidSta2;
1030 };
1031 
1033  : TestCase ("UL-OFDMA PPDU UID attribution test"),
1034  m_ppduUidAp (UINT64_MAX),
1035  m_ppduUidSta1 (UINT64_MAX),
1036  m_ppduUidSta2 (UINT64_MAX)
1037 {
1038 }
1039 
1041 {
1042 }
1043 
1044 void
1046 {
1047  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
1048  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
1049  lossModel->SetFrequency (DEFAULT_FREQUENCY);
1050  spectrumChannel->AddPropagationLossModel (lossModel);
1051  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
1052  spectrumChannel->SetPropagationDelayModel (delayModel);
1053 
1054  Ptr<Node> apNode = CreateObject<Node> ();
1055  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice> ();
1056  m_phyAp = CreateObject<OfdmaSpectrumWifiPhy> (0);
1059  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper> ();
1060  m_phyAp->SetInterferenceHelper (apInterferenceHelper);
1061  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel> ();
1062  m_phyAp->SetErrorRateModel (apErrorModel);
1063  auto channelNum = std::get<0> (*WifiPhyOperatingChannel::FindFirst (0, DEFAULT_FREQUENCY,
1068  (int)(WIFI_PHY_BAND_5GHZ), 0});
1069  m_phyAp->SetDevice (apDev);
1070  m_phyAp->SetChannel (spectrumChannel);
1072  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel> ();
1073  m_phyAp->SetMobility (apMobility);
1074  apDev->SetPhy (m_phyAp);
1075  apNode->AggregateObject (apMobility);
1076  apNode->AddDevice (apDev);
1077 
1078  Ptr<Node> sta1Node = CreateObject<Node> ();
1079  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice> ();
1080  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy> (1);
1083  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper> ();
1084  m_phySta1->SetInterferenceHelper (sta1InterferenceHelper);
1085  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel> ();
1086  m_phySta1->SetErrorRateModel (sta1ErrorModel);
1088  (int)(WIFI_PHY_BAND_5GHZ), 0});
1089  m_phySta1->SetDevice (sta1Dev);
1090  m_phySta1->SetChannel (spectrumChannel);
1092  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel> ();
1093  m_phySta1->SetMobility (sta1Mobility);
1094  sta1Dev->SetPhy (m_phySta1);
1095  sta1Node->AggregateObject (sta1Mobility);
1096  sta1Node->AddDevice (sta1Dev);
1097 
1098  Ptr<Node> sta2Node = CreateObject<Node> ();
1099  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice> ();
1100  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy> (2);
1103  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper> ();
1104  m_phySta2->SetInterferenceHelper (sta2InterferenceHelper);
1105  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel> ();
1106  m_phySta2->SetErrorRateModel (sta2ErrorModel);
1108  (int)(WIFI_PHY_BAND_5GHZ), 0});
1109  m_phySta2->SetDevice (sta2Dev);
1110  m_phySta2->SetChannel (spectrumChannel);
1112  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel> ();
1113  m_phySta2->SetMobility (sta2Mobility);
1114  sta2Dev->SetPhy (m_phySta2);
1115  sta2Node->AggregateObject (sta2Mobility);
1116  sta2Node->AddDevice (sta2Dev);
1117 }
1118 
1119 void
1121 {
1122  m_phyAp->Dispose ();
1123  m_phyAp = 0;
1124  m_phySta1->Dispose ();
1125  m_phySta1 = 0;
1126  m_phySta2->Dispose ();
1127  m_phySta2 = 0;
1128 }
1129 
1130 void
1131 TestUlOfdmaPpduUid::CheckUid (uint16_t staId, uint64_t expectedUid)
1132 {
1133  uint64_t uid;
1134  std::string device;
1135  switch (staId)
1136  {
1137  case 0:
1138  uid = m_ppduUidAp;
1139  device = "AP";
1140  break;
1141  case 1:
1142  uid = m_ppduUidSta1;
1143  device = "STA1";
1144  break;
1145  case 2:
1146  uid = m_ppduUidSta2;
1147  device = "STA2";
1148  break;
1149  default:
1150  NS_ABORT_MSG ("Unexpected STA-ID");
1151  }
1152  NS_TEST_ASSERT_MSG_EQ (uid, expectedUid, "UID " << uid << " does not match expected one " << expectedUid << " for " << device << " at " << Simulator::Now ());
1153 }
1154 
1155 void
1157 {
1158  NS_LOG_FUNCTION (this << uid);
1159  m_ppduUidAp = uid;
1160 }
1161 
1162 void
1164 {
1165  NS_LOG_FUNCTION (this << uid);
1166  m_ppduUidSta1 = uid;
1167 }
1168 
1169 void
1171 {
1172  NS_LOG_FUNCTION (this << uid);
1173  m_ppduUidSta2 = uid;
1174 }
1175 
1176 void
1178 {
1179  NS_LOG_FUNCTION (this);
1180  m_phyAp->SetPpduUid (0); //one is enough since it's a global attribute
1181  return;
1182 }
1183 
1184 void
1186 {
1187  WifiConstPsduMap psdus;
1188  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_MU, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false);
1189 
1190  uint16_t rxStaId1 = 1;
1191  HeRu::RuSpec ru1 (HeRu::RU_106_TONE, 1, false);
1192  txVector.SetRu (ru1, rxStaId1);
1193  txVector.SetMode (HePhy::GetHeMcs7 (), rxStaId1);
1194  txVector.SetNss (1, rxStaId1);
1195 
1196  uint16_t rxStaId2 = 2;
1197  HeRu::RuSpec ru2 (HeRu::RU_106_TONE, 2, false);
1198  txVector.SetRu (ru2, rxStaId2);
1199  txVector.SetMode (HePhy::GetHeMcs9 (), rxStaId2);
1200  txVector.SetNss (1, rxStaId2);
1201 
1202  Ptr<Packet> pkt1 = Create<Packet> (1000);
1203  WifiMacHeader hdr1;
1204  hdr1.SetType (WIFI_MAC_QOSDATA);
1205  hdr1.SetQosTid (0);
1206  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:01"));
1207  hdr1.SetSequenceNumber (1);
1208  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu> (pkt1, hdr1);
1209  psdus.insert (std::make_pair (rxStaId1, psdu1));
1210 
1211  Ptr<Packet> pkt2 = Create<Packet> (1500);
1212  WifiMacHeader hdr2;
1213  hdr2.SetType (WIFI_MAC_QOSDATA);
1214  hdr2.SetQosTid (0);
1215  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
1216  hdr2.SetSequenceNumber (2);
1217  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu> (pkt2, hdr2);
1218  psdus.insert (std::make_pair (rxStaId2, psdu2));
1219 
1220  m_phyAp->Send (psdus, txVector);
1221 }
1222 
1223 void
1225 {
1226  WifiConstPsduMap psdus1;
1227  WifiConstPsduMap psdus2;
1228  WifiTxVector txVector1 = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false);
1229  WifiTxVector txVector2 = txVector1;
1230 
1231  uint16_t rxStaId1 = 1;
1232  HeRu::RuSpec ru1 (HeRu::RU_106_TONE, 1, false);
1233  txVector1.SetRu (ru1, rxStaId1);
1234  txVector1.SetMode (HePhy::GetHeMcs7 (), rxStaId1);
1235  txVector1.SetNss (1, rxStaId1);
1236 
1237  Ptr<Packet> pkt1 = Create<Packet> (1000);
1238  WifiMacHeader hdr1;
1239  hdr1.SetType (WIFI_MAC_QOSDATA);
1240  hdr1.SetQosTid (0);
1241  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
1242  hdr1.SetSequenceNumber (1);
1243  Ptr<WifiPsdu> psdu1 = Create<WifiPsdu> (pkt1, hdr1);
1244  psdus1.insert (std::make_pair (rxStaId1, psdu1));
1245 
1246  uint16_t rxStaId2 = 2;
1247  HeRu::RuSpec ru2 (HeRu::RU_106_TONE, 2, false);
1248  txVector2.SetRu (ru2, rxStaId2);
1249  txVector2.SetMode (HePhy::GetHeMcs9 (), rxStaId2);
1250  txVector2.SetNss (1, rxStaId2);
1251 
1252  Ptr<Packet> pkt2 = Create<Packet> (1500);
1253  WifiMacHeader hdr2;
1254  hdr2.SetType (WIFI_MAC_QOSDATA);
1255  hdr2.SetQosTid (0);
1256  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
1257  hdr2.SetSequenceNumber (2);
1258  Ptr<WifiPsdu> psdu2 = Create<WifiPsdu> (pkt2, hdr2);
1259  psdus2.insert (std::make_pair (rxStaId2, psdu2));
1260 
1261  Time txDuration1 = m_phySta1->CalculateTxDuration (psdu1->GetSize (), txVector1,
1262  m_phySta1->GetPhyBand (), rxStaId1);
1263  Time txDuration2 = m_phySta2->CalculateTxDuration (psdu2->GetSize (), txVector2,
1264  m_phySta1->GetPhyBand (), rxStaId2);
1265  Time txDuration = std::max (txDuration1, txDuration2);
1266 
1267  txVector1.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, txVector1, m_phySta1->GetPhyBand ()).first);
1268  txVector2.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, txVector2, m_phySta2->GetPhyBand ()).first);
1269 
1270  m_phySta1->Send (psdus1, txVector1);
1271  m_phySta2->Send (psdus2, txVector2);
1272 }
1273 
1274 void
1276 {
1277  WifiConstPsduMap psdus;
1278  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false);
1279 
1280  Ptr<Packet> pkt = Create<Packet> (1000);
1281  WifiMacHeader hdr;
1282  hdr.SetType (WIFI_MAC_QOSDATA);
1283  hdr.SetQosTid (0);
1284  hdr.SetAddr1 (Mac48Address::GetBroadcast ());
1285  hdr.SetSequenceNumber (1);
1286  Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
1287  psdus.insert (std::make_pair (SU_STA_ID, psdu));
1288 
1289  switch (txStaId)
1290  {
1291  case 0:
1292  m_phyAp->Send (psdus, txVector);
1293  break;
1294  case 1:
1295  m_phySta1->Send (psdus, txVector);
1296  break;
1297  case 2:
1298  m_phySta2->Send (psdus, txVector);
1299  break;
1300  default:
1301  NS_ABORT_MSG ("Unexpected STA-ID");
1302  }
1303 }
1304 
1305 void
1307 {
1308  RngSeedManager::SetSeed (1);
1309  RngSeedManager::SetRun (1);
1310  int64_t streamNumber = 0;
1311  m_phyAp->AssignStreams (streamNumber);
1312  m_phySta1->AssignStreams (streamNumber);
1313  m_phySta2->AssignStreams (streamNumber);
1314 
1315  //Reset PPDU UID so as not to be dependent on previously executed test cases,
1316  //since global attribute will be changed).
1317  ResetPpduUid ();
1318 
1319  //Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
1320  //PPDU UID should be equal to 0 (the first counter value).
1321  Simulator::Schedule (Seconds (1.0), &TestUlOfdmaPpduUid::SendMuPpdu, this);
1322  Simulator::Schedule (Seconds (1.0), &TestUlOfdmaPpduUid::CheckUid, this, 0, 0);
1323 
1324  //Send HE SU PPDU from AP.
1325  //PPDU UID should be incremented since this is a new PPDU.
1326  Simulator::Schedule (Seconds (1.1), &TestUlOfdmaPpduUid::SendSuPpdu, this, 0);
1327  Simulator::Schedule (Seconds (1.1), &TestUlOfdmaPpduUid::CheckUid, this, 0, 1);
1328 
1329  //Send HE TB PPDU from STAs to AP.
1330  //PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
1331  //preceding correctly received PPDU (which normally contains the trigger frame).
1332  Simulator::Schedule (Seconds (1.15), &TestUlOfdmaPpduUid::SendTbPpdu, this);
1333  Simulator::Schedule (Seconds (1.15), &TestUlOfdmaPpduUid::CheckUid, this, 1, 1);
1334  Simulator::Schedule (Seconds (1.15), &TestUlOfdmaPpduUid::CheckUid, this, 2, 1);
1335 
1336  //Send HE SU PPDU from STA1.
1337  //PPDU UID should be incremented since this is a new PPDU.
1338  Simulator::Schedule (Seconds (1.2), &TestUlOfdmaPpduUid::SendSuPpdu, this, 1);
1339  Simulator::Schedule (Seconds (1.2), &TestUlOfdmaPpduUid::CheckUid, this, 1, 2);
1340 
1341  Simulator::Run ();
1342  Simulator::Destroy ();
1343 }
1344 
1352 {
1353 public:
1355  virtual ~TestMultipleHeTbPreambles ();
1356 
1357 private:
1358  void DoSetup (void) override;
1359  void DoTeardown (void) override;
1360  void DoRun (void) override;
1361 
1370  void RxHeTbPpdu (uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize);
1371 
1386 
1393 
1397  void Reset (void);
1398 
1404  void CheckHeTbPreambles (size_t nEvents, std::vector <uint64_t> uids);
1405 
1410  void CheckBytesDropped (size_t expectedBytesDropped);
1411 
1413 
1416 };
1417 
1419  : TestCase ("UL-OFDMA multiple RX events test"),
1420  m_totalBytesDropped (0),
1421  m_trigVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false)
1422 {
1423 }
1424 
1426 {
1427 }
1428 
1429 void
1431 {
1432  NS_LOG_FUNCTION (this);
1433  m_totalBytesDropped = 0;
1434  //We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
1435  m_phy->Reset ();
1436  m_trigVector.GetHeMuUserInfoMap ().clear ();
1437 }
1438 
1439 void
1441 {
1442  NS_LOG_FUNCTION (this << p << reason);
1443  m_totalBytesDropped += (p->GetSize () - 30);
1444 }
1445 
1446 void
1447 TestMultipleHeTbPreambles::CheckHeTbPreambles (size_t nEvents, std::vector <uint64_t> uids)
1448 {
1449  auto events = m_phy->GetCurrentPreambleEvents ();
1450  NS_TEST_ASSERT_MSG_EQ (events.size (), nEvents, "The number of UL MU events is not correct!");
1451  for (auto const& uid : uids)
1452  {
1453  auto pair = std::make_pair (uid, WIFI_PREAMBLE_HE_TB);
1454  auto it = events.find (pair);
1455  bool found = (it != events.end ());
1456  NS_TEST_ASSERT_MSG_EQ (found, true, "HE TB PPDU with UID " << uid << " has not been received!");
1457  }
1458 }
1459 
1460 void
1462 {
1463  NS_TEST_ASSERT_MSG_EQ (m_totalBytesDropped, expectedBytesDropped, "The number of dropped bytes is not correct!");
1464 }
1465 
1466 void
1467 TestMultipleHeTbPreambles::RxHeTbPpdu (uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize)
1468 {
1469  WifiConstPsduMap psdus;
1470  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false);
1471 
1472  HeRu::RuSpec ru (HeRu::RU_106_TONE, staId, false);
1474  txVector.SetRu (ru, staId);
1475  txVector.SetMode (HePhy::GetHeMcs7 (), staId);
1476  txVector.SetNss (1, staId);
1477 
1478  m_trigVector.GetHeMuUserInfoMap ().insert ({staId, HeMuUserInfo {ru, HePhy::GetHeMcs7 (), 1}});
1479 
1480  Ptr<Packet> pkt = Create<Packet> (payloadSize);
1481  WifiMacHeader hdr;
1482  hdr.SetType (WIFI_MAC_QOSDATA);
1483  hdr.SetQosTid (0);
1484  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
1485  hdr.SetSequenceNumber (1);
1486  Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
1487  psdus.insert (std::make_pair (staId, psdu));
1488 
1489  Time ppduDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand (), staId);
1490  Ptr<HePpdu> ppdu = Create<HePpdu> (psdus, txVector, ppduDuration, WIFI_PHY_BAND_5GHZ, uid,
1491  HePpdu::PSD_HE_TB_NON_OFDMA_PORTION, 0);
1492 
1493  //Send non-OFDMA part
1494  Time nonOfdmaDuration = m_phy->GetHePhy ()->CalculateNonOfdmaDurationForHeTb (txVector);
1495  uint32_t centerFrequency = m_phy->GetHePhy ()->GetCenterFrequencyForNonOfdmaPart (txVector, staId);
1496  uint16_t ruWidth = HeRu::GetBandwidth (txVector.GetRu (staId).GetRuType ());
1497  uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
1498  Ptr<SpectrumValue> rxPsd = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (centerFrequency, channelWidth, txPowerWatts, m_phy->GetGuardBandwidth (channelWidth));
1499  Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters> ();
1500  rxParams->psd = rxPsd;
1501  rxParams->txPhy = 0;
1502  rxParams->duration = nonOfdmaDuration;
1503  rxParams->ppdu = ppdu;
1504 
1505  uint16_t length;
1506  std::tie (length, ppduDuration) = HePhy::ConvertHeTbPpduDurationToLSigLength (ppduDuration, txVector, m_phy->GetPhyBand ());
1507  txVector.SetLength (length);
1508  m_trigVector.SetLength (length);
1509  auto hePhy = DynamicCast<HePhy> (m_phy->GetPhyEntity (WIFI_MOD_CLASS_HE));
1510  hePhy->SetTrigVector (m_trigVector, ppduDuration);
1511  m_phy->StartRx (rxParams);
1512 
1513  //Schedule OFDMA part
1514  Ptr<HePpdu> ppduOfdma = DynamicCast<HePpdu> (ppdu->Copy ()); //since flag will be modified
1515  ppduOfdma->SetTxPsdFlag (HePpdu::PSD_HE_TB_OFDMA_PORTION);
1516  WifiSpectrumBand band = m_phy->GetHePhy ()->GetRuBandForRx (txVector, staId);
1517  Ptr<SpectrumValue> rxPsdOfdma = WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity (DEFAULT_FREQUENCY, DEFAULT_CHANNEL_WIDTH, txPowerWatts, DEFAULT_GUARD_WIDTH, band);
1518  Ptr<WifiSpectrumSignalParameters> rxParamsOfdma = Create<WifiSpectrumSignalParameters> ();
1519  rxParamsOfdma->psd = rxPsd;
1520  rxParamsOfdma->txPhy = 0;
1521  rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
1522  rxParamsOfdma->ppdu = ppduOfdma;
1523  Simulator::Schedule (nonOfdmaDuration, &TestMultipleHeTbPreambles::RxHeTbPpduOfdmaPart, this, rxParamsOfdma);
1524 }
1525 
1526 void
1528 {
1529  Simulator::ScheduleNow (&TestMultipleHeTbPreambles::DoRxHeTbPpduOfdmaPart, this, rxParamsOfdma);
1530 }
1531 
1532 void
1534 {
1535  //This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should end at the exact same time as the start
1536  //For normal WifiNetDevices, this the reception of the OFDMA part is scheduled after end of HE-SIG-A decoding.
1537  m_phy->StartRx (rxParamsOfdma);
1538 }
1539 
1540 void
1542 {
1543  Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice> ();
1544  m_phy = CreateObject<OfdmaSpectrumWifiPhy> (0);
1546  Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper> ();
1547  Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
1548  Ptr<ApWifiMac> mac = CreateObject<ApWifiMac> ();
1549  mac->SetAttribute ("BeaconGeneration", BooleanValue (false));
1550  dev->SetMac (mac);
1551  m_phy->SetInterferenceHelper (interferenceHelper);
1552  m_phy->SetErrorRateModel (error);
1554  (int)(WIFI_PHY_BAND_5GHZ), 0});
1556  m_phy->SetDevice (dev);
1557  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel> ();
1558  preambleDetectionModel->SetAttribute ("Threshold", DoubleValue (4));
1559  preambleDetectionModel->SetAttribute ("MinimumRssi", DoubleValue (-82));
1560  m_phy->SetPreambleDetectionModel (preambleDetectionModel);
1561 }
1562 
1563 void
1565 {
1566  m_phy->Dispose ();
1567  m_phy = 0;
1568 }
1569 
1570 void
1572 {
1573  RngSeedManager::SetSeed (1);
1574  RngSeedManager::SetRun (1);
1575  int64_t streamNumber = 0;
1576  m_phy->AssignStreams (streamNumber);
1577 
1578  double txPowerWatts = 0.01;
1579 
1580  {
1581  //Verify a single UL MU transmission with two stations belonging to the same BSS
1582  std::vector<uint64_t> uids {0};
1583  Simulator::Schedule (Seconds (1), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1584  Simulator::Schedule (Seconds (1) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1585  //Check that we received a single UL MU transmission with the corresponding UID
1586  Simulator::Schedule (Seconds (1.0) + MicroSeconds (1), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 1, uids);
1587  Simulator::Schedule (Seconds (1.5), &TestMultipleHeTbPreambles::Reset, this);
1588  }
1589 
1590  {
1591  //Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where the second transmission
1592  //arrives during the preamble detection window and with half the power of the first transmission.
1593  std::vector<uint64_t> uids {1, 2};
1594  Simulator::Schedule (Seconds (2), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1595  Simulator::Schedule (Seconds (2) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1596  Simulator::Schedule (Seconds (2) + NanoSeconds (200), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 1, txPowerWatts / 2, 1003);
1597  Simulator::Schedule (Seconds (2) + NanoSeconds (300), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 2, txPowerWatts / 2, 1004);
1598  //Check that we received the correct reception of 2 UL MU transmissions with the corresponding UIDs
1599  Simulator::Schedule (Seconds (2.0) + MicroSeconds (1), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 2, uids);
1600  Simulator::Schedule (Seconds (2.5), &TestMultipleHeTbPreambles::Reset, this);
1601  //TODO: verify PPDUs from second UL MU transmission are dropped
1602  }
1603 
1604  {
1605  //Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where the second transmission
1606  //arrives during the preamble detection window and with twice the power of the first transmission.
1607  std::vector<uint64_t> uids {3, 4};
1608  Simulator::Schedule (Seconds (3), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts / 2, 1001);
1609  Simulator::Schedule (Seconds (3) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts / 2, 1002);
1610  Simulator::Schedule (Seconds (3) + NanoSeconds (200), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 1, txPowerWatts, 1003);
1611  Simulator::Schedule (Seconds (3) + NanoSeconds (300), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 2, txPowerWatts, 1004);
1612  //Check that we received the correct reception of 2 UL MU transmissions with the corresponding UIDs
1613  Simulator::Schedule (Seconds (3.0) + MicroSeconds (1), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 2, uids);
1614  Simulator::Schedule (Seconds (3.5), &TestMultipleHeTbPreambles::Reset, this);
1615  //TODO: verify PPDUs from first UL MU transmission are dropped
1616  }
1617 
1618  {
1619  //Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where the second transmission
1620  //arrives during PHY header reception and with the same power as the first transmission.
1621  std::vector<uint64_t> uids {5, 6};
1622  Simulator::Schedule (Seconds (4), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1623  Simulator::Schedule (Seconds (4) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1624  Simulator::Schedule (Seconds (4) + MicroSeconds (5), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 1, txPowerWatts, 1003);
1625  Simulator::Schedule (Seconds (4) + MicroSeconds (5) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 2, txPowerWatts, 1004);
1626  //Check that we received the correct reception of the first UL MU transmission with the corresponding UID (second one dropped)
1627  Simulator::Schedule (Seconds (4.0) + MicroSeconds (10), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 1, std::vector<uint64_t> {uids[0]});
1628  //The packets of the second UL MU transmission should have been dropped
1629  Simulator::Schedule (Seconds (4.0) + MicroSeconds (10), &TestMultipleHeTbPreambles::CheckBytesDropped, this, 1003 + 1004);
1630  Simulator::Schedule (Seconds (4.5), &TestMultipleHeTbPreambles::Reset, this);
1631  }
1632 
1633  {
1634  //Verify the correct reception of one UL MU transmission out of 2 with two stations per BSS, where the second transmission
1635  //arrives during payload reception and with the same power as the first transmission.
1636  std::vector<uint64_t> uids {7, 8};
1637  Simulator::Schedule (Seconds (5), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1638  Simulator::Schedule (Seconds (5) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1639  Simulator::Schedule (Seconds (5) + MicroSeconds (50), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 1, txPowerWatts, 1003);
1640  Simulator::Schedule (Seconds (5) + MicroSeconds (50) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 2, txPowerWatts, 1004);
1641  //Check that we received the correct reception of the first UL MU transmission with the corresponding UID (second one dropped)
1642  Simulator::Schedule (Seconds (5.0) + MicroSeconds (100), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 1, std::vector<uint64_t> {uids[0]});
1643  //The packets of the second UL MU transmission should have been dropped
1644  Simulator::Schedule (Seconds (5.0) + MicroSeconds (100), &TestMultipleHeTbPreambles::CheckBytesDropped, this, 1003 + 1004);
1645  Simulator::Schedule (Seconds (5.5), &TestMultipleHeTbPreambles::Reset, this);
1646  }
1647 
1648  {
1649  //Verify the correct reception of a single UL MU transmission with two stations belonging to the same BSS,
1650  //and the second PPDU arrives 500ns after the first PPDU
1651  std::vector<uint64_t> uids {9};
1652  Simulator::Schedule (Seconds (6), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1653  Simulator::Schedule (Seconds (6) + NanoSeconds (500), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1654  //Check that we received a single UL MU transmission with the corresponding UID
1655  Simulator::Schedule (Seconds (6.0) + MicroSeconds (1), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 1, uids);
1656  //No packet is dropped (we check after 5us to verify that PD is successful)
1657  Simulator::Schedule (Seconds (6.0) + MicroSeconds (5), &TestMultipleHeTbPreambles::CheckBytesDropped, this, 0);
1658  Simulator::Schedule (Seconds (6.5), &TestMultipleHeTbPreambles::Reset, this);
1659  }
1660 
1661  Simulator::Run ();
1662  Simulator::Destroy ();
1663 }
1664 
1672 {
1673 public:
1678  {
1679  NONE = 0,
1684  MCS
1685  };
1686 
1688  virtual ~TestUlOfdmaPhyTransmission ();
1689 
1690 private:
1691  void DoSetup (void) override;
1692  void DoTeardown (void) override;
1693  void DoRun (void) override;
1694 
1702  WifiTxVector GetTxVectorForHeTbPpdu (uint16_t txStaId, std::size_t index, uint8_t bssColor) const;
1709  void SetTrigVector (uint8_t bssColor, TrigVectorInfo error);
1718  void SendHeTbPpdu (uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
1719 
1727  void SendHeSuPpdu (uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
1728 
1734  void SetBssColor (Ptr<WifiPhy> phy, uint8_t bssColor);
1735 
1741  void SetPsdLimit (Ptr<WifiPhy> phy, double psdLimit);
1742 
1748  void GenerateInterference (Ptr<SpectrumValue> interferencePsd, Time duration);
1752  void StopInterference (void);
1753 
1757  void RunOne ();
1758 
1765  void CheckRxFromSta1 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes);
1766 
1773  void CheckRxFromSta2 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes);
1774 
1781  void CheckNonOfdmaRxPower (Ptr<OfdmaSpectrumWifiPhy> phy, WifiSpectrumBand band, double expectedRxPower);
1788  void CheckOfdmaRxPower (Ptr<OfdmaSpectrumWifiPhy> phy, WifiSpectrumBand band, double expectedRxPower);
1789 
1793  void VerifyEventsCleared (void);
1794 
1803 
1807  void Reset ();
1808 
1816  void RxSuccess (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector<bool> statusPerMpdu);
1817 
1822  void RxFailure (Ptr<WifiPsdu> psdu);
1823 
1841  void ScheduleTest (Time delay, bool solicited, WifiPhyState expectedStateAtEnd,
1842  uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1,
1843  uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2,
1844  bool scheduleTxSta1 = true, WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
1845  TrigVectorInfo error = NONE);
1846 
1856  void SchedulePowerMeasurementChecks (Time delay, double rxPowerNonOfdmaRu1, double rxPowerNonOfdmaRu2,
1857  double rxPowerOfdmaRu1, double rxPowerOfdmaRu2);
1863  void LogScenario (std::string log) const;
1864 
1869 
1871 
1878 
1879  uint16_t m_frequency;
1880  uint16_t m_channelWidth;
1882 };
1883 
1885  : TestCase ("UL-OFDMA PHY test"),
1886  m_countRxSuccessFromSta1 (0),
1887  m_countRxSuccessFromSta2 (0),
1888  m_countRxFailureFromSta1 (0),
1889  m_countRxFailureFromSta2 (0),
1890  m_countRxBytesFromSta1 (0),
1891  m_countRxBytesFromSta2 (0),
1892  m_frequency (DEFAULT_FREQUENCY),
1893  m_channelWidth (DEFAULT_CHANNEL_WIDTH),
1894  m_expectedPpduDuration (NanoSeconds (271200))
1895 {
1896 }
1897 
1898 void
1899 TestUlOfdmaPhyTransmission::SendHeSuPpdu (uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
1900 {
1901  NS_LOG_FUNCTION (this << txStaId << payloadSize << uid << +bssColor);
1902  WifiConstPsduMap psdus;
1903 
1904  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, m_channelWidth, false, false, false, bssColor);
1905 
1906  Ptr<Packet> pkt = Create<Packet> (payloadSize);
1907  WifiMacHeader hdr;
1908  hdr.SetType (WIFI_MAC_QOSDATA);
1909  hdr.SetQosTid (0);
1910  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
1911  std::ostringstream addr;
1912  addr << "00:00:00:00:00:0" << txStaId;
1913  hdr.SetAddr2 (Mac48Address (addr.str ().c_str ()));
1914  hdr.SetSequenceNumber (1);
1915  Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
1916  psdus.insert (std::make_pair (SU_STA_ID, psdu));
1917 
1919  if (txStaId == 1)
1920  {
1921  phy = m_phySta1;
1922  }
1923  else if (txStaId == 2)
1924  {
1925  phy = m_phySta2;
1926  }
1927  else if (txStaId == 3)
1928  {
1929  phy = m_phySta3;
1930  }
1931  else if (txStaId == 0)
1932  {
1933  phy = m_phyAp;
1934  }
1935  phy->SetPpduUid (uid);
1936  phy->Send (psdus, txVector);
1937 }
1938 
1940 TestUlOfdmaPhyTransmission::GetTxVectorForHeTbPpdu (uint16_t txStaId, std::size_t index, uint8_t bssColor) const
1941 {
1942  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, m_channelWidth, false, false, false, bssColor);
1943 
1944  HeRu::RuType ruType = HeRu::RU_106_TONE;
1945  if (m_channelWidth == 20)
1946  {
1947  ruType = HeRu::RU_106_TONE;
1948  }
1949  else if (m_channelWidth == 40)
1950  {
1951  ruType = HeRu::RU_242_TONE;
1952  }
1953  else if (m_channelWidth == 80)
1954  {
1955  ruType = HeRu::RU_484_TONE;
1956  }
1957  else if (m_channelWidth == 160)
1958  {
1959  ruType = HeRu::RU_996_TONE;
1960  }
1961  else
1962  {
1963  NS_ASSERT_MSG (false, "Unsupported channel width");
1964  }
1965 
1966  bool primary80MHz = true;
1967  if (m_channelWidth == 160 && index == 2)
1968  {
1969  primary80MHz = false;
1970  index = 1;
1971  }
1972  HeRu::RuSpec ru (ruType, index, primary80MHz);
1973  ru.SetPhyIndex (m_channelWidth, 0);
1974  txVector.SetRu (ru, txStaId);
1975  txVector.SetMode (HePhy::GetHeMcs7 (), txStaId);
1976  txVector.SetNss (1, txStaId);
1977  return txVector;
1978 }
1979 
1980 void
1982 {
1983  uint16_t channelWidth = m_channelWidth;
1984  if (error == CHANNEL_WIDTH)
1985  {
1986  channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
1987  }
1988 
1989  WifiTxVector txVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0,
1990  channelWidth, false, false, false, bssColor);
1991 
1992  HeRu::RuType ruType = HeRu::RU_106_TONE;
1993  if (channelWidth == 20)
1994  {
1995  ruType = (error == RU_TYPE ? HeRu::RU_52_TONE : HeRu::RU_106_TONE);
1996  }
1997  else if (channelWidth == 40)
1998  {
1999  ruType = (error == RU_TYPE ? HeRu::RU_106_TONE : HeRu::RU_242_TONE);
2000  }
2001  else if (channelWidth == 80)
2002  {
2003  ruType = (error == RU_TYPE ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
2004  }
2005  else if (channelWidth == 160)
2006  {
2007  ruType = (error == RU_TYPE ? HeRu::RU_484_TONE : HeRu::RU_996_TONE);
2008  }
2009  else
2010  {
2011  NS_ASSERT_MSG (false, "Unsupported channel width");
2012  }
2013 
2014  uint16_t aid1 = (error == AID ? 3 : 1);
2015  uint16_t aid2 = (error == AID ? 4 : 2);
2016 
2017  HeRu::RuSpec ru1 (ruType, 1, true);
2018  ru1.SetPhyIndex (channelWidth, 0);
2019  txVector.SetRu (ru1, aid1);
2020  txVector.SetMode ((error == MCS ? HePhy::GetHeMcs5 () : HePhy::GetHeMcs7 ()), aid1);
2021  txVector.SetNss (1, aid1);
2022 
2023  HeRu::RuSpec ru2 (ruType, (channelWidth == 160 ? 1 : 2),
2024  (channelWidth == 160 ? false : true));
2025  ru2.SetPhyIndex (channelWidth, 0);
2026  txVector.SetRu (ru2, aid2);
2027  txVector.SetMode ((error == MCS ? HePhy::GetHeMcs5 () : HePhy::GetHeMcs7 ()), aid2);
2028  txVector.SetNss (1, aid2);
2029 
2030  uint16_t length;
2031  std::tie (length, m_expectedPpduDuration) = HePhy::ConvertHeTbPpduDurationToLSigLength (m_expectedPpduDuration,
2032  txVector,
2033  m_phyAp->GetPhyBand ());
2034  if (error == UL_LENGTH)
2035  {
2036  ++length;
2037  }
2038  txVector.SetLength (length);
2039  auto hePhyAp = DynamicCast<HePhy> (m_phyAp->GetPhyEntity (WIFI_MOD_CLASS_HE));
2040  hePhyAp->SetTrigVector (txVector, m_expectedPpduDuration);
2041 }
2042 
2043 void
2044 TestUlOfdmaPhyTransmission::SendHeTbPpdu (uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
2045 {
2046  NS_LOG_FUNCTION (this << txStaId << index << payloadSize << uid << +bssColor);
2047  WifiConstPsduMap psdus;
2048 
2049  WifiTxVector txVector = GetTxVectorForHeTbPpdu (txStaId, index, bssColor);
2050  Ptr<Packet> pkt = Create<Packet> (payloadSize);
2051  WifiMacHeader hdr;
2052  hdr.SetType (WIFI_MAC_QOSDATA);
2053  hdr.SetQosTid (0);
2054  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
2055  std::ostringstream addr;
2056  addr << "00:00:00:00:00:0" << txStaId;
2057  hdr.SetAddr2 (Mac48Address (addr.str ().c_str ()));
2058  hdr.SetSequenceNumber (1);
2059  Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
2060  psdus.insert (std::make_pair (txStaId, psdu));
2061 
2063  if (txStaId == 1)
2064  {
2065  phy = m_phySta1;
2066  }
2067  else if (txStaId == 2)
2068  {
2069  phy = m_phySta2;
2070  }
2071  else if (txStaId == 3)
2072  {
2073  phy = m_phySta3;
2074  }
2075 
2076  Time txDuration = phy->CalculateTxDuration (psdu->GetSize (), txVector, phy->GetPhyBand (), txStaId);
2077  txVector.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, txVector, phy->GetPhyBand ()).first);
2078 
2079  phy->SetPpduUid (uid);
2080  phy->Send (psdus, txVector);
2081 }
2082 
2083 void
2085 {
2086  NS_LOG_FUNCTION (this << duration);
2087  m_phyInterferer->SetTxPowerSpectralDensity (interferencePsd);
2088  m_phyInterferer->SetPeriod (duration);
2089  m_phyInterferer->Start ();
2090  Simulator::Schedule (duration, &TestUlOfdmaPhyTransmission::StopInterference, this);
2091 }
2092 
2093 void
2095 {
2096  m_phyInterferer->Stop();
2097 }
2098 
2100 {
2101 }
2102 
2103 void
2104 TestUlOfdmaPhyTransmission::RxSuccess (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
2105 {
2106  NS_LOG_FUNCTION (this << *psdu << psdu->GetAddr2 () << rxSignalInfo << txVector);
2107  if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:01"))
2108  {
2110  m_countRxBytesFromSta1 += (psdu->GetSize () - 30);
2111  }
2112  else if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:02"))
2113  {
2115  m_countRxBytesFromSta2 += (psdu->GetSize () - 30);
2116  }
2117 }
2118 
2119 void
2121 {
2122  NS_LOG_FUNCTION (this << *psdu << psdu->GetAddr2 ());
2123  if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:01"))
2124  {
2126  }
2127  else if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:02"))
2128  {
2130  }
2131 }
2132 
2133 void
2134 TestUlOfdmaPhyTransmission::CheckRxFromSta1 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
2135 {
2136  NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessFromSta1, expectedSuccess, "The number of successfully received packets from STA 1 is not correct!");
2137  NS_TEST_ASSERT_MSG_EQ (m_countRxFailureFromSta1, expectedFailures, "The number of unsuccessfully received packets from STA 1 is not correct!");
2138  NS_TEST_ASSERT_MSG_EQ (m_countRxBytesFromSta1, expectedBytes, "The number of bytes received from STA 1 is not correct!");
2139 }
2140 
2141 void
2142 TestUlOfdmaPhyTransmission::CheckRxFromSta2 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
2143 {
2144  NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessFromSta2, expectedSuccess, "The number of successfully received packets from STA 2 is not correct!");
2145  NS_TEST_ASSERT_MSG_EQ (m_countRxFailureFromSta2, expectedFailures, "The number of unsuccessfully received packets from STA 2 is not correct!");
2146  NS_TEST_ASSERT_MSG_EQ (m_countRxBytesFromSta2, expectedBytes, "The number of bytes received from STA 2 is not correct!");
2147 }
2148 
2149 void
2151 {
2152  Ptr<Event> event = phy->GetCurrentEvent ();
2153  NS_ASSERT (event);
2154  double rxPower = event->GetRxPowerW (band);
2155  NS_LOG_FUNCTION (this << band.first << band.second << expectedRxPower << rxPower);
2156  //Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
2157  NS_TEST_ASSERT_MSG_EQ_TOL (rxPower, expectedRxPower, 5e-3, "RX power " << rxPower << " over (" << band.first << ", " << band.second << ") does not match expected power " << expectedRxPower << " at " << Simulator::Now ());
2158 }
2159 
2160 void
2162 {
2168  NS_LOG_FUNCTION (this << band.first << band.second << expectedRxPower);
2169  double step = 5e-3;
2170  if (expectedRxPower > 0.0)
2171  {
2172  NS_TEST_ASSERT_MSG_EQ (phy->GetEnergyDuration (expectedRxPower - step, band).IsStrictlyPositive (), true,
2173  "At least " << expectedRxPower << " W expected for OFDMA part over (" << band.first << ", " << band.second << ") at " << Simulator::Now ());
2174  NS_TEST_ASSERT_MSG_EQ (phy->GetEnergyDuration (expectedRxPower + step, band).IsStrictlyPositive (), false,
2175  "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first << ", " << band.second << ") at " << Simulator::Now ());
2176  }
2177  else
2178  {
2179  NS_TEST_ASSERT_MSG_EQ (phy->GetEnergyDuration (expectedRxPower + step, band).IsStrictlyPositive (), false,
2180  "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first << ", " << band.second << ") at " << Simulator::Now ());
2181  }
2182 }
2183 
2184 void
2186 {
2187  NS_TEST_ASSERT_MSG_EQ (m_phyAp->GetCurrentEvent (), 0, "m_currentEvent for AP was not cleared");
2188  NS_TEST_ASSERT_MSG_EQ (m_phySta1->GetCurrentEvent (), 0, "m_currentEvent for STA 1 was not cleared");
2189  NS_TEST_ASSERT_MSG_EQ (m_phySta2->GetCurrentEvent (), 0, "m_currentEvent for STA 2 was not cleared");
2190 }
2191 
2192 void
2194 {
2195  //This is needed to make sure PHY state will be checked as the last event if a state change occurred at the exact same time as the check
2196  Simulator::ScheduleNow (&TestUlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
2197 }
2198 
2199 void
2201 {
2202  WifiPhyState currentState;
2203  PointerValue ptr;
2204  phy->GetAttribute ("State", ptr);
2205  Ptr <WifiPhyStateHelper> state = DynamicCast <WifiPhyStateHelper> (ptr.Get<WifiPhyStateHelper> ());
2206  currentState = state->GetState ();
2207  NS_LOG_FUNCTION (this << currentState);
2208  NS_TEST_ASSERT_MSG_EQ (currentState, expectedState, "PHY State " << currentState << " does not match expected state " << expectedState << " at " << Simulator::Now ());
2209 }
2210 
2211 void
2213 {
2220  m_phySta1->SetPpduUid (0);
2223  SetBssColor (m_phyAp, 0);
2224 }
2225 
2226 void
2228 {
2229  Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (phy->GetDevice ());
2230  Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration ();
2231  heConfiguration->SetAttribute ("BssColor", UintegerValue (bssColor));
2232 }
2233 
2234 void
2236 {
2237  NS_LOG_FUNCTION (this << phy << psdLimit);
2238  phy->SetAttribute ("PowerDensityLimit", DoubleValue (psdLimit));
2239 }
2240 
2241 void
2243 {
2244  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
2245  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
2246  lossModel->SetFrequency (m_frequency);
2247  spectrumChannel->AddPropagationLossModel (lossModel);
2248  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
2249  spectrumChannel->SetPropagationDelayModel (delayModel);
2250 
2251  Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel> ();
2252  preambleDetectionModel->SetAttribute ("MinimumRssi", DoubleValue (-8)); //to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
2253  preambleDetectionModel->SetAttribute ("Threshold", DoubleValue (-100)); //no limit on SNR
2254 
2255  Ptr<Node> apNode = CreateObject<Node> ();
2256  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice> ();
2258  Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac> ();
2259  apMac->SetAttribute ("BeaconGeneration", BooleanValue (false));
2260  apDev->SetMac (apMac);
2261  m_phyAp = CreateObject<OfdmaSpectrumWifiPhy> (0);
2264  Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration> ();
2265  apDev->SetHeConfiguration (heConfiguration);
2266  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper> ();
2267  m_phyAp->SetInterferenceHelper (apInterferenceHelper);
2268  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel> ();
2269  m_phyAp->SetErrorRateModel (apErrorModel);
2270  m_phyAp->SetDevice (apDev);
2271  m_phyAp->SetChannel (spectrumChannel);
2274  m_phyAp->SetPreambleDetectionModel (preambleDetectionModel);
2275  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel> ();
2276  m_phyAp->SetMobility (apMobility);
2277  apDev->SetPhy (m_phyAp);
2278  apNode->AggregateObject (apMobility);
2279  apNode->AddDevice (apDev);
2280 
2281  Ptr<Node> sta1Node = CreateObject<Node> ();
2282  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice> ();
2283  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy> (1);
2286  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper> ();
2287  m_phySta1->SetInterferenceHelper (sta1InterferenceHelper);
2288  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel> ();
2289  m_phySta1->SetErrorRateModel (sta1ErrorModel);
2290  m_phySta1->SetDevice (sta1Dev);
2291  m_phySta1->SetChannel (spectrumChannel);
2292  m_phySta1->SetPreambleDetectionModel (preambleDetectionModel);
2293  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel> ();
2294  m_phySta1->SetMobility (sta1Mobility);
2295  sta1Dev->SetPhy (m_phySta1);
2296  sta1Node->AggregateObject (sta1Mobility);
2297  sta1Node->AddDevice (sta1Dev);
2298 
2299  Ptr<Node> sta2Node = CreateObject<Node> ();
2300  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice> ();
2301  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy> (2);
2304  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper> ();
2305  m_phySta2->SetInterferenceHelper (sta2InterferenceHelper);
2306  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel> ();
2307  m_phySta2->SetErrorRateModel (sta2ErrorModel);
2308  m_phySta2->SetDevice (sta2Dev);
2309  m_phySta2->SetChannel (spectrumChannel);
2310  m_phySta2->SetPreambleDetectionModel (preambleDetectionModel);
2311  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel> ();
2312  m_phySta2->SetMobility (sta2Mobility);
2313  sta2Dev->SetPhy (m_phySta2);
2314  sta2Node->AggregateObject (sta2Mobility);
2315  sta2Node->AddDevice (sta2Dev);
2316 
2317  Ptr<Node> sta3Node = CreateObject<Node> ();
2318  Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice> ();
2319  m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy> (3);
2322  Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper> ();
2323  m_phySta3->SetInterferenceHelper (sta3InterferenceHelper);
2324  Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel> ();
2325  m_phySta3->SetErrorRateModel (sta3ErrorModel);
2326  m_phySta3->SetDevice (sta3Dev);
2327  m_phySta3->SetChannel (spectrumChannel);
2328  m_phySta3->SetPreambleDetectionModel (preambleDetectionModel);
2329  Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel> ();
2330  m_phySta3->SetMobility (sta3Mobility);
2331  sta3Dev->SetPhy (m_phySta3);
2332  sta3Node->AggregateObject (sta3Mobility);
2333  sta3Node->AddDevice (sta3Dev);
2334 
2335  Ptr<Node> interfererNode = CreateObject<Node> ();
2336  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice> ();
2337  m_phyInterferer = CreateObject<WaveformGenerator> ();
2338  m_phyInterferer->SetDevice (interfererDev);
2339  m_phyInterferer->SetChannel (spectrumChannel);
2341  interfererNode->AddDevice (interfererDev);
2342 
2343  //Configure power attributes of all wifi devices
2344  std::list<Ptr<WifiPhy>> phys {m_phyAp, m_phySta1, m_phySta2, m_phySta3};
2345  for (auto & phy : phys)
2346  {
2347  phy->SetAttribute ("TxGain", DoubleValue (1.0));
2348  phy->SetAttribute ("TxPowerStart", DoubleValue (16.0));
2349  phy->SetAttribute ("TxPowerEnd", DoubleValue (16.0));
2350  phy->SetAttribute ("PowerDensityLimit", DoubleValue (100.0)); //no impact by default
2351  phy->SetAttribute ("RxGain", DoubleValue (2.0));
2352  }
2353 }
2354 
2355 void
2357 {
2358  m_phyAp->Dispose ();
2359  m_phyAp = 0;
2360  m_phySta1->Dispose ();
2361  m_phySta1 = 0;
2362  m_phySta2->Dispose ();
2363  m_phySta2 = 0;
2364  m_phySta3->Dispose ();
2365  m_phySta3 = 0;
2367  m_phyInterferer = 0;
2368 }
2369 
2370 void
2372 {
2373  NS_LOG_INFO (log);
2374 }
2375 
2376 void
2377 TestUlOfdmaPhyTransmission::ScheduleTest (Time delay, bool solicited, WifiPhyState expectedStateAtEnd,
2378  uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1,
2379  uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2,
2380  bool scheduleTxSta1, WifiPhyState expectedStateBeforeEnd,
2381  TrigVectorInfo error)
2382 {
2383  static uint64_t uid = 0;
2384 
2385  //AP sends an SU packet preceding HE TB PPDUs
2386  Simulator::Schedule (delay - MilliSeconds (10), &TestUlOfdmaPhyTransmission::SendHeSuPpdu, this, 0, 50, ++uid, 0);
2387  if (!solicited)
2388  {
2389  // UID of TB PPDUs will be different than the one of the preceding frame
2390  ++uid;
2391  }
2392  else
2393  {
2394  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::SetTrigVector, this, 0, error);
2395  }
2396  //STA1 and STA2 send MU UL PPDUs addressed to AP
2397  if (scheduleTxSta1)
2398  {
2399  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 1, 1, 1000, uid, 0);
2400  }
2401  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 2, 2, 1001, uid, 0);
2402 
2403  //Verify it takes m_expectedPpduDuration to transmit the PPDUs
2404  Simulator::Schedule (delay + m_expectedPpduDuration - NanoSeconds (1), &TestUlOfdmaPhyTransmission::CheckPhyState, this, m_phyAp, expectedStateBeforeEnd);
2405  Simulator::Schedule (delay + m_expectedPpduDuration, &TestUlOfdmaPhyTransmission::CheckPhyState, this, m_phyAp, expectedStateAtEnd);
2406  //TODO: add checks on TX stop for STAs
2407 
2408  delay += MilliSeconds (100);
2409  //Check reception state from STA 1
2410  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::CheckRxFromSta1, this,
2411  expectedSuccessFromSta1, expectedFailuresFromSta1, expectedBytesFromSta1);
2412  //Check reception state from STA 2
2413  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::CheckRxFromSta2, this,
2414  expectedSuccessFromSta2, expectedFailuresFromSta2, expectedBytesFromSta2);
2415  //Verify events data have been cleared
2416  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::VerifyEventsCleared, this);
2417 
2418  delay += MilliSeconds (100);
2419  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::Reset, this);
2420 }
2421 
2422 void
2423 TestUlOfdmaPhyTransmission::SchedulePowerMeasurementChecks (Time delay, double rxPowerNonOfdmaRu1, double rxPowerNonOfdmaRu2,
2424  double rxPowerOfdmaRu1, double rxPowerOfdmaRu2)
2425 {
2426  Time detectionDuration = WifiPhy::GetPreambleDetectionDuration ();
2427  WifiTxVector txVectorSta1 = GetTxVectorForHeTbPpdu (1, 1, 0);
2428  WifiTxVector txVectorSta2 = GetTxVectorForHeTbPpdu (2, 2, 0);
2429  Ptr<const HePhy> hePhy = m_phyAp->GetHePhy ();
2430  Time nonOfdmaDuration = hePhy->CalculateNonOfdmaDurationForHeTb (txVectorSta2);
2431  NS_ASSERT (nonOfdmaDuration == hePhy->CalculateNonOfdmaDurationForHeTb (txVectorSta1));
2432 
2433  std::vector<double> rxPowerNonOfdma { rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2 };
2434  std::vector<WifiSpectrumBand> nonOfdmaBand { hePhy->GetNonOfdmaBand (txVectorSta1, 1), hePhy->GetNonOfdmaBand (txVectorSta2, 2) };
2435  std::vector<double> rxPowerOfdma { rxPowerOfdmaRu1, rxPowerOfdmaRu2 };
2436  std::vector<WifiSpectrumBand> ofdmaBand { hePhy->GetRuBandForRx (txVectorSta1, 1), hePhy->GetRuBandForRx (txVectorSta2, 2) };
2437 
2438  for (uint8_t i = 0; i < 2; ++i)
2439  {
2443  //Check received power on non-OFDMA portion
2444  Simulator::Schedule (delay + detectionDuration + NanoSeconds (1), //just after beginning of portion (once event is stored)
2446  nonOfdmaBand[i], rxPowerNonOfdma[i]);
2447  Simulator::Schedule (delay + nonOfdmaDuration - NanoSeconds (1), //just before end of portion
2449  nonOfdmaBand[i], rxPowerNonOfdma[i]);
2450  //Check received power on OFDMA portion
2451  Simulator::Schedule (delay + nonOfdmaDuration + NanoSeconds (1), //just after beginning of portion
2453  ofdmaBand[i], rxPowerOfdma[i]);
2454  Simulator::Schedule (delay + m_expectedPpduDuration - NanoSeconds (1), //just before end of portion
2456  ofdmaBand[i], rxPowerOfdma[i]);
2457 
2463  //Check received power on non-OFDMA portion
2464  Simulator::Schedule (delay + detectionDuration + NanoSeconds (1), //just after beginning of portion (once event is stored)
2466  nonOfdmaBand[i], rxPowerNonOfdma[i]);
2467  Simulator::Schedule (delay + nonOfdmaDuration - NanoSeconds (1), //just before end of portion
2469  nonOfdmaBand[i], rxPowerNonOfdma[i]);
2470  //Check received power on OFDMA portion
2471  Simulator::Schedule (delay + nonOfdmaDuration + NanoSeconds (1), //just after beginning of portion
2473  ofdmaBand[i], rxPowerOfdma[i]);
2474  Simulator::Schedule (delay + m_expectedPpduDuration - NanoSeconds (1), //just before end of portion
2476  ofdmaBand[i], rxPowerOfdma[i]);
2477  }
2478 
2479  if (rxPowerOfdmaRu1 != 0.0)
2480  {
2486  double rxPowerNonOfdmaSta1Only = (m_channelWidth >= 40) ? rxPowerNonOfdma[0] : rxPowerNonOfdma[0] / 2; //both STAs transmit over the same 20 MHz channel
2487  //Check received power on non-OFDMA portion
2488  Simulator::Schedule (delay + detectionDuration + NanoSeconds (1), //just after beginning of portion (once event is stored)
2490  nonOfdmaBand[0], rxPowerNonOfdmaSta1Only);
2491  Simulator::Schedule (delay + nonOfdmaDuration - NanoSeconds (1), //just before end of portion
2493  nonOfdmaBand[0], rxPowerNonOfdmaSta1Only);
2494  //Check received power on OFDMA portion
2495  Simulator::Schedule (delay + nonOfdmaDuration + NanoSeconds (1), //just after beginning of portion
2497  ofdmaBand[0], rxPowerOfdma[0]);
2498  Simulator::Schedule (delay + m_expectedPpduDuration - NanoSeconds (1), //just before end of portion
2500  ofdmaBand[0], rxPowerOfdma[0]);
2501  }
2502 }
2503 
2504 void
2506 {
2507  RngSeedManager::SetSeed (1);
2508  RngSeedManager::SetRun (1);
2509  int64_t streamNumber = 0;
2510  m_phyAp->AssignStreams (streamNumber);
2511  m_phySta1->AssignStreams (streamNumber);
2512  m_phySta2->AssignStreams (streamNumber);
2513  m_phySta3->AssignStreams (streamNumber);
2514 
2515  auto channelNum = std::get<0> (*WifiPhyOperatingChannel::FindFirst (0, m_frequency, m_channelWidth,
2518 
2520  (int)(WIFI_PHY_BAND_5GHZ), 0});
2522  (int)(WIFI_PHY_BAND_5GHZ), 0});
2524  (int)(WIFI_PHY_BAND_5GHZ), 0});
2526  (int)(WIFI_PHY_BAND_5GHZ), 0});
2527 
2528  Time delay = Seconds (0.0);
2529  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::Reset, this);
2530  delay += Seconds (1.0);
2531 
2540  //---------------------------------------------------------------------------
2541  //Verify that both solicited HE TB PPDUs have been corrected received
2542  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2543  "Reception of solicited HE TB PPDUs");
2544  ScheduleTest (delay, true,
2546  1, 0, 1000, //One PSDU of 1000 bytes should have been successfully received from STA 1
2547  1, 0, 1001); //One PSDU of 1001 bytes should have been successfully received from STA 2
2548  delay += Seconds (1.0);
2549 
2550  //---------------------------------------------------------------------------
2551  //Verify that no unsolicited HE TB PPDU is received
2552  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2553  "Dropping of unsolicited HE TB PPDUs");
2554  ScheduleTest (delay, false,
2556  0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2557  0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2558  true, WifiPhyState::CCA_BUSY);
2559  delay += Seconds (1.0);
2560 
2561  //---------------------------------------------------------------------------
2562  //Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
2563  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2564  "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
2565  ScheduleTest (delay, true,
2567  0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2568  0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2570  delay += Seconds (1.0);
2571 
2572  //---------------------------------------------------------------------------
2573  //Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
2574  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2575  "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
2576  ScheduleTest (delay, true,
2578  0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2579  0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2581  delay += Seconds (1.0);
2582 
2583  //---------------------------------------------------------------------------
2584  //Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
2585  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2586  "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
2587  ScheduleTest (delay, true,
2589  0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2590  0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2591  true, WifiPhyState::CCA_BUSY, AID);
2592  delay += Seconds (1.0);
2593 
2594  //---------------------------------------------------------------------------
2595  //Verify that HE TB PPDUs with RU type differing from TRIGVECTOR are discarded
2596  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2597  "Dropping of HE TB PPDUs with RU type differing from TRIGVECTOR");
2598  ScheduleTest (delay, true,
2600  0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2601  0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2603  delay += Seconds (1.0);
2604 
2605  //---------------------------------------------------------------------------
2606  //Verify that HE TB PPDUs with MCS differing from TRIGVECTOR are discarded
2607  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2608  "Dropping of HE TB PPDUs with MCS differing from TRIGVECTOR");
2609  ScheduleTest (delay, true,
2611  0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2612  0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2613  true, WifiPhyState::CCA_BUSY, MCS);
2614  delay += Seconds (1.0);
2615 
2616  //---------------------------------------------------------------------------
2617  //Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been impacted
2618  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2619  "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
2620  //A strong non-wifi interference is generated on RU 1 during PSDU reception
2621  BandInfo bandInfo;
2622  bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
2623  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
2624  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
2625  Bands bands;
2626  bands.push_back (bandInfo);
2627 
2628  Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel> (bands);
2629  Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue> (SpectrumInterferenceRu1);
2630  double interferencePower = 0.1; //watts
2631  *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
2632 
2633  Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdRu1, MilliSeconds (100));
2634  ScheduleTest (delay, true,
2635  WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY instead of IDLE due to the interference
2636  0, 1, 0, //Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
2637  1, 0, 1001); //One PSDU of 1001 bytes should have been successfully received from STA 2
2638  delay += Seconds (1.0);
2639 
2640  //---------------------------------------------------------------------------
2641  //Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been impacted
2642  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2643  "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
2644  //A strong non-wifi interference is generated on RU 2 during PSDU reception
2645  bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
2646  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
2647  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
2648  bands.clear ();
2649  bands.push_back (bandInfo);
2650 
2651  Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel> (bands);
2652  Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue> (SpectrumInterferenceRu2);
2653  *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
2654 
2655  Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdRu2, MilliSeconds (100));
2656  ScheduleTest (delay, true,
2657  WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY since measurement channel encompasses total channel width
2658  1, 0, 1000, //One PSDU of 1000 bytes should have been successfully received from STA 1
2659  0, 1, 0); //Reception of the PSDU from STA 2 should have failed (since interference occupies RU 2)
2660  delay += Seconds (1.0);
2661 
2662  //---------------------------------------------------------------------------
2663  //Generate an interference on the full band and verify that both solicited HE TB PPDUs have been impacted
2664  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2665  "Reception of solicited HE TB PPDUs with interference on the full band during PSDU reception");
2666  //A strong non-wifi interference is generated on the full band during PSDU reception
2667  bandInfo.fc = m_frequency * 1e6;
2668  bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
2669  bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
2670  bands.clear ();
2671  bands.push_back (bandInfo);
2672 
2673  Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel> (bands);
2674  Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue> (SpectrumInterferenceAll);
2675  *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
2676 
2677  Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdAll, MilliSeconds (100));
2678  ScheduleTest (delay, true,
2679  WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY instead of IDLE due to the interference
2680  0, 1, 0, //Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
2681  0, 1, 0); //Reception of the PSDU from STA 2 should have failed (since interference occupies RU 2)
2682  delay += Seconds (1.0);
2683 
2684  //---------------------------------------------------------------------------
2685  //Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both solicited HE TB PPDUs have been impacted if they are on the same
2686  // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
2687  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2688  "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU 1 during PSDU reception");
2689  //Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
2690  Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 3, 1, 1002, 1, 0);
2691  //Expected figures from STA 2
2692  uint32_t succ, fail, bytes;
2693  if (m_channelWidth > 20)
2694  {
2695  //One PSDU of 1001 bytes should have been successfully received from STA 2 (since interference from STA 3 on distinct 20 MHz channel)
2696  succ = 1;
2697  fail = 0;
2698  bytes = 1001;
2699  }
2700  else
2701  {
2702  //Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on same 20 MHz channel)
2703  succ = 0;
2704  fail = 1;
2705  bytes = 0;
2706  }
2707  ScheduleTest (delay, true,
2708  WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY instead of IDLE due to the interference on measurement channel width
2709  0, 1, 0, //Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on same 20 MHz channel)
2710  succ, fail, bytes);
2711  delay += Seconds (1.0);
2712 
2713  //---------------------------------------------------------------------------
2714  //Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both solicited HE TB PPDUs have been impacted if they are on the same
2715  // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
2716  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2717  "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU 2 during PSDU reception");
2718  //Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
2719  Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 3, 2, 1002, 1, 0);
2720  //Expected figures from STA 1
2721  if (m_channelWidth > 20)
2722  {
2723  //One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference from STA 3 on distinct 20 MHz channel)
2724  succ = 1;
2725  fail = 0;
2726  bytes = 1000;
2727  }
2728  else
2729  {
2730  //Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on same 20 MHz channel)
2731  succ = 0;
2732  fail = 1;
2733  bytes = 0;
2734  }
2735  ScheduleTest (delay, true,
2736  WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY instead of IDLE due to the interference on measurement channel width
2737  succ, fail, bytes,
2738  0, 1, 0); //Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on same 20 MHz channel)
2739  delay += Seconds (1.0);
2740 
2741  //---------------------------------------------------------------------------
2742  //Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been impacted
2743  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2744  "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
2745  //One HE SU arrives at AP during the 400ns window
2746  Simulator::Schedule (delay + NanoSeconds (300), &TestUlOfdmaPhyTransmission::SendHeSuPpdu, this, 3, 1002, 1, 0);
2747  ScheduleTest (delay, true,
2749  0, 1, 0, //Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
2750  0, 1, 0); //Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
2751  delay += Seconds (1.0);
2752 
2753  //---------------------------------------------------------------------------
2754  //Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly received
2755  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2756  "Reception of solicited HE TB PPDU only on RU 2");
2757  //Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE otherwise
2758  Simulator::Schedule (delay + m_expectedPpduDuration - NanoSeconds (1), &TestUlOfdmaPhyTransmission::CheckPhyState, this, m_phySta3,
2759  (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY); //PHY should move to CCA_BUSY instead of IDLE if HE TB PPDU on primary channel;
2760  ScheduleTest (delay, true,
2762  0, 0, 0, //No transmission scheduled for STA 1
2763  1, 0, 1001, //One PSDU of 1001 bytes should have been successfully received from STA 2
2764  false, WifiPhyState::RX); //Measurement channel is total channel width
2765  delay += Seconds (1.0);
2766 
2767  //---------------------------------------------------------------------------
2768  //Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
2769  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2770  "Measure power for reception of HE TB PPDU only on RU 2");
2771  double rxPower = DbmToW (19); //16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
2773  (m_channelWidth >= 40) ? 0.0 : rxPower, rxPower, //power detected on RU1 only if same 20 MHz as RU 2
2774  0.0, rxPower);
2775  ScheduleTest (delay, true,
2777  0, 0, 0, //No transmission scheduled for STA 1
2778  1, 0, 1001, //One PSDU of 1001 bytes should have been successfully received from STA 2
2779  false, WifiPhyState::RX); //Measurement channel is total channel width
2780  delay += Seconds (1.0);
2781 
2782  //---------------------------------------------------------------------------
2783  //Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density limitation enforced
2784  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2785  "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
2786  //Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz, 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
2787  Simulator::Schedule (delay - NanoSeconds (1), //just before sending HE TB
2789 
2790  rxPower = (m_channelWidth > 40) ? DbmToW (19) : DbmToW (18.0103); //15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA transmitted only on one 20 MHz channel
2791  double rxPowerOfdma = rxPower;
2792  if (m_channelWidth <= 40)
2793  {
2794  rxPowerOfdma = (m_channelWidth == 20) ? DbmToW (14.0309) //11.0309+1 dBm at STA and +2 at AP if 106-tone RU
2795  : DbmToW (18.0103); //15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
2796  }
2798  (m_channelWidth >= 40) ? 0.0 : rxPower, rxPower, //power detected on RU1 only if same 20 MHz as RU 2
2799  0.0, rxPowerOfdma);
2800 
2801  //Reset PSD limitation once HE TB has been sent
2802  Simulator::Schedule (delay + m_expectedPpduDuration,
2804  ScheduleTest (delay, true,
2806  0, 0, 0, //No transmission scheduled for STA 1
2807  1, 0, 1001, //One PSDU of 1001 bytes should have been successfully received from STA 2
2808  false, WifiPhyState::RX); //Measurement channel is total channel width
2809  delay += Seconds (1.0);
2810 
2811  //---------------------------------------------------------------------------
2812  //Measure the power of 2 solicited HE TB PPDU from both STAs
2813  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2814  "Measure power for reception of HE TB PPDU on both RUs");
2815  rxPower = DbmToW (19); //16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
2816  double rxPowerNonOfdma = (m_channelWidth >= 40) ? rxPower : rxPower * 2; //both STAs transmit over the same 20 MHz channel
2818  rxPowerNonOfdma, rxPowerNonOfdma,
2819  rxPower, rxPower);
2820  ScheduleTest (delay, true,
2822  1, 0, 1000, //One PSDU of 1000 bytes should have been successfully received from STA 1
2823  1, 0, 1001); //One PSDU of 1001 bytes should have been successfully received from STA 2
2824  delay += Seconds (1.0);
2825 
2826  //---------------------------------------------------------------------------
2827  //Verify that an HE SU PPDU from another BSS has been correctly received (no UL MU transmission ongoing)
2828  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2829  "Reception of an HE SU PPDU from another BSS");
2830  //One HE SU from another BSS (BSS color 2) arrives at AP (BSS color 1)
2831  Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
2832  Simulator::Schedule (delay + MilliSeconds (100), &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 3, 1, 1002, 1, 2);
2833 
2834  //Verify events data have been cleared
2835  Simulator::Schedule (delay + MilliSeconds (200), &TestUlOfdmaPhyTransmission::VerifyEventsCleared, this);
2836 
2837  Simulator::Schedule (delay + MilliSeconds (500), &TestUlOfdmaPhyTransmission::Reset, this);
2838  delay += Seconds (1.0);
2839 
2840  Simulator::Run ();
2841 }
2842 
2843 void
2845 {
2846  m_frequency = 5180;
2847  m_channelWidth = 20;
2849  NS_LOG_DEBUG ("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
2850  RunOne ();
2851 
2852  m_frequency = 5190;
2853  m_channelWidth = 40;
2855  NS_LOG_DEBUG ("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
2856  RunOne ();
2857 
2858  m_frequency = 5210;
2859  m_channelWidth = 80;
2861  NS_LOG_DEBUG ("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
2862  RunOne ();
2863 
2864  m_frequency = 5250;
2865  m_channelWidth = 160;
2867  NS_LOG_DEBUG ("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
2868  RunOne ();
2869 
2870  Simulator::Destroy ();
2871 }
2872 
2880 {
2881 public:
2883  virtual ~TestPhyPaddingExclusion ();
2884 
2885 private:
2886  void DoSetup (void) override;
2887  void DoTeardown (void) override;
2888  void DoRun (void) override;
2889 
2897  void SendHeTbPpdu (uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration);
2903  void SetTrigVector (Time ppduDuration);
2904 
2910  void GenerateInterference (Ptr<SpectrumValue> interferencePsd, Time duration);
2914  void StopInterference (void);
2915 
2919  void RunOne ();
2920 
2927  void CheckRxFromSta1 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes);
2928 
2935  void CheckRxFromSta2 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes);
2936 
2940  void VerifyEventsCleared (void);
2941 
2950 
2954  void Reset ();
2955 
2963  void RxSuccess (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector<bool> statusPerMpdu);
2964 
2969  void RxFailure (Ptr<WifiPsdu> psdu);
2970 
2974 
2976 
2983 };
2984 
2986  : TestCase ("PHY padding exclusion test"),
2987  m_countRxSuccessFromSta1 (0),
2988  m_countRxSuccessFromSta2 (0),
2989  m_countRxFailureFromSta1 (0),
2990  m_countRxFailureFromSta2 (0),
2991  m_countRxBytesFromSta1 (0),
2992  m_countRxBytesFromSta2 (0)
2993 {
2994 }
2995 
2996 void
2997 TestPhyPaddingExclusion::SendHeTbPpdu (uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
2998 {
2999  WifiConstPsduMap psdus;
3000 
3001  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false, 1);
3002 
3003  HeRu::RuSpec ru (HeRu::RU_106_TONE, index, false);
3004  txVector.SetRu (ru, txStaId);
3005  txVector.SetMode (HePhy::GetHeMcs7 (), txStaId);
3006  txVector.SetNss (1, txStaId);
3007 
3008  Ptr<Packet> pkt = Create<Packet> (payloadSize);
3009  WifiMacHeader hdr;
3010  hdr.SetType (WIFI_MAC_QOSDATA);
3011  hdr.SetQosTid (0);
3012  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
3013  std::ostringstream addr;
3014  addr << "00:00:00:00:00:0" << txStaId;
3015  hdr.SetAddr2 (Mac48Address (addr.str ().c_str ()));
3016  hdr.SetSequenceNumber (1);
3017  Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
3018  psdus.insert (std::make_pair (txStaId, psdu));
3019 
3021  if (txStaId == 1)
3022  {
3023  phy = m_phySta1;
3024  }
3025  else if (txStaId == 2)
3026  {
3027  phy = m_phySta2;
3028  }
3029 
3030  txVector.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, txVector, phy->GetPhyBand ()).first);
3031 
3032  phy->SetPpduUid (0);
3033  phy->Send (psdus, txVector);
3034 }
3035 
3036 void
3038 {
3039  m_phyInterferer->SetTxPowerSpectralDensity (interferencePsd);
3040  m_phyInterferer->SetPeriod (duration);
3041  m_phyInterferer->Start ();
3042  Simulator::Schedule (duration, &TestPhyPaddingExclusion::StopInterference, this);
3043 }
3044 
3045 void
3047 {
3048  m_phyInterferer->Stop();
3049 }
3050 
3052 {
3053 }
3054 
3055 void
3056 TestPhyPaddingExclusion::RxSuccess (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
3057 {
3058  NS_LOG_FUNCTION (this << *psdu << psdu->GetAddr2 () << rxSignalInfo << txVector);
3059  if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:01"))
3060  {
3062  m_countRxBytesFromSta1 += (psdu->GetSize () - 30);
3063  }
3064  else if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:02"))
3065  {
3067  m_countRxBytesFromSta2 += (psdu->GetSize () - 30);
3068  }
3069 }
3070 
3071 void
3073 {
3074  NS_LOG_FUNCTION (this << *psdu << psdu->GetAddr2 ());
3075  if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:01"))
3076  {
3078  }
3079  else if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:02"))
3080  {
3082  }
3083 }
3084 
3085 void
3086 TestPhyPaddingExclusion::CheckRxFromSta1 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
3087 {
3088  NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessFromSta1, expectedSuccess, "The number of successfully received packets from STA 1 is not correct!");
3089  NS_TEST_ASSERT_MSG_EQ (m_countRxFailureFromSta1, expectedFailures, "The number of unsuccessfully received packets from STA 1 is not correct!");
3090  NS_TEST_ASSERT_MSG_EQ (m_countRxBytesFromSta1, expectedBytes, "The number of bytes received from STA 1 is not correct!");
3091 }
3092 
3093 void
3094 TestPhyPaddingExclusion::CheckRxFromSta2 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
3095 {
3096  NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessFromSta2, expectedSuccess, "The number of successfully received packets from STA 2 is not correct!");
3097  NS_TEST_ASSERT_MSG_EQ (m_countRxFailureFromSta2, expectedFailures, "The number of unsuccessfully received packets from STA 2 is not correct!");
3098  NS_TEST_ASSERT_MSG_EQ (m_countRxBytesFromSta2, expectedBytes, "The number of bytes received from STA 2 is not correct!");
3099 }
3100 
3101 void
3103 {
3104  NS_TEST_ASSERT_MSG_EQ (m_phyAp->GetCurrentEvent (), 0, "m_currentEvent for AP was not cleared");
3105  NS_TEST_ASSERT_MSG_EQ (m_phySta1->GetCurrentEvent (), 0, "m_currentEvent for STA 1 was not cleared");
3106  NS_TEST_ASSERT_MSG_EQ (m_phySta2->GetCurrentEvent (), 0, "m_currentEvent for STA 2 was not cleared");
3107 }
3108 
3109 void
3111 {
3112  //This is needed to make sure PHY state will be checked as the last event if a state change occurred at the exact same time as the check
3113  Simulator::ScheduleNow (&TestPhyPaddingExclusion::DoCheckPhyState, this, phy, expectedState);
3114 }
3115 
3116 void
3118 {
3119  WifiPhyState currentState = phy->GetState ()->GetState ();
3120  NS_LOG_FUNCTION (this << currentState);
3121  NS_TEST_ASSERT_MSG_EQ (currentState, expectedState, "PHY State " << currentState << " does not match expected state " << expectedState << " at " << Simulator::Now ());
3122 }
3123 
3124 void
3126 {
3133  m_phySta1->SetPpduUid (0);
3136 }
3137 
3138 void
3140 {
3141  RngSeedManager::SetSeed (1);
3142  RngSeedManager::SetRun (1);
3143  int64_t streamNumber = 0;
3144 
3145  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
3146  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
3147  lossModel->SetFrequency (DEFAULT_FREQUENCY * 1e6);
3148  spectrumChannel->AddPropagationLossModel (lossModel);
3149  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
3150  spectrumChannel->SetPropagationDelayModel (delayModel);
3151 
3152  Ptr<Node> apNode = CreateObject<Node> ();
3153  Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice> ();
3154  Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac> ();
3155  apMac->SetAttribute ("BeaconGeneration", BooleanValue (false));
3156  apDev->SetMac (apMac);
3157  m_phyAp = CreateObject<OfdmaSpectrumWifiPhy> (0);
3160  Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration> ();
3161  apDev->SetHeConfiguration (heConfiguration);
3162  Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper> ();
3163  m_phyAp->SetInterferenceHelper (apInterferenceHelper);
3164  Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel> ();
3165  m_phyAp->SetErrorRateModel (apErrorModel);
3166  m_phyAp->SetDevice (apDev);
3167  m_phyAp->SetChannel (spectrumChannel);
3168  m_phyAp->AssignStreams (streamNumber);
3169  auto channelNum = std::get<0> (*WifiPhyOperatingChannel::FindFirst (0, DEFAULT_FREQUENCY,
3173 
3175  (int)(WIFI_PHY_BAND_5GHZ), 0});
3178  Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel> ();
3179  m_phyAp->SetMobility (apMobility);
3180  apDev->SetPhy (m_phyAp);
3181  apNode->AggregateObject (apMobility);
3182  apNode->AddDevice (apDev);
3183 
3184  Ptr<Node> sta1Node = CreateObject<Node> ();
3185  Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice> ();
3186  m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy> (1);
3189  Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper> ();
3190  m_phySta1->SetInterferenceHelper (sta1InterferenceHelper);
3191  Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel> ();
3192  m_phySta1->SetErrorRateModel (sta1ErrorModel);
3193  m_phySta1->SetDevice (sta1Dev);
3194  m_phySta1->SetChannel (spectrumChannel);
3195  m_phySta1->AssignStreams (streamNumber);
3197  (int)(WIFI_PHY_BAND_5GHZ), 0});
3198  Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel> ();
3199  m_phySta1->SetMobility (sta1Mobility);
3200  sta1Dev->SetPhy (m_phySta1);
3201  sta1Node->AggregateObject (sta1Mobility);
3202  sta1Node->AddDevice (sta1Dev);
3203 
3204  Ptr<Node> sta2Node = CreateObject<Node> ();
3205  Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice> ();
3206  m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy> (2);
3209  Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper> ();
3210  m_phySta2->SetInterferenceHelper (sta2InterferenceHelper);
3211  Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel> ();
3212  m_phySta2->SetErrorRateModel (sta2ErrorModel);
3213  m_phySta2->SetDevice (sta2Dev);
3214  m_phySta2->SetChannel (spectrumChannel);
3215  m_phySta2->AssignStreams (streamNumber);
3217  (int)(WIFI_PHY_BAND_5GHZ), 0});
3218  Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel> ();
3219  m_phySta2->SetMobility (sta2Mobility);
3220  sta2Dev->SetPhy (m_phySta2);
3221  sta2Node->AggregateObject (sta2Mobility);
3222  sta2Node->AddDevice (sta2Dev);
3223 
3224  Ptr<Node> interfererNode = CreateObject<Node> ();
3225  Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice> ();
3226  m_phyInterferer = CreateObject<WaveformGenerator> ();
3227  m_phyInterferer->SetDevice (interfererDev);
3228  m_phyInterferer->SetChannel (spectrumChannel);
3230  interfererNode->AddDevice (interfererDev);
3231 }
3232 
3233 void
3235 {
3236  m_phyAp->Dispose ();
3237  m_phyAp = 0;
3238  m_phySta1->Dispose ();
3239  m_phySta1 = 0;
3240  m_phySta2->Dispose ();
3241  m_phySta2 = 0;
3243  m_phyInterferer = 0;
3244 }
3245 
3246 void
3248 {
3249  WifiTxVector trigVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0,
3250  DEFAULT_CHANNEL_WIDTH, false, false, 1);
3251  trigVector.SetRu (HeRu::RuSpec (HeRu::RU_106_TONE, 1, false), 1);
3252  trigVector.SetMode (HePhy::GetHeMcs7 (), 1);
3253  trigVector.SetNss (1, 1);
3254  trigVector.SetRu (HeRu::RuSpec (HeRu::RU_106_TONE, 2, false), 2);
3255  trigVector.SetMode (HePhy::GetHeMcs7 (), 2);
3256  trigVector.SetNss (1, 2);
3257  uint16_t length;
3258  std::tie (length, ppduDuration) = HePhy::ConvertHeTbPpduDurationToLSigLength (ppduDuration,
3259  trigVector,
3260  m_phyAp->GetPhyBand ());
3261  trigVector.SetLength (length);
3262  auto hePhyAp = DynamicCast<HePhy> (m_phyAp->GetPhyEntity (WIFI_MOD_CLASS_HE));
3263  hePhyAp->SetTrigVector (trigVector, ppduDuration);
3264 }
3265 
3266 void
3268 {
3269  Time expectedPpduDuration = NanoSeconds (279200);
3270  Time ppduWithPaddingDuration = expectedPpduDuration + 10 * NanoSeconds (12800 + 800 /* GI */); //add 10 extra OFDM symbols
3271 
3272  Simulator::Schedule (Seconds (0.0), &TestPhyPaddingExclusion::Reset, this);
3273 
3274  //STA1 and STA2 send MU UL PPDUs addressed to AP:
3275  Simulator::Schedule (Seconds (1.0), &TestPhyPaddingExclusion::SendHeTbPpdu, this, 1, 1, 1000, ppduWithPaddingDuration);
3276  Simulator::Schedule (Seconds (1.0), &TestPhyPaddingExclusion::SendHeTbPpdu, this, 2, 2, 1001, ppduWithPaddingDuration);
3277 
3278  // Set TRIGVECTOR on AP
3279  Simulator::Schedule (Seconds (1.0), &TestPhyPaddingExclusion::SetTrigVector, this,
3280  ppduWithPaddingDuration);
3281 
3282  //Verify it takes expectedPpduDuration + padding to transmit the PPDUs
3283  Simulator::Schedule (Seconds (1.0) + ppduWithPaddingDuration - NanoSeconds (1), &TestPhyPaddingExclusion::CheckPhyState, this, m_phyAp, WifiPhyState::RX);
3284  Simulator::Schedule (Seconds (1.0) + ppduWithPaddingDuration, &TestPhyPaddingExclusion::CheckPhyState, this, m_phyAp, WifiPhyState::IDLE);
3285 
3286  //One PSDU of 1000 bytes should have been successfully received from STA 1
3287  Simulator::Schedule (Seconds (1.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
3288  //One PSDU of 1001 bytes should have been successfully received from STA 2
3289  Simulator::Schedule (Seconds (1.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
3290  //Verify events data have been cleared
3291  Simulator::Schedule (Seconds (1.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
3292 
3293  Simulator::Schedule (Seconds (1.5), &TestPhyPaddingExclusion::Reset, this);
3294 
3295 
3296  //STA1 and STA2 send MU UL PPDUs addressed to AP:
3297  Simulator::Schedule (Seconds (2.0), &TestPhyPaddingExclusion::SendHeTbPpdu, this, 1, 1, 1000, ppduWithPaddingDuration);
3298  Simulator::Schedule (Seconds (2.0), &TestPhyPaddingExclusion::SendHeTbPpdu, this, 2, 2, 1001, ppduWithPaddingDuration);
3299 
3300  // Set TRIGVECTOR on AP
3301  Simulator::Schedule (Seconds (2.0), &TestPhyPaddingExclusion::SetTrigVector, this,
3302  ppduWithPaddingDuration);
3303 
3304  //A strong non-wifi interference is generated on RU 1 during padding reception
3305  BandInfo bandInfo;
3306  bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
3307  bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
3308  bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
3309  Bands bands;
3310  bands.push_back (bandInfo);
3311 
3312  Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel> (bands);
3313  Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue> (SpectrumInterferenceRu1);
3314  double interferencePower = 0.1; //watts
3315  *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
3316 
3317  Simulator::Schedule (Seconds (2.0) + MicroSeconds (50) + expectedPpduDuration, &TestPhyPaddingExclusion::GenerateInterference, this, interferencePsdRu1, MilliSeconds (100));
3318 
3319  //Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to CCA_BUSY instead of IDLE due to the interference)
3320  Simulator::Schedule (Seconds (2.0) + ppduWithPaddingDuration - NanoSeconds (1), &TestPhyPaddingExclusion::CheckPhyState, this, m_phyAp, WifiPhyState::RX);
3321  Simulator::Schedule (Seconds (2.0) + ppduWithPaddingDuration, &TestPhyPaddingExclusion::CheckPhyState, this, m_phyAp, WifiPhyState::CCA_BUSY);
3322 
3323  //One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference occupies RU 1 after payload, during PHY padding)
3324  Simulator::Schedule (Seconds (2.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
3325  //One PSDU of 1001 bytes should have been successfully received from STA 2
3326  Simulator::Schedule (Seconds (2.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
3327  //Verify events data have been cleared
3328  Simulator::Schedule (Seconds (2.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
3329 
3330  Simulator::Schedule (Seconds (2.5), &TestPhyPaddingExclusion::Reset, this);
3331 
3332  Simulator::Run ();
3333 
3334  Simulator::Destroy ();
3335 }
3336 
3344 {
3345 public:
3347  virtual ~TestUlOfdmaPowerControl ();
3348 
3349 private:
3350  void DoSetup (void) override;
3351  void DoTeardown (void) override;
3352  void DoRun (void) override;
3353 
3359  void SendMuBar (std::vector <uint16_t> staIds);
3360 
3367  void SetupBa (Address destination);
3368 
3375  void RunOne (bool setupBa);
3376 
3381  void ReplaceReceiveOkCallbackOfAp (void);
3382 
3392  void ReceiveOkCallbackAtAp (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
3393  WifiTxVector txVector, std::vector<bool> statusPerMpdu);
3394 
3395  uint8_t m_bssColor;
3396 
3400 
3402 
3403  double m_txPowerAp;
3405  double m_txPowerEnd;
3407 
3410 
3411  double m_rssiSta1;
3412  double m_rssiSta2;
3413 
3414  double m_tol;
3415 };
3416 
3418  : TestCase ("UL-OFDMA power control test"),
3419  m_bssColor (1),
3420  m_txPowerAp (0),
3421  m_txPowerStart (0),
3422  m_txPowerEnd (0),
3423  m_txPowerLevels (0),
3424  m_requestedRssiSta1 (0),
3425  m_requestedRssiSta2 (0),
3426  m_rssiSta1 (0),
3427  m_rssiSta2 (0),
3428  m_tol (0.1)
3429 {
3430 }
3431 
3433 {
3434  m_phyAp = 0;
3435  m_apDev = 0;
3436  m_sta1Dev = 0;
3437  m_sta2Dev = 0;
3438 }
3439 
3440 void
3442 {
3443  //Only one packet is sufficient to set up BA since AP and STAs are HE capable
3444  Ptr<Packet> pkt = Create<Packet> (100); // 100 dummy bytes of data
3445  m_apDev->Send (pkt, destination, 0);
3446 }
3447 
3448 void
3449 TestUlOfdmaPowerControl::SendMuBar (std::vector <uint16_t> staIds)
3450 {
3451  NS_ASSERT (!staIds.empty () && staIds.size () <= 2);
3452 
3453  //Build MU-BAR trigger frame
3454  CtrlTriggerHeader muBar;
3455  muBar.SetType (MU_BAR_TRIGGER);
3456  muBar.SetMoreTF (true);
3457  muBar.SetCsRequired (true);
3459  muBar.SetGiAndLtfType (1600, 2);
3460  muBar.SetApTxPower (static_cast<int8_t> (m_txPowerAp));
3461  muBar.SetUlSpatialReuse (60500);
3462 
3463  HeRu::RuType ru = (staIds.size () == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
3464  std::size_t index = 1;
3465  int8_t ulTargetRssi = -40; //will be overwritten
3466  for (auto const& staId : staIds)
3467  {
3469  ui.SetAid12 (staId);
3470  ui.SetRuAllocation ({ru, index, true});
3471  ui.SetUlFecCodingType (true);
3472  ui.SetUlMcs (7);
3473  ui.SetUlDcm (false);
3474  ui.SetSsAllocation (1, 1);
3475  if (staId == 1)
3476  {
3477  ulTargetRssi = m_requestedRssiSta1;
3478  }
3479  else if (staId == 2)
3480  {
3481  ulTargetRssi = m_requestedRssiSta2;
3482  }
3483  else
3484  {
3485  NS_ABORT_MSG ("Unknown STA-ID (" << staId << ")");
3486  }
3487  ui.SetUlTargetRssi (ulTargetRssi);
3488 
3490  bar.SetType (BlockAckReqType::COMPRESSED);
3491  bar.SetTidInfo (0);
3492  bar.SetStartingSequence (4095);
3493  ui.SetMuBarTriggerDepUserInfo (bar);
3494 
3495  ++index;
3496  }
3497 
3498  WifiTxVector tbTxVector = muBar.GetHeTbTxVector (staIds.front ());
3499  muBar.SetUlLength (HePhy::ConvertHeTbPpduDurationToLSigLength (MicroSeconds (128), tbTxVector, WIFI_PHY_BAND_5GHZ).first);
3500 
3501  WifiConstPsduMap psdus;
3502  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0,
3503  DEFAULT_CHANNEL_WIDTH, false, false, false, m_bssColor);
3504 
3505  Ptr<Packet> bar = Create<Packet> ();
3506  bar->AddHeader (muBar);
3507 
3508  Mac48Address receiver = Mac48Address::GetBroadcast ();
3509  if (staIds.size () == 1)
3510  {
3511  uint16_t aidSta1 = DynamicCast<StaWifiMac> (m_sta1Dev->GetMac ())->GetAssociationId ();
3512  if (staIds.front () == aidSta1)
3513  {
3514  receiver = Mac48Address::ConvertFrom (m_sta1Dev->GetAddress ());
3515  }
3516  else
3517  {
3518  NS_ASSERT (staIds.front () == DynamicCast<StaWifiMac> (m_sta2Dev->GetMac ())->GetAssociationId ());
3519  receiver = Mac48Address::ConvertFrom (m_sta2Dev->GetAddress ());
3520  }
3521  }
3522 
3523  WifiMacHeader hdr;
3525  hdr.SetAddr1 (receiver);
3526  hdr.SetAddr2 (Mac48Address::ConvertFrom (m_apDev->GetAddress ()));
3527  hdr.SetAddr3 (Mac48Address::ConvertFrom (m_apDev->GetAddress ()));
3528  hdr.SetDsNotTo ();
3529  hdr.SetDsFrom ();
3530  hdr.SetNoRetry ();
3531  hdr.SetNoMoreFragments ();
3532  Ptr<WifiPsdu> psdu = Create<WifiPsdu> (bar, hdr);
3533 
3534  Time nav = m_apDev->GetPhy ()->GetSifs ();
3535  uint16_t staId = staIds.front (); //either will do
3536  nav += m_phyAp->CalculateTxDuration (GetBlockAckSize (BlockAckType::COMPRESSED), tbTxVector, DEFAULT_WIFI_BAND, staId);
3537  psdu->SetDuration (nav);
3538  psdus.insert (std::make_pair (SU_STA_ID, psdu));
3539 
3540  m_phyAp->Send (psdus, txVector);
3541 }
3542 
3543 void
3545  WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
3546 {
3547  NS_TEST_ASSERT_MSG_EQ (txVector.GetPreambleType (), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
3548  double rssi = rxSignalInfo.rssi;
3549  NS_ASSERT (psdu->GetNMpdus () == 1);
3550  WifiMacHeader hdr = psdu->GetHeader (0);
3551  NS_TEST_ASSERT_MSG_EQ (hdr.GetType (), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
3552  if (hdr.GetAddr2 () == m_sta1Dev->GetAddress ())
3553  {
3554  NS_TEST_ASSERT_MSG_EQ_TOL (rssi, m_rssiSta1, m_tol, "The obtained RSSI from STA 1 at AP is different from the expected one (" << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
3555  }
3556  else if (psdu->GetAddr2 () == m_sta2Dev->GetAddress ())
3557  {
3558  NS_TEST_ASSERT_MSG_EQ_TOL (rssi, m_rssiSta2, m_tol, "The obtained RSSI from STA 2 at AP is different from the expected one (" << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
3559  }
3560  else
3561  {
3562  NS_ABORT_MSG ("The receiver address is unknown");
3563  }
3564 }
3565 
3566 void
3568 {
3569  //Now that BA session has been established we can plug our method
3571 }
3572 
3573 void
3575 {
3576  Ptr<Node> apNode = CreateObject<Node> ();
3577  NodeContainer staNodes;
3578  staNodes.Create (2);
3579 
3580  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
3581  Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel> ();
3582  spectrumChannel->AddPropagationLossModel (lossModel);
3583  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
3584  spectrumChannel->SetPropagationDelayModel (delayModel);
3585 
3586  SpectrumWifiPhyHelper spectrumPhy;
3587  spectrumPhy.SetChannel (spectrumChannel);
3588  spectrumPhy.SetErrorRateModel ("ns3::NistErrorRateModel");
3589  spectrumPhy.Set ("ChannelSettings", StringValue ("{0, 0, BAND_5GHZ, 0}"));
3590 
3591  WifiHelper wifi;
3592  wifi.SetStandard (WIFI_STANDARD_80211ax);
3593  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
3594  "DataMode", StringValue ("HeMcs7"),
3595  "ControlMode", StringValue ("HeMcs7"));
3596 
3598  mac.SetType ("ns3::StaWifiMac");
3599  NetDeviceContainer staDevs = wifi.Install (spectrumPhy, mac, staNodes);
3600  wifi.AssignStreams (staDevs, 0);
3601  m_sta1Dev = DynamicCast<WifiNetDevice> (staDevs.Get (0));
3602  NS_ASSERT (m_sta1Dev);
3603  m_sta2Dev = DynamicCast<WifiNetDevice> (staDevs.Get (1));
3604  NS_ASSERT (m_sta2Dev);
3605 
3606  //Set the beacon interval long enough so that associated STAs may not consider link lost when
3607  //beacon generation is disabled during the actual tests. Having such a long interval also
3608  //avoids bloating logs with beacons during the set up phase.
3609  mac.SetType ("ns3::ApWifiMac",
3610  "BeaconGeneration", BooleanValue (true),
3611  "BeaconInterval", TimeValue (MicroSeconds (1024 * 600)));
3612  m_apDev = DynamicCast<WifiNetDevice> (wifi.Install (spectrumPhy, mac, apNode).Get (0));
3613  NS_ASSERT (m_apDev);
3614  m_apDev->GetHeConfiguration ()->SetAttribute ("BssColor", UintegerValue (m_bssColor));
3615  m_phyAp = DynamicCast<SpectrumWifiPhy> (m_apDev->GetPhy ());
3616  NS_ASSERT (m_phyAp);
3617  //ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been set up for both STAs
3618 
3620  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
3621  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
3622  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
3623  positionAlloc->Add (Vector (1.0, 0.0, 0.0)); // put close enough in order to use MCS
3624  positionAlloc->Add (Vector (2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
3625  mobility.SetPositionAllocator (positionAlloc);
3626 
3627  mobility.Install (apNode);
3628  mobility.Install (staNodes);
3629 
3630  lossModel->SetDefaultLoss (50.0);
3631  lossModel->SetLoss (apNode->GetObject<MobilityModel> (), staNodes.Get (1)->GetObject<MobilityModel> (),
3632  56.0, true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
3633 }
3634 
3635 void
3637 {
3638  m_phyAp->Dispose ();
3639  m_phyAp = 0;
3640  m_apDev->Dispose ();
3641  m_apDev = 0;
3642  m_sta1Dev->Dispose ();
3643  m_sta1Dev = 0;
3644  m_sta2Dev->Dispose ();
3645  m_sta2Dev = 0;
3646 }
3647 
3648 void
3650 {
3651  RngSeedManager::SetSeed (1);
3652  RngSeedManager::SetRun (1);
3653  int64_t streamNumber = 0;
3654 
3655  Ptr<WifiPhy> phySta1 = m_sta1Dev->GetPhy ();
3656  Ptr<WifiPhy> phySta2 = m_sta2Dev->GetPhy ();
3657 
3658  m_phyAp->AssignStreams (streamNumber);
3659  phySta1->AssignStreams (streamNumber);
3660  phySta2->AssignStreams (streamNumber);
3661 
3662  m_phyAp->SetAttribute ("TxPowerStart", DoubleValue (m_txPowerAp));
3663  m_phyAp->SetAttribute ("TxPowerEnd", DoubleValue (m_txPowerAp));
3664  m_phyAp->SetAttribute ("TxPowerLevels", UintegerValue (1));
3665 
3666  phySta1->SetAttribute ("TxPowerStart", DoubleValue (m_txPowerStart));
3667  phySta1->SetAttribute ("TxPowerEnd", DoubleValue (m_txPowerEnd));
3668  phySta1->SetAttribute ("TxPowerLevels", UintegerValue (m_txPowerLevels));
3669 
3670  phySta2->SetAttribute ("TxPowerStart", DoubleValue (m_txPowerStart));
3671  phySta2->SetAttribute ("TxPowerEnd", DoubleValue (m_txPowerEnd));
3672  phySta2->SetAttribute ("TxPowerLevels", UintegerValue (m_txPowerLevels));
3673 
3674  Time relativeStart = MilliSeconds (0);
3675  if (setupBa)
3676  {
3677  //Set up BA for each station once the association phase has ended
3678  //so that a BA session is established when the MU-BAR is received.
3679  Simulator::Schedule (MilliSeconds (800), &TestUlOfdmaPowerControl::SetupBa, this, m_sta1Dev->GetAddress ());
3680  Simulator::Schedule (MilliSeconds (850), &TestUlOfdmaPowerControl::SetupBa, this, m_sta2Dev->GetAddress ());
3681  relativeStart = MilliSeconds (1000);
3682  }
3683  else
3684  {
3685  Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac> (m_apDev->GetMac ());
3686  NS_ASSERT (apMac);
3687  apMac->SetAttribute ("BeaconGeneration", BooleanValue (false));
3688  }
3689 
3690  Simulator::Schedule (relativeStart, &TestUlOfdmaPowerControl::ReplaceReceiveOkCallbackOfAp, this);
3691 
3692  {
3693  //Verify that the RSSI from STA 1 is consistent with what was requested
3694  std::vector<uint16_t> staIds {1};
3695  Simulator::Schedule (relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
3696  }
3697 
3698  {
3699  //Verify that the RSSI from STA 2 is consistent with what was requested
3700  std::vector<uint16_t> staIds {2};
3701  Simulator::Schedule (relativeStart + MilliSeconds (20), &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
3702  }
3703 
3704  {
3705  //Verify that the RSSI from STA 1 and 2 is consistent with what was requested
3706  std::vector<uint16_t> staIds {1, 2};
3707  Simulator::Schedule (relativeStart + MilliSeconds (40), &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
3708  }
3709 
3710  Simulator::Stop (relativeStart + MilliSeconds (100));
3711  Simulator::Run ();
3712 }
3713 
3714 void
3716 {
3717  //Power configurations
3718  m_txPowerAp = 20; //dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
3719  //since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
3720  m_txPowerStart = 15; //dBm
3721 
3722  //Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
3723  m_requestedRssiSta1 = -30.0;
3724  m_requestedRssiSta2 = -36.0;
3725 
3726  //Test single power level
3727  {
3728  //STA power configurations: 15 dBm only
3729  m_txPowerEnd = 15;
3730  m_txPowerLevels = 1;
3731 
3732  //Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
3733  //regardless of the estimated path loss.
3734  m_rssiSta1 = -35.0; // 15 dBm - 50 dB
3735  m_rssiSta2 = -41.0; // 15 dBm - 56 dB
3736 
3737  RunOne (true);
3738  }
3739 
3740  //Test 2 dBm granularity
3741  {
3742  //STA power configurations: [15:2:25] dBm
3743  m_txPowerEnd = 25;
3744  m_txPowerLevels = 6;
3745 
3746  //Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than requested
3747  m_rssiSta1 = -29.0; // 21 dBm - 50 dB
3748  m_rssiSta2 = -35.0; // 21 dBm - 50 dB
3749 
3750  RunOne (false);
3751  }
3752 
3753  //Test 1 dBm granularity
3754  {
3755  //STA power configurations: [15:1:25] dBm
3756  m_txPowerEnd = 25;
3757  m_txPowerLevels = 11;
3758 
3759  //Expected UL RSSIs, considering that we can correctly tune the transmit power
3760  m_rssiSta1 = -30.0; // 20 dBm - 50 dB
3761  m_rssiSta2 = -36.0; // 20 dBm - 56 dB
3762 
3763  RunOne (false);
3764  }
3765 
3766  //Ask for different power levels (3 dB difference between HE_TB_PPDUs)
3767  {
3768  //STA power configurations: [15:1:25] dBm
3769  m_txPowerEnd = 25;
3770  m_txPowerLevels = 11;
3771 
3772  //Requested UL RSSIs
3773  m_requestedRssiSta1 = -28.0; //2 dB higher than previously -> Tx power = 22 dBm at STA 1
3774  m_requestedRssiSta2 = -37.0; //1 dB less than previously -> Tx power = 19 dBm at STA 2
3775 
3776  //Expected UL RSSIs, considering that we can correctly tune the transmit power
3777  m_rssiSta1 = -28.0; // 22 dBm - 50 dB
3778  m_rssiSta2 = -37.0; // 19 dBm - 56 dB
3779 
3780  RunOne (false);
3781  }
3782 
3783  Simulator::Destroy ();
3784 }
3785 
3786 
3794 {
3795 public:
3797 };
3798 
3800  : TestSuite ("wifi-phy-ofdma", UNIT)
3801 {
3802  AddTestCase (new TestDlOfdmaPhyTransmission, TestCase::QUICK);
3803  AddTestCase (new TestUlOfdmaPpduUid, TestCase::QUICK);
3804  AddTestCase (new TestMultipleHeTbPreambles, TestCase::QUICK);
3805  AddTestCase (new TestUlOfdmaPhyTransmission, TestCase::QUICK);
3806  AddTestCase (new TestPhyPaddingExclusion, TestCase::QUICK);
3807  AddTestCase (new TestUlOfdmaPowerControl, TestCase::QUICK);
3808 }
3809 
#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.
void(* TxPpduUidCallback)(uint64_t uid)
TracedCallback signature for UID of transmitted PPDU.
void StartTx(Ptr< WifiPpdu > ppdu) override
void SetPpduUid(uint64_t uid)
Set the global PPDU UID counter.
Ptr< Event > GetCurrentEvent(void)
void DoInitialize(void) override
Initialize() implementation.
Ptr< const HePhy > GetHePhy(void) const
Ptr< OfdmaTestHePhy > m_ofdmTestHePhy
Pointer to HE PHY instance used for OFDMA test.
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const override
void DoDispose(void) override
Destructor implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents(void)
static TypeId GetTypeId(void)
Get the type ID.
TracedCallback< uint64_t > m_phyTxPpduUidTrace
Callback providing UID of the PPDU that is about to be transmitted.
HE PHY slightly modified so as to return a given STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
OfdmaTestHePhy(uint16_t staId)
Constructor.
void SetGlobalPpduUid(uint64_t uid)
Set the global PPDU UID counter.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
uint16_t m_staId
ID of the STA to which this PHY belongs to.
uint16_t m_frequency
frequency in MHz
uint16_t m_channelWidth
channel width in MHz
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxSuccessSta3(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 3.
void RunOne()
Run one function.
void RxFailureSta2(Ptr< WifiPsdu > psdu)
Receive failure function for STA 2.
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
Time m_expectedPpduDuration
expected duration to send MU PPDU
void RxFailureSta1(Ptr< WifiPsdu > psdu)
Receive failure function for STA 1.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
void DoRun(void) override
Implementation to actually run this TestCase.
void RxSuccessSta2(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
void StopInterference(void)
Stop interference function.
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void DoSetup(void) override
Implementation to do any local setup required for 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 RxFailureSta3(Ptr< WifiPsdu > psdu)
Receive failure function for STA 3.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
uint32_t m_countRxSuccessSta3
count RX success for STA 3
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
uint32_t m_countRxBytesSta3
count RX bytes for STA 3
void RxSuccessSta1(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 1.
void ResetResults()
Reset the results.
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 Reset(void)
Reset function.
void DoRun(void) override
Implementation to actually run this TestCase.
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 DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize)
Receive HE TB PPDU function.
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
uint64_t m_totalBytesDropped
total number of dropped bytes
void CheckBytesDropped(size_t expectedBytesDropped)
Check the number of bytes dropped.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
PHY padding exclusion test.
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(void)
Verify all events are cleared at end of TX or RX.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void RxFailure(Ptr< WifiPsdu > psdu)
Receive failure function.
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 DoSetup(void) override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
void StopInterference(void)
Stop interference function.
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
void RxSuccess(Ptr< 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 RunOne()
Run one function.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
void DoRun(void) override
Implementation to actually run this TestCase.
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 DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
void VerifyEventsCleared(void)
Verify all events are cleared at end of TX or RX.
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 StopInterference(void)
Stop interference function.
void RxFailure(Ptr< WifiPsdu > psdu)
Receive failure function.
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
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.
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, WifiPhyState expectedStateBeforeEnd=WifiPhyState::RX, TrigVectorInfo error=NONE)
Schedule test to perform.
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 SetPsdLimit(Ptr< WifiPhy > phy, double psdLimit)
Set the PSD limit.
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void DoSetup(void) 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 CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
void DoRun(void) override
Implementation to actually run this TestCase.
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 RxSuccess(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
void RunOne()
Run one function.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
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 SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE TB PPDU function.
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
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
void DoRun(void) override
Implementation to actually run this TestCase.
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
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
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
double m_txPowerAp
transmit power (in dBm) of AP
void ReplaceReceiveOkCallbackOfAp(void)
Replace the AP's callback on its PHY's ReceiveOkCallback by the ReceiveOkCallbackAtAp method.
void RunOne(bool setupBa)
Run one simulation with an optional BA session set up phase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void ReceiveOkCallbackAtAp(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive OK callback function at AP.
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
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 SendMuPpdu(void)
Send MU-PPDU toward both STAs.
void TxPpduSta1(uint64_t uid)
Transmitted PPDU information function for STA 1.
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.
void DoRun(void) override
Implementation to actually run this TestCase.
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
void SendTbPpdu(void)
Send TB-PPDU from both STAs.
void ResetPpduUid(void)
Reset the global PPDU UID counter in WifiPhy.
uint64_t m_ppduUidSta1
UID of PPDU transmitted by STA1.
uint64_t m_ppduUidSta2
UID of PPDU transmitted by STA2.
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
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:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAckRequest.
Definition: ctrl-headers.h:49
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:886
CtrlTriggerUserInfoField & AddUserInfoField(void)
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:582
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:41
PHY entity for HE (11ax)
Definition: he-phy.h:61
RU Specification.
Definition: he-ru.h:68
RuType GetRuType(void) const
Get the RU type.
Definition: he-ru.cc:167
void SetPhyIndex(uint16_t bw, uint8_t p20Index)
Set the RU PHY index.
Definition: he-ru.cc:188
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:42
an EUI-48 address
Definition: mac48-address.h:44
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:130
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:256
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:252
void Dispose(void)
Dispose of this Object.
Definition: object.cc:214
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:83
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:809
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get(void) const
Definition: pointer.h:201
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
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.
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:41
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetChannel(Ptr< SpectrumChannel > c)
Set the channel attached to this device.
void SetDevice(Ptr< NetDevice > d)
Set the associated NetDevice instance.
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:274
Implements the IEEE 802.11 MAC header.
void SetNoRetry(void)
Un-set the Retry bit in the Frame Control field.
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
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.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetDsFrom(void)
Set the From DS bit in the Frame Control field.
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
create MAC layers for a ns3::WifiNetDevice.
void SetMac(const Ptr< WifiMac > mac)
void SetHeConfiguration(Ptr< HeConfiguration > heConfiguration)
Ptr< WifiMac > GetMac(void) const
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Address GetAddress(void) const override
Ptr< WifiPhy > GetPhy(void) const
void SetStandard(WifiStandard standard)
Set the Wifi standard.
void SetPhy(const Ptr< WifiPhy > phy)
Ptr< HeConfiguration > GetHeConfiguration(void) const
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:154
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
Definition: wifi-helper.h:440
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:566
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:1506
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:574
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:1154
WifiPhyBand GetPhyBand(void) const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:887
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:396
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:835
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1327
void Reset(void)
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1611
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1175
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:930
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1153
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class, for the WifiPhy instance.
Definition: wifi-phy.cc:644
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1156
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:535
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:594
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:676
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:547
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1142
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:390
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:833
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:2012
This objects implements the PHY state machine of the Wifi device.
uint32_t GetSize(void) const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:260
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:266
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:319
Mac48Address GetAddr2(void) const
Get the Transmitter Address (TA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:126
void SetDuration(Time duration)
Set the Duration/ID field on all the MPDUs.
Definition: wifi-psdu.cc:156
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiPreamble GetPreambleType(void) const
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the 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.
const HeMuUserInfoMap & GetHeMuUserInfoMap(void) const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#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:88
void Reset(void)
Reset the initial value of every attribute as well as the value of every global to what they were bef...
Definition: config.cc:820
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:281
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
#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:141
#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:323
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1268
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
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
@ 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)
@ MU_BAR_TRIGGER
Definition: ctrl-headers.h:564
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.
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:37
@ 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:63
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
mac
Definition: third.py:99
wifi
Definition: third.py:96
mobility
Definition: third.py:108
phy
Definition: third.py:93
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
HE MU specific user transmission parameters.
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:67
double rssi
RSSI in dBm.
Definition: phy-entity.h:69
#define SU_STA_ID
Definition: wifi-mode.h:32
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.