A Discrete-Event Network Simulator
QKDNetSim v2.0 (NS-3 v3.41) @ (+)
API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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  const auto expectedWidth =
390  std::min(m_phyAp->GetChannelWidth(), m_phyStas.at(index)->GetChannelWidth());
392  expectedWidth,
393  "Incorrect channel width in TXVECTOR");
394  m_countRxSuccessStas.at(index)++;
395 }
396 
397 void
399 {
400  NS_LOG_FUNCTION(this << index << *psdu);
401  m_countRxFailureStas.at(index)++;
402 }
403 
404 void
406  uint32_t expectedRxSuccess,
407  uint32_t expectedRxFailure)
408 {
409  NS_LOG_FUNCTION(this << index << expectedRxSuccess << expectedRxFailure);
411  expectedRxSuccess,
412  "The number of successfully received packets by STA "
413  << index << " is not correct!");
415  expectedRxFailure,
416  "The number of unsuccessfully received packets by STA "
417  << index << " is not correct!");
418 }
419 
420 void
422 {
423  auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
424  auto lossModel = CreateObject<FriisPropagationLossModel>();
425  lossModel->SetFrequency(m_apFrequency * 1e6);
426  spectrumChannel->AddPropagationLossModel(lossModel);
427  auto delayModel = CreateObject<ConstantSpeedPropagationDelayModel>();
428  spectrumChannel->SetPropagationDelayModel(delayModel);
429 
430  auto apNode = CreateObject<Node>();
431  auto apDev = CreateObject<WifiNetDevice>();
432  m_phyAp = CreateObject<SpectrumWifiPhy>();
433  auto apInterferenceHelper = CreateObject<InterferenceHelper>();
434  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
435  auto apErrorModel = CreateObject<NistErrorRateModel>();
436  m_phyAp->SetErrorRateModel(apErrorModel);
437  m_phyAp->SetDevice(apDev);
438  m_phyAp->AddChannel(spectrumChannel);
440  auto apMobility = CreateObject<ConstantPositionMobilityModel>();
441  m_phyAp->SetMobility(apMobility);
442  apDev->SetPhy(m_phyAp);
443  apNode->AggregateObject(apMobility);
444  apNode->AddDevice(apDev);
445 
446  for (const auto& staParams : m_stasParams)
447  {
448  auto staNode = CreateObject<Node>();
449  auto staDev = CreateObject<WifiNetDevice>();
450  auto staPhy = CreateObject<SpectrumWifiPhy>();
451  auto sta1InterferenceHelper = CreateObject<InterferenceHelper>();
452  staPhy->SetInterferenceHelper(sta1InterferenceHelper);
453  auto sta1ErrorModel = CreateObject<NistErrorRateModel>();
454  staPhy->SetErrorRateModel(sta1ErrorModel);
455  staPhy->SetDevice(staDev);
456  staPhy->AddChannel(spectrumChannel);
457  staPhy->ConfigureStandard(std::get<0>(staParams));
458  staPhy->SetReceiveOkCallback(
460  staPhy->SetReceiveErrorCallback(
462  auto staMobility = CreateObject<ConstantPositionMobilityModel>();
463  staPhy->SetMobility(staMobility);
464  staDev->SetPhy(staPhy);
465  staNode->AggregateObject(staMobility);
466  staNode->AddDevice(staDev);
467  m_phyStas.push_back(staPhy);
468  m_countRxSuccessStas.push_back(0);
469  m_countRxFailureStas.push_back(0);
470  }
471 
472  if (!m_per20MhzInterference.empty())
473  {
474  [[maybe_unused]] auto [channelNum, centerFreq, apChannelWidth, type, phyBand] =
475  (*WifiPhyOperatingChannel::FindFirst(0,
477  0,
478  m_apStandard,
480  NS_ASSERT(m_per20MhzInterference.size() == (apChannelWidth / 20));
481  for (std::size_t i = 0; i < m_per20MhzInterference.size(); ++i)
482  {
483  auto interfererNode = CreateObject<Node>();
484  auto interfererDev = CreateObject<NonCommunicatingNetDevice>();
485  auto phyInterferer = CreateObject<WaveformGenerator>();
486  phyInterferer->SetDevice(interfererDev);
487  phyInterferer->SetChannel(spectrumChannel);
488  phyInterferer->SetDutyCycle(1);
489  interfererNode->AddDevice(interfererDev);
490  m_phyInterferers.push_back(phyInterferer);
491  }
492  }
493 }
494 
495 void
497 {
498  m_phyAp->Dispose();
499  m_phyAp = nullptr;
500  for (auto phySta : m_phyStas)
501  {
502  phySta->Dispose();
503  phySta = nullptr;
504  }
505  for (auto phyInterferer : m_phyInterferers)
506  {
507  phyInterferer->Dispose();
508  phyInterferer = nullptr;
509  }
510 }
511 
512 void
514 {
515  RngSeedManager::SetSeed(1);
516  RngSeedManager::SetRun(1);
517  int64_t streamNumber = 0;
518  m_phyAp->AssignStreams(streamNumber);
519  for (auto phySta : m_phyStas)
520  {
521  phySta->AssignStreams(streamNumber);
522  }
523 
524  [[maybe_unused]] auto [apChannelNum, centerFreq, apChannelWidth, type, phyBand] =
525  (*WifiPhyOperatingChannel::FindFirst(0,
527  0,
528  m_apStandard,
531  WifiPhy::ChannelTuple{apChannelNum, apChannelWidth, WIFI_PHY_BAND_5GHZ, m_apP20Index});
532 
533  auto index = 0;
534  for (const auto& [staStandard, staFrequency, staP20Index] : m_stasParams)
535  {
536  [[maybe_unused]] auto [staChannelNum, centerFreq, staChannelWidth, type, phyBand] =
537  (*WifiPhyOperatingChannel::FindFirst(0,
538  staFrequency,
539  0,
540  staStandard,
542  m_phyStas.at(index++)->SetOperatingChannel(
543  WifiPhy::ChannelTuple{staChannelNum, staChannelWidth, WIFI_PHY_BAND_5GHZ, staP20Index});
544  }
545 
546  index = 0;
547  const auto minApCenterFrequency =
548  m_phyAp->GetFrequency() - (m_phyAp->GetChannelWidth() / 2) + (20 / 2);
549  for (auto channelWidth = 20; channelWidth <= apChannelWidth; channelWidth *= 2, ++index)
550  {
551  if (!m_phyInterferers.empty())
552  {
553  for (std::size_t i = 0; i < m_phyInterferers.size(); ++i)
554  {
555  if (!m_per20MhzInterference.at(i))
556  {
557  continue;
558  }
559  BandInfo bandInfo;
560  bandInfo.fc = (minApCenterFrequency + (i * 20)) * 1e6;
561  bandInfo.fl = bandInfo.fc - (5 * 1e6);
562  bandInfo.fh = bandInfo.fc + (5 * 1e6);
563  Bands bands;
564  bands.push_back(bandInfo);
565  auto spectrumInterference = Create<SpectrumModel>(bands);
566  auto interferencePsd = Create<SpectrumValue>(spectrumInterference);
567  auto interferencePower = 0.005; // in watts (designed to make PHY headers reception
568  // successful but payload reception fail)
569  *interferencePsd = interferencePower / 10e6;
570  Simulator::Schedule(Seconds(index),
572  this,
573  m_phyInterferers.at(i),
574  interferencePsd,
575  Seconds(0.5));
576  }
577  }
578  const auto apCenterFreq =
580  const auto apMinFreq = apCenterFreq - (channelWidth / 2);
581  const auto apMaxFreq = apCenterFreq + (channelWidth / 2);
582  Simulator::Schedule(Seconds(index + 0.1),
584  this,
585  channelWidth);
586  for (std::size_t i = 0; i < m_stasParams.size(); ++i)
587  {
588  const auto p20Width = 20;
589  const auto staP20Freq =
590  m_phyStas.at(i)->GetOperatingChannel().GetPrimaryChannelCenterFrequency(p20Width);
591  const auto staP20MinFreq = staP20Freq - (p20Width / 2);
592  const auto staP20MaxFreq = staP20Freq + (p20Width / 2);
593  bool expectRx = (staP20MinFreq >= apMinFreq && staP20MaxFreq <= apMaxFreq);
594  bool expectSuccess = true;
595  if (!m_per20MhzInterference.empty())
596  {
597  const auto index20MhzSubBand = ((staP20Freq - minApCenterFrequency) / 20);
598  expectSuccess = !m_per20MhzInterference.at(index20MhzSubBand);
599  }
600  Simulator::Schedule(Seconds(index + 0.5),
602  this,
603  i,
604  expectRx ? expectSuccess : 0,
605  expectRx ? !expectSuccess : 0);
606  }
607  Simulator::Schedule(Seconds(index + 0.5),
609  this);
610  }
611 
612  Simulator::Run();
613  Simulator::Destroy();
614 }
615 
630 {
631  public:
633  struct CtsTxInfos
634  {
635  uint16_t bw{20};
636  bool discard{false};
637  };
638 
643  TestMultipleCtsResponsesFromMuRts(const std::vector<CtsTxInfos>& ctsTxInfosPerSta);
644 
645  private:
646  void DoSetup() override;
647  void DoTeardown() override;
648  void DoRun() override;
649 
653  void FakePreviousMuRts();
654 
660  void TxNonHtDuplicateCts(std::size_t phyIndex);
661 
670  void RxCtsSuccess(std::size_t phyIndex,
671  Ptr<const WifiPsdu> psdu,
672  RxSignalInfo rxSignalInfo,
673  WifiTxVector txVector,
674  std::vector<bool> statusPerMpdu);
675 
681  void RxCtsFailure(std::size_t phyIndex, Ptr<const WifiPsdu> psdu);
682 
686  void CheckResults();
687 
689  std::vector<Ptr<MuRtsCtsSpectrumWifiPhy>> m_phyStas;
690 
691  std::vector<CtsTxInfos> m_ctsTxInfosPerSta;
692 
693  std::size_t
695  std::size_t
701 
703 };
704 
706  const std::vector<CtsTxInfos>& ctsTxInfosPerSta)
707  : TestCase{"test PHY reception of multiple CTS frames following a MU-RTS frame"},
708  m_ctsTxInfosPerSta{ctsTxInfosPerSta},
709  m_countApRxCtsSuccess{0},
710  m_countApRxCtsFailure{0},
711  m_countStaRxCtsSuccess{0},
712  m_countStaRxCtsFailure{0},
713  m_stasTxPowerDbm(10.0)
714 {
715 }
716 
717 void
719 {
720  NS_LOG_FUNCTION(this);
721 
722  const auto bw =
723  std::max_element(m_ctsTxInfosPerSta.cbegin(),
724  m_ctsTxInfosPerSta.cend(),
725  [](const auto& lhs, const auto& rhs) { return lhs.bw < rhs.bw; })
726  ->bw;
727  WifiTxVector txVector;
728  txVector.SetChannelWidth(bw); // only the channel width matters for this test
729 
730  // set the TXVECTOR and the UID of the previously transmitted MU-RTS in the AP PHY
731  m_phyAp->SetMuRtsTxVector(txVector);
732  m_phyAp->SetPpduUid(0);
733 
734  // set the UID of the previously received MU-RTS in the STAs PHYs
735  for (auto& phySta : m_phyStas)
736  {
737  phySta->SetPpduUid(0);
738  }
739 }
740 
741 void
743 {
744  const auto bw = m_ctsTxInfosPerSta.at(phyIndex).bw;
745  const auto discarded = m_ctsTxInfosPerSta.at(phyIndex).discard;
746  NS_LOG_FUNCTION(this << phyIndex << bw << discarded);
747 
748  if (discarded)
749  {
750  return;
751  }
752 
753  WifiTxVector txVector =
754  WifiTxVector(OfdmPhy::GetOfdmRate54Mbps(), // use less robust modulation for test purpose
755  0,
757  800,
758  1,
759  1,
760  0,
761  bw,
762  false,
763  false);
764  txVector.SetTriggerResponding(true);
765 
766  WifiMacHeader hdr;
768  hdr.SetDsNotFrom();
769  hdr.SetDsNotTo();
770  hdr.SetNoMoreFragments();
771  hdr.SetNoRetry();
772 
773  auto pkt = Create<Packet>();
774  auto mpdu = Create<WifiMpdu>(pkt, hdr);
775  auto psdu = Create<WifiPsdu>(mpdu, false);
776 
777  m_phyStas.at(phyIndex)->Send(psdu, txVector);
778 }
779 
780 void
782  Ptr<const WifiPsdu> psdu,
783  RxSignalInfo rxSignalInfo,
784  WifiTxVector txVector,
785  std::vector<bool> /*statusPerMpdu*/)
786 {
787  NS_LOG_FUNCTION(this << phyIndex << *psdu << rxSignalInfo << txVector);
788  std::vector<CtsTxInfos> successfulCtsInfos{};
789  std::copy_if(m_ctsTxInfosPerSta.cbegin(),
790  m_ctsTxInfosPerSta.cend(),
791  std::back_inserter(successfulCtsInfos),
792  [](const auto& info) { return !info.discard; });
793  const auto isAp = (phyIndex == 0);
794  if (isAp)
795  {
796  NS_TEST_EXPECT_MSG_EQ_TOL(rxSignalInfo.rssi,
797  WToDbm(DbmToW(m_stasTxPowerDbm) * successfulCtsInfos.size()),
798  0.1,
799  "RX power is not correct!");
800  }
801  auto expectedWidth =
802  std::max_element(successfulCtsInfos.cbegin(),
803  successfulCtsInfos.cend(),
804  [](const auto& lhs, const auto& rhs) { return lhs.bw < rhs.bw; })
805  ->bw;
806  if (!isAp)
807  {
808  expectedWidth = std::min(m_ctsTxInfosPerSta.at(phyIndex - 1).bw, expectedWidth);
809  }
811  expectedWidth,
812  "Incorrect channel width in TXVECTOR");
813  if (isAp)
814  {
816  }
817  else
818  {
820  }
821 }
822 
823 void
825 {
826  NS_LOG_FUNCTION(this << phyIndex << *psdu);
827  const auto isAp = (phyIndex == 0);
828  if (isAp)
829  {
831  }
832  else
833  {
835  }
836 }
837 
838 void
840 {
842  1,
843  "The number of successfully received CTS frames by AP is not correct!");
846  m_ctsTxInfosPerSta.size(),
847  "The number of successfully received CTS frames by non-participating STAs is not correct!");
849  0,
850  "The number of unsuccessfully received CTS frames by AP is not correct!");
852  0,
853  "The number of unsuccessfully received CTS frames by non-participating "
854  "STAs is not correct!");
855 }
856 
857 void
859 {
860  RngSeedManager::SetSeed(1);
861  RngSeedManager::SetRun(1);
862  int64_t streamNumber = 0;
863 
864  auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
865  auto lossModel = CreateObject<FriisPropagationLossModel>();
866  lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
867  spectrumChannel->AddPropagationLossModel(lossModel);
868  auto delayModel = CreateObject<ConstantSpeedPropagationDelayModel>();
869  spectrumChannel->SetPropagationDelayModel(delayModel);
870 
871  auto apNode = CreateObject<Node>();
872  auto apDev = CreateObject<WifiNetDevice>();
873  auto apMac = CreateObject<ApWifiMac>();
874  apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
875  apDev->SetMac(apMac);
876  m_phyAp = CreateObject<MuRtsCtsSpectrumWifiPhy>();
877  apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
878  auto apInterferenceHelper = CreateObject<InterferenceHelper>();
879  m_phyAp->SetInterferenceHelper(apInterferenceHelper);
880  auto apErrorModel = CreateObject<NistErrorRateModel>();
881  m_phyAp->SetErrorRateModel(apErrorModel);
882  m_phyAp->SetDevice(apDev);
883  m_phyAp->AddChannel(spectrumChannel);
885  m_phyAp->AssignStreams(streamNumber);
886 
891 
892  const auto apBw =
893  std::max_element(m_ctsTxInfosPerSta.cbegin(),
894  m_ctsTxInfosPerSta.cend(),
895  [](const auto& lhs, const auto& rhs) { return lhs.bw < rhs.bw; })
896  ->bw;
897  auto apChannelNum = std::get<0>(
898  *WifiPhyOperatingChannel::FindFirst(0, 0, apBw, WIFI_STANDARD_80211ac, WIFI_PHY_BAND_5GHZ));
899 
901 
902  auto apMobility = CreateObject<ConstantPositionMobilityModel>();
903  m_phyAp->SetMobility(apMobility);
904  apDev->SetPhy(m_phyAp);
905  apDev->SetStandard(WIFI_STANDARD_80211ax);
906  apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
907  apMac->SetWifiPhys({m_phyAp});
908  apNode->AggregateObject(apMobility);
909  apNode->AddDevice(apDev);
910 
911  for (std::size_t i = 0; i < m_ctsTxInfosPerSta.size(); ++i)
912  {
913  auto staNode = CreateObject<Node>();
914  auto staDev = CreateObject<WifiNetDevice>();
915  auto phySta = CreateObject<MuRtsCtsSpectrumWifiPhy>();
916  auto staInterferenceHelper = CreateObject<InterferenceHelper>();
917  phySta->SetInterferenceHelper(staInterferenceHelper);
918  auto staErrorModel = CreateObject<NistErrorRateModel>();
919  phySta->SetErrorRateModel(staErrorModel);
920  phySta->SetDevice(staDev);
921  phySta->AddChannel(spectrumChannel);
922  phySta->ConfigureStandard(WIFI_STANDARD_80211ax);
923  phySta->AssignStreams(streamNumber);
924  phySta->SetTxPowerStart(m_stasTxPowerDbm);
925  phySta->SetTxPowerEnd(m_stasTxPowerDbm);
926 
927  auto channelNum =
928  std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
929  0,
930  m_ctsTxInfosPerSta.at(i).bw,
933 
934  phySta->SetOperatingChannel(
936 
937  auto staMobility = CreateObject<ConstantPositionMobilityModel>();
938  phySta->SetMobility(staMobility);
939  staDev->SetPhy(phySta);
940  staDev->SetStandard(WIFI_STANDARD_80211ax);
941  staDev->SetHeConfiguration(CreateObject<HeConfiguration>());
942  staNode->AggregateObject(staMobility);
943  staNode->AddDevice(staDev);
944  m_phyStas.push_back(phySta);
945 
946  // non-participating HE STA
947  auto nonParticipatingHeStaNode = CreateObject<Node>();
948  auto nonParticipatingHeStaDev = CreateObject<WifiNetDevice>();
949  auto nonParticipatingHePhySta = CreateObject<SpectrumWifiPhy>();
950  auto nonParticipatingHeStaInterferenceHelper = CreateObject<InterferenceHelper>();
951  nonParticipatingHePhySta->SetInterferenceHelper(nonParticipatingHeStaInterferenceHelper);
952  auto nonParticipatingHeStaErrorModel = CreateObject<NistErrorRateModel>();
953  nonParticipatingHePhySta->SetErrorRateModel(nonParticipatingHeStaErrorModel);
954  nonParticipatingHePhySta->SetDevice(nonParticipatingHeStaDev);
955  nonParticipatingHePhySta->AddChannel(spectrumChannel);
956  nonParticipatingHePhySta->ConfigureStandard(WIFI_STANDARD_80211ax);
957 
958  nonParticipatingHePhySta->SetOperatingChannel(
960 
961  auto nonParticipatingHeStaMobility = CreateObject<ConstantPositionMobilityModel>();
962  nonParticipatingHePhySta->SetMobility(nonParticipatingHeStaMobility);
963  nonParticipatingHeStaDev->SetPhy(nonParticipatingHePhySta);
964  nonParticipatingHeStaDev->SetStandard(WIFI_STANDARD_80211ax);
965  nonParticipatingHeStaDev->SetHeConfiguration(CreateObject<HeConfiguration>());
966  nonParticipatingHePhySta->AssignStreams(streamNumber);
967  nonParticipatingHeStaNode->AggregateObject(nonParticipatingHeStaMobility);
968  nonParticipatingHeStaNode->AddDevice(nonParticipatingHeStaDev);
969 
970  nonParticipatingHePhySta->SetReceiveOkCallback(
972  nonParticipatingHePhySta->SetReceiveErrorCallback(
974  }
975 
976  // non-HE STA
977  auto nonHeStaNode = CreateObject<Node>();
978  auto nonHeStaDev = CreateObject<WifiNetDevice>();
979  auto nonHePhySta = CreateObject<SpectrumWifiPhy>();
980  auto nonHeStaInterferenceHelper = CreateObject<InterferenceHelper>();
981  nonHePhySta->SetInterferenceHelper(nonHeStaInterferenceHelper);
982  auto nonHeStaErrorModel = CreateObject<NistErrorRateModel>();
983  nonHePhySta->SetErrorRateModel(nonHeStaErrorModel);
984  nonHePhySta->SetDevice(nonHeStaDev);
985  nonHePhySta->AddChannel(spectrumChannel);
986  nonHePhySta->ConfigureStandard(WIFI_STANDARD_80211ac);
987  nonHePhySta->SetOperatingChannel(
988  WifiPhy::ChannelTuple{apChannelNum, apBw, WIFI_PHY_BAND_5GHZ, 0});
989  auto nonHeStaMobility = CreateObject<ConstantPositionMobilityModel>();
990  nonHePhySta->SetMobility(nonHeStaMobility);
991  nonHeStaDev->SetPhy(nonHePhySta);
992  nonHeStaDev->SetStandard(WIFI_STANDARD_80211ac);
993  nonHePhySta->AssignStreams(streamNumber);
994  nonHeStaNode->AggregateObject(nonHeStaMobility);
995  nonHeStaNode->AddDevice(nonHeStaDev);
996 }
997 
998 void
1000 {
1001  m_phyAp->Dispose();
1002  m_phyAp = nullptr;
1003  for (auto& phySta : m_phyStas)
1004  {
1005  phySta->Dispose();
1006  phySta = nullptr;
1007  }
1008  m_phyStas.clear();
1009 }
1010 
1011 void
1013 {
1014  // Fake transmission of a MU-RTS frame preceding the CTS responses
1015  Simulator::Schedule(Seconds(0.0), &TestMultipleCtsResponsesFromMuRts::FakePreviousMuRts, this);
1016 
1017  for (std::size_t index = 0; index < m_phyStas.size(); ++index)
1018  {
1019  // Transmit CTS responses over their operating bandwidth with 1 nanosecond delay between
1020  // each other
1021  const auto delay = (index + 1) * NanoSeconds(1.0);
1022  Simulator::Schedule(delay,
1024  this,
1025  index);
1026  }
1027 
1028  // Verify successful reception of the CTS frames: since multiple copies are sent
1029  // simultaneously, a single CTS frame should be forwarded up to the MAC.
1030  Simulator::Schedule(Seconds(1.0), &TestMultipleCtsResponsesFromMuRts::CheckResults, this);
1031 
1032  Simulator::Run();
1033  Simulator::Destroy();
1034 }
1035 
1043 {
1044  public:
1046 };
1047 
1049  : TestSuite("wifi-non-ht-dup", UNIT)
1050 {
1086  5210,
1087  0,
1088  {{WIFI_STANDARD_80211a, 5180, 0},
1089  {WIFI_STANDARD_80211n, 5200, 0},
1090  {WIFI_STANDARD_80211ac, 5230, 0}}),
1091  TestCase::QUICK);
1092  /* same channel map and test scenario as previously but inject interference on channel 40 */
1094  5210,
1095  0,
1096  {{WIFI_STANDARD_80211a, 5180, 0},
1097  {WIFI_STANDARD_80211n, 5200, 0},
1098  {WIFI_STANDARD_80211ac, 5230, 0}},
1099  {false, true, false, false}),
1100  TestCase::QUICK);
1101  /* test PHY reception of multiple CTS responses following a MU-RTS */
1102  /* 4 STAs operating on 20 MHz */
1103  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{20}, {20}, {20}, {20}}), TestCase::QUICK);
1104  /* 4 STAs operating on 40 MHz */
1105  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{40}, {40}, {40}, {40}}), TestCase::QUICK);
1106  /* 4 STAs operating on 80 MHz */
1107  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{80}, {80}, {80}, {80}}), TestCase::QUICK);
1108  /* 4 STAs operating on 160 MHz */
1109  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{160}, {160}, {160}, {160}}),
1110  TestCase::QUICK);
1111  /* 4 STAs operating on different bandwidths with PPDUs sent with decreasing BW: 160, 80, 40 and
1112  * 20 MHz */
1113  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{160}, {80}, {40}, {20}}), TestCase::QUICK);
1114  /* 4 STAs operating on different bandwidths with PPDUs sent with increasing BW: 20, 40, 80 and
1115  * 160 MHz */
1116  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{20}, {40}, {80}, {160}}), TestCase::QUICK);
1117  /* 2 STAs operating on different bandwidths with PPDUs sent with decreasing BW but the first STA
1118  * does not respond */
1119  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{80, true}, {40, false}}), TestCase::QUICK);
1120  /* 2 STAs operating on different bandwidths with PPDUs sent with decreasing BW but the second
1121  * STA does not respond */
1122  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{80, false}, {40, true}}), TestCase::QUICK);
1123  /* 2 STAs operating on different bandwidths with PPDUs sent with increasing BW but the first STA
1124  * does not respond */
1125  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{40, true}, {80, false}}), TestCase::QUICK);
1126  /* 2 STAs operating on different bandwidths with PPDUs sent with increasing BW but the second
1127  * STA does not respond */
1128  AddTestCase(new TestMultipleCtsResponsesFromMuRts({{40, false}, {80, true}}), TestCase::QUICK);
1129 }
1130 
#define min(a, b)
Definition: 80211b.c:41
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.
TestMultipleCtsResponsesFromMuRts(const std::vector< CtsTxInfos > &ctsTxInfosPerSta)
Constructor.
std::size_t m_countApRxCtsFailure
count the number of unsuccessfully received CTS frames by the AP
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::size_t m_countStaRxCtsFailure
count the number of unsuccessfully received CTS frames by the non-participating STA
void RxCtsSuccess(std::size_t phyIndex, Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
CTS RX success function.
void FakePreviousMuRts()
Function called to fake the transmission of a MU-RTS.
std::vector< CtsTxInfos > m_ctsTxInfosPerSta
information about CTS responses
std::vector< Ptr< MuRtsCtsSpectrumWifiPhy > > m_phyStas
STAs PHYs.
void TxNonHtDuplicateCts(std::size_t phyIndex)
Function called to trigger a CTS frame sent by a STA using non-HT duplicate.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
std::size_t m_countApRxCtsSuccess
count the number of successfully received CTS frames by the AP
Ptr< MuRtsCtsSpectrumWifiPhy > m_phyAp
AP PHY.
void RxCtsFailure(std::size_t phyIndex, Ptr< const WifiPsdu > psdu)
CTS RX failure function.
double m_stasTxPowerDbm
TX power in dBm configured for the STAs.
std::size_t m_countStaRxCtsSuccess
count the number of successfully received CTS frames by the non-participating STA
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
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:567
uint64_t m_previouslyTxPpduUid
UID of the previously sent PPDU, used by AP to recognize response HE TB PPDUs.
Definition: he-phy.h:556
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 SetDevice(const Ptr< WifiNetDevice > device) override
Sets the device this PHY is associated with.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void 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:631
void Send(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
This function is a wrapper for the Send variant that accepts a WifiConstPsduMap as first argument.
Definition: wifi-phy.cc:1720
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:639
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:1051
uint16_t GetFrequency() const
Definition: wifi-phy.cc:1039
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:455
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:961
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1507
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1298
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:1098
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1021
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1278
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:891
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:619
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:449
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1033
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: wifi-phy.cc:2227
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.
uint16_t GetChannelWidth() const
#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:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
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:704
std::vector< BandInfo > Bands
Container of BandInfo.
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
@ WIFI_MAC_CTL_CTS
@ WIFI_MAC_QOSDATA
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
Information about CTS responses to expect in the test.
uint16_t bw
the width in MHz of the CTS response
bool discard
flag whether the CTS response shall be discarded
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
double rssi
RSSI in dBm.
Definition: phy-entity.h:71
static WifiNonHtDuplicateTestSuite wifiNonHtDuplicateTestSuite
the test suite
constexpr uint32_t DEFAULT_FREQUENCY