A Discrete-Event Network Simulator
API
wifi-mac-ofdma-test.cc
Go to the documentation of this file.
1  /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 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/string.h"
23 #include "ns3/qos-utils.h"
24 #include "ns3/packet.h"
25 #include "ns3/wifi-net-device.h"
26 #include "ns3/wifi-mac-header.h"
27 #include "ns3/he-frame-exchange-manager.h"
28 #include "ns3/wifi-acknowledgment.h"
29 #include "ns3/wifi-protection.h"
30 #include "ns3/he-configuration.h"
31 #include "ns3/mobility-helper.h"
32 #include "ns3/spectrum-wifi-helper.h"
33 #include "ns3/multi-model-spectrum-channel.h"
34 #include "ns3/packet-socket-server.h"
35 #include "ns3/packet-socket-client.h"
36 #include "ns3/packet-socket-helper.h"
37 #include "ns3/config.h"
38 #include "ns3/pointer.h"
39 #include "ns3/rng-seed-manager.h"
40 #include "ns3/wifi-psdu.h"
41 #include "ns3/multi-user-scheduler.h"
42 #include "ns3/he-phy.h"
43 
44 using namespace ns3;
45 
46 NS_LOG_COMPONENT_DEFINE ("WifiMacOfdmaTestSuite");
47 
61 {
62 public:
67  static TypeId GetTypeId (void);
69  virtual ~TestMultiUserScheduler ();
70 
71 private:
72  // Implementation of pure virtual methods of MultiUserScheduler class
73  TxFormat SelectTxFormat (void) override;
74  DlMuInfo ComputeDlMuInfo (void) override;
75  UlMuInfo ComputeUlMuInfo (void) override;
76 
80  void ComputeWifiTxVector (void);
81 
89 };
90 
91 
93 
94 TypeId
96 {
97  static TypeId tid = TypeId ("ns3::TestMultiUserScheduler")
99  .SetGroupName ("Wifi")
100  .AddConstructor<TestMultiUserScheduler> ()
101  ;
102  return tid;
103 }
104 
106  : m_txFormat (SU_TX),
107  m_ulTriggerType (TriggerFrameType::BSRP_TRIGGER)
108 {
109  NS_LOG_FUNCTION (this);
110 }
111 
113 {
115 }
116 
119 {
120  NS_LOG_FUNCTION (this);
121 
122  // Do not use OFDMA if a BA agreement has not been established with all the stations
123  if (Simulator::Now () < Seconds (1.5))
124  {
125  NS_LOG_DEBUG ("Return SU_TX");
126  return SU_TX;
127  }
128 
130 
131  if (m_txFormat == SU_TX || m_txFormat == DL_MU_TX
133  {
134  // try to send a Trigger Frame
135  TriggerFrameType ulTriggerType = (m_txFormat == SU_TX || m_txFormat == DL_MU_TX
138 
139  CtrlTriggerHeader trigger (ulTriggerType, m_txVector);
140 
141  WifiTxVector txVector = m_txVector;
142  txVector.SetGuardInterval (trigger.GetGuardInterval ());
143 
144  uint32_t ampduSize = (ulTriggerType == TriggerFrameType::BSRP_TRIGGER ? m_sizeOf8QosNull : 3500);
145 
146  Time duration = WifiPhy::CalculateTxDuration (ampduSize, txVector,
147  m_apMac->GetWifiPhy ()->GetPhyBand (),
148  m_apMac->GetStaList ().begin ()->first);
149 
150  uint16_t length = HePhy::ConvertHeTbPpduDurationToLSigLength (duration,
151  m_apMac->GetWifiPhy ()->GetPhyBand ());
152  trigger.SetUlLength (length);
153  m_heFem->SetTargetRssi (trigger);
154 
155  Ptr<Packet> packet = Create<Packet> ();
156  packet->AddHeader (trigger);
157 
159  hdr.SetAddr1 (Mac48Address::GetBroadcast ());
160  hdr.SetAddr2 (m_apMac->GetAddress ());
161  hdr.SetDsNotTo ();
162  hdr.SetDsNotFrom ();
163 
164  m_trigger = Create<WifiMacQueueItem> (packet, hdr);
165 
166  m_txParams.Clear ();
167  // set the TXVECTOR used to send the Trigger Frame
168  m_txParams.m_txVector = m_apMac->GetWifiRemoteStationManager ()->GetRtsTxVector (hdr.GetAddr1 ());
169 
170  if (!m_heFem->TryAddMpdu (m_trigger, m_txParams, m_availableTime)
171  || (m_availableTime != Time::Min ()
172  && m_txParams.m_protection->protectionTime
173  + m_txParams.m_txDuration // TF tx time
174  + m_apMac->GetWifiPhy ()->GetSifs ()
175  + duration
176  + m_txParams.m_acknowledgment->acknowledgmentTime
177  > m_availableTime ))
178  {
179  NS_LOG_DEBUG ("Remaining TXOP duration is not enough for BSRP TF exchange");
180  return SU_TX;
181  }
182 
184  m_ulTriggerType = ulTriggerType;
185  m_tbPpduDuration = duration;
186  }
187  else if (m_txFormat == UL_MU_TX)
188  {
189  // try to send a DL MU PPDU
190  m_psduMap.clear ();
191  const std::map<uint16_t, Mac48Address>& staList = m_apMac->GetStaList ();
192  NS_ABORT_MSG_IF (staList.size () != 4, "There must be 4 associated stations");
193 
194  /* Initialize TX params */
195  m_txParams.Clear ();
197 
198  for (auto& sta : staList)
199  {
200  Ptr<const WifiMacQueueItem> peeked = m_apMac->GetQosTxop (AC_BE)->PeekNextMpdu (0, sta.second);
201 
202  if (peeked == 0)
203  {
204  NS_LOG_DEBUG ("No frame to send");
205  return SU_TX;
206  }
207 
209  Ptr<WifiMacQueueItem> mpdu = m_apMac->GetQosTxop (AC_BE)->GetNextMpdu (peeked, m_txParams,
211  m_initialFrame, queueIt);
212  if (mpdu == 0)
213  {
214  NS_LOG_DEBUG ("Not enough time to send frames to all the stations");
215  return SU_TX;
216  }
217 
218  std::vector<Ptr<WifiMacQueueItem>> mpduList;
219  mpduList = m_heFem->GetMpduAggregator ()->GetNextAmpdu (mpdu, m_txParams, m_availableTime, queueIt);
220 
221  if (mpduList.size () > 1)
222  {
223  m_psduMap[sta.first] = Create<WifiPsdu> (std::move (mpduList));
224  }
225  else
226  {
227  m_psduMap[sta.first] = Create<WifiPsdu> (mpdu, true);
228  }
229  }
230 
232  }
233  else
234  {
235  NS_ABORT_MSG ("Cannot get here.");
236  }
237 
238  NS_LOG_DEBUG ("Return " << m_txFormat);
239  return m_txFormat;
240 }
241 
242 void
244 {
246  {
247  // the TX vector has been already computed
248  return;
249  }
250 
251  uint16_t bw = m_apMac->GetWifiPhy ()->GetChannelWidth ();
252 
255  m_txVector.SetGuardInterval (m_apMac->GetHeConfiguration ()->GetGuardInterval ().GetNanoSeconds ());
256  m_txVector.SetTxPowerLevel (GetWifiRemoteStationManager ()->GetDefaultTxPowerLevel ());
257 
258  const std::map<uint16_t, Mac48Address>& staList = m_apMac->GetStaList ();
259  NS_ABORT_MSG_IF (staList.size () != 4, "There must be 4 associated stations");
260 
261  HeRu::RuType ruType;
262  switch (bw)
263  {
264  case 20:
265  ruType = HeRu::RU_52_TONE;
266  break;
267  case 40:
268  ruType = HeRu::RU_106_TONE;
269  break;
270  case 80:
271  ruType = HeRu::RU_242_TONE;
272  break;
273  case 160:
274  ruType = HeRu::RU_484_TONE;
275  break;
276  default:
277  NS_ABORT_MSG ("Unsupported channel width");
278  }
279 
280  bool primary80 = true;
281  std::size_t ruIndex = 1;
282 
283  for (auto& sta : staList)
284  {
285  if (bw == 160 && ruIndex == 3)
286  {
287  ruIndex = 1;
288  primary80 = false;
289  }
290  m_txVector.SetHeMuUserInfo (sta.first,
291  {{ruType, ruIndex++, primary80}, WifiMode ("HeMcs11"), 1});
292  }
293 }
294 
297 {
298  NS_LOG_FUNCTION (this);
299  return DlMuInfo {m_psduMap, std::move (m_txParams)};
300 }
301 
304 {
305  NS_LOG_FUNCTION (this);
306  return UlMuInfo {m_trigger, m_tbPpduDuration, std::move (m_txParams)};
307 }
308 
309 
326 {
327 public:
332  {
333  uint8_t muAifsn;
334  uint16_t muCwMin;
335  uint16_t muCwMax;
336  uint8_t muTimer;
337  };
338 
348  OfdmaAckSequenceTest (uint16_t width, WifiAcknowledgment::Method dlType, uint32_t maxAmpduSize,
349  uint16_t txopLimit, uint16_t nPktsPerSta,
350  MuEdcaParameterSet muEdcaParameterSet);
351  virtual ~OfdmaAckSequenceTest ();
352 
359  void L7Receive (std::string context, Ptr<const Packet> p, const Address &addr);
366  void TraceCw (uint32_t staIndex, uint32_t oldCw, uint32_t cw);
374  void Transmit (std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW);
381  void CheckResults (Time sifs, Time slotTime, uint8_t aifsn);
382 
383 private:
384  void DoRun (void) override;
385 
387  struct FrameInfo
388  {
393  };
394 
395  uint16_t m_nStations;
398  uint16_t m_channelWidth;
399  std::vector<FrameInfo> m_txPsdus;
401  uint32_t m_maxAmpduSize;
402  uint16_t m_txopLimit;
403  uint16_t m_nPktsPerSta;
405  uint16_t m_received;
406  uint16_t m_flushed;
408  std::vector<uint32_t> m_cwValues;
409 };
410 
412  uint32_t maxAmpduSize, uint16_t txopLimit,
413  uint16_t nPktsPerSta,
414  MuEdcaParameterSet muEdcaParameterSet)
415  : TestCase ("Check correct operation of DL OFDMA acknowledgment sequences"),
416  m_nStations (4),
417  m_channelWidth (width),
418  m_dlMuAckType (dlType),
419  m_maxAmpduSize (maxAmpduSize),
420  m_txopLimit (txopLimit),
421  m_nPktsPerSta (nPktsPerSta),
422  m_muEdcaParameterSet (muEdcaParameterSet),
423  m_received (0),
424  m_flushed (0),
425  m_edcaDisabledStartTime (Seconds (0)),
426  m_cwValues (std::vector<uint32_t> (m_nStations, 2)) // 2 is an invalid CW value
427 {
428 }
429 
431 {
432 }
433 
434 void
435 OfdmaAckSequenceTest::L7Receive (std::string context, Ptr<const Packet> p, const Address &addr)
436 {
437  if (p->GetSize () >= 1400 && Simulator::Now () > Seconds (1.5))
438  {
439  m_received++;
440  }
441 }
442 
443 void
444 OfdmaAckSequenceTest::TraceCw (uint32_t staIndex, uint32_t oldCw, uint32_t cw)
445 {
446  if (m_cwValues.at (staIndex) == 2)
447  {
448  // store the first CW used after MU exchange (the last one may be used after
449  // the MU EDCA timer expired)
450  m_cwValues[staIndex] = cw;
451  }
452 }
453 
454 void
455 OfdmaAckSequenceTest::Transmit (std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
456 {
457  // skip beacon frames and frames transmitted before 1.5s (association
458  // request/response, ADDBA request, ...)
459  if (!psduMap.begin ()->second->GetHeader (0).IsBeacon ()
460  && Simulator::Now () > Seconds (1.5))
461  {
462  Time txDuration = WifiPhy::CalculateTxDuration (psduMap, txVector, WIFI_PHY_BAND_5GHZ);
463  m_txPsdus.push_back ({Simulator::Now (),
464  Simulator::Now () + txDuration,
465  psduMap, txVector});
466 
467  for (const auto& psduPair : psduMap)
468  {
469  NS_LOG_INFO ("Sending " << psduPair.second->GetHeader (0).GetTypeString ()
470  << " #MPDUs " << psduPair.second->GetNMpdus ()
471  << " txDuration " << txDuration
472  << " duration/ID " << psduPair.second->GetHeader (0).GetDuration ()
473  << " #TX PSDUs = " << m_txPsdus.size ());
474  }
475  }
476 
477  // Flush the MAC queue of the AP after sending a DL MU PPDU (no need for
478  // further transmissions)
479  if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_MU)
480  {
481  auto dev = DynamicCast<WifiNetDevice> (m_apDevice);
482  Ptr<WifiMacQueue> queue = DynamicCast<RegularWifiMac> (dev->GetMac ())->GetQosTxop (AC_BE)->GetWifiMacQueue ();
483  m_flushed = 0;
484  for (auto it = queue->begin (); it != queue->end (); )
485  {
486  auto tmp = it++;
487  if (!(*tmp)->IsInFlight ())
488  {
489  queue->Remove (tmp);
490  m_flushed++;
491  }
492  }
493  }
494  else if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
495  && psduMap.begin ()->second->GetHeader (0).HasData ())
496  {
497  Mac48Address sender = psduMap.begin ()->second->GetAddr2 ();
498 
499  for (uint32_t i = 0; i < m_staDevices.GetN (); i++)
500  {
501  auto dev = DynamicCast<WifiNetDevice> (m_staDevices.Get (i));
502 
503  if (dev->GetAddress () == sender)
504  {
505  Ptr<QosTxop> qosTxop = DynamicCast<RegularWifiMac> (dev->GetMac ())->GetQosTxop (AC_BE);
506 
508  {
509  // stations use worse access parameters, trace CW. MU AIFSN must be large
510  // enough to avoid collisions between stations trying to transmit using EDCA
511  // right after the UL MU transmission and the AP trying to send a DL MU PPDU
512  qosTxop->TraceConnectWithoutContext ("CwTrace",
514  this).Bind (i));
515  }
516  else
517  {
518  // there is no "protection" against collisions from stations, hence flush
519  // their MAC queues after sending an HE TB PPDU containing QoS data frames,
520  // so that the AP can send a DL MU PPDU
521  qosTxop->GetWifiMacQueue ()->Flush ();
522  }
523  break;
524  }
525  }
526  }
527  else if (!txVector.IsMu () && psduMap.begin ()->second->GetHeader (0).IsBlockAck ()
528  && psduMap.begin ()->second->GetHeader (0).GetAddr2 () == m_apDevice->GetAddress ()
530  {
531  CtrlBAckResponseHeader blockAck;
532  psduMap.begin ()->second->GetPayload (0)->PeekHeader (blockAck);
533 
534  if (blockAck.IsMultiSta ())
535  {
536  // AP is transmitting a multi-STA BlockAck and stations have to disable EDCA,
537  // record the starting time
538  m_edcaDisabledStartTime = Simulator::Now () + m_txPsdus.back ().endTx - m_txPsdus.back ().startTx;
539  }
540  }
541 }
542 
543 void
544 OfdmaAckSequenceTest::CheckResults (Time sifs, Time slotTime, uint8_t aifsn)
545 {
546  CtrlTriggerHeader trigger;
547  CtrlBAckResponseHeader blockAck;
548  Time tEnd, // TX end for a frame
549  tStart, // TX start fot the next frame
550  tolerance = NanoSeconds (500), // due to propagation delay
551  ifs = (m_txopLimit > 0 ? sifs : sifs + aifsn * slotTime),
552  navEnd;
553 
554  /*
555  * |--------------NAV------------------>|
556  * |------NAV------->| | |------NAV-------->|
557  * |---------| |----------| |---------| |----------| |-----------|
558  * | | |QoS Null 1| | | |QoS Data 1| | |
559  * | BSRP | |----------| | Basic | |----------| | Multi-STA |
560  * | Trigger | |QoS Null 2| | Trigger | |QoS Data 2| | Block Ack |
561  * | Frame |<SIFS>|----------|<IFS>| Frame |<SIFS>|----------|<SIFS>| |
562  * | | |QoS Null 3| | | |QoS Data 3| | |
563  * | | |----------| | | |----------| | |
564  * | | |QoS Null 4| | | |QoS Data 4| | |
565  * -----------------------------------------------------------------------------------------
566  * From: AP AP AP
567  * To: all AP all AP all
568  */
569 
570  // the first packet sent after 1.5s is a BSRP Trigger Frame
571  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 5, "Expected at least 5 transmitted packet");
572  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[0].psduMap.size () == 1
573  && m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader (0).IsTrigger ()
574  && m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader (0).GetAddr1 ().IsBroadcast ()),
575  true, "Expected a Trigger Frame");
576  m_txPsdus[0].psduMap[SU_STA_ID]->GetPayload (0)->PeekHeader (trigger);
577  NS_TEST_EXPECT_MSG_EQ (trigger.IsBsrp (), true, "Expected a BSRP Trigger Frame");
578  NS_TEST_EXPECT_MSG_EQ (trigger.GetNUserInfoFields (), 4, "Expected one User Info field per station");
579 
580  // A first STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
581  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[1].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
582  && m_txPsdus[1].psduMap.size () == 1
583  && m_txPsdus[1].psduMap.begin ()->second->GetNMpdus () == 8),
584  true, "Expected 8 QoS Null frames in an HE TB PPDU");
585  for (uint8_t i = 0; i < 8; i++)
586  {
587  const WifiMacHeader& hdr = m_txPsdus[1].psduMap.begin ()->second->GetHeader (i);
588  NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
589  uint8_t tid = hdr.GetQosTid ();
590  if (tid == 0)
591  {
592  NS_TEST_EXPECT_MSG_GT (hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
593  }
594  else
595  {
596  NS_TEST_EXPECT_MSG_EQ (hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
597  }
598  }
599  tEnd = m_txPsdus[0].endTx;
600  navEnd = tEnd + m_txPsdus[0].psduMap[SU_STA_ID]->GetDuration ();
601  tStart = m_txPsdus[1].startTx;
602  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
603  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
604  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[1].endTx, "Duration/ID in BSRP Trigger Frame is too short");
605 
606  // A second STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
607  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[2].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
608  && m_txPsdus[2].psduMap.size () == 1
609  && m_txPsdus[2].psduMap.begin ()->second->GetNMpdus () == 8),
610  true, "Expected 8 QoS Null frames in an HE TB PPDU");
611  for (uint8_t i = 0; i < 8; i++)
612  {
613  const WifiMacHeader& hdr = m_txPsdus[2].psduMap.begin ()->second->GetHeader (i);
614  NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
615  uint8_t tid = hdr.GetQosTid ();
616  if (tid == 0)
617  {
618  NS_TEST_EXPECT_MSG_GT (hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
619  }
620  else
621  {
622  NS_TEST_EXPECT_MSG_EQ (hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
623  }
624  }
625  tStart = m_txPsdus[2].startTx;
626  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
627  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
628  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[2].endTx, "Duration/ID in BSRP Trigger Frame is too short");
629 
630  // A third STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
631  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[3].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
632  && m_txPsdus[3].psduMap.size () == 1
633  && m_txPsdus[3].psduMap.begin ()->second->GetNMpdus () == 8),
634  true, "Expected 8 QoS Null frames in an HE TB PPDU");
635  for (uint8_t i = 0; i < 8; i++)
636  {
637  const WifiMacHeader& hdr = m_txPsdus[3].psduMap.begin ()->second->GetHeader (i);
638  NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
639  uint8_t tid = hdr.GetQosTid ();
640  if (tid == 0)
641  {
642  NS_TEST_EXPECT_MSG_GT (hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
643  }
644  else
645  {
646  NS_TEST_EXPECT_MSG_EQ (hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
647  }
648  }
649  tStart = m_txPsdus[3].startTx;
650  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
651  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
652  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[3].endTx, "Duration/ID in BSRP Trigger Frame is too short");
653 
654  // A fourth STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
655  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[4].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
656  && m_txPsdus[4].psduMap.size () == 1
657  && m_txPsdus[4].psduMap.begin ()->second->GetNMpdus () == 8),
658  true, "Expected 8 QoS Null frames in an HE TB PPDU");
659  for (uint8_t i = 0; i < 8; i++)
660  {
661  const WifiMacHeader& hdr = m_txPsdus[4].psduMap.begin ()->second->GetHeader (i);
662  NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
663  uint8_t tid = hdr.GetQosTid ();
664  if (tid == 0)
665  {
666  NS_TEST_EXPECT_MSG_GT (hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
667  }
668  else
669  {
670  NS_TEST_EXPECT_MSG_EQ (hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
671  }
672  }
673  tStart = m_txPsdus[4].startTx;
674  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
675  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
676  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[4].endTx, "Duration/ID in BSRP Trigger Frame is too short");
677 
678  // the AP sends a Basic Trigger Frame to solicit QoS data frames
679  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 11, "Expected at least 11 transmitted packet");
680  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[5].psduMap.size () == 1
681  && m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader (0).IsTrigger ()
682  && m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader (0).GetAddr1 ().IsBroadcast ()),
683  true, "Expected a Trigger Frame");
684  m_txPsdus[5].psduMap[SU_STA_ID]->GetPayload (0)->PeekHeader (trigger);
685  NS_TEST_EXPECT_MSG_EQ (trigger.IsBasic (), true, "Expected a Basic Trigger Frame");
686  NS_TEST_EXPECT_MSG_EQ (trigger.GetNUserInfoFields (), 4, "Expected one User Info field per station");
687  tEnd = m_txPsdus[1].endTx;
688  tStart = m_txPsdus[5].startTx;
689  NS_TEST_EXPECT_MSG_LT (tEnd + ifs, tStart, "Basic Trigger Frame sent too early");
690  if (m_txopLimit > 0)
691  {
692  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Basic Trigger Frame sent too late");
693  }
694 
695  // A first STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
696  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[6].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
697  && m_txPsdus[6].psduMap.size () == 1
698  && m_txPsdus[6].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
699  true, "Expected QoS data frames in an HE TB PPDU");
700  tEnd = m_txPsdus[5].endTx;
701  tStart = m_txPsdus[6].startTx;
702  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
703  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
704 
705  // A second STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
706  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[7].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
707  && m_txPsdus[7].psduMap.size () == 1
708  && m_txPsdus[7].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
709  true, "Expected QoS data frames in an HE TB PPDU");
710  tEnd = m_txPsdus[5].endTx;
711  tStart = m_txPsdus[7].startTx;
712  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
713  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
714 
715  // A third STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
716  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[8].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
717  && m_txPsdus[8].psduMap.size () == 1
718  && m_txPsdus[8].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
719  true, "Expected QoS data frames in an HE TB PPDU");
720  tEnd = m_txPsdus[5].endTx;
721  tStart = m_txPsdus[8].startTx;
722  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
723  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
724 
725  // A fourth STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
726  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[9].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
727  && m_txPsdus[9].psduMap.size () == 1
728  && m_txPsdus[9].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
729  true, "Expected QoS data frames in an HE TB PPDU");
730  tEnd = m_txPsdus[5].endTx;
731  tStart = m_txPsdus[9].startTx;
732  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
733  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
734 
735  // the AP sends a Multi-STA Block Ack
736  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[10].psduMap.size () == 1
737  && m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()
738  && m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader (0).GetAddr1 ().IsBroadcast ()),
739  true, "Expected a Block Ack");
740  m_txPsdus[10].psduMap[SU_STA_ID]->GetPayload (0)->PeekHeader (blockAck);
741  NS_TEST_EXPECT_MSG_EQ (blockAck.IsMultiSta (), true, "Expected a Multi-STA Block Ack");
743  "Expected one Per AID TID Info subfield per station");
744  for (uint8_t i = 0; i < 4; i++)
745  {
746  NS_TEST_EXPECT_MSG_EQ (blockAck.GetAckType (i), true, "Expected All-ack context");
747  NS_TEST_EXPECT_MSG_EQ (+blockAck.GetTidInfo (i), 14, "Expected All-ack context");
748  }
749  tEnd = m_txPsdus[9].endTx;
750  tStart = m_txPsdus[10].startTx;
751  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Multi-STA Block Ack sent too early");
752  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Multi-STA Block Ack sent too late");
753 
754  navEnd = m_txPsdus[5].endTx + m_txPsdus[5].psduMap[SU_STA_ID]->GetDuration (); // Basic TF's NAV
755  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in Basic Trigger Frame is too short");
756  navEnd = m_txPsdus[6].endTx + m_txPsdus[6].psduMap.begin ()->second->GetDuration (); // 1st QoS Data frame's NAV
757  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 1st QoS Data frame is too short");
758  navEnd = m_txPsdus[7].endTx + m_txPsdus[7].psduMap.begin ()->second->GetDuration (); // 2nd QoS Data frame's NAV
759  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 2nd QoS Data frame is too short");
760  navEnd = m_txPsdus[8].endTx + m_txPsdus[8].psduMap.begin ()->second->GetDuration (); // 3rd QoS Data frame's NAV
761  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 3rd QoS Data frame is too short");
762  navEnd = m_txPsdus[9].endTx + m_txPsdus[9].psduMap.begin ()->second->GetDuration (); // 4th QoS Data frame's NAV
763  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 4th QoS Data frame is too short");
764 
765  // the AP sends a DL MU PPDU
766  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 12, "Expected at least 12 transmitted packet");
767  NS_TEST_EXPECT_MSG_EQ (m_txPsdus[11].txVector.GetPreambleType (), WIFI_PREAMBLE_HE_MU,
768  "Expected a DL MU PPDU");
769  NS_TEST_EXPECT_MSG_EQ (m_txPsdus[11].psduMap.size (), 4, "Expected 4 PSDUs within the DL MU PPDU");
770  // the TX duration cannot exceed the maximum PPDU duration
771  NS_TEST_EXPECT_MSG_LT_OR_EQ (m_txPsdus[11].endTx - m_txPsdus[11].startTx,
772  GetPpduMaxTime (m_txPsdus[11].txVector.GetPreambleType ()),
773  "TX duration cannot exceed max PPDU duration");
774  for (auto& psdu : m_txPsdus[11].psduMap)
775  {
776  NS_TEST_EXPECT_MSG_LT_OR_EQ (psdu.second->GetSize (), m_maxAmpduSize, "Max A-MPDU size exceeded");
777  }
778  tEnd = m_txPsdus[10].endTx;
779  tStart = m_txPsdus[11].startTx;
780  NS_TEST_EXPECT_MSG_LT_OR_EQ (tEnd + ifs, tStart, "DL MU PPDU sent too early");
781 
782  // The Duration/ID field is the same for all the PSDUs
783  navEnd = m_txPsdus[11].endTx;
784  for (auto& psdu : m_txPsdus[11].psduMap)
785  {
786  if (navEnd == m_txPsdus[11].endTx)
787  {
788  navEnd += psdu.second->GetDuration ();
789  }
790  else
791  {
792  NS_TEST_EXPECT_MSG_EQ (m_txPsdus[11].endTx + psdu.second->GetDuration (), navEnd,
793  "Duration/ID must be the same for all PSDUs");
794  }
795  }
796  NS_TEST_EXPECT_MSG_GT (navEnd, m_txPsdus[11].endTx, "Duration/ID of the DL MU PPDU cannot be zero");
797 
798  std::size_t nTxPsdus = 0;
799 
800  if (m_dlMuAckType == WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE)
801  {
802  /*
803  * |----------------------------------------NAV---------------------------------------------->|
804  * | |--------------------------NAV---------------------------------->|
805  * | | |-------------------NAV--------------->|
806  * | | | |----NAV---->|
807  * |------| |-----| |-----| |-----| |-----| |-----| |-----| |-----|
808  * |PSDU 1| | | | | | | | | | | | | | |
809  * |------| |Block| |Block| |Block| |Block| |Block| |Block| |Block|
810  * |PSDU 2| | Ack | | Ack | | Ack | | Ack | | Ack | | Ack | | Ack |
811  * |------|<SIFS>| |<SIFS>| Req |<SIFS>| |<SIFS>| Req |<SIFS>| |<SIFS>| Req |<SIFS>| |
812  * |PSDU 3| | | | | | | | | | | | | | |
813  * |------| | | | | | | | | | | | | | |
814  * |PSDU 4| | | | | | | | | | | | | | |
815  * ---------------------------------------------------------------------------------------------------
816  * From: AP STA 1 AP STA 2 AP STA 3 AP STA 4
817  * To: AP STA 2 AP STA 3 AP STA 4 AP
818  */
819  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 19, "Expected at least 19 packets");
820 
821  // A first STA sends a Block Ack a SIFS after the reception of the DL MU PPDU
822  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[12].psduMap.size () == 1
823  && m_txPsdus[12].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
824  true, "Expected a Block Ack");
825  tEnd = m_txPsdus[11].endTx;
826  tStart = m_txPsdus[12].startTx;
827  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "First Block Ack sent too early");
828  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "First Block Ack sent too late");
829 
830  // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
831  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[13].psduMap.size () == 1
832  && m_txPsdus[13].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAckReq ()),
833  true, "Expected a Block Ack Request");
834  tEnd = m_txPsdus[12].endTx;
835  tStart = m_txPsdus[13].startTx;
836  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "First Block Ack Request sent too early");
837  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "First Block Ack Request sent too late");
838 
839  // A second STA sends a Block Ack a SIFS after the reception of the Block Ack Request
840  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[14].psduMap.size () == 1
841  && m_txPsdus[14].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
842  true, "Expected a Block Ack");
843  tEnd = m_txPsdus[13].endTx;
844  tStart = m_txPsdus[14].startTx;
845  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Second Block Ack sent too early");
846  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Second Block Ack sent too late");
847 
848  // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
849  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[15].psduMap.size () == 1
850  && m_txPsdus[15].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAckReq ()),
851  true, "Expected a Block Ack Request");
852  tEnd = m_txPsdus[14].endTx;
853  tStart = m_txPsdus[15].startTx;
854  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Second Block Ack Request sent too early");
855  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Second Block Ack Request sent too late");
856 
857  // A third STA sends a Block Ack a SIFS after the reception of the Block Ack Request
858  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[16].psduMap.size () == 1
859  && m_txPsdus[16].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
860  true, "Expected a Block Ack");
861  tEnd = m_txPsdus[15].endTx;
862  tStart = m_txPsdus[16].startTx;
863  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Third Block Ack sent too early");
864  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Third Block Ack sent too late");
865 
866  // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
867  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[17].psduMap.size () == 1
868  && m_txPsdus[17].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAckReq ()),
869  true, "Expected a Block Ack Request");
870  tEnd = m_txPsdus[16].endTx;
871  tStart = m_txPsdus[17].startTx;
872  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Third Block Ack Request sent too early");
873  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Third Block Ack Request sent too late");
874 
875  // A fourth STA sends a Block Ack a SIFS after the reception of the Block Ack Request
876  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[18].psduMap.size () == 1
877  && m_txPsdus[18].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
878  true, "Expected a Block Ack");
879  tEnd = m_txPsdus[17].endTx;
880  tStart = m_txPsdus[18].startTx;
881  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Fourth Block Ack sent too early");
882  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Fourth Block Ack sent too late");
883 
884  if (m_txopLimit > 0)
885  {
886  // DL MU PPDU's NAV
887  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the DL MU PPDU is too short");
888  // 1st BlockAckReq's NAV
889  navEnd = m_txPsdus[13].endTx + m_txPsdus[13].psduMap[SU_STA_ID]->GetDuration ();
890  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the 1st BlockAckReq is too short");
891  // 2nd BlockAckReq's NAV
892  navEnd = m_txPsdus[15].endTx + m_txPsdus[15].psduMap[SU_STA_ID]->GetDuration ();
893  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the 2nd BlockAckReq is too short");
894  // 3rd BlockAckReq's NAV
895  navEnd = m_txPsdus[17].endTx + m_txPsdus[17].psduMap[SU_STA_ID]->GetDuration ();
896  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the 3rd BlockAckReq is too short");
897  }
898  nTxPsdus = 19;
899  }
900  else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_TF_MU_BAR)
901  {
902  /*
903  * |----------------NAV--------------->|
904  * | |--------NAV------>|
905  * |------| |---------| |-----------|
906  * |PSDU 1| | | |Block Ack 1|
907  * |------| | MU-BAR | |-----------|
908  * |PSDU 2| | Trigger | |Block Ack 2|
909  * |------|<SIFS>| Frame |<SIFS>|-----------|
910  * |PSDU 3| | | |Block Ack 3|
911  * |------| | | |-----------|
912  * |PSDU 4| | | |Block Ack 4|
913  * --------------------------------------------------
914  * From: AP AP
915  * To: all AP
916  */
917  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 17, "Expected at least 17 packets");
918 
919  // the AP transmits a MU-BAR Trigger Frame an IFS after the transmission of the DL MU PPDU
920  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[12].psduMap.size () == 1
921  && m_txPsdus[12].psduMap[SU_STA_ID]->GetHeader (0).IsTrigger ()),
922  true, "Expected a MU-BAR Trigger Frame");
923  tEnd = m_txPsdus[11].endTx;
924  tStart = m_txPsdus[12].startTx;
925  NS_TEST_EXPECT_MSG_EQ (tStart, tEnd + sifs, "MU-BAR Trigger Frame sent at wrong time");
926 
927  // A first STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
928  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[13].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
929  && m_txPsdus[13].psduMap.size () == 1
930  && m_txPsdus[13].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
931  true, "Expected a Block Ack");
932  tEnd = m_txPsdus[12].endTx;
933  tStart = m_txPsdus[13].startTx;
934  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
935  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
936 
937  // A second STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
938  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[14].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
939  && m_txPsdus[14].psduMap.size () == 1
940  && m_txPsdus[14].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
941  true, "Expected a Block Ack");
942  tEnd = m_txPsdus[12].endTx;
943  tStart = m_txPsdus[14].startTx;
944  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
945  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
946 
947  // A third STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
948  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[15].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
949  && m_txPsdus[15].psduMap.size () == 1
950  && m_txPsdus[15].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
951  true, "Expected a Block Ack");
952  tEnd = m_txPsdus[12].endTx;
953  tStart = m_txPsdus[15].startTx;
954  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
955  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
956 
957  // A fourth STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
958  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[16].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
959  && m_txPsdus[16].psduMap.size () == 1
960  && m_txPsdus[16].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
961  true, "Expected a Block Ack");
962  tEnd = m_txPsdus[12].endTx;
963  tStart = m_txPsdus[16].startTx;
964  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
965  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
966 
967  if (m_txopLimit > 0)
968  {
969  // DL MU PPDU's NAV
970  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[13].endTx, "Duration/ID in the DL MU PPDU is too short");
971  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[14].endTx, "Duration/ID in the DL MU PPDU is too short");
972  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[15].endTx, "Duration/ID in the DL MU PPDU is too short");
973  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[16].endTx, "Duration/ID in the DL MU PPDU is too short");
974  }
975  // MU-BAR Trigger Frame's NAV
976  navEnd = m_txPsdus[12].endTx + m_txPsdus[12].psduMap[SU_STA_ID]->GetDuration ();
977  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[13].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
978  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[14].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
979  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[15].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
980  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[16].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
981 
982  nTxPsdus = 17;
983  }
984  else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_AGGREGATE_TF)
985  {
986  /*
987  * |--------NAV------>|
988  * |------|-----------| |-----------|
989  * |PSDU 1|MU-BAR TF 1| |Block Ack 1|
990  * |------------------| |-----------|
991  * |PSDU 2|MU-BAR TF 2| |Block Ack 2|
992  * |------------------|<SIFS>|-----------|
993  * |PSDU 3|MU-BAR TF 3| |Block Ack 3|
994  * |------------------| |-----------|
995  * |PSDU 4|MU-BAR TF 4| |Block Ack 4|
996  * --------------------------------------------------
997  * From: AP
998  * To: AP
999  */
1000  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 16, "Expected at least 16 packets");
1001 
1002  // The last MPDU in each PSDU is a MU-BAR Trigger Frame
1003  for (auto& psdu : m_txPsdus[11].psduMap)
1004  {
1005  NS_TEST_EXPECT_MSG_EQ ((*(--psdu.second->end ()))->GetHeader ().IsTrigger (), true,
1006  "Expected an aggregated MU-BAR Trigger Frame");
1007  }
1008 
1009  // A first STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1010  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[12].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1011  && m_txPsdus[12].psduMap.size () == 1
1012  && m_txPsdus[12].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1013  true, "Expected a Block Ack");
1014  tEnd = m_txPsdus[11].endTx;
1015  tStart = m_txPsdus[12].startTx;
1016  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1017  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1018  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[12].endTx, "Duration/ID in the DL MU PPDU is too short");
1019 
1020  // A second STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1021  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[13].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1022  && m_txPsdus[13].psduMap.size () == 1
1023  && m_txPsdus[13].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1024  true, "Expected a Block Ack");
1025  tEnd = m_txPsdus[11].endTx;
1026  tStart = m_txPsdus[13].startTx;
1027  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1028  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1029  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[13].endTx, "Duration/ID in the DL MU PPDU is too short");
1030 
1031  // A third STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1032  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[14].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1033  && m_txPsdus[14].psduMap.size () == 1
1034  && m_txPsdus[14].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1035  true, "Expected a Block Ack");
1036  tEnd = m_txPsdus[11].endTx;
1037  tStart = m_txPsdus[14].startTx;
1038  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1039  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1040  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[14].endTx, "Duration/ID in the DL MU PPDU is too short");
1041 
1042  // A fourth STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1043  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[15].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1044  && m_txPsdus[15].psduMap.size () == 1
1045  && m_txPsdus[15].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1046  true, "Expected a Block Ack");
1047  tEnd = m_txPsdus[11].endTx;
1048  tStart = m_txPsdus[15].startTx;
1049  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1050  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1051  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[15].endTx, "Duration/ID in the DL MU PPDU is too short");
1052 
1053  nTxPsdus = 16;
1054  }
1055 
1057  "Not all DL packets have been received");
1058 
1060  {
1061  // EDCA disabled, find the first PSDU transmitted by a station not in an
1062  // HE TB PPDU and check that it was not transmitted before the MU EDCA
1063  // timer expired
1064  for (std::size_t i = nTxPsdus; i < m_txPsdus.size (); ++i)
1065  {
1066  if (m_txPsdus[i].psduMap.size () == 1
1067  && m_txPsdus[i].psduMap.begin ()->second->GetHeader (0).GetAddr2 () != m_apDevice->GetAddress ()
1068  && !m_txPsdus[i].txVector.IsUlMu ())
1069  {
1070  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus[i].startTx.GetMicroSeconds (),
1072  + m_muEdcaParameterSet.muTimer * 8192,
1073  "A station transmitted before the MU EDCA timer expired");
1074  break;
1075  }
1076  }
1077  }
1079  {
1080  // stations used worse access parameters after successful UL MU transmission
1081  for (const auto& cwValue : m_cwValues)
1082  {
1083  NS_TEST_EXPECT_MSG_EQ ((cwValue == 2 || cwValue >= m_muEdcaParameterSet.muCwMin),
1084  true, "A station did not set the correct MU CW min");
1085  }
1086  }
1087 
1088  m_txPsdus.clear ();
1089 }
1090 
1091 void
1093 {
1094  RngSeedManager::SetSeed (1);
1095  RngSeedManager::SetRun (2);
1096  int64_t streamNumber = 100;
1097 
1099  wifiApNode.Create (1);
1100 
1102  wifiStaNodes.Create (m_nStations);
1103 
1104  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
1105  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
1106  spectrumChannel->AddPropagationLossModel (lossModel);
1107  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
1108  spectrumChannel->SetPropagationDelayModel (delayModel);
1109 
1111  phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
1112  phy.SetErrorRateModel ("ns3::NistErrorRateModel");
1113  phy.SetChannel (spectrumChannel);
1114  switch (m_channelWidth)
1115  {
1116  case 20:
1117  phy.Set ("ChannelNumber", UintegerValue (36));
1118  break;
1119  case 40:
1120  phy.Set ("ChannelNumber", UintegerValue (38));
1121  break;
1122  case 80:
1123  phy.Set ("ChannelNumber", UintegerValue (42));
1124  break;
1125  case 160:
1126  phy.Set ("ChannelNumber", UintegerValue (50));
1127  break;
1128  default:
1129  NS_ABORT_MSG ("Invalid channel bandwidth (must be 20, 40, 80 or 160)");
1130  }
1131  phy.Set ("ChannelWidth", UintegerValue (m_channelWidth));
1132 
1133  Config::SetDefault ("ns3::HeConfiguration::MuBeAifsn",
1135  Config::SetDefault ("ns3::HeConfiguration::MuBeCwMin",
1137  Config::SetDefault ("ns3::HeConfiguration::MuBeCwMax",
1139  Config::SetDefault ("ns3::HeConfiguration::BeMuEdcaTimer",
1141  // MU EDCA timers must be either all null or all non-null
1142  Config::SetDefault ("ns3::HeConfiguration::BkMuEdcaTimer",
1144  Config::SetDefault ("ns3::HeConfiguration::ViMuEdcaTimer",
1146  Config::SetDefault ("ns3::HeConfiguration::VoMuEdcaTimer",
1148 
1149  // increase MSDU lifetime so that it does not expire before the MU EDCA timer ends
1150  Config::SetDefault ("ns3::WifiMacQueue::MaxDelay", TimeValue (Seconds (2)));
1151 
1152  WifiHelper wifi;
1153  wifi.SetStandard (WIFI_STANDARD_80211ax_5GHZ);
1154  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
1155 
1157  Ssid ssid = Ssid ("ns-3-ssid");
1158  mac.SetType ("ns3::StaWifiMac",
1159  "BE_MaxAmsduSize", UintegerValue (0),
1160  "BE_MaxAmpduSize", UintegerValue (0),
1161  "Ssid", SsidValue (ssid),
1162  /* setting blockack threshold for sta's BE queue */
1163  "BE_BlockAckThreshold", UintegerValue (2),
1164  "ActiveProbing", BooleanValue (false));
1165 
1166  m_staDevices = wifi.Install (phy, mac, wifiStaNodes);
1167 
1168  mac.SetType ("ns3::ApWifiMac",
1169  "BE_MaxAmsduSize", UintegerValue (0),
1170  "BE_MaxAmpduSize", UintegerValue (0),
1171  "Ssid", SsidValue (ssid),
1172  "BeaconGeneration", BooleanValue (true));
1173  mac.SetMultiUserScheduler ("ns3::TestMultiUserScheduler");
1174  mac.SetAckManager ("ns3::WifiDefaultAckManager", "DlMuAckSequenceType", EnumValue (m_dlMuAckType));
1175 
1176  m_apDevice = wifi.Install (phy, mac, wifiApNode).Get (0);
1177 
1178  // Assign fixed streams to random variables in use
1179  streamNumber += wifi.AssignStreams (NetDeviceContainer (m_apDevice), streamNumber);
1180  streamNumber += wifi.AssignStreams (m_staDevices, streamNumber);
1181 
1183  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
1184 
1185  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
1186  positionAlloc->Add (Vector (1.0, 0.0, 0.0));
1187  positionAlloc->Add (Vector (0.0, 1.0, 0.0));
1188  positionAlloc->Add (Vector (-1.0, 0.0, 0.0));
1189  positionAlloc->Add (Vector (-1.0, -1.0, 0.0));
1190  mobility.SetPositionAllocator (positionAlloc);
1191 
1192  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
1193  mobility.Install (wifiApNode);
1194  mobility.Install (wifiStaNodes);
1195 
1196  Ptr<WifiNetDevice> dev;
1197 
1198  // Set maximum A-MPDU size
1199  for (uint32_t i = 0; i < m_staDevices.GetN (); i++)
1200  {
1201  dev = DynamicCast<WifiNetDevice> (m_staDevices.Get (i));
1202  dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (m_maxAmpduSize));
1203  }
1204  dev = DynamicCast<WifiNetDevice> (m_apDevice);
1205  dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (m_maxAmpduSize));
1206 
1207  PointerValue ptr;
1208  dev->GetMac ()->GetAttribute ("BE_Txop", ptr);
1209  Ptr<QosTxop> apBeQosTxop = ptr.Get<QosTxop> ();
1210  // set the TXOP limit on BE AC
1211  apBeQosTxop->SetTxopLimit (MicroSeconds (m_txopLimit));
1212 
1213  PacketSocketHelper packetSocket;
1214  packetSocket.Install (wifiApNode);
1215  packetSocket.Install (wifiStaNodes);
1216 
1217  // DL Traffic
1218  for (uint16_t i = 0; i < m_nStations; i++)
1219  {
1220  PacketSocketAddress socket;
1221  socket.SetSingleDevice (m_apDevice->GetIfIndex ());
1222  socket.SetPhysicalAddress (m_staDevices.Get (i)->GetAddress ());
1223  socket.SetProtocol (1);
1224 
1225  // the first client application generates two packets in order
1226  // to trigger the establishment of a Block Ack agreement
1227  Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient> ();
1228  client1->SetAttribute ("PacketSize", UintegerValue (1400));
1229  client1->SetAttribute ("MaxPackets", UintegerValue (2));
1230  client1->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1231  client1->SetRemote (socket);
1232  wifiApNode.Get (0)->AddApplication (client1);
1233  client1->SetStartTime (Seconds (1) + i * MilliSeconds (1));
1234  client1->SetStopTime (Seconds (2.0));
1235 
1236  // the second client application generates the selected number of packets,
1237  // which are sent in DL MU PPDUs.
1238  Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient> ();
1239  client2->SetAttribute ("PacketSize", UintegerValue (1400 + i * 100));
1240  client2->SetAttribute ("MaxPackets", UintegerValue (m_nPktsPerSta));
1241  client2->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1242  client2->SetRemote (socket);
1243  wifiApNode.Get (0)->AddApplication (client2);
1244  client2->SetStartTime (Seconds (1.5));
1245  client2->SetStopTime (Seconds (2.5));
1246 
1247  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
1248  server->SetLocal (socket);
1249  wifiStaNodes.Get (i)->AddApplication (server);
1250  server->SetStartTime (Seconds (0.0));
1251  server->SetStopTime (Seconds (3.0));
1252  }
1253 
1254  // UL Traffic
1255  for (uint16_t i = 0; i < m_nStations; i++)
1256  {
1257  PacketSocketAddress socket;
1258  socket.SetSingleDevice (m_staDevices.Get (i)->GetIfIndex ());
1260  socket.SetProtocol (1);
1261 
1262  // the first client application generates two packets in order
1263  // to trigger the establishment of a Block Ack agreement
1264  Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient> ();
1265  client1->SetAttribute ("PacketSize", UintegerValue (1400));
1266  client1->SetAttribute ("MaxPackets", UintegerValue (2));
1267  client1->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1268  client1->SetRemote (socket);
1269  wifiStaNodes.Get (i)->AddApplication (client1);
1270  client1->SetStartTime (Seconds (1.005) + i * MilliSeconds (1));
1271  client1->SetStopTime (Seconds (2.0));
1272 
1273  // the second client application generates the selected number of packets,
1274  // which are sent in HE TB PPDUs.
1275  Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient> ();
1276  client2->SetAttribute ("PacketSize", UintegerValue (1400 + i * 100));
1277  client2->SetAttribute ("MaxPackets", UintegerValue (m_nPktsPerSta));
1278  client2->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1279  client2->SetRemote (socket);
1280  wifiStaNodes.Get (i)->AddApplication (client2);
1281  client2->SetStartTime (Seconds (1.50011)); // start before sending QoS Null frames
1282  client2->SetStopTime (Seconds (2.5));
1283 
1284  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
1285  server->SetLocal (socket);
1286  wifiApNode.Get (0)->AddApplication (server);
1287  server->SetStartTime (Seconds (0.0));
1288  server->SetStopTime (Seconds (3.0));
1289  }
1290 
1291  Config::Connect ("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx",
1293  // Trace PSDUs passed to the PHY on all devices
1294  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
1296 
1297  Simulator::Stop (Seconds (3));
1298  Simulator::Run ();
1299 
1300  CheckResults (dev->GetMac ()->GetWifiPhy ()->GetSifs (), dev->GetMac ()->GetWifiPhy ()->GetSlot (),
1301  apBeQosTxop->GetAifsn ());
1302 
1303  Simulator::Destroy ();
1304 }
1305 
1306 
1314 {
1315 public:
1317 };
1318 
1320  : TestSuite ("wifi-mac-ofdma", UNIT)
1321 {
1322  using MuEdcaParams = std::initializer_list<OfdmaAckSequenceTest::MuEdcaParameterSet>;
1323 
1324  for (auto& muEdcaParameterSet : MuEdcaParams {{0, 0, 0, 0} /* no MU EDCA */,
1325  {0, 127, 2047, 100} /* EDCA disabled */,
1326  {10, 127, 2047, 100} /* worse parameters */})
1327  {
1328  AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1329  AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_AGGREGATE_TF, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1330  AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_TF_MU_BAR, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1331  AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1332  AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_AGGREGATE_TF, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1333  AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_TF_MU_BAR, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1334  }
1335 }
1336 
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
ns3::TypeId
a unique identifier for an interface.
Definition: type-id.h:59
NS_LOG_COMPONENT_DEFINE
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
ns3::MultiUserScheduler::DL_MU_TX
@ DL_MU_TX
Definition: multi-user-scheduler.h:66
ns3::WIFI_MAC_QOSDATA_NULL
@ WIFI_MAC_QOSDATA_NULL
Definition: wifi-mac-header.h:74
ns3::MultiUserScheduler::UlMuInfo
Information to be provided in case of UL MU transmission.
Definition: multi-user-scheduler.h:79
ns3::TestCase::AddTestCase
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
ns3::ListPositionAllocator::Add
void Add(Vector v)
Add a position to the list of positions.
Definition: position-allocator.cc:70
OfdmaAckSequenceTest::CheckResults
void CheckResults(Time sifs, Time slotTime, uint8_t aifsn)
Check correctness of transmitted frames.
Definition: wifi-mac-ofdma-test.cc:544
ns3::WifiTxVector::SetTxPowerLevel
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
Definition: wifi-tx-vector.cc:242
NS_OBJECT_ENSURE_REGISTERED
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
OfdmaAckSequenceTest::FrameInfo::txVector
WifiTxVector txVector
TXVECTOR.
Definition: wifi-mac-ofdma-test.cc:392
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
ns3::WifiPsduMap
std::unordered_map< uint16_t, Ptr< WifiPsdu > > WifiPsduMap
Map of PSDUs indexed by STA-ID.
Definition: he-frame-exchange-manager.h:34
OfdmaAckSequenceTest::MuEdcaParameterSet::muTimer
uint8_t muTimer
MU EDCA Timer in units of 8192 microseconds (0 not to use MU EDCA)
Definition: wifi-mac-ofdma-test.cc:336
ns3::WifiMacHeader::GetQosQueueSize
uint8_t GetQosQueueSize(void) const
Get the Queue Size subfield in the QoS control field.
Definition: wifi-mac-header.cc:869
OfdmaAckSequenceTest::FrameInfo::psduMap
WifiConstPsduMap psduMap
transmitted PSDU map
Definition: wifi-mac-ofdma-test.cc:391
ns3::Packet::GetSize
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
ns3::Packet::AddHeader
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
ns3::NetDevice::GetAddress
virtual Address GetAddress(void) const =0
ns3::WifiTxParameters::m_txDuration
Time m_txDuration
TX duration of the frame.
Definition: wifi-tx-parameters.h:65
ns3::MultiUserScheduler
MultiUserScheduler is an abstract base class defining the API that APs supporting at least VHT can us...
Definition: multi-user-scheduler.h:51
OfdmaAckSequenceTest::DoRun
void DoRun(void) override
Implementation to actually run this TestCase.
Definition: wifi-mac-ofdma-test.cc:1092
TestMultiUserScheduler::m_txVector
WifiTxVector m_txVector
the TX vector for MU PPDUs
Definition: wifi-mac-ofdma-test.cc:86
TestMultiUserScheduler::TestMultiUserScheduler
TestMultiUserScheduler()
Definition: wifi-mac-ofdma-test.cc:105
OfdmaAckSequenceTest::L7Receive
void L7Receive(std::string context, Ptr< const Packet > p, const Address &addr)
Function to trace packets received by the server application.
Definition: wifi-mac-ofdma-test.cc:435
OfdmaAckSequenceTest::m_staDevices
NetDeviceContainer m_staDevices
stations' devices
Definition: wifi-mac-ofdma-test.cc:396
ns3
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ns3::CtrlTriggerHeader::GetGuardInterval
uint16_t GetGuardInterval(void) const
Get the guard interval duration (in nanoseconds) of the solicited HE TB PPDU.
Definition: ctrl-headers.cc:1919
NS_TEST_EXPECT_MSG_GT_OR_EQ
#define NS_TEST_EXPECT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to limit and report if not.
Definition: test.h:1109
ns3::WifiHelper
helps to create WifiNetDevice objects
Definition: wifi-helper.h:327
ns3::MicroSeconds
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
OfdmaAckSequenceTest::MuEdcaParameterSet::muCwMin
uint16_t muCwMin
MU CW min.
Definition: wifi-mac-ofdma-test.cc:334
ns3::WifiTxVector::SetGuardInterval
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
Definition: wifi-tx-vector.cc:260
ns3::WIFI_PHY_BAND_5GHZ
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
OfdmaAckSequenceTest::m_apDevice
Ptr< NetDevice > m_apDevice
AP's device.
Definition: wifi-mac-ofdma-test.cc:397
ns3::WIFI_STANDARD_80211ax_5GHZ
@ WIFI_STANDARD_80211ax_5GHZ
Definition: wifi-standards.h:135
ns3::WifiMacHeader::SetDsNotFrom
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
Definition: wifi-mac-header.cc:90
ns3::MultiUserScheduler::m_initialFrame
bool m_initialFrame
true if a TXOP is being started
Definition: multi-user-scheduler.h:139
OfdmaAckSequenceTest::m_txopLimit
uint16_t m_txopLimit
TXOP limit in microseconds.
Definition: wifi-mac-ofdma-test.cc:402
TestMultiUserScheduler::m_psduMap
WifiPsduMap m_psduMap
the DL MU PPDU to transmit
Definition: wifi-mac-ofdma-test.cc:88
ns3::TriggerFrameType
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:561
ns3::PointerValue
Hold objects of type Ptr<T>.
Definition: pointer.h:37
ns3::Mac48Address
an EUI-48 address
Definition: mac48-address.h:44
Min
#define Min(a, b)
Definition: aarf-wifi-manager.cc:25
ns3::PacketSocketAddress
an address for a packet socket
Definition: packet-socket-address.h:39
ns3::ObjectBase::SetAttribute
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
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
WifiMacOfdmaTestSuite
wifi MAC OFDMA Test Suite
Definition: wifi-mac-ofdma-test.cc:1314
ns3::CtrlBAckResponseHeader::GetNPerAidTidInfoSubfields
std::size_t GetNPerAidTidInfoSubfields(void) const
For Multi-STA Block Acks, get the number of Per AID TID Info subfields included in this Block Ack.
Definition: ctrl-headers.cc:621
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::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
OfdmaAckSequenceTest::MuEdcaParameterSet
MU EDCA Parameter Set.
Definition: wifi-mac-ofdma-test.cc:332
ns3::WifiTxParameters
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
Definition: wifi-tx-parameters.h:45
ns3::PacketSocketClient::SetRemote
void SetRemote(PacketSocketAddress addr)
set the remote address and protocol to be used
Definition: packet-socket-client.cc:91
ns3::TypeId::SetParent
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
OfdmaAckSequenceTest::m_edcaDisabledStartTime
Time m_edcaDisabledStartTime
time when disabling EDCA started
Definition: wifi-mac-ofdma-test.cc:407
ns3::MultiUserScheduler::SU_TX
@ SU_TX
Definition: multi-user-scheduler.h:65
ns3::EnumValue
Hold variables of type enum.
Definition: enum.h:55
ns3::SsidValue
AttributeValue implementation for Ssid.
Definition: ssid.h:105
ns3::Ssid
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
OfdmaAckSequenceTest::MuEdcaParameterSet::muAifsn
uint8_t muAifsn
MU AIFS (0 to disable EDCA)
Definition: wifi-mac-ofdma-test.cc:333
ns3::WifiTxParameters::m_protection
std::unique_ptr< WifiProtection > m_protection
protection method
Definition: wifi-tx-parameters.h:63
OfdmaAckSequenceTest::m_channelWidth
uint16_t m_channelWidth
PHY channel bandwidth in MHz.
Definition: wifi-mac-ofdma-test.cc:398
TestMultiUserScheduler::m_ulTriggerType
TriggerFrameType m_ulTriggerType
Trigger Frame type for UL MU.
Definition: wifi-mac-ofdma-test.cc:83
TestMultiUserScheduler::GetTypeId
static TypeId GetTypeId(void)
Get the type ID.
Definition: wifi-mac-ofdma-test.cc:95
ns3::GetPpduMaxTime
Time GetPpduMaxTime(WifiPreamble preamble)
Get the maximum PPDU duration (see Section 10.14 of 802.11-2016) for the PHY layers defining the aPPD...
Definition: wifi-phy-common.cc:135
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
OfdmaAckSequenceTest::m_maxAmpduSize
uint32_t m_maxAmpduSize
maximum A-MPDU size in bytes
Definition: wifi-mac-ofdma-test.cc:401
TestMultiUserScheduler::m_txFormat
TxFormat m_txFormat
the format of next transmission
Definition: wifi-mac-ofdma-test.cc:82
ns3::WifiMacHeader
Implements the IEEE 802.11 MAC header.
Definition: wifi-mac-header.h:85
ns3::CtrlBAckResponseHeader::IsMultiSta
bool IsMultiSta(void) const
Check if the BlockAck frame variant is Multi-STA Block Ack.
Definition: ctrl-headers.cc:564
ns3::Application::SetStopTime
void SetStopTime(Time stop)
Specify application stop time.
Definition: application.cc:75
TestMultiUserScheduler
Dummy Multi User Scheduler used to test OFDMA ack sequences.
Definition: wifi-mac-ofdma-test.cc:61
ns3::PacketSocketHelper::Install
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
Definition: packet-socket-helper.cc:37
third.wifi
wifi
Definition: third.py:96
TestMultiUserScheduler::ComputeUlMuInfo
UlMuInfo ComputeUlMuInfo(void) override
Prepare the information required to solicit an UL MU transmission.
Definition: wifi-mac-ofdma-test.cc:303
ns3::Ptr< WifiMacQueueItem >
ns3::WifiMacQueueItem::ConstIterator
std::list< Ptr< WifiMacQueueItem > >::const_iterator ConstIterator
Const iterator typedef.
Definition: wifi-mac-queue-item.h:144
OfdmaAckSequenceTest::m_muEdcaParameterSet
MuEdcaParameterSet m_muEdcaParameterSet
MU EDCA Parameter Set.
Definition: wifi-mac-ofdma-test.cc:404
ns3::Application::SetStartTime
void SetStartTime(Time start)
Specify application start time.
Definition: application.cc:69
NS_TEST_EXPECT_MSG_GT
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
Definition: test.h:1088
ns3::WifiMacHeader::GetType
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
Definition: wifi-mac-header.cc:448
ns3::QosTxop::GetAifsn
uint8_t GetAifsn(void) const override
Return the number of slots that make up an AIFS according to the EDCA Parameter Set or the MU EDCA Pa...
Definition: qos-txop.cc:233
OfdmaAckSequenceTest::m_nStations
uint16_t m_nStations
number of stations
Definition: wifi-mac-ofdma-test.cc:395
ns3::WifiMode
represent a single transmission mode
Definition: wifi-mode.h:48
ns3::Now
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
ns3::MultiUserScheduler::m_availableTime
Time m_availableTime
the time available for frame exchange
Definition: multi-user-scheduler.h:138
ns3::NanoSeconds
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1313
ns3::Address
a polymophic address class
Definition: address.h:91
ns3::Time::GetMicroSeconds
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:388
ns3::MultiUserScheduler::DlMuInfo
Information to be provided in case of DL MU transmission.
Definition: multi-user-scheduler.h:72
NS_LOG_INFO
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
ns3::MilliSeconds
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
ns3::CtrlTriggerHeader::IsBasic
bool IsBasic(void) const
Check if this is a Basic Trigger frame.
Definition: ctrl-headers.cc:1768
ns3::BSRP_TRIGGER
@ BSRP_TRIGGER
Definition: ctrl-headers.h:566
OfdmaAckSequenceTest::FrameInfo
Information about transmitted frames.
Definition: wifi-mac-ofdma-test.cc:388
ns3::Txop::GetWifiMacQueue
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:154
ns3::HeRu::RuType
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:42
ns3::MultiUserScheduler::m_heFem
Ptr< HeFrameExchangeManager > m_heFem
HE Frame Exchange Manager.
Definition: multi-user-scheduler.h:136
OfdmaAckSequenceTest::FrameInfo::endTx
Time endTx
end TX time
Definition: wifi-mac-ofdma-test.cc:390
ns3::CtrlTriggerHeader
Headers for Trigger frames.
Definition: ctrl-headers.h:886
ns3::MultiUserScheduler::UL_MU_TX
@ UL_MU_TX
Definition: multi-user-scheduler.h:67
ns3::AC_BE
@ AC_BE
Best Effort.
Definition: qos-utils.h:73
SU_STA_ID
#define SU_STA_ID
Definition: wifi-mode.h:32
ns3::PointerValue::Get
Ptr< T > Get(void) const
Definition: pointer.h:201
ns3::WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_CTL_TRIGGER
Definition: wifi-mac-header.h:38
ns3::WifiTxParameters::Clear
void Clear(void)
Reset the TX parameters.
Definition: wifi-tx-parameters.cc:67
OfdmaAckSequenceTest::FrameInfo::startTx
Time startTx
start TX time
Definition: wifi-mac-ofdma-test.cc:389
ns3::WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_MU
Definition: wifi-phy-common.h:76
ns3::WifiTxVector::GetPreambleType
WifiPreamble GetPreambleType(void) const
Definition: wifi-tx-vector.cc:148
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
TestMultiUserScheduler::m_tbPpduDuration
Time m_tbPpduDuration
Duration of the solicited TB PPDUs.
Definition: wifi-mac-ofdma-test.cc:85
ns3::Time
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
TestMultiUserScheduler::SelectTxFormat
TxFormat SelectTxFormat(void) override
Select the format of the next transmission.
Definition: wifi-mac-ofdma-test.cc:118
ns3::WifiTxVector::SetChannelWidth
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
Definition: wifi-tx-vector.cc:254
third.wifiApNode
wifiApNode
Definition: third.py:90
NS_ABORT_MSG_IF
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
ns3::MultiUserScheduler::m_apMac
Ptr< ApWifiMac > m_apMac
the AP wifi MAC
Definition: multi-user-scheduler.h:135
ns3::CtrlTriggerHeader::GetNUserInfoFields
std::size_t GetNUserInfoFields(void) const
Get the number of User Info fields in this Trigger Frame.
Definition: ctrl-headers.cc:2034
ns3::PacketSocketAddress::SetSingleDevice
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Definition: packet-socket-address.cc:46
ns3::PacketSocketHelper
Give ns3::PacketSocket powers to ns3::Node.
Definition: packet-socket-helper.h:32
ns3::MultiUserScheduler::GetWifiRemoteStationManager
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(void) const
Get the station manager attached to the AP.
Definition: multi-user-scheduler.cc:121
ns3::WifiTxVector::IsMu
bool IsMu(void) const
Return true if this TX vector is used for a multi-user transmission.
Definition: wifi-tx-vector.cc:370
ns3::CtrlTriggerHeader::SetUlLength
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
Definition: ctrl-headers.cc:1816
ns3::QosTxop
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:72
ns3::WifiTxParameters::m_acknowledgment
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
Definition: wifi-tx-parameters.h:64
TestMultiUserScheduler::~TestMultiUserScheduler
virtual ~TestMultiUserScheduler()
Definition: wifi-mac-ofdma-test.cc:112
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
WifiMacOfdmaTestSuite::WifiMacOfdmaTestSuite
WifiMacOfdmaTestSuite()
Definition: wifi-mac-ofdma-test.cc:1319
OfdmaAckSequenceTest::m_received
uint16_t m_received
number of packets received by the stations
Definition: wifi-mac-ofdma-test.cc:405
OfdmaAckSequenceTest::MuEdcaParameterSet::muCwMax
uint16_t muCwMax
MU CW max.
Definition: wifi-mac-ofdma-test.cc:335
ns3::WifiMacHeader::SetAddr2
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
Definition: wifi-mac-header.cc:114
OfdmaAckSequenceTest::m_cwValues
std::vector< uint32_t > m_cwValues
CW used by stations after MU exchange.
Definition: wifi-mac-ofdma-test.cc:408
ns3::WifiMacHeader::GetQosTid
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
Definition: wifi-mac-header.cc:862
ns3::TestSuite
A suite of tests to run.
Definition: test.h:1344
NS_LOG_FUNCTION_NOARGS
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
Definition: log-macros-enabled.h:209
OfdmaAckSequenceTest::~OfdmaAckSequenceTest
virtual ~OfdmaAckSequenceTest()
Definition: wifi-mac-ofdma-test.cc:430
ns3::CtrlBAckResponseHeader::GetAckType
bool GetAckType(std::size_t index) const
For Multi-STA Block Acks, get the Ack Type subfield of the Per AID TID Info subfield identified by th...
Definition: ctrl-headers.cc:597
ns3::Config::Connect
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
ns3::CtrlBAckResponseHeader::GetTidInfo
uint8_t GetTidInfo(std::size_t index=0) const
For Block Ack variants other than Multi-STA Block Ack, get the TID_INFO subfield of the BA Control fi...
Definition: ctrl-headers.cc:510
NS_TEST_EXPECT_MSG_LT_OR_EQ
#define NS_TEST_EXPECT_MSG_LT_OR_EQ(actual, limit, msg)
Test that an actual value is less than or equal to a limit and report if not.
Definition: test.h:922
ns3::WifiMacQueue::Remove
Ptr< WifiMacQueueItem > Remove(void) override
Remove the packet in the front of the queue.
Definition: wifi-mac-queue.cc:303
OfdmaAckSequenceTest::m_dlMuAckType
WifiAcknowledgment::Method m_dlMuAckType
DL MU ack sequence type.
Definition: wifi-mac-ofdma-test.cc:400
NS_LOG_DEBUG
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
ns3::WifiTxParameters::m_txVector
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
Definition: wifi-tx-parameters.h:62
OfdmaAckSequenceTest::m_nPktsPerSta
uint16_t m_nPktsPerSta
number of packets to send to each station
Definition: wifi-mac-ofdma-test.cc:403
OfdmaAckSequenceTest
Test OFDMA acknowledgment sequences.
Definition: wifi-mac-ofdma-test.cc:326
ns3::Seconds
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
OfdmaAckSequenceTest::TraceCw
void TraceCw(uint32_t staIndex, uint32_t oldCw, uint32_t cw)
Function to trace CW value used by the given station after the MU exchange.
Definition: wifi-mac-ofdma-test.cc:444
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
ns3::PacketSocketAddress::SetPhysicalAddress
void SetPhysicalAddress(const Address address)
Set the destination address.
Definition: packet-socket-address.cc:53
ns3::BASIC_TRIGGER
@ BASIC_TRIGGER
Definition: ctrl-headers.h:562
third.ssid
ssid
Definition: third.py:100
ns3::TimeValue
AttributeValue implementation for Time.
Definition: nstime.h:1353
OfdmaAckSequenceTest::OfdmaAckSequenceTest
OfdmaAckSequenceTest(uint16_t width, WifiAcknowledgment::Method dlType, uint32_t maxAmpduSize, uint16_t txopLimit, uint16_t nPktsPerSta, MuEdcaParameterSet muEdcaParameterSet)
Constructor.
Definition: wifi-mac-ofdma-test.cc:411
NS_LOG_FUNCTION
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Definition: log-macros-enabled.h:244
ns3::Txop::SetTxopLimit
void SetTxopLimit(Time txopLimit)
Set the TXOP limit.
Definition: txop.cc:254
g_wifiMacOfdmaTestSuite
static WifiMacOfdmaTestSuite g_wifiMacOfdmaTestSuite
the test suite
Definition: wifi-mac-ofdma-test.cc:1337
ns3::CtrlTriggerHeader::IsBsrp
bool IsBsrp(void) const
Check if this is a Buffer Status Report Poll Trigger frame.
Definition: ctrl-headers.cc:1792
ns3::NodeContainer
keep track of a set of node pointers.
Definition: node-container.h:39
TestMultiUserScheduler::ComputeDlMuInfo
DlMuInfo ComputeDlMuInfo(void) override
Compute the information required to perform a DL MU transmission.
Definition: wifi-mac-ofdma-test.cc:296
TestMultiUserScheduler::ComputeWifiTxVector
void ComputeWifiTxVector(void)
Compute the TX vector to use for MU PPDUs.
Definition: wifi-mac-ofdma-test.cc:243
OfdmaAckSequenceTest::m_flushed
uint16_t m_flushed
number of DL packets flushed after DL MU PPDU
Definition: wifi-mac-ofdma-test.cc:406
TestMultiUserScheduler::m_txParams
WifiTxParameters m_txParams
TX parameters.
Definition: wifi-mac-ofdma-test.cc:87
third.wifiStaNodes
wifiStaNodes
Definition: third.py:88
ns3::MultiUserScheduler::m_sizeOf8QosNull
uint32_t m_sizeOf8QosNull
size in bytes of 8 QoS Null frames
Definition: multi-user-scheduler.h:140
OfdmaAckSequenceTest::m_txPsdus
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
Definition: wifi-mac-ofdma-test.cc:399
ns3::PacketSocketAddress::SetProtocol
void SetProtocol(uint16_t protocol)
Set the protocol.
Definition: packet-socket-address.cc:33
ns3::WifiAcknowledgment::Method
Method
Available acknowledgment methods.
Definition: wifi-acknowledgment.h:51
ns3::UintegerValue
Hold an unsigned integer type.
Definition: uinteger.h:44
OfdmaAckSequenceTest::Transmit
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when FrameExchangeManager passes PSDUs to the PHY.
Definition: wifi-mac-ofdma-test.cc:455
TestMultiUserScheduler::m_trigger
Ptr< WifiMacQueueItem > m_trigger
Trigger Frame to send.
Definition: wifi-mac-ofdma-test.cc:84
ns3::WifiMacHelper
create MAC layers for a ns3::WifiNetDevice.
Definition: wifi-mac-helper.h:48
ns3::Config::SetDefault
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
ns3::NetDeviceContainer::GetN
uint32_t GetN(void) const
Get the number of Ptr<NetDevice> stored in this container.
Definition: net-device-container.cc:57
ns3::WifiMacHeader::SetDsNotTo
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
Definition: wifi-mac-header.cc:102
ns3::ObjectBase::TraceConnectWithoutContext
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:293
ns3::MultiUserScheduler::TxFormat
TxFormat
Enumeration of the possible transmission formats.
Definition: multi-user-scheduler.h:63
ns3::PacketSocketServer::SetLocal
void SetLocal(PacketSocketAddress addr)
set the local address and protocol to be used
Definition: packet-socket-server.cc:102
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::NetDevice::GetIfIndex
virtual uint32_t GetIfIndex(void) const =0
ns3::WifiTxVector::SetPreambleType
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
Definition: wifi-tx-vector.cc:248
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
third.mobility
mobility
Definition: third.py:108
third.phy
phy
Definition: third.py:93
NS_TEST_EXPECT_MSG_LT
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report if not.
Definition: test.h:901
ns3::CtrlBAckResponseHeader
Headers for BlockAck response.
Definition: ctrl-headers.h:202
ns3::WifiNetDevice::GetMac
Ptr< WifiMac > GetMac(void) const
Definition: wifi-net-device.cc:201
NS_ABORT_MSG
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50