A Discrete-Event Network Simulator
API
wifi-primary-channels-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
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: Stefano Avallone <stavallo@unina.it>
19  */
20 
21 #include "ns3/test.h"
22 #include "ns3/wifi-net-device.h"
23 #include "ns3/mobility-helper.h"
24 #include "ns3/spectrum-wifi-helper.h"
25 #include "ns3/multi-model-spectrum-channel.h"
26 #include "ns3/config.h"
27 #include "ns3/rng-seed-manager.h"
28 #include "ns3/wifi-psdu.h"
29 #include "ns3/ap-wifi-mac.h"
30 #include "ns3/sta-wifi-mac.h"
31 #include "ns3/he-phy.h"
32 #include "ns3/he-configuration.h"
33 #include "ns3/ctrl-headers.h"
34 #include <bitset>
35 #include <algorithm>
36 #include <sstream>
37 
38 using namespace ns3;
39 
40 NS_LOG_COMPONENT_DEFINE ("WifiPrimaryChannelsTest");
41 
59 {
60 public:
67  WifiPrimaryChannelsTest (uint16_t channelWidth, bool useDistinctBssColors);
68  virtual ~WifiPrimaryChannelsTest ();
69 
79  void Transmit (std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW);
87  void SendDlSuPpdu (uint8_t bss, uint16_t txChannelWidth);
97  void SendDlMuPpdu (uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus);
108  void SendHeTbPpdu (uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus);
118  void DoSendHeTbPpdu (uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus);
129  void ReceiveDl (uint8_t bss, uint8_t station, Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
130  WifiTxVector txVector, std::vector<bool> perMpduStatus);
140  void ReceiveUl (uint8_t bss, Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
141  WifiTxVector txVector, std::vector<bool> perMpduStatus);
145  void CheckAssociation (void);
156  void CheckReceivedSuPpdus (std::set<uint8_t> txBss, uint16_t txChannelWidth);
170  void CheckReceivedMuPpdus (std::set<uint8_t> txBss, uint16_t txChannelWidth, HeRu::RuType ruType,
171  std::size_t nRus, bool isDlMu);
181  void CheckReceivedTriggerFrames (std::set<uint8_t> txBss, uint16_t txChannelWidth);
182 
183 private:
184  void DoSetup (void) override;
185  void DoRun (void) override;
186 
187  uint16_t m_channelWidth;
189  uint8_t m_nBss;
191  std::vector<NetDeviceContainer> m_staDevices;
193  std::vector<std::bitset<74>> m_received;
195  std::vector<std::bitset<74>> m_processed;
201 };
202 
203 WifiPrimaryChannelsTest::WifiPrimaryChannelsTest (uint16_t channelWidth, bool useDistinctBssColors)
204  : TestCase ("Check correct transmissions for various primary channel settings"),
205  m_channelWidth (channelWidth),
206  m_useDistinctBssColors (useDistinctBssColors)
207 {
208 }
209 
211 {
212 }
213 
214 void
215 WifiPrimaryChannelsTest::Transmit (std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
216 {
217  for (const auto& psduPair : psduMap)
218  {
219  std::stringstream ss;
220 
221  if (psduPair.first != SU_STA_ID)
222  {
223  ss << " STA-ID " << psduPair.first;
224  }
225  ss << " " << psduPair.second->GetHeader (0).GetTypeString ()
226  << " seq " << psduPair.second->GetHeader (0).GetSequenceNumber ()
227  << " from " << psduPair.second->GetAddr2 ()
228  << " to " << psduPair.second->GetAddr1 ();
229  NS_LOG_INFO (ss.str ());
230  }
231  NS_LOG_INFO (" TXVECTOR " << txVector);
232 }
233 
234 void
235 WifiPrimaryChannelsTest::ReceiveDl (uint8_t bss, uint8_t station, Ptr<WifiPsdu> psdu,
236  RxSignalInfo rxSignalInfo, WifiTxVector txVector,
237  std::vector<bool> perMpduStatus)
238 {
239  if (psdu->GetNMpdus () == 1)
240  {
241  const WifiMacHeader& hdr = psdu->GetHeader (0);
242 
243  if (hdr.IsQosData () || hdr.IsTrigger ())
244  {
245  NS_LOG_INFO ("RECEIVED BY BSS=" << +bss << " STA=" << +station << " " << *psdu);
246  // the MAC received a PSDU from the PHY
247  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (station), false, "Station [" << +bss << "]["
248  << +station << "] received a frame twice");
249  m_received[bss].set (station);
250  // check if we are the intended destination of the PSDU
251  auto dev = DynamicCast<WifiNetDevice> (m_staDevices[bss].Get (station));
252  if ((hdr.IsQosData () && hdr.GetAddr1 () == dev->GetMac ()->GetAddress ())
253  || (hdr.IsTrigger () && hdr.GetAddr1 () == Mac48Address::GetBroadcast ()))
254  {
255  NS_TEST_EXPECT_MSG_EQ (m_processed[bss].test (station), false, "Station [" << +bss << "]["
256  << +station << "] processed a frame twice");
257  m_processed[bss].set (station);
258  }
259  }
260  }
261 }
262 
263 void
265  WifiTxVector txVector, std::vector<bool> perMpduStatus)
266 {
267  // if the BSS color is zero, this AP might receive the frame sent by another AP. Given that
268  // stations only send TB PPDUs, we discard this frame if the TX vector is UL MU.
269  if (psdu->GetNMpdus () == 1 && psdu->GetHeader (0).IsQosData () && txVector.IsUlMu ())
270  {
271  auto dev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
272 
273  uint16_t staId = txVector.GetHeMuUserInfoMap ().begin ()->first;
274  uint8_t station = staId - 1;
275  NS_LOG_INFO ("RECEIVED FROM BSS=" << +bss << " STA=" << +station
276  << " " << *psdu);
277  // the MAC received a PSDU containing a QoS data frame from the PHY
278  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (station), false, "AP of BSS " << +bss
279  << " received a frame from station " << +station << " twice");
280  m_received[bss].set (station);
281  // check if we are the intended destination of the PSDU
282  if (psdu->GetHeader (0).GetAddr1 () == dev->GetMac ()->GetAddress ())
283  {
284  NS_TEST_EXPECT_MSG_EQ (m_processed[bss].test (station), false, "AP of BSS " << +bss
285  << " received a frame from station " << +station << " twice");
286  m_processed[bss].set (station);
287  }
288  }
289 }
290 
291 void
293 {
294  RngSeedManager::SetSeed (1);
295  RngSeedManager::SetRun (40);
296  int64_t streamNumber = 100;
297  uint16_t frequency;
298 
299  // we create as many stations per BSS as the number of 26-tone RUs in a channel
300  // of the configured width
301  switch (m_channelWidth)
302  {
303  case 20:
304  m_nStationsPerBss = 9;
305  frequency = 5180;
306  break;
307  case 40:
308  m_nStationsPerBss = 18;
309  frequency = 5190;
310  break;
311  case 80:
312  m_nStationsPerBss = 37;
313  frequency = 5210;
314  break;
315  case 160:
316  m_nStationsPerBss = 74;
317  frequency = 5250;
318  break;
319  default:
320  NS_ABORT_MSG ("Channel width (" << m_channelWidth << ") not allowed");
321  }
322 
323  // we create as many BSSes as the number of 20 MHz subchannels
324  m_nBss = m_channelWidth / 20;
325 
326  NodeContainer wifiApNodes;
327  wifiApNodes.Create (m_nBss);
328 
329  std::vector<NodeContainer> wifiStaNodes (m_nBss);
330  for (auto& container : wifiStaNodes)
331  {
332  container.Create (m_nStationsPerBss);
333  }
334 
335  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
336  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
337  spectrumChannel->AddPropagationLossModel (lossModel);
338  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
339  spectrumChannel->SetPropagationDelayModel (delayModel);
340 
342  phy.SetChannel (spectrumChannel);
343  phy.Set ("Frequency", UintegerValue (frequency)); // same frequency for all BSSes
344 
346  wifi.SetStandard (WIFI_STANDARD_80211ax_5GHZ);
347  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager");
348 
350  mac.SetType ("ns3::StaWifiMac",
351  "Ssid", SsidValue (Ssid ("non-existent-ssid")),
352  "WaitBeaconTimeout", TimeValue (MicroSeconds (102400))); // same as BeaconInterval
353 
354  // Each BSS uses a distinct primary20 channel
355  for (uint8_t bss = 0; bss < m_nBss; bss++)
356  {
357  phy.Set ("Primary20MHzIndex", UintegerValue (bss));
358 
359  m_staDevices.push_back (wifi.Install (phy, mac, wifiStaNodes[bss]));
360  }
361 
362  for (uint8_t bss = 0; bss < m_nBss; bss++)
363  {
364  phy.Set ("Primary20MHzIndex", UintegerValue (bss));
365 
366  mac.SetType ("ns3::ApWifiMac",
367  "Ssid", SsidValue (Ssid ("wifi-ssid-" + std::to_string (bss))),
368  "BeaconInterval", TimeValue (MicroSeconds (102400)),
369  "EnableBeaconJitter", BooleanValue (false));
370 
371  m_apDevices.Add (wifi.Install (phy, mac, wifiApNodes.Get (bss)));
372  }
373 
374  // Assign fixed streams to random variables in use
375  streamNumber = wifi.AssignStreams (m_apDevices, streamNumber);
376  for (uint8_t bss = 0; bss < m_nBss; bss++)
377  {
378  streamNumber = wifi.AssignStreams (m_staDevices[bss], streamNumber);
379  }
380 
381  // set BSS color
383  {
384  for (uint8_t bss = 0; bss < m_nBss; bss++)
385  {
386  auto dev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
387  dev->GetHeConfiguration ()->SetBssColor (bss + 1);
388  }
389  }
390 
392  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
393 
394  positionAlloc->Add (Vector (0.0, 0.0, 0.0)); // all stations are co-located
395  mobility.SetPositionAllocator (positionAlloc);
396 
397  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
398  mobility.Install (wifiApNodes);
399  for (uint8_t bss = 0; bss < m_nBss; bss++)
400  {
401  mobility.Install (wifiStaNodes[bss]);
402  }
403 
404  m_received.resize (m_nBss);
405  m_processed.resize (m_nBss);
406 
407  // pre-compute the Basic Trigger Frame to send
408  auto apDev = DynamicCast<WifiNetDevice> (m_apDevices.Get (0));
409 
410  WifiMacHeader hdr;
412  hdr.SetAddr1 (Mac48Address::GetBroadcast ());
413  // Addr2 has to be set
414  hdr.SetSequenceNumber (1);
415 
416  Ptr<Packet> pkt = Create<Packet> ();
417  CtrlTriggerHeader trigger;
419  pkt->AddHeader (trigger);
420 
421  m_triggerTxVector = WifiTxVector (OfdmPhy::GetOfdmRate6Mbps (), 0, WIFI_PREAMBLE_LONG, 800, 1, 1, 0,
422  20, false, false, false);
423  m_trigger = Create<WifiPsdu> (pkt, hdr);
424 
425  m_triggerTxDuration = WifiPhy::CalculateTxDuration (m_trigger->GetSize (), m_triggerTxVector,
426  apDev->GetMac ()->GetWifiPhy ()->GetPhyBand ());
427 }
428 
429 void
431 {
432  // schedule association requests at different times
433  Ptr<WifiNetDevice> dev;
434 
435  for (uint16_t i = 0; i < m_nStationsPerBss; i++)
436  {
437  // association can be done in parallel over the multiple BSSes
438  for (uint8_t bss = 0; bss < m_nBss; bss++)
439  {
440  dev = DynamicCast<WifiNetDevice> (m_staDevices[bss].Get (i));
441  Simulator::Schedule (i * MicroSeconds (102400), &WifiMac::SetSsid,
442  dev->GetMac (), Ssid ("wifi-ssid-" + std::to_string (bss)));
443  }
444  }
445 
446  // just before sending the beacon preceding the last association, increase the beacon
447  // interval (to the max allowed value) so that beacons do not interfere with data frames
448  for (uint8_t bss = 0; bss < m_nBss; bss++)
449  {
450  dev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
451  auto mac = DynamicCast<ApWifiMac> (dev->GetMac ());
452 
453  Simulator::Schedule ((m_nStationsPerBss - 1) * MicroSeconds (102400),
454  &ApWifiMac::SetBeaconInterval, mac, MicroSeconds (1024 * 65535));
455  }
456 
457  m_time = (m_nStationsPerBss + 1) * MicroSeconds (102400);
458 
459  Simulator::Schedule (m_time, &WifiPrimaryChannelsTest::CheckAssociation, this);
460 
461  // we are done with association. We now intercept frames received by the
462  // PHY layer on stations and APs, which will no longer be passed to the FEM.
463  for (uint8_t bss = 0; bss < m_nBss; bss++)
464  {
465  for (uint8_t i = 0; i < m_nStationsPerBss; i++)
466  {
467  auto dev = DynamicCast<WifiNetDevice> (m_staDevices[bss].Get (i));
468  Simulator::Schedule (m_time, &WifiPhy::SetReceiveOkCallback, dev->GetPhy (),
470  .TwoBind (bss, i));
471  }
472  auto dev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
473  Simulator::Schedule (m_time, &WifiPhy::SetReceiveOkCallback, dev->GetPhy (),
475  .Bind (bss));
476  }
477 
478  /*
479  * We start generating (downlink) SU PPDUs.
480  * First, APs operating on non-adjacent primary20 channels send a frame simultaneously
481  * in their primary20. This is done in two rounds. As an example, we consider the
482  * case of an 160 MHz operating channel:
483  *
484  * AP0 AP2 AP4 AP6
485  * |-----| |-----| |-----| |-----| |
486  *
487  * AP1 AP3 AP5 AP7
488  * | |-----| |-----| |-----| |-----|
489  *
490  * Then, we double the transmission channel width. We will have four rounds
491  * of transmissions. We avoid using adjacent channels to avoid interfence
492  * among transmissions:
493  *
494  * AP0 AP4
495  * |-----------| |-----------| |
496  * AP1 AP5
497  * |-----------| |-----------| |
498  * AP2 AP6
499  * | |-----------| |-----------|
500  * AP3 AP7
501  * | |-----------| |-----------|
502  *
503  * We double the transmission channel width again. We will have eight rounds
504  * of transmissions:
505  *
506  * AP0
507  * |-----------------------| |
508  * AP1
509  * |-----------------------| |
510  * AP2
511  * |-----------------------| |
512  * AP3
513  * |-----------------------| |
514  * AP4
515  * | |-----------------------|
516  * AP5
517  * | |-----------------------|
518  * AP6
519  * | |-----------------------|
520  * AP7
521  * | |-----------------------|
522  *
523  * We double the transmission channel width again. We will have eight rounds
524  * of transmissions:
525  *
526  * AP0
527  * |-----------------------------------------------|
528  * AP1
529  * |-----------------------------------------------|
530  * AP2
531  * |-----------------------------------------------|
532  * AP3
533  * |-----------------------------------------------|
534  * AP4
535  * |-----------------------------------------------|
536  * AP5
537  * |-----------------------------------------------|
538  * AP6
539  * |-----------------------------------------------|
540  * AP7
541  * |-----------------------------------------------|
542  *
543  * The transmission channel width reached the operating channel width, we are done.
544  */
545 
546  Time roundDuration = MilliSeconds (5); // upper bound on the duration of a round
547 
548  // To have simultaneous transmissions on adjacent channels, just initialize
549  // nRounds to 1 and nApsPerRound to m_channelWidth / 20. Of course, the test
550  // will fail because some stations will not receive some frames due to interfence
551  for (uint16_t txChannelWidth = 20, nRounds = 2, nApsPerRound = m_channelWidth / 20 / 2;
552  txChannelWidth <= m_channelWidth;
553  txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
554  {
555  nRounds = std::min<uint16_t> (nRounds, m_nBss);
556  nApsPerRound = std::max<uint16_t> (nApsPerRound, 1);
557 
558  for (uint16_t round = 0; round < nRounds; round++)
559  {
560  std::set<uint8_t> txBss;
561 
562  for (uint16_t i = 0; i < nApsPerRound; i++)
563  {
564  uint16_t ap = round + i * nRounds;
565  txBss.insert (ap);
566  Simulator::Schedule (m_time, &WifiPrimaryChannelsTest::SendDlSuPpdu, this,
567  ap, txChannelWidth);
568  }
569  // check that the SU frames were correctly received
570  Simulator::Schedule (m_time + roundDuration, &WifiPrimaryChannelsTest::CheckReceivedSuPpdus,
571  this, txBss, txChannelWidth);
572  m_time += roundDuration;
573  }
574  }
575 
576  /*
577  * Repeat the same scheme as before with DL MU transmissions. For each transmission
578  * channel width, every round is repeated as many times as the number of ways in
579  * which we can partition the transmission channel width in equal sized RUs.
580  */
581  for (uint16_t txChannelWidth = 20, nRounds = 2, nApsPerRound = m_channelWidth / 20 / 2;
582  txChannelWidth <= m_channelWidth;
583  txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
584  {
585  nRounds = std::min<uint16_t> (nRounds, m_nBss);
586  nApsPerRound = std::max<uint16_t> (nApsPerRound, 1);
587 
588  for (uint16_t round = 0; round < nRounds; round++)
589  {
590  for (unsigned int type = 0; type < 7; type++)
591  {
592  HeRu::RuType ruType = static_cast <HeRu::RuType> (type);
593  std::size_t nRus = HeRu::GetNRus (txChannelWidth, ruType);
594  std::set<uint8_t> txBss;
595  if (nRus > 0)
596  {
597  for (uint16_t i = 0; i < nApsPerRound; i++)
598  {
599  uint16_t ap = round + i * nRounds;
600  txBss.insert (ap);
601  Simulator::Schedule (m_time, &WifiPrimaryChannelsTest::SendDlMuPpdu, this,
602  ap, txChannelWidth, ruType, nRus);
603  }
604  // check that the MU frame was correctly received
605  Simulator::Schedule (m_time + roundDuration, &WifiPrimaryChannelsTest::CheckReceivedMuPpdus,
606  this, txBss, txChannelWidth, ruType, nRus, /* isDlMu */ true);
607  m_time += roundDuration;
608  }
609  }
610  }
611  }
612 
613  /*
614  * Repeat the same scheme as before with DL MU transmissions. For each transmission
615  * channel width, every round is repeated as many times as the number of ways in
616  * which we can partition the transmission channel width in equal sized RUs.
617  */
618  for (uint16_t txChannelWidth = 20, nRounds = 2, nApsPerRound = m_channelWidth / 20 / 2;
619  txChannelWidth <= m_channelWidth;
620  txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
621  {
622  nRounds = std::min<uint16_t> (nRounds, m_nBss);
623  nApsPerRound = std::max<uint16_t> (nApsPerRound, 1);
624 
625  for (uint16_t round = 0; round < nRounds; round++)
626  {
627  for (unsigned int type = 0; type < 7; type++)
628  {
629  HeRu::RuType ruType = static_cast <HeRu::RuType> (type);
630  std::size_t nRus = HeRu::GetNRus (txChannelWidth, ruType);
631  std::set<uint8_t> txBss;
632  if (nRus > 0)
633  {
634  for (uint16_t i = 0; i < nApsPerRound; i++)
635  {
636  uint16_t ap = round + i * nRounds;
637  txBss.insert (ap);
638  Simulator::Schedule (m_time, &WifiPrimaryChannelsTest::SendHeTbPpdu, this,
639  ap, txChannelWidth, ruType, nRus);
640  }
641  // check that Trigger Frames and TB PPDUs were correctly received
642  Simulator::Schedule (m_time + m_triggerTxDuration + MicroSeconds (10), /* during SIFS */
644  this, txBss, txChannelWidth);
645  Simulator::Schedule (m_time + roundDuration, &WifiPrimaryChannelsTest::CheckReceivedMuPpdus,
646  this, txBss, txChannelWidth, ruType, nRus, /* isDlMu */ false);
647  m_time += roundDuration;
648  }
649  }
650  }
651  }
652 
653  // Trace PSDUs passed to the PHY on all devices
654  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
656 
657  Simulator::Stop (m_time);
658  Simulator::Run ();
659 
660  Simulator::Destroy ();
661 }
662 
663 void
664 WifiPrimaryChannelsTest::SendDlSuPpdu (uint8_t bss, uint16_t txChannelWidth)
665 {
666  NS_LOG_INFO ("*** BSS " << +bss << " transmits on primary " << txChannelWidth << " MHz channel");
667 
668  auto apDev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
669  auto staDev = DynamicCast<WifiNetDevice> (m_staDevices[bss].Get (0));
670 
671  uint8_t bssColor = apDev->GetHeConfiguration ()->GetBssColor ();
672  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs8 (), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, txChannelWidth, false, false, false, bssColor);
673  WifiMacHeader hdr;
675  hdr.SetQosTid (0);
676  hdr.SetAddr1 (staDev->GetMac ()->GetAddress ());
677  hdr.SetAddr2 (apDev->GetMac ()->GetAddress ());
678  hdr.SetAddr3 (apDev->GetMac ()->GetBssid ());
679  hdr.SetSequenceNumber (1);
680  Ptr<WifiPsdu> psdu = Create<WifiPsdu> (Create<Packet> (1000), hdr);
681  apDev->GetPhy ()->Send (WifiConstPsduMap ({std::make_pair (SU_STA_ID, psdu)}), txVector);
682 }
683 
684 void
685 WifiPrimaryChannelsTest::SendDlMuPpdu (uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
686 {
687  NS_LOG_INFO ("*** BSS " << +bss << " transmits on primary " << txChannelWidth
688  << " MHz channel a DL MU PPDU " << "addressed to " << nRus
689  << " stations (RU type: " << ruType << ")");
690 
691  auto apDev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
692  uint8_t bssColor = apDev->GetHeConfiguration ()->GetBssColor ();
693 
694  WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs8 (), 0, WIFI_PREAMBLE_HE_MU, 800, 1, 1, 0, txChannelWidth, false, false, false, bssColor);
695  WifiMacHeader hdr;
697  hdr.SetQosTid (0);
698  hdr.SetAddr2 (apDev->GetMac ()->GetAddress ());
699  hdr.SetAddr3 (apDev->GetMac ()->GetBssid ());
700  hdr.SetSequenceNumber (1);
701 
702  WifiConstPsduMap psduMap;
703 
704  for (std::size_t i = 1; i <= nRus; i++)
705  {
706  std::size_t index = (txChannelWidth == 160 && i > nRus / 2 ? i - nRus / 2 : i);
707  bool primary80 = (txChannelWidth == 160 && i > nRus / 2 ? false : true);
708 
709  auto staDev = DynamicCast<WifiNetDevice> (m_staDevices[bss].Get (i - 1));
710  uint16_t staId = DynamicCast<StaWifiMac> (staDev->GetMac ())->GetAssociationId ();
711  txVector.SetHeMuUserInfo (staId, {{ruType, index, primary80}, HePhy::GetHeMcs8 (), 1});
712  hdr.SetAddr1 (staDev->GetMac ()->GetAddress ());
713  psduMap[staId] = Create<const WifiPsdu> (Create<Packet> (1000), hdr);
714  }
715  apDev->GetPhy ()->Send (psduMap, txVector);
716 }
717 
718 void
719 WifiPrimaryChannelsTest::SendHeTbPpdu (uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
720 {
721  NS_LOG_INFO ("*** BSS " << +bss << " transmits a Basic Trigger Frame");
722 
723  auto apDev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
724 
725  m_trigger->GetHeader (0).SetAddr2 (apDev->GetMac ()->GetAddress ());
726 
727  apDev->GetPhy ()->Send (m_trigger, m_triggerTxVector);
728 
729  // schedule the transmission of HE TB PPDUs
730  Simulator::Schedule (m_triggerTxDuration + apDev->GetPhy ()->GetSifs (),
732  bss, txChannelWidth, ruType, nRus);
733 }
734 
735 void
736 WifiPrimaryChannelsTest::DoSendHeTbPpdu (uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
737 {
738  auto apDev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
739  uint8_t bssColor = apDev->GetHeConfiguration ()->GetBssColor ();
740 
741  WifiMacHeader hdr;
743  hdr.SetQosTid (0);
744  hdr.SetAddr1 (apDev->GetMac ()->GetAddress ());
745  hdr.SetAddr3 (apDev->GetMac ()->GetBssid ());
746  hdr.SetSequenceNumber (1);
747 
748  Time duration = Seconds (0);
749  uint16_t length = 0;
750 
751  for (std::size_t i = 1; i <= nRus; i++)
752  {
753  NS_LOG_INFO ("*** BSS " << +bss << " STA " << i - 1 << " transmits on primary "
754  << txChannelWidth << " MHz channel an HE TB PPDU (RU type: " << ruType << ")");
755 
756  std::size_t index = (txChannelWidth == 160 && i > nRus / 2 ? i - nRus / 2 : i);
757  bool primary80 = (txChannelWidth == 160 && i > nRus / 2 ? false : true);
758 
759  auto staDev = DynamicCast<WifiNetDevice> (m_staDevices[bss].Get (i - 1));
760  uint16_t staId = DynamicCast<StaWifiMac> (staDev->GetMac ())->GetAssociationId ();
761 
762  WifiTxVector txVector (HePhy::GetHeMcs8 (), 0, WIFI_PREAMBLE_HE_TB, 3200, 1, 1, 0, txChannelWidth, false, false, false, bssColor);
763  txVector.SetHeMuUserInfo (staId, {{ruType, index, primary80}, HePhy::GetHeMcs8 (), 1});
764 
765  hdr.SetAddr2 (staDev->GetMac ()->GetAddress ());
766  Ptr<const WifiPsdu> psdu = Create<const WifiPsdu> (Create<Packet> (1000), hdr);
767 
768  if (duration.IsZero ())
769  {
770  // calculate just once
771  duration = WifiPhy::CalculateTxDuration (psdu->GetSize (), txVector,
772  staDev->GetMac ()->GetWifiPhy ()->GetPhyBand (), staId);
773  length = HePhy::ConvertHeTbPpduDurationToLSigLength (duration,
774  staDev->GetMac ()->GetWifiPhy ()->GetPhyBand ());
775  }
776  txVector.SetLength (length);
777 
778  staDev->GetPhy ()->Send (WifiConstPsduMap {{staId, psdu}}, txVector);
779  }
780 }
781 
782 void
784 {
785  for (uint8_t bss = 0; bss < m_nBss; bss++)
786  {
787  auto dev = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss));
788  auto mac = DynamicCast<ApWifiMac> (dev->GetMac ());
789  NS_TEST_EXPECT_MSG_EQ (mac->GetStaList ().size (), m_nStationsPerBss,
790  "Not all the stations completed association");
791  }
792 }
793 
794 void
795 WifiPrimaryChannelsTest::CheckReceivedSuPpdus (std::set<uint8_t> txBss, uint16_t txChannelWidth)
796 {
797  for (uint8_t bss = 0; bss < m_nBss; bss++)
798  {
799  if (txBss.find (bss) != txBss.end ())
800  {
801  // Every station in the BSS of an AP that transmitted the frame hears (i.e.,
802  // passes to the MAC) the frame
803  for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
804  {
805  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), true, "Station [" << +bss << "][" << +sta
806  << "] did not receive the SU frame on primary" << txChannelWidth << " channel");
807  }
808  // only the first station actually processed the frames
809  NS_TEST_EXPECT_MSG_EQ (m_processed[bss].test (0), true, "Station [" << +bss << "][0]"
810  << " did not process the SU frame on primary" << txChannelWidth << " channel");
811  for (uint8_t sta = 1; sta < m_nStationsPerBss; sta++)
812  {
813  NS_TEST_EXPECT_MSG_EQ (m_processed[bss].test (sta), false, "Station [" << +bss << "][" << +sta
814  << "] processed the SU frame on primary" << txChannelWidth << " channel");
815  }
816  }
817  else
818  {
819  // There was no transmission in this BSS. If BSS Color filtering is enabled or no frame
820  // transmission overlaps with the primary20 channel of this BSS, stations in this BSS
821  // did not hear any frame.
823  || std::none_of (txBss.begin (), txBss.end (),
824  [&](const uint8_t& txAp)
825  {
826  auto txApPhy = DynamicCast<WifiNetDevice> (m_apDevices.Get (txAp))->GetPhy ();
827  auto thisApPhy = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss))->GetPhy ();
828  return txApPhy->GetOperatingChannel ().GetPrimaryChannelIndex (txChannelWidth)
829  == thisApPhy->GetOperatingChannel ().GetPrimaryChannelIndex (txChannelWidth);
830  }))
831  {
832  for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
833  {
834  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), false, "Station [" << +bss << "][" << +sta
835  << "] received the SU frame on primary" << txChannelWidth << " channel");
836  }
837  }
838  else
839  {
840  // all stations heard the frame but no station processed it
841  for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
842  {
843  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), true, "Station [" << +bss << "][" << +sta
844  << "] did not receive the SU frame on primary" << txChannelWidth << " channel");
845  NS_TEST_EXPECT_MSG_EQ (m_processed[bss].test (sta), false, "Station [" << +bss << "][" << +sta
846  << "] processed the SU frame on primary" << txChannelWidth << " channel");
847  }
848  }
849  }
850  // reset bitmaps
851  m_received[bss].reset ();
852  m_processed[bss].reset ();
853  }
854 }
855 
856 void
857 WifiPrimaryChannelsTest::CheckReceivedMuPpdus (std::set<uint8_t> txBss, uint16_t txChannelWidth,
858  HeRu::RuType ruType, std::size_t nRus, bool isDlMu)
859 {
860  for (uint8_t bss = 0; bss < m_nBss; bss++)
861  {
862  if (txBss.find (bss) != txBss.end ())
863  {
864  // Due to AID filtering, only stations that are addressed by the MU PPDU do hear the frame
865  for (uint8_t sta = 0; sta < nRus; sta++)
866  {
867  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), true,
868  (isDlMu ? "A DL MU PPDU transmitted to" : "An HE TB PPDU transmitted by")
869  << " station [" << +bss << "][" << +sta << "] on primary"
870  << txChannelWidth << " channel, RU type " << ruType
871  << " was not received");
872  }
873  for (uint8_t sta = nRus; sta < m_nStationsPerBss; sta++)
874  {
875  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), false,
876  (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
877  << " transmitted on primary" << txChannelWidth
878  << " channel, RU type " << ruType << " was received "
879  << (isDlMu ? "by" : "from") << " station [" << +bss << "]["
880  << +sta << "]");
881  }
882  // only the addressed stations actually processed the frames
883  for (uint8_t sta = 0; sta < nRus; sta++)
884  {
885  NS_TEST_EXPECT_MSG_EQ (m_processed[bss].test (sta), true,
886  (isDlMu ? "A DL MU PPDU transmitted to" : "An HE TB PPDU transmitted by")
887  << " station [" << +bss << "][" << +sta << "] on primary"
888  << txChannelWidth << " channel, RU type " << ruType
889  << " was not processed");
890  }
891  for (uint8_t sta = nRus; sta < m_nStationsPerBss; sta++)
892  {
893  NS_TEST_EXPECT_MSG_EQ (m_processed[bss].test (sta), false,
894  (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
895  << " transmitted on primary" << txChannelWidth
896  << " channel, RU type " << ruType << " was received "
897  << (isDlMu ? "by" : "from") << " station [" << +bss << "]["
898  << +sta << "] and processed");
899  }
900  }
901  else
902  {
903  // There was no transmission in this BSS. If BSS Color filtering is enabled or no frame
904  // transmission overlaps with the primary20 channel of this BSS, stations in this BSS
905  // did not hear any frame.
907  || std::none_of (txBss.begin (), txBss.end (),
908  [&](const uint8_t& txAp)
909  {
910  auto txApPhy = DynamicCast<WifiNetDevice> (m_apDevices.Get (txAp))->GetPhy ();
911  auto thisApPhy = DynamicCast<WifiNetDevice> (m_apDevices.Get (bss))->GetPhy ();
912  return txApPhy->GetOperatingChannel ().GetPrimaryChannelIndex (txChannelWidth)
913  == thisApPhy->GetOperatingChannel ().GetPrimaryChannelIndex (txChannelWidth);
914  }))
915  {
916  for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
917  {
918  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), false,
919  (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
920  << " transmitted on primary" << txChannelWidth
921  << " channel, RU type " << ruType << " was received "
922  << (isDlMu ? "by" : "from") << " station [" << +bss << "]["
923  << +sta << "]");
924  }
925  }
926  else
927  {
928  // stations having the same AID of the stations addressed by the MU PPDI received the frame
929  for (uint8_t sta = 0; sta < nRus; sta++)
930  {
931  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), true,
932  (isDlMu ? "A DL MU PPDU transmitted to" : "An HE TB PPDU transmitted by")
933  << " station [" << +bss << "][" << +sta << "] on primary"
934  << txChannelWidth << " channel, RU type " << ruType
935  << " was not received");
936  }
937  for (uint8_t sta = nRus; sta < m_nStationsPerBss; sta++)
938  {
939  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), false,
940  (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
941  << " transmitted on primary" << txChannelWidth
942  << " channel, RU type " << ruType << " was received "
943  << (isDlMu ? "by" : "from") << " station [" << +bss << "]["
944  << +sta << "]");
945  }
946  // no station processed the frame
947  for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
948  {
949  NS_TEST_EXPECT_MSG_EQ (m_processed[bss].test (sta), false,
950  (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
951  << " transmitted on primary" << txChannelWidth
952  << " channel, RU type " << ruType << " was received "
953  << (isDlMu ? "by" : "from") << " station [" << +bss << "]["
954  << +sta << "] and processed");
955  }
956  }
957  }
958  // reset bitmaps
959  m_received[bss].reset ();
960  m_processed[bss].reset ();
961  }
962 }
963 
964 void
965 WifiPrimaryChannelsTest::CheckReceivedTriggerFrames (std::set<uint8_t> txBss, uint16_t txChannelWidth)
966 {
967  for (uint8_t bss = 0; bss < m_nBss; bss++)
968  {
969  if (txBss.find (bss) != txBss.end ())
970  {
971  // Every station in the BSS of an AP that transmitted the Trigger Frame hears (i.e.,
972  // passes to the MAC) and processes the frame
973  for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
974  {
975  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), true, "Station [" << +bss << "][" << +sta
976  << "] did not receive the Trigger Frame soliciting a transmission on primary"
977  << txChannelWidth << " channel");
978  NS_TEST_EXPECT_MSG_EQ (m_processed[bss].test (sta), true, "Station [" << +bss << "][" << +sta
979  << "] did not process the Trigger Frame soliciting a transmission on primary"
980  << txChannelWidth << " channel");
981  }
982  }
983  else
984  {
985  // Given that a Trigger Frame is transmitted on the primary20 channel and all the
986  // primary20 channels are distinct, stations in other BSSes did not hear the frame
987  for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
988  {
989  NS_TEST_EXPECT_MSG_EQ (m_received[bss].test (sta), false, "Station [" << +bss << "][" << +sta
990  << "] received the Trigger Frame soliciting a transmission on primary"
991  << txChannelWidth << " channel");
992  }
993  }
994  // reset bitmaps
995  m_received[bss].reset ();
996  m_processed[bss].reset ();
997  }
998 }
999 
1000 
1008 {
1009 public:
1011 };
1012 
1014  : TestSuite ("wifi-primary-channels", UNIT)
1015 {
1016  // Test cases for 20 MHz can be added, but are not that useful (there would be a single BSS)
1017  AddTestCase (new WifiPrimaryChannelsTest (40, true), TestCase::QUICK);
1018  AddTestCase (new WifiPrimaryChannelsTest (40, false), TestCase::QUICK);
1019  AddTestCase (new WifiPrimaryChannelsTest (80, true), TestCase::EXTENSIVE);
1020  AddTestCase (new WifiPrimaryChannelsTest (80, false), TestCase::EXTENSIVE);
1021  AddTestCase (new WifiPrimaryChannelsTest (160, true), TestCase::TAKES_FOREVER);
1022  AddTestCase (new WifiPrimaryChannelsTest (160, false), TestCase::TAKES_FOREVER);
1023 }
1024 
ns3::SpectrumChannel::SetPropagationDelayModel
void SetPropagationDelayModel(Ptr< PropagationDelayModel > delay)
Set the propagation delay model to be used.
Definition: spectrum-channel.cc:139
ns3::NetDeviceContainer
holds a vector of ns3::NetDevice pointers
Definition: net-device-container.h:42
NS_LOG_COMPONENT_DEFINE
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
ns3::TestCase::AddTestCase
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
WifiPrimaryChannelsTest::ReceiveDl
void ReceiveDl(uint8_t bss, uint8_t station, Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > perMpduStatus)
Callback invoked when a station receives a DL PPDU.
Definition: wifi-primary-channels-test.cc:235
ns3::ListPositionAllocator::Add
void Add(Vector v)
Add a position to the list of positions.
Definition: position-allocator.cc:70
WifiPrimaryChannelsTest::~WifiPrimaryChannelsTest
virtual ~WifiPrimaryChannelsTest()
Definition: wifi-primary-channels-test.cc:210
ns3::BooleanValue
AttributeValue implementation for Boolean.
Definition: boolean.h:37
ns3::SpectrumChannel::AddPropagationLossModel
void AddPropagationLossModel(Ptr< PropagationLossModel > loss)
Add the single-frequency propagation loss model to be used.
Definition: spectrum-channel.cc:117
WifiPrimaryChannelsTestSuite::WifiPrimaryChannelsTestSuite
WifiPrimaryChannelsTestSuite()
Definition: wifi-primary-channels-test.cc:1013
WifiPrimaryChannelsTest::SendHeTbPpdu
void SendHeTbPpdu(uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
Have the AP of the given BSS transmit a Basic Trigger Frame.
Definition: wifi-primary-channels-test.cc:719
ns3::Packet::AddHeader
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
WifiPrimaryChannelsTest::m_useDistinctBssColors
bool m_useDistinctBssColors
true to set distinct BSS colors to BSSes
Definition: wifi-primary-channels-test.cc:188
ns3::WifiNetDevice::GetPhy
Ptr< WifiPhy > GetPhy(void) const
Definition: wifi-net-device.cc:207
WifiPrimaryChannelsTest::m_nBss
uint8_t m_nBss
number of BSSes
Definition: wifi-primary-channels-test.cc:189
ns3
Every class exported by the ns3 library is enclosed in the ns3 namespace.
WifiPrimaryChannelsTest::Transmit
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when PHY receives a PSDU to transmit.
Definition: wifi-primary-channels-test.cc:215
ns3::WifiHelper
helps to create WifiNetDevice objects
Definition: wifi-helper.h:327
ns3::WifiMacHeader::SetSequenceNumber
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
Definition: wifi-mac-header.cc:312
ns3::MicroSeconds
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
ns3::WifiMacHeader::IsTrigger
bool IsTrigger(void) const
Return true if the header is a Trigger header.
Definition: wifi-mac-header.cc:753
WifiPrimaryChannelsTest::m_time
Time m_time
the time when the current action is executed
Definition: wifi-primary-channels-test.cc:197
ns3::WIFI_STANDARD_80211ax_5GHZ
@ WIFI_STANDARD_80211ax_5GHZ
Definition: wifi-standards.h:135
WifiPrimaryChannelsTest::DoSetup
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
Definition: wifi-primary-channels-test.cc:292
WifiPrimaryChannelsTest::m_trigger
Ptr< WifiPsdu > m_trigger
Basic Trigger Frame.
Definition: wifi-primary-channels-test.cc:198
ns3::WifiTxVector
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
Definition: wifi-tx-vector.h:71
ns3::WifiMacHeader::GetAddr1
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
Definition: wifi-mac-header.cc:424
third.mac
mac
Definition: third.py:99
ns3::WifiMacHeader::SetAddr3
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
Definition: wifi-mac-header.cc:120
ns3::WifiConstPsduMap
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition: he-frame-exchange-manager.h:43
ns3::WIFI_PREAMBLE_HE_SU
@ WIFI_PREAMBLE_HE_SU
Definition: wifi-phy-common.h:74
ns3::NodeContainer::Create
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Definition: node-container.cc:98
ns3::SsidValue
AttributeValue implementation for Ssid.
Definition: ssid.h:105
ns3::Ssid
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
g_wifiPrimaryChannelsTestSuite
static WifiPrimaryChannelsTestSuite g_wifiPrimaryChannelsTestSuite
the test suite
Definition: wifi-primary-channels-test.cc:1025
WifiPrimaryChannelsTest::m_triggerTxDuration
Time m_triggerTxDuration
TX duration for Basic Trigger Frame.
Definition: wifi-primary-channels-test.cc:200
ns3::CtrlTriggerHeader::SetType
void SetType(TriggerFrameType type)
Set the Trigger frame type.
Definition: ctrl-headers.cc:1726
ns3::WifiTxVector::IsUlMu
bool IsUlMu(void) const
Return true if this TX vector is used for an uplink multi-user transmission.
Definition: wifi-tx-vector.cc:382
ns3::TestCase
encapsulates test code
Definition: test.h:1154
ns3::WifiMacHeader::SetAddr1
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
Definition: wifi-mac-header.cc:108
ns3::WifiMacHeader
Implements the IEEE 802.11 MAC header.
Definition: wifi-mac-header.h:85
third.wifi
wifi
Definition: third.py:96
ns3::Ptr< WifiPsdu >
ns3::WifiTxVector::SetLength
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
Definition: wifi-tx-vector.cc:322
WifiPrimaryChannelsTest::m_received
std::vector< std::bitset< 74 > > m_received
whether the last packet transmitted to/from each of the (up to 74 per BSS) stations was received
Definition: wifi-primary-channels-test.cc:193
ns3::Time::IsZero
bool IsZero(void) const
Exactly equivalent to t == 0.
Definition: nstime.h:301
WifiPrimaryChannelsTest::CheckReceivedSuPpdus
void CheckReceivedSuPpdus(std::set< uint8_t > txBss, uint16_t txChannelWidth)
Check that (i) all stations belonging to the given BSSes received the SU PPDUs transmitted over the g...
Definition: wifi-primary-channels-test.cc:795
WifiPrimaryChannelsTest::DoRun
void DoRun(void) override
Implementation to actually run this TestCase.
Definition: wifi-primary-channels-test.cc:430
NS_LOG_INFO
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
ns3::WifiPsdu::GetHeader
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:266
ns3::MilliSeconds
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
WifiPrimaryChannelsTest::CheckReceivedTriggerFrames
void CheckReceivedTriggerFrames(std::set< uint8_t > txBss, uint16_t txChannelWidth)
Check that (i) all stations belonging to the given BSSes received the transmitted Trigger Frame; and ...
Definition: wifi-primary-channels-test.cc:965
ns3::HeRu::RuType
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:42
ns3::CtrlTriggerHeader
Headers for Trigger frames.
Definition: ctrl-headers.h:886
ns3::WifiPsdu::GetSize
uint32_t GetSize(void) const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:260
ns3::WifiTxVector::GetHeMuUserInfoMap
const HeMuUserInfoMap & GetHeMuUserInfoMap(void) const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
Definition: wifi-tx-vector.cc:421
WifiPrimaryChannelsTest::CheckAssociation
void CheckAssociation(void)
Check that all stations associated with an AP.
Definition: wifi-primary-channels-test.cc:783
SU_STA_ID
#define SU_STA_ID
Definition: wifi-mode.h:32
ns3::WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_CTL_TRIGGER
Definition: wifi-mac-header.h:38
ns3::NodeContainer::Get
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Definition: node-container.cc:93
ns3::WifiPsdu::GetNMpdus
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:319
ns3::WifiMacHeader::IsQosData
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
Definition: wifi-mac-header.cc:565
ns3::WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_MU
Definition: wifi-phy-common.h:76
NS_TEST_EXPECT_MSG_EQ
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:283
ns3::Time
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
WifiPrimaryChannelsTest::m_nStationsPerBss
uint8_t m_nStationsPerBss
number of stations per AP
Definition: wifi-primary-channels-test.cc:190
ns3::MakeCallback
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:1642
ns3::WifiMacHeader::SetAddr2
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
Definition: wifi-mac-header.cc:114
ns3::WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_LONG
Definition: wifi-phy-common.h:69
ns3::TestSuite
A suite of tests to run.
Definition: test.h:1344
ns3::Config::Connect
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
WifiPrimaryChannelsTest::m_channelWidth
uint16_t m_channelWidth
operating channel width in MHz
Definition: wifi-primary-channels-test.cc:187
WifiPrimaryChannelsTest::m_triggerTxVector
WifiTxVector m_triggerTxVector
TX vector for Basic Trigger Frame.
Definition: wifi-primary-channels-test.cc:199
ns3::RxSignalInfo
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:67
ns3::Seconds
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
ns3::WifiTxVector::SetHeMuUserInfo
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
Definition: wifi-tx-vector.cc:411
WifiPrimaryChannelsTestSuite
wifi primary channels test suite
Definition: wifi-primary-channels-test.cc:1008
ns3::WIFI_MAC_QOSDATA
@ WIFI_MAC_QOSDATA
Definition: wifi-mac-header.h:70
ns3::BASIC_TRIGGER
@ BASIC_TRIGGER
Definition: ctrl-headers.h:562
ns3::TimeValue
AttributeValue implementation for Time.
Definition: nstime.h:1353
ns3::NodeContainer
keep track of a set of node pointers.
Definition: node-container.h:39
WifiPrimaryChannelsTest::DoSendHeTbPpdu
void DoSendHeTbPpdu(uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
Have the STAs of the given BSS transmit an HE TB PPDU using the given transmission channel width and ...
Definition: wifi-primary-channels-test.cc:736
WifiPrimaryChannelsTest::ReceiveUl
void ReceiveUl(uint8_t bss, Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > perMpduStatus)
Callback invoked when an AP receives an UL PPDU.
Definition: wifi-primary-channels-test.cc:264
third.wifiStaNodes
wifiStaNodes
Definition: third.py:88
ns3::WifiMacHeader::SetType
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
Definition: wifi-mac-header.cc:132
ns3::UintegerValue
Hold an unsigned integer type.
Definition: uinteger.h:44
ns3::WifiMacHelper
create MAC layers for a ns3::WifiNetDevice.
Definition: wifi-mac-helper.h:48
WifiPrimaryChannelsTest::WifiPrimaryChannelsTest
WifiPrimaryChannelsTest(uint16_t channelWidth, bool useDistinctBssColors)
Constructor.
Definition: wifi-primary-channels-test.cc:203
WifiPrimaryChannelsTest::SendDlMuPpdu
void SendDlMuPpdu(uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
Have the AP of the given BSS transmit a MU PPDU using the given transmission channel width and RU typ...
Definition: wifi-primary-channels-test.cc:685
WifiPrimaryChannelsTest::m_processed
std::vector< std::bitset< 74 > > m_processed
whether the last packet transmitted to/from each of the (up to 74 per BSS) stations was processed
Definition: wifi-primary-channels-test.cc:195
WifiPrimaryChannelsTest::m_apDevices
NetDeviceContainer m_apDevices
container for AP's NetDevice
Definition: wifi-primary-channels-test.cc:192
ns3::WifiMacHeader::SetQosTid
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
Definition: wifi-mac-header.cc:352
WifiPrimaryChannelsTest::m_staDevices
std::vector< NetDeviceContainer > m_staDevices
containers for stations' NetDevices
Definition: wifi-primary-channels-test.cc:191
ns3::NetDeviceContainer::Get
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
Definition: net-device-container.cc:62
ns3::WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_TB
Definition: wifi-phy-common.h:77
ns3::NetDeviceContainer::Add
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Definition: net-device-container.cc:67
ns3::MobilityHelper
Helper class used to assign positions and mobility models to nodes.
Definition: mobility-helper.h:43
ns3::SpectrumWifiPhyHelper
Make it easy to create and manage PHY objects for the spectrum model.
Definition: spectrum-wifi-helper.h:38
WifiPrimaryChannelsTest::CheckReceivedMuPpdus
void CheckReceivedMuPpdus(std::set< uint8_t > txBss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus, bool isDlMu)
Check that (i) all stations/APs belonging to the given BSSes received the DL/UL MU PPDUs transmitted ...
Definition: wifi-primary-channels-test.cc:857
third.mobility
mobility
Definition: third.py:108
third.phy
phy
Definition: third.py:93
ns3::WifiNetDevice::GetMac
Ptr< WifiMac > GetMac(void) const
Definition: wifi-net-device.cc:201
WifiPrimaryChannelsTest::SendDlSuPpdu
void SendDlSuPpdu(uint8_t bss, uint16_t txChannelWidth)
Have the AP of the given BSS transmit a SU PPDU using the given transmission channel width.
Definition: wifi-primary-channels-test.cc:664
WifiPrimaryChannelsTest
Test transmissions under different primary channel settings.
Definition: wifi-primary-channels-test.cc:59
NS_ABORT_MSG
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50