A Discrete-Event Network Simulator
API
wifi-non-ht-dup-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
18  */
19 
20 #include "ns3/ap-wifi-mac.h"
21 #include "ns3/boolean.h"
22 #include "ns3/constant-position-mobility-model.h"
23 #include "ns3/he-configuration.h"
24 #include "ns3/he-phy.h"
25 #include "ns3/interference-helper.h"
26 #include "ns3/log.h"
27 #include "ns3/mobility-helper.h"
28 #include "ns3/multi-model-spectrum-channel.h"
29 #include "ns3/nist-error-rate-model.h"
30 #include "ns3/node.h"
31 #include "ns3/non-communicating-net-device.h"
32 #include "ns3/rng-seed-manager.h"
33 #include "ns3/simulator.h"
34 #include "ns3/spectrum-wifi-helper.h"
35 #include "ns3/spectrum-wifi-phy.h"
36 #include "ns3/sta-wifi-mac.h"
37 #include "ns3/test.h"
38 #include "ns3/waveform-generator.h"
39 #include "ns3/wifi-mac-header.h"
40 #include "ns3/wifi-net-device.h"
41 #include "ns3/wifi-psdu.h"
42 #include "ns3/wifi-spectrum-signal-parameters.h"
43 #include "ns3/wifi-spectrum-value-helper.h"
44 #include "ns3/wifi-utils.h"
45 
46 #include <vector>
47 
48 using namespace ns3;
49 
50 NS_LOG_COMPONENT_DEFINE("WifiNonHtDuplicateTest");
51 
52 constexpr uint32_t DEFAULT_FREQUENCY = 5180; // MHz
53 
57 class MuRtsCtsHePhy : public HePhy
58 {
59  public:
60  MuRtsCtsHePhy();
61  ~MuRtsCtsHePhy() override;
62 
68  void SetPreviousTxPpduUid(uint64_t uid);
69 
75  void SetMuRtsTxVector(const WifiTxVector& muRtsTxVector);
76 }; // class MuRtsCtsHePhy
77 
79  : HePhy()
80 {
81  NS_LOG_FUNCTION(this);
82 }
83 
85 {
86  NS_LOG_FUNCTION(this);
87 }
88 
89 void
91 {
92  NS_LOG_FUNCTION(this << uid);
94 }
95 
96 void
98 {
99  NS_LOG_FUNCTION(this << muRtsTxVector);
100  m_currentTxVector = muRtsTxVector;
101 }
102 
107 {
108  public:
113  static TypeId GetTypeId();
114 
116  ~MuRtsCtsSpectrumWifiPhy() override;
117 
118  void DoInitialize() override;
119  void DoDispose() override;
120 
126  void SetPpduUid(uint64_t uid);
127 
133  void SetMuRtsTxVector(const WifiTxVector& muRtsTxVector);
134 
135  private:
137 }; // class MuRtsCtsSpectrumWifiPhy
138 
139 TypeId
141 {
142  static TypeId tid =
143  TypeId("ns3::MuRtsCtsSpectrumWifiPhy").SetParent<SpectrumWifiPhy>().SetGroupName("Wifi");
144  return tid;
145 }
146 
148  : SpectrumWifiPhy()
149 {
150  NS_LOG_FUNCTION(this);
151  m_muRtsCtsHePhy = Create<MuRtsCtsHePhy>();
152  m_muRtsCtsHePhy->SetOwner(this);
153 }
154 
156 {
157  NS_LOG_FUNCTION(this);
158 }
159 
160 void
162 {
163  // Replace HE PHY instance with test instance
165  SpectrumWifiPhy::DoInitialize();
166 }
167 
168 void
170 {
171  m_muRtsCtsHePhy = nullptr;
172  SpectrumWifiPhy::DoDispose();
173 }
174 
175 void
177 {
178  NS_LOG_FUNCTION(this << uid);
180  m_previouslyRxPpduUid = uid;
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION(this << muRtsTxVector);
187  m_muRtsCtsHePhy->SetMuRtsTxVector(muRtsTxVector);
188 }
189 
202 {
203  public:
205  using StasParams = std::vector<std::tuple<WifiStandard, uint16_t, uint8_t>>;
206 
218  uint16_t apFrequency,
219  uint8_t apP20Index,
220  StasParams stasParams,
221  std::vector<bool> per20MhzInterference = {});
222 
223  private:
224  void DoSetup() override;
225  void DoTeardown() override;
226  void DoRun() override;
227 
236  void RxSuccess(std::size_t index,
237  Ptr<const WifiPsdu> psdu,
238  RxSignalInfo rxSignalInfo,
239  WifiTxVector txVector,
240  std::vector<bool> statusPerMpdu);
241 
247  void RxFailure(std::size_t index, Ptr<const WifiPsdu> psdu);
248 
255  void CheckResults(std::size_t index, uint32_t expectedRxSuccess, uint32_t expectedRxFailure);
256 
260  void ResetResults();
261 
266  void SendNonHtDuplicatePpdu(uint16_t channelWidth);
267 
275  Ptr<SpectrumValue> interferencePsd,
276  Time duration);
281  void StopInterference(Ptr<WaveformGenerator> interferer);
282 
284  uint16_t m_apFrequency;
285  uint8_t m_apP20Index;
287  std::vector<bool>
290 
291  std::vector<uint32_t> m_countRxSuccessStas;
292  std::vector<uint32_t> m_countRxFailureStas;
293 
295  std::vector<Ptr<SpectrumWifiPhy>> m_phyStas;
296 
297  std::vector<Ptr<WaveformGenerator>>
299 };
300 
302  WifiStandard apStandard,
303  uint16_t apFrequency,
304  uint8_t apP20Index,
305  StasParams stasParams,
306  std::vector<bool> per20MhzInterference)
307  : TestCase{"non-HT duplicate PHY reception test"},
308  m_apStandard{apStandard},
309  m_apFrequency{apFrequency},
310  m_apP20Index{apP20Index},
311  m_stasParams{stasParams},
312  m_per20MhzInterference{per20MhzInterference},
313  m_countRxSuccessStas{},
314  m_countRxFailureStas{},
315  m_phyStas{}
316 {
317 }
318 
319 void
321 {
322  for (auto& countRxSuccess : m_countRxSuccessStas)
323  {
324  countRxSuccess = 0;
325  }
326  for (auto& countRxFailure : m_countRxFailureStas)
327  {
328  countRxFailure = 0;
329  }
330 }
331 
332 void
334 {
335  NS_LOG_FUNCTION(this << channelWidth);
336  WifiTxVector txVector = WifiTxVector(OfdmPhy::GetOfdmRate24Mbps(),
337  0,
339  800,
340  1,
341  1,
342  0,
343  channelWidth,
344  false);
345 
346  Ptr<Packet> pkt = Create<Packet>(1000);
347  WifiMacHeader hdr;
348 
350  hdr.SetQosTid(0);
351 
352  Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
353  Time txDuration =
354  m_phyAp->CalculateTxDuration(psdu->GetSize(), txVector, m_phyAp->GetPhyBand());
355 
356  m_phyAp->Send(WifiConstPsduMap({std::make_pair(SU_STA_ID, psdu)}), txVector);
357 }
358 
359 void
361  Ptr<SpectrumValue> interferencePsd,
362  Time duration)
363 {
364  NS_LOG_FUNCTION(this << interferer << duration);
365  interferer->SetTxPowerSpectralDensity(interferencePsd);
366  interferer->SetPeriod(duration);
367  interferer->Start();
368  Simulator::Schedule(duration,
370  this,
371  interferer);
372 }
373 
374 void
376 {
377  NS_LOG_FUNCTION(this << interferer);
378  interferer->Stop();
379 }
380 
381 void
383  Ptr<const WifiPsdu> psdu,
384  RxSignalInfo rxSignalInfo,
385  WifiTxVector txVector,
386  std::vector<bool> /*statusPerMpdu*/)
387 {
388  NS_LOG_FUNCTION(this << index << *psdu << rxSignalInfo << txVector);
389  m_countRxSuccessStas.at(index)++;
390 }
391 
392 void
394 {
395  NS_LOG_FUNCTION(this << index << *psdu);
396  m_countRxFailureStas.at(index)++;
397 }
398 
399 void
401  uint32_t expectedRxSuccess,
402  uint32_t expectedRxFailure)
403 {
404  NS_LOG_FUNCTION(this << index << expectedRxSuccess << expectedRxFailure);
406  expectedRxSuccess,
407  "The number of successfully received packets by STA "
408  << index << " is not correct!");
410  expectedRxFailure,
411  "The number of unsuccessfully received packets by STA "
412  << index << " is not correct!");
413 }
414 
415 void
417 {
418  auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
419  auto lossModel = CreateObject<FriisPropagationLossModel>();
420  lossModel->SetFrequency(m_apFrequency * 1e6);
421  spectrumChannel->AddPropagationLossModel(lossModel);
422  auto delayModel = CreateObject<ConstantSpeedPropagationDelayModel>();
423  spectrumChannel->SetPropagationDelayModel(delayModel);
424 
425  auto apNode = CreateObject<Node>();
426  auto apDev = CreateObject<WifiNetDevice>();
427  m_phyAp = CreateObject<SpectrumWifiPhy>();
429  auto apInterferenceHelper = CreateObject<InterferenceHelper>();
430  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
431  auto apErrorModel = CreateObject<NistErrorRateModel>();
432  m_phyAp->SetErrorRateModel(apErrorModel);
433  m_phyAp->SetDevice(apDev);
434  m_phyAp->SetChannel(spectrumChannel);
436  auto apMobility = CreateObject<ConstantPositionMobilityModel>();
437  m_phyAp->SetMobility(apMobility);
438  apDev->SetPhy(m_phyAp);
439  apNode->AggregateObject(apMobility);
440  apNode->AddDevice(apDev);
441 
442  for (const auto& staParams : m_stasParams)
443  {
444  auto staNode = CreateObject<Node>();
445  auto staDev = CreateObject<WifiNetDevice>();
446  auto staPhy = CreateObject<SpectrumWifiPhy>();
447  staPhy->CreateWifiSpectrumPhyInterface(staDev);
448  auto sta1InterferenceHelper = CreateObject<InterferenceHelper>();
449  staPhy->SetInterferenceHelper(sta1InterferenceHelper);
450  auto sta1ErrorModel = CreateObject<NistErrorRateModel>();
451  staPhy->SetErrorRateModel(sta1ErrorModel);
452  staPhy->SetDevice(staDev);
453  staPhy->SetChannel(spectrumChannel);
454  staPhy->ConfigureStandard(std::get<0>(staParams));
455  staPhy->SetReceiveOkCallback(
457  staPhy->SetReceiveErrorCallback(
459  auto staMobility = CreateObject<ConstantPositionMobilityModel>();
460  staPhy->SetMobility(staMobility);
461  staDev->SetPhy(staPhy);
462  staNode->AggregateObject(staMobility);
463  staNode->AddDevice(staDev);
464  m_phyStas.push_back(staPhy);
465  m_countRxSuccessStas.push_back(0);
466  m_countRxFailureStas.push_back(0);
467  }
468 
469  if (!m_per20MhzInterference.empty())
470  {
471  [[maybe_unused]] auto [channelNum, centerFreq, apChannelWidth, type, phyBand] =
472  (*WifiPhyOperatingChannel::FindFirst(0,
474  0,
475  m_apStandard,
477  NS_ASSERT(m_per20MhzInterference.size() == (apChannelWidth / 20));
478  for (std::size_t i = 0; i < m_per20MhzInterference.size(); ++i)
479  {
480  auto interfererNode = CreateObject<Node>();
481  auto interfererDev = CreateObject<NonCommunicatingNetDevice>();
482  auto phyInterferer = CreateObject<WaveformGenerator>();
483  phyInterferer->SetDevice(interfererDev);
484  phyInterferer->SetChannel(spectrumChannel);
485  phyInterferer->SetDutyCycle(1);
486  interfererNode->AddDevice(interfererDev);
487  m_phyInterferers.push_back(phyInterferer);
488  }
489  }
490 }
491 
492 void
494 {
495  m_phyAp->Dispose();
496  m_phyAp = nullptr;
497  for (auto phySta : m_phyStas)
498  {
499  phySta->Dispose();
500  phySta = nullptr;
501  }
502  for (auto phyInterferer : m_phyInterferers)
503  {
504  phyInterferer->Dispose();
505  phyInterferer = nullptr;
506  }
507 }
508 
509 void
511 {
512  RngSeedManager::SetSeed(1);
513  RngSeedManager::SetRun(1);
514  int64_t streamNumber = 0;
515  m_phyAp->AssignStreams(streamNumber);
516  for (auto phySta : m_phyStas)
517  {
518  phySta->AssignStreams(streamNumber);
519  }
520 
521  [[maybe_unused]] auto [apChannelNum, centerFreq, apChannelWidth, type, phyBand] =
522  (*WifiPhyOperatingChannel::FindFirst(0,
524  0,
525  m_apStandard,
528  WifiPhy::ChannelTuple{apChannelNum, apChannelWidth, WIFI_PHY_BAND_5GHZ, m_apP20Index});
529 
530  auto index = 0;
531  for (const auto& [staStandard, staFrequency, staP20Index] : m_stasParams)
532  {
533  [[maybe_unused]] auto [staChannelNum, centerFreq, staChannelWidth, type, phyBand] =
534  (*WifiPhyOperatingChannel::FindFirst(0,
535  staFrequency,
536  0,
537  staStandard,
539  m_phyStas.at(index++)->SetOperatingChannel(
540  WifiPhy::ChannelTuple{staChannelNum, staChannelWidth, WIFI_PHY_BAND_5GHZ, staP20Index});
541  }
542 
543  index = 0;
544  const auto minApCenterFrequency =
545  m_phyAp->GetFrequency() - (m_phyAp->GetChannelWidth() / 2) + (20 / 2);
546  for (auto channelWidth = 20; channelWidth <= apChannelWidth; channelWidth *= 2, ++index)
547  {
548  if (!m_phyInterferers.empty())
549  {
550  for (std::size_t i = 0; i < m_phyInterferers.size(); ++i)
551  {
552  if (!m_per20MhzInterference.at(i))
553  {
554  continue;
555  }
556  BandInfo bandInfo;
557  bandInfo.fc = (minApCenterFrequency + (i * 20)) * 1e6;
558  bandInfo.fl = bandInfo.fc - (5 * 1e6);
559  bandInfo.fh = bandInfo.fc + (5 * 1e6);
560  Bands bands;
561  bands.push_back(bandInfo);
562  auto spectrumInterference = Create<SpectrumModel>(bands);
563  auto interferencePsd = Create<SpectrumValue>(spectrumInterference);
564  auto interferencePower = 0.005; // in watts (designed to make PHY headers reception
565  // successful but payload reception fail)
566  *interferencePsd = interferencePower / 10e6;
567  Simulator::Schedule(Seconds(index),
569  this,
570  m_phyInterferers.at(i),
571  interferencePsd,
572  Seconds(0.5));
573  }
574  }
575  const auto apCenterFreq =
577  const auto apMinFreq = apCenterFreq - (channelWidth / 2);
578  const auto apMaxFreq = apCenterFreq + (channelWidth / 2);
579  Simulator::Schedule(Seconds(index + 0.1),
581  this,
582  channelWidth);
583  for (std::size_t i = 0; i < m_stasParams.size(); ++i)
584  {
585  const auto p20Width = 20;
586  const auto staP20Freq =
587  m_phyStas.at(i)->GetOperatingChannel().GetPrimaryChannelCenterFrequency(p20Width);
588  const auto staP20MinFreq = staP20Freq - (p20Width / 2);
589  const auto staP20MaxFreq = staP20Freq + (p20Width / 2);
590  bool expectRx = (staP20MinFreq >= apMinFreq && staP20MaxFreq <= apMaxFreq);
591  bool expectSuccess = true;
592  if (!m_per20MhzInterference.empty())
593  {
594  const auto index20MhzSubBand = ((staP20Freq - minApCenterFrequency) / 20);
595  expectSuccess = !m_per20MhzInterference.at(index20MhzSubBand);
596  }
597  Simulator::Schedule(Seconds(index + 0.5),
599  this,
600  i,
601  expectRx ? expectSuccess : 0,
602  expectRx ? !expectSuccess : 0);
603  }
604  Simulator::Schedule(Seconds(index + 0.5),
606  this);
607  }
608 
609  Simulator::Run();
610  Simulator::Destroy();
611 }
612 
624 {
625  public:
630  TestMultipleCtsResponsesFromMuRts(const std::vector<uint16_t>& bwPerSta);
631 
632  private:
633  void DoSetup() override;
634  void DoTeardown() override;
635  void DoRun() override;
636 
642  void FakePreviousMuRts(uint16_t bw);
643 
650  void TxNonHtDuplicateCts(Ptr<SpectrumWifiPhy> phy, uint16_t bw);
651 
660  RxSignalInfo rxSignalInfo,
661  WifiTxVector txVector,
662  std::vector<bool> statusPerMpdu);
663 
669 
675  void CheckResults(std::size_t expectedRxCtsSuccess, std::size_t expectedRxCtsFailure);
676 
678  std::vector<Ptr<MuRtsCtsSpectrumWifiPhy>> m_phyStas;
679 
680  std::vector<uint16_t> m_bwPerSta;
681 
682  std::size_t m_countRxCtsSuccess;
683  std::size_t m_countRxCtsFailure;
684 
686 };
687 
689  const std::vector<uint16_t>& bwPerSta)
690  : TestCase{"test PHY reception of multiple CTS frames following a MU-RTS frame"},
691  m_bwPerSta{bwPerSta},
692  m_countRxCtsSuccess{0},
693  m_countRxCtsFailure{0},
694  m_stasTxPowerDbm(10.0)
695 {
696 }
697 
698 void
700 {
701  NS_LOG_FUNCTION(this << bw);
702 
703  WifiTxVector txVector;
704  txVector.SetChannelWidth(bw); // only the channel width matters for this test
705 
706  // set the TXVECTOR and the UID of the previously transmitted MU-RTS in the AP PHY
707  m_phyAp->SetMuRtsTxVector(txVector);
708  m_phyAp->SetPpduUid(0);
709 
710  // set the UID of the previously received MU-RTS in the STAs PHYs
711  for (auto& phySta : m_phyStas)
712  {
713  phySta->SetPpduUid(0);
714  }
715 }
716 
717 void
719 {
720  NS_LOG_FUNCTION(this << phy << bw);
721 
722  WifiTxVector txVector =
723  WifiTxVector(OfdmPhy::GetOfdmRate54Mbps(), // use less robust modulation for test purpose
724  0,
726  800,
727  1,
728  1,
729  0,
730  bw,
731  false,
732  false);
733  txVector.SetTriggerResponding(true);
734 
735  WifiMacHeader hdr;
737  hdr.SetDsNotFrom();
738  hdr.SetDsNotTo();
739  hdr.SetNoMoreFragments();
740  hdr.SetNoRetry();
741 
742  auto pkt = Create<Packet>();
743  auto mpdu = Create<WifiMpdu>(pkt, hdr);
744  auto psdu = Create<WifiPsdu>(mpdu, false);
745 
746  phy->Send(psdu, txVector);
747 }
748 
749 void
751  RxSignalInfo rxSignalInfo,
752  WifiTxVector txVector,
753  std::vector<bool> /*statusPerMpdu*/)
754 {
755  NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
756  NS_TEST_EXPECT_MSG_EQ_TOL(rxSignalInfo.rssi,
758  0.1,
759  "RX power is not correct!");
761 }
762 
763 void
765 {
766  NS_LOG_FUNCTION(this << *psdu);
768 }
769 
770 void
771 TestMultipleCtsResponsesFromMuRts::CheckResults(std::size_t expectedRxCtsSuccess,
772  std::size_t expectedRxCtsFailure)
773 {
775  expectedRxCtsSuccess,
776  "The number of successfully received CTS frames by AP is not correct!");
778  expectedRxCtsFailure,
779  "The number of unsuccessfully received CTS frames by AP is not correct!");
780 }
781 
782 void
784 {
785  RngSeedManager::SetSeed(1);
786  RngSeedManager::SetRun(1);
787  int64_t streamNumber = 0;
788 
789  auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
790  auto lossModel = CreateObject<FriisPropagationLossModel>();
791  lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
792  spectrumChannel->AddPropagationLossModel(lossModel);
793  auto delayModel = CreateObject<ConstantSpeedPropagationDelayModel>();
794  spectrumChannel->SetPropagationDelayModel(delayModel);
795 
796  auto apNode = CreateObject<Node>();
797  auto apDev = CreateObject<WifiNetDevice>();
798  auto apMac = CreateObject<ApWifiMac>();
799  apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
800  apDev->SetMac(apMac);
801  m_phyAp = CreateObject<MuRtsCtsSpectrumWifiPhy>();
803  apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
804  auto apInterferenceHelper = CreateObject<InterferenceHelper>();
805  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
806  auto apErrorModel = CreateObject<NistErrorRateModel>();
807  m_phyAp->SetErrorRateModel(apErrorModel);
808  m_phyAp->SetDevice(apDev);
809  m_phyAp->SetChannel(spectrumChannel);
811  m_phyAp->AssignStreams(streamNumber);
812 
817 
818  const auto apBw = *std::max_element(m_bwPerSta.cbegin(), m_bwPerSta.cend());
819  auto channelNum = std::get<0>(
820  *WifiPhyOperatingChannel::FindFirst(0, 0, apBw, WIFI_STANDARD_80211ax, WIFI_PHY_BAND_5GHZ));
821 
823 
824  auto apMobility = CreateObject<ConstantPositionMobilityModel>();
825  m_phyAp->SetMobility(apMobility);
826  apDev->SetPhy(m_phyAp);
827  apDev->SetStandard(WIFI_STANDARD_80211ax);
828  apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
829  apMac->SetWifiPhys({m_phyAp});
830  apNode->AggregateObject(apMobility);
831  apNode->AddDevice(apDev);
832 
833  for (std::size_t i = 0; i < m_bwPerSta.size(); ++i)
834  {
835  auto staNode = CreateObject<Node>();
836  auto staDev = CreateObject<WifiNetDevice>();
837  auto phySta = CreateObject<MuRtsCtsSpectrumWifiPhy>();
838  phySta->CreateWifiSpectrumPhyInterface(staDev);
839  auto staInterferenceHelper = CreateObject<InterferenceHelper>();
840  phySta->SetInterferenceHelper(staInterferenceHelper);
841  auto staErrorModel = CreateObject<NistErrorRateModel>();
842  phySta->SetErrorRateModel(staErrorModel);
843  phySta->SetDevice(staDev);
844  phySta->SetChannel(spectrumChannel);
845  phySta->ConfigureStandard(WIFI_STANDARD_80211ax);
846  phySta->AssignStreams(streamNumber);
847  phySta->SetTxPowerStart(m_stasTxPowerDbm);
848  phySta->SetTxPowerEnd(m_stasTxPowerDbm);
849 
850  channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
851  0,
852  m_bwPerSta.at(i),
855 
856  phySta->SetOperatingChannel(
857  WifiPhy::ChannelTuple{channelNum, m_bwPerSta.at(i), WIFI_PHY_BAND_5GHZ, 0});
858 
859  auto staMobility = CreateObject<ConstantPositionMobilityModel>();
860  phySta->SetMobility(staMobility);
861  staDev->SetPhy(phySta);
862  staDev->SetStandard(WIFI_STANDARD_80211ax);
863  staDev->SetHeConfiguration(CreateObject<HeConfiguration>());
864  staNode->AggregateObject(staMobility);
865  staNode->AddDevice(staDev);
866  m_phyStas.push_back(phySta);
867  }
868 }
869 
870 void
872 {
873  m_phyAp->Dispose();
874  m_phyAp = nullptr;
875  for (auto& phySta : m_phyStas)
876  {
877  phySta->Dispose();
878  phySta = nullptr;
879  }
880  m_phyStas.clear();
881 }
882 
883 void
885 {
886  // Fake transmission of a MU-RTS frame preceding the CTS responses
887  Simulator::Schedule(Seconds(0.0),
889  this,
890  *std::max_element(m_bwPerSta.cbegin(), m_bwPerSta.cend()));
891 
892  std::size_t index = 1;
893  for (auto& phySta : m_phyStas)
894  {
895  // Transmit CTS responses over their operating bandwidth with 1 nanosecond delay between
896  // each other
897  const auto delay = index * NanoSeconds(1.0);
898  Simulator::Schedule(Seconds(0.0) + delay,
900  this,
901  phySta,
902  m_bwPerSta.at(index - 1));
903  index++;
904  }
905 
906  // Verify successful reception of the CTS frames: since multiple copies are sent
907  // simultaneously, a single CTS frame should be forwarded up to the MAC.
908  Simulator::Schedule(Seconds(1.0), &TestMultipleCtsResponsesFromMuRts::CheckResults, this, 1, 0);
909 
910  Simulator::Run();
911  Simulator::Destroy();
912 }
913 
921 {
922  public:
924 };
925 
927  : TestSuite("wifi-non-ht-dup", UNIT)
928 {
964  5210,
965  0,
966  {{WIFI_STANDARD_80211a, 5180, 0},
967  {WIFI_STANDARD_80211n, 5200, 0},
968  {WIFI_STANDARD_80211ac, 5230, 0}}),
969  TestCase::QUICK);
970  /* same channel map and test scenario as previously but inject interference on channel 40 */
972  5210,
973  0,
974  {{WIFI_STANDARD_80211a, 5180, 0},
975  {WIFI_STANDARD_80211n, 5200, 0},
976  {WIFI_STANDARD_80211ac, 5230, 0}},
977  {false, true, false, false}),
978  TestCase::QUICK);
979 
980  /* test PHY reception of multiple CTS responses following a MU-RTS */
981  /* 4 STAs operating on 20 MHz */
982  AddTestCase(new TestMultipleCtsResponsesFromMuRts({20, 20, 20, 20}), TestCase::QUICK);
983  /* 4 STAs operating on 40 MHz */
984  AddTestCase(new TestMultipleCtsResponsesFromMuRts({40, 40, 40, 40}), TestCase::QUICK);
985  /* 4 STAs operating on 80 MHz */
986  AddTestCase(new TestMultipleCtsResponsesFromMuRts({80, 80, 80, 80}), TestCase::QUICK);
987  /* 4 STAs operating on 160 MHz */
988  AddTestCase(new TestMultipleCtsResponsesFromMuRts({160, 160, 160, 160}), TestCase::QUICK);
989  /* 4 STAs operating on different bandwidths: 160, 80, 40 and 20 MHz */
990  AddTestCase(new TestMultipleCtsResponsesFromMuRts({160, 80, 40, 20}), TestCase::QUICK);
991 }
992 
HE PHY used for testing MU-RTS/CTS.
void SetPreviousTxPpduUid(uint64_t uid)
Set the previous TX PPDU UID counter.
void SetMuRtsTxVector(const WifiTxVector &muRtsTxVector)
Set the TXVECTOR of the previously transmitted MU-RTS.
~MuRtsCtsHePhy() override
Spectrum PHY used for testing MU-RTS/CTS.
void DoDispose() override
Destructor implementation.
Ptr< MuRtsCtsHePhy > m_muRtsCtsHePhy
Pointer to HE PHY instance used for MU-RTS/CTS PHY test.
void SetPpduUid(uint64_t uid)
Set the global PPDU UID counter.
void SetMuRtsTxVector(const WifiTxVector &muRtsTxVector)
Set the TXVECTOR of the previously transmitted MU-RTS.
void DoInitialize() override
Initialize() implementation.
static TypeId GetTypeId()
Get the type ID.
test PHY reception of multiple CTS frames as a response to a MU-RTS frame.
void FakePreviousMuRts(uint16_t bw)
Function called to fake the transmission of a MU-RTS.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void RxCtsFailure(Ptr< const WifiPsdu > psdu)
CTS RX failure function.
TestMultipleCtsResponsesFromMuRts(const std::vector< uint16_t > &bwPerSta)
Constructor.
std::vector< uint16_t > m_bwPerSta
Bandwidth per STA in MHz.
std::size_t m_countRxCtsFailure
count the number of unsuccessfully received CTS frames
void RxCtsSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
CTS RX success function.
std::vector< Ptr< MuRtsCtsSpectrumWifiPhy > > m_phyStas
STAs PHYs.
std::size_t m_countRxCtsSuccess
count the number of successfully received CTS frames
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void CheckResults(std::size_t expectedRxCtsSuccess, std::size_t expectedRxCtsFailure)
Check the results.
Ptr< MuRtsCtsSpectrumWifiPhy > m_phyAp
AP PHY.
double m_stasTxPowerDbm
TX power in dBm configured for the STAs.
void TxNonHtDuplicateCts(Ptr< SpectrumWifiPhy > phy, uint16_t bw)
Function called to trigger a CTS frame sent by a STA using non-HT duplicate.
non-HT duplicate PHY reception test The test consists in an AP sending a single non-HT duplicate PPDU...
void GenerateInterference(Ptr< WaveformGenerator > interferer, Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
std::vector< bool > m_per20MhzInterference
flags per 20 MHz subchannel whether an interference should be generated on that subchannel
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void ResetResults()
Reset the results.
std::vector< Ptr< SpectrumWifiPhy > > m_phyStas
PHYs of STAs.
void RxFailure(std::size_t index, Ptr< const WifiPsdu > psdu)
Receive failure function.
std::vector< uint32_t > m_countRxFailureStas
count RX failure for STAs
void SendNonHtDuplicatePpdu(uint16_t channelWidth)
Send non-HT duplicate PPDU function.
StasParams m_stasParams
the parameters of the STAs
std::vector< std::tuple< WifiStandard, uint16_t, uint8_t > > StasParams
A vector containing parameters per STA: the standard, the center frequency and the P20 index.
void CheckResults(std::size_t index, uint32_t expectedRxSuccess, uint32_t expectedRxFailure)
Check the results.
void StopInterference(Ptr< WaveformGenerator > interferer)
Stop interference function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
TestNonHtDuplicatePhyReception(WifiStandard apStandard, uint16_t apFrequency, uint8_t apP20Index, StasParams stasParams, std::vector< bool > per20MhzInterference={})
Constructor.
void RxSuccess(std::size_t index, Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
WifiStandard m_apStandard
the standard to use for the AP
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
uint8_t m_apP20Index
the index of the primary 20 MHz channel of the AP
void DoRun() override
Implementation to actually run this TestCase.
std::vector< uint32_t > m_countRxSuccessStas
count RX success for STAs
std::vector< Ptr< WaveformGenerator > > m_phyInterferers
PHYs of interferers (1 interferer per 20 MHz subchannel)
uint16_t m_apFrequency
the center frequency of the AP (in MHz)
wifi non-HT duplicate Test Suite
AttributeValue implementation for Boolean.
Definition: boolean.h:37
PHY entity for HE (11ax)
Definition: he-phy.h:68
std::optional< WifiTxVector > m_currentTxVector
If the STA is an AP STA, this holds the TXVECTOR of the PPDU that has been sent.
Definition: he-phy.h:529
uint64_t m_previouslyTxPpduUid
UID of the previously sent PPDU, used by AP to recognize response HE TB PPDUs.
Definition: he-phy.h:518
void Dispose()
Dispose of this Object.
Definition: object.cc:219
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:89
802.11 PHY layer model
void SetChannel(const Ptr< SpectrumChannel > channel)
Set the SpectrumChannel this SpectrumWifiPhy is to be connected to.
void CreateWifiSpectrumPhyInterface(Ptr< NetDevice > device)
Method to encapsulate the creation of the WifiSpectrumPhyInterface object (used to bind the WifiSpect...
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
virtual void Start()
Start the waveform generator.
void SetTxPowerSpectralDensity(Ptr< SpectrumValue > txs)
Set the Power Spectral Density used for outgoing waveforms.
void SetPeriod(Time period)
Set the period according to which the WaveformGenerator switches on and off.
virtual void Stop()
Stop the waveform generator.
Implements the IEEE 802.11 MAC header.
void SetNoMoreFragments()
Un-set the More Fragment bit in the Frame Control Field.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
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()
Un-set the To DS bit in the Frame Control field.
void SetNoRetry()
Un-set the Retry bit in the Frame Control field.
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:624
void Send(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
This function is a wrapper for the Send variant that accepts a WifiConstPsduMap as first argument.
Definition: wifi-phy.cc:1693
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:632
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:1026
uint16_t GetFrequency() const
Definition: wifi-phy.cc:1014
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:448
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:941
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1480
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1244
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:1062
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:996
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1224
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:600
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:612
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:442
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:870
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1008
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: wifi-phy.cc:2184
uint16_t GetPrimaryChannelCenterFrequency(uint16_t primaryChannelWidth) const
Get the center frequency of the primary channel of the given width.
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:273
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetTriggerResponding(bool triggerResponding)
Set the Trigger Responding parameter to the given value.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:144
#define NS_TEST_EXPECT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report if ...
Definition: test.h:510
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ WIFI_PREAMBLE_LONG
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
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.
double WToDbm(double w)
Convert from Watts to dBm.
Definition: wifi-utils.cc:46
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707
std::vector< BandInfo > Bands
Container of BandInfo.
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
@ WIFI_MAC_CTL_CTS
@ WIFI_MAC_QOSDATA
phy
Definition: third.py:82
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:70
double rssi
RSSI in dBm.
Definition: phy-entity.h:72
#define SU_STA_ID
Definition: wifi-mode.h:34
static WifiNonHtDuplicateTestSuite wifiNonHtDuplicateTestSuite
the test suite
constexpr uint32_t DEFAULT_FREQUENCY