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 
208  Ptr<WifiMacQueueItem> mpdu = m_apMac->GetQosTxop (AC_BE)->GetNextMpdu (peeked, m_txParams,
211  if (mpdu == 0)
212  {
213  NS_LOG_DEBUG ("Not enough time to send frames to all the stations");
214  return SU_TX;
215  }
216 
217  std::vector<Ptr<WifiMacQueueItem>> mpduList;
218  mpduList = m_heFem->GetMpduAggregator ()->GetNextAmpdu (mpdu, m_txParams, m_availableTime);
219 
220  if (mpduList.size () > 1)
221  {
222  m_psduMap[sta.first] = Create<WifiPsdu> (std::move (mpduList));
223  }
224  else
225  {
226  m_psduMap[sta.first] = Create<WifiPsdu> (mpdu, true);
227  }
228  }
229 
231  }
232  else
233  {
234  NS_ABORT_MSG ("Cannot get here.");
235  }
236 
237  NS_LOG_DEBUG ("Return " << m_txFormat);
238  return m_txFormat;
239 }
240 
241 void
243 {
245  {
246  // the TX vector has been already computed
247  return;
248  }
249 
250  uint16_t bw = m_apMac->GetWifiPhy ()->GetChannelWidth ();
251 
254  m_txVector.SetGuardInterval (m_apMac->GetHeConfiguration ()->GetGuardInterval ().GetNanoSeconds ());
255  m_txVector.SetTxPowerLevel (GetWifiRemoteStationManager ()->GetDefaultTxPowerLevel ());
256 
257  const std::map<uint16_t, Mac48Address>& staList = m_apMac->GetStaList ();
258  NS_ABORT_MSG_IF (staList.size () != 4, "There must be 4 associated stations");
259 
260  HeRu::RuType ruType;
261  switch (bw)
262  {
263  case 20:
264  ruType = HeRu::RU_52_TONE;
265  break;
266  case 40:
267  ruType = HeRu::RU_106_TONE;
268  break;
269  case 80:
270  ruType = HeRu::RU_242_TONE;
271  break;
272  case 160:
273  ruType = HeRu::RU_484_TONE;
274  break;
275  default:
276  NS_ABORT_MSG ("Unsupported channel width");
277  }
278 
279  bool primary80 = true;
280  std::size_t ruIndex = 1;
281 
282  for (auto& sta : staList)
283  {
284  if (bw == 160 && ruIndex == 3)
285  {
286  ruIndex = 1;
287  primary80 = false;
288  }
289  m_txVector.SetHeMuUserInfo (sta.first,
290  {{ruType, ruIndex++, primary80}, WifiMode ("HeMcs11"), 1});
291  }
292 }
293 
296 {
297  NS_LOG_FUNCTION (this);
298  return DlMuInfo {m_psduMap, std::move (m_txParams)};
299 }
300 
303 {
304  NS_LOG_FUNCTION (this);
305  return UlMuInfo {m_trigger, m_tbPpduDuration, std::move (m_txParams)};
306 }
307 
308 
325 {
326 public:
331  {
332  uint8_t muAifsn;
333  uint16_t muCwMin;
334  uint16_t muCwMax;
335  uint8_t muTimer;
336  };
337 
347  OfdmaAckSequenceTest (uint16_t width, WifiAcknowledgment::Method dlType, uint32_t maxAmpduSize,
348  uint16_t txopLimit, uint16_t nPktsPerSta,
349  MuEdcaParameterSet muEdcaParameterSet);
350  virtual ~OfdmaAckSequenceTest ();
351 
358  void L7Receive (std::string context, Ptr<const Packet> p, const Address &addr);
365  void TraceCw (uint32_t staIndex, uint32_t oldCw, uint32_t cw);
373  void Transmit (std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW);
380  void CheckResults (Time sifs, Time slotTime, uint8_t aifsn);
381 
382 private:
383  void DoRun (void) override;
384 
386  struct FrameInfo
387  {
392  };
393 
394  uint16_t m_nStations;
397  uint16_t m_channelWidth;
398  std::vector<FrameInfo> m_txPsdus;
400  uint32_t m_maxAmpduSize;
401  uint16_t m_txopLimit;
402  uint16_t m_nPktsPerSta;
404  uint16_t m_received;
405  uint16_t m_flushed;
407  std::vector<uint32_t> m_cwValues;
408 };
409 
411  uint32_t maxAmpduSize, uint16_t txopLimit,
412  uint16_t nPktsPerSta,
413  MuEdcaParameterSet muEdcaParameterSet)
414  : TestCase ("Check correct operation of DL OFDMA acknowledgment sequences"),
415  m_nStations (4),
416  m_channelWidth (width),
417  m_dlMuAckType (dlType),
418  m_maxAmpduSize (maxAmpduSize),
419  m_txopLimit (txopLimit),
420  m_nPktsPerSta (nPktsPerSta),
421  m_muEdcaParameterSet (muEdcaParameterSet),
422  m_received (0),
423  m_flushed (0),
424  m_edcaDisabledStartTime (Seconds (0)),
425  m_cwValues (std::vector<uint32_t> (m_nStations, 2)) // 2 is an invalid CW value
426 {
427 }
428 
430 {
431 }
432 
433 void
434 OfdmaAckSequenceTest::L7Receive (std::string context, Ptr<const Packet> p, const Address &addr)
435 {
436  if (p->GetSize () >= 1400 && Simulator::Now () > Seconds (1.5))
437  {
438  m_received++;
439  }
440 }
441 
442 void
443 OfdmaAckSequenceTest::TraceCw (uint32_t staIndex, uint32_t oldCw, uint32_t cw)
444 {
445  if (m_cwValues.at (staIndex) == 2)
446  {
447  // store the first CW used after MU exchange (the last one may be used after
448  // the MU EDCA timer expired)
449  m_cwValues[staIndex] = cw;
450  }
451 }
452 
453 void
454 OfdmaAckSequenceTest::Transmit (std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
455 {
456  // skip beacon frames and frames transmitted before 1.5s (association
457  // request/response, ADDBA request, ...)
458  if (!psduMap.begin ()->second->GetHeader (0).IsBeacon ()
459  && Simulator::Now () > Seconds (1.5))
460  {
461  Time txDuration = WifiPhy::CalculateTxDuration (psduMap, txVector, WIFI_PHY_BAND_5GHZ);
462  m_txPsdus.push_back ({Simulator::Now (),
463  Simulator::Now () + txDuration,
464  psduMap, txVector});
465 
466  for (const auto& psduPair : psduMap)
467  {
468  NS_LOG_INFO ("Sending " << psduPair.second->GetHeader (0).GetTypeString ()
469  << " #MPDUs " << psduPair.second->GetNMpdus ()
470  << " txDuration " << txDuration
471  << " duration/ID " << psduPair.second->GetHeader (0).GetDuration ()
472  << " #TX PSDUs = " << m_txPsdus.size ());
473  }
474  }
475 
476  // Flush the MAC queue of the AP after sending a DL MU PPDU (no need for
477  // further transmissions)
478  if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_MU)
479  {
480  auto dev = DynamicCast<WifiNetDevice> (m_apDevice);
481  Ptr<WifiMacQueue> queue = DynamicCast<RegularWifiMac> (dev->GetMac ())->GetQosTxop (AC_BE)->GetWifiMacQueue ();
482  m_flushed = 0;
483  for (auto it = queue->begin (); it != queue->end (); )
484  {
485  auto tmp = it++;
486  if (!(*tmp)->IsInFlight ())
487  {
488  queue->Remove (*tmp, false);
489  m_flushed++;
490  }
491  }
492  }
493  else if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
494  && psduMap.begin ()->second->GetHeader (0).HasData ())
495  {
496  Mac48Address sender = psduMap.begin ()->second->GetAddr2 ();
497 
498  for (uint32_t i = 0; i < m_staDevices.GetN (); i++)
499  {
500  auto dev = DynamicCast<WifiNetDevice> (m_staDevices.Get (i));
501 
502  if (dev->GetAddress () == sender)
503  {
504  Ptr<QosTxop> qosTxop = DynamicCast<RegularWifiMac> (dev->GetMac ())->GetQosTxop (AC_BE);
505 
507  {
508  // stations use worse access parameters, trace CW. MU AIFSN must be large
509  // enough to avoid collisions between stations trying to transmit using EDCA
510  // right after the UL MU transmission and the AP trying to send a DL MU PPDU
511  qosTxop->TraceConnectWithoutContext ("CwTrace",
513  this).Bind (i));
514  }
515  else
516  {
517  // there is no "protection" against collisions from stations, hence flush
518  // their MAC queues after sending an HE TB PPDU containing QoS data frames,
519  // so that the AP can send a DL MU PPDU
520  qosTxop->GetWifiMacQueue ()->Flush ();
521  }
522  break;
523  }
524  }
525  }
526  else if (!txVector.IsMu () && psduMap.begin ()->second->GetHeader (0).IsBlockAck ()
527  && psduMap.begin ()->second->GetHeader (0).GetAddr2 () == m_apDevice->GetAddress ()
529  {
530  CtrlBAckResponseHeader blockAck;
531  psduMap.begin ()->second->GetPayload (0)->PeekHeader (blockAck);
532 
533  if (blockAck.IsMultiSta ())
534  {
535  // AP is transmitting a multi-STA BlockAck and stations have to disable EDCA,
536  // record the starting time
537  m_edcaDisabledStartTime = Simulator::Now () + m_txPsdus.back ().endTx - m_txPsdus.back ().startTx;
538  }
539  }
540 }
541 
542 void
543 OfdmaAckSequenceTest::CheckResults (Time sifs, Time slotTime, uint8_t aifsn)
544 {
545  CtrlTriggerHeader trigger;
546  CtrlBAckResponseHeader blockAck;
547  Time tEnd, // TX end for a frame
548  tStart, // TX start fot the next frame
549  tolerance = NanoSeconds (500), // due to propagation delay
550  ifs = (m_txopLimit > 0 ? sifs : sifs + aifsn * slotTime),
551  navEnd;
552 
553  /*
554  * |--------------NAV------------------>|
555  * |------NAV------->| | |------NAV-------->|
556  * |---------| |----------| |---------| |----------| |-----------|
557  * | | |QoS Null 1| | | |QoS Data 1| | |
558  * | BSRP | |----------| | Basic | |----------| | Multi-STA |
559  * | Trigger | |QoS Null 2| | Trigger | |QoS Data 2| | Block Ack |
560  * | Frame |<SIFS>|----------|<IFS>| Frame |<SIFS>|----------|<SIFS>| |
561  * | | |QoS Null 3| | | |QoS Data 3| | |
562  * | | |----------| | | |----------| | |
563  * | | |QoS Null 4| | | |QoS Data 4| | |
564  * -----------------------------------------------------------------------------------------
565  * From: AP AP AP
566  * To: all AP all AP all
567  */
568 
569  // the first packet sent after 1.5s is a BSRP Trigger Frame
570  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 5, "Expected at least 5 transmitted packet");
571  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[0].psduMap.size () == 1
572  && m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader (0).IsTrigger ()
573  && m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader (0).GetAddr1 ().IsBroadcast ()),
574  true, "Expected a Trigger Frame");
575  m_txPsdus[0].psduMap[SU_STA_ID]->GetPayload (0)->PeekHeader (trigger);
576  NS_TEST_EXPECT_MSG_EQ (trigger.IsBsrp (), true, "Expected a BSRP Trigger Frame");
577  NS_TEST_EXPECT_MSG_EQ (trigger.GetNUserInfoFields (), 4, "Expected one User Info field per station");
578 
579  // A first STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
580  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[1].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
581  && m_txPsdus[1].psduMap.size () == 1
582  && m_txPsdus[1].psduMap.begin ()->second->GetNMpdus () == 8),
583  true, "Expected 8 QoS Null frames in an HE TB PPDU");
584  for (uint8_t i = 0; i < 8; i++)
585  {
586  const WifiMacHeader& hdr = m_txPsdus[1].psduMap.begin ()->second->GetHeader (i);
587  NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
588  uint8_t tid = hdr.GetQosTid ();
589  if (tid == 0)
590  {
591  NS_TEST_EXPECT_MSG_GT (+hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
592  }
593  else
594  {
595  NS_TEST_EXPECT_MSG_EQ (+hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
596  }
597  }
598  tEnd = m_txPsdus[0].endTx;
599  navEnd = tEnd + m_txPsdus[0].psduMap[SU_STA_ID]->GetDuration ();
600  tStart = m_txPsdus[1].startTx;
601  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
602  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
603  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[1].endTx, "Duration/ID in BSRP Trigger Frame is too short");
604 
605  // A second STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
606  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[2].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
607  && m_txPsdus[2].psduMap.size () == 1
608  && m_txPsdus[2].psduMap.begin ()->second->GetNMpdus () == 8),
609  true, "Expected 8 QoS Null frames in an HE TB PPDU");
610  for (uint8_t i = 0; i < 8; i++)
611  {
612  const WifiMacHeader& hdr = m_txPsdus[2].psduMap.begin ()->second->GetHeader (i);
613  NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
614  uint8_t tid = hdr.GetQosTid ();
615  if (tid == 0)
616  {
617  NS_TEST_EXPECT_MSG_GT (+hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
618  }
619  else
620  {
621  NS_TEST_EXPECT_MSG_EQ (+hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
622  }
623  }
624  tStart = m_txPsdus[2].startTx;
625  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
626  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
627  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[2].endTx, "Duration/ID in BSRP Trigger Frame is too short");
628 
629  // A third STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
630  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[3].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
631  && m_txPsdus[3].psduMap.size () == 1
632  && m_txPsdus[3].psduMap.begin ()->second->GetNMpdus () == 8),
633  true, "Expected 8 QoS Null frames in an HE TB PPDU");
634  for (uint8_t i = 0; i < 8; i++)
635  {
636  const WifiMacHeader& hdr = m_txPsdus[3].psduMap.begin ()->second->GetHeader (i);
637  NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
638  uint8_t tid = hdr.GetQosTid ();
639  if (tid == 0)
640  {
641  NS_TEST_EXPECT_MSG_GT (+hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
642  }
643  else
644  {
645  NS_TEST_EXPECT_MSG_EQ (+hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
646  }
647  }
648  tStart = m_txPsdus[3].startTx;
649  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
650  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
651  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[3].endTx, "Duration/ID in BSRP Trigger Frame is too short");
652 
653  // A fourth STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
654  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[4].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
655  && m_txPsdus[4].psduMap.size () == 1
656  && m_txPsdus[4].psduMap.begin ()->second->GetNMpdus () == 8),
657  true, "Expected 8 QoS Null frames in an HE TB PPDU");
658  for (uint8_t i = 0; i < 8; i++)
659  {
660  const WifiMacHeader& hdr = m_txPsdus[4].psduMap.begin ()->second->GetHeader (i);
661  NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
662  uint8_t tid = hdr.GetQosTid ();
663  if (tid == 0)
664  {
665  NS_TEST_EXPECT_MSG_GT (+hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
666  }
667  else
668  {
669  NS_TEST_EXPECT_MSG_EQ (+hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
670  }
671  }
672  tStart = m_txPsdus[4].startTx;
673  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
674  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
675  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[4].endTx, "Duration/ID in BSRP Trigger Frame is too short");
676 
677  // the AP sends a Basic Trigger Frame to solicit QoS data frames
678  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 11, "Expected at least 11 transmitted packet");
679  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[5].psduMap.size () == 1
680  && m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader (0).IsTrigger ()
681  && m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader (0).GetAddr1 ().IsBroadcast ()),
682  true, "Expected a Trigger Frame");
683  m_txPsdus[5].psduMap[SU_STA_ID]->GetPayload (0)->PeekHeader (trigger);
684  NS_TEST_EXPECT_MSG_EQ (trigger.IsBasic (), true, "Expected a Basic Trigger Frame");
685  NS_TEST_EXPECT_MSG_EQ (trigger.GetNUserInfoFields (), 4, "Expected one User Info field per station");
686  tEnd = m_txPsdus[1].endTx;
687  tStart = m_txPsdus[5].startTx;
688  NS_TEST_EXPECT_MSG_LT (tEnd + ifs, tStart, "Basic Trigger Frame sent too early");
689  if (m_txopLimit > 0)
690  {
691  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Basic Trigger Frame sent too late");
692  }
693 
694  // A first STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
695  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[6].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
696  && m_txPsdus[6].psduMap.size () == 1
697  && m_txPsdus[6].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
698  true, "Expected QoS data frames in an HE TB PPDU");
699  tEnd = m_txPsdus[5].endTx;
700  tStart = m_txPsdus[6].startTx;
701  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
702  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
703 
704  // A second STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
705  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[7].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
706  && m_txPsdus[7].psduMap.size () == 1
707  && m_txPsdus[7].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
708  true, "Expected QoS data frames in an HE TB PPDU");
709  tEnd = m_txPsdus[5].endTx;
710  tStart = m_txPsdus[7].startTx;
711  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
712  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
713 
714  // A third STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
715  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[8].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
716  && m_txPsdus[8].psduMap.size () == 1
717  && m_txPsdus[8].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
718  true, "Expected QoS data frames in an HE TB PPDU");
719  tEnd = m_txPsdus[5].endTx;
720  tStart = m_txPsdus[8].startTx;
721  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
722  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
723 
724  // A fourth STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
725  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[9].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
726  && m_txPsdus[9].psduMap.size () == 1
727  && m_txPsdus[9].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
728  true, "Expected QoS data frames in an HE TB PPDU");
729  tEnd = m_txPsdus[5].endTx;
730  tStart = m_txPsdus[9].startTx;
731  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
732  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
733 
734  // the AP sends a Multi-STA Block Ack
735  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[10].psduMap.size () == 1
736  && m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()
737  && m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader (0).GetAddr1 ().IsBroadcast ()),
738  true, "Expected a Block Ack");
739  m_txPsdus[10].psduMap[SU_STA_ID]->GetPayload (0)->PeekHeader (blockAck);
740  NS_TEST_EXPECT_MSG_EQ (blockAck.IsMultiSta (), true, "Expected a Multi-STA Block Ack");
742  "Expected one Per AID TID Info subfield per station");
743  for (uint8_t i = 0; i < 4; i++)
744  {
745  NS_TEST_EXPECT_MSG_EQ (blockAck.GetAckType (i), true, "Expected All-ack context");
746  NS_TEST_EXPECT_MSG_EQ (+blockAck.GetTidInfo (i), 14, "Expected All-ack context");
747  }
748  tEnd = m_txPsdus[9].endTx;
749  tStart = m_txPsdus[10].startTx;
750  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Multi-STA Block Ack sent too early");
751  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Multi-STA Block Ack sent too late");
752 
753  navEnd = m_txPsdus[5].endTx + m_txPsdus[5].psduMap[SU_STA_ID]->GetDuration (); // Basic TF's NAV
754  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in Basic Trigger Frame is too short");
755  navEnd = m_txPsdus[6].endTx + m_txPsdus[6].psduMap.begin ()->second->GetDuration (); // 1st QoS Data frame's NAV
756  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 1st QoS Data frame is too short");
757  navEnd = m_txPsdus[7].endTx + m_txPsdus[7].psduMap.begin ()->second->GetDuration (); // 2nd QoS Data frame's NAV
758  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 2nd QoS Data frame is too short");
759  navEnd = m_txPsdus[8].endTx + m_txPsdus[8].psduMap.begin ()->second->GetDuration (); // 3rd QoS Data frame's NAV
760  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 3rd QoS Data frame is too short");
761  navEnd = m_txPsdus[9].endTx + m_txPsdus[9].psduMap.begin ()->second->GetDuration (); // 4th QoS Data frame's NAV
762  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 4th QoS Data frame is too short");
763 
764  // the AP sends a DL MU PPDU
765  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 12, "Expected at least 12 transmitted packet");
766  NS_TEST_EXPECT_MSG_EQ (m_txPsdus[11].txVector.GetPreambleType (), WIFI_PREAMBLE_HE_MU,
767  "Expected a DL MU PPDU");
768  NS_TEST_EXPECT_MSG_EQ (m_txPsdus[11].psduMap.size (), 4, "Expected 4 PSDUs within the DL MU PPDU");
769  // the TX duration cannot exceed the maximum PPDU duration
770  NS_TEST_EXPECT_MSG_LT_OR_EQ (m_txPsdus[11].endTx - m_txPsdus[11].startTx,
771  GetPpduMaxTime (m_txPsdus[11].txVector.GetPreambleType ()),
772  "TX duration cannot exceed max PPDU duration");
773  for (auto& psdu : m_txPsdus[11].psduMap)
774  {
775  NS_TEST_EXPECT_MSG_LT_OR_EQ (psdu.second->GetSize (), m_maxAmpduSize, "Max A-MPDU size exceeded");
776  }
777  tEnd = m_txPsdus[10].endTx;
778  tStart = m_txPsdus[11].startTx;
779  NS_TEST_EXPECT_MSG_LT_OR_EQ (tEnd + ifs, tStart, "DL MU PPDU sent too early");
780 
781  // The Duration/ID field is the same for all the PSDUs
782  navEnd = m_txPsdus[11].endTx;
783  for (auto& psdu : m_txPsdus[11].psduMap)
784  {
785  if (navEnd == m_txPsdus[11].endTx)
786  {
787  navEnd += psdu.second->GetDuration ();
788  }
789  else
790  {
791  NS_TEST_EXPECT_MSG_EQ (m_txPsdus[11].endTx + psdu.second->GetDuration (), navEnd,
792  "Duration/ID must be the same for all PSDUs");
793  }
794  }
795  NS_TEST_EXPECT_MSG_GT (navEnd, m_txPsdus[11].endTx, "Duration/ID of the DL MU PPDU cannot be zero");
796 
797  std::size_t nTxPsdus = 0;
798 
799  if (m_dlMuAckType == WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE)
800  {
801  /*
802  * |----------------------------------------NAV---------------------------------------------->|
803  * | |--------------------------NAV---------------------------------->|
804  * | | |-------------------NAV--------------->|
805  * | | | |----NAV---->|
806  * |------| |-----| |-----| |-----| |-----| |-----| |-----| |-----|
807  * |PSDU 1| | | | | | | | | | | | | | |
808  * |------| |Block| |Block| |Block| |Block| |Block| |Block| |Block|
809  * |PSDU 2| | Ack | | Ack | | Ack | | Ack | | Ack | | Ack | | Ack |
810  * |------|<SIFS>| |<SIFS>| Req |<SIFS>| |<SIFS>| Req |<SIFS>| |<SIFS>| Req |<SIFS>| |
811  * |PSDU 3| | | | | | | | | | | | | | |
812  * |------| | | | | | | | | | | | | | |
813  * |PSDU 4| | | | | | | | | | | | | | |
814  * ---------------------------------------------------------------------------------------------------
815  * From: AP STA 1 AP STA 2 AP STA 3 AP STA 4
816  * To: AP STA 2 AP STA 3 AP STA 4 AP
817  */
818  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 19, "Expected at least 19 packets");
819 
820  // A first STA sends a Block Ack a SIFS after the reception of the DL MU PPDU
821  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[12].psduMap.size () == 1
822  && m_txPsdus[12].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
823  true, "Expected a Block Ack");
824  tEnd = m_txPsdus[11].endTx;
825  tStart = m_txPsdus[12].startTx;
826  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "First Block Ack sent too early");
827  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "First Block Ack sent too late");
828 
829  // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
830  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[13].psduMap.size () == 1
831  && m_txPsdus[13].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAckReq ()),
832  true, "Expected a Block Ack Request");
833  tEnd = m_txPsdus[12].endTx;
834  tStart = m_txPsdus[13].startTx;
835  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "First Block Ack Request sent too early");
836  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "First Block Ack Request sent too late");
837 
838  // A second STA sends a Block Ack a SIFS after the reception of the Block Ack Request
839  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[14].psduMap.size () == 1
840  && m_txPsdus[14].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
841  true, "Expected a Block Ack");
842  tEnd = m_txPsdus[13].endTx;
843  tStart = m_txPsdus[14].startTx;
844  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Second Block Ack sent too early");
845  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Second Block Ack sent too late");
846 
847  // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
848  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[15].psduMap.size () == 1
849  && m_txPsdus[15].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAckReq ()),
850  true, "Expected a Block Ack Request");
851  tEnd = m_txPsdus[14].endTx;
852  tStart = m_txPsdus[15].startTx;
853  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Second Block Ack Request sent too early");
854  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Second Block Ack Request sent too late");
855 
856  // A third STA sends a Block Ack a SIFS after the reception of the Block Ack Request
857  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[16].psduMap.size () == 1
858  && m_txPsdus[16].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
859  true, "Expected a Block Ack");
860  tEnd = m_txPsdus[15].endTx;
861  tStart = m_txPsdus[16].startTx;
862  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Third Block Ack sent too early");
863  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Third Block Ack sent too late");
864 
865  // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
866  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[17].psduMap.size () == 1
867  && m_txPsdus[17].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAckReq ()),
868  true, "Expected a Block Ack Request");
869  tEnd = m_txPsdus[16].endTx;
870  tStart = m_txPsdus[17].startTx;
871  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Third Block Ack Request sent too early");
872  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Third Block Ack Request sent too late");
873 
874  // A fourth STA sends a Block Ack a SIFS after the reception of the Block Ack Request
875  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[18].psduMap.size () == 1
876  && m_txPsdus[18].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
877  true, "Expected a Block Ack");
878  tEnd = m_txPsdus[17].endTx;
879  tStart = m_txPsdus[18].startTx;
880  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Fourth Block Ack sent too early");
881  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Fourth Block Ack sent too late");
882 
883  if (m_txopLimit > 0)
884  {
885  // DL MU PPDU's NAV
886  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the DL MU PPDU is too short");
887  // 1st BlockAckReq's NAV
888  navEnd = m_txPsdus[13].endTx + m_txPsdus[13].psduMap[SU_STA_ID]->GetDuration ();
889  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the 1st BlockAckReq is too short");
890  // 2nd BlockAckReq's NAV
891  navEnd = m_txPsdus[15].endTx + m_txPsdus[15].psduMap[SU_STA_ID]->GetDuration ();
892  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the 2nd BlockAckReq is too short");
893  // 3rd BlockAckReq's NAV
894  navEnd = m_txPsdus[17].endTx + m_txPsdus[17].psduMap[SU_STA_ID]->GetDuration ();
895  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the 3rd BlockAckReq is too short");
896  }
897  nTxPsdus = 19;
898  }
899  else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_TF_MU_BAR)
900  {
901  /*
902  * |----------------NAV--------------->|
903  * | |--------NAV------>|
904  * |------| |---------| |-----------|
905  * |PSDU 1| | | |Block Ack 1|
906  * |------| | MU-BAR | |-----------|
907  * |PSDU 2| | Trigger | |Block Ack 2|
908  * |------|<SIFS>| Frame |<SIFS>|-----------|
909  * |PSDU 3| | | |Block Ack 3|
910  * |------| | | |-----------|
911  * |PSDU 4| | | |Block Ack 4|
912  * --------------------------------------------------
913  * From: AP AP
914  * To: all AP
915  */
916  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 17, "Expected at least 17 packets");
917 
918  // the AP transmits a MU-BAR Trigger Frame an IFS after the transmission of the DL MU PPDU
919  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[12].psduMap.size () == 1
920  && m_txPsdus[12].psduMap[SU_STA_ID]->GetHeader (0).IsTrigger ()),
921  true, "Expected a MU-BAR Trigger Frame");
922  tEnd = m_txPsdus[11].endTx;
923  tStart = m_txPsdus[12].startTx;
924  NS_TEST_EXPECT_MSG_EQ (tStart, tEnd + sifs, "MU-BAR Trigger Frame sent at wrong time");
925 
926  // A first STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
927  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[13].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
928  && m_txPsdus[13].psduMap.size () == 1
929  && m_txPsdus[13].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
930  true, "Expected a Block Ack");
931  tEnd = m_txPsdus[12].endTx;
932  tStart = m_txPsdus[13].startTx;
933  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
934  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
935 
936  // A second STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
937  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[14].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
938  && m_txPsdus[14].psduMap.size () == 1
939  && m_txPsdus[14].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
940  true, "Expected a Block Ack");
941  tEnd = m_txPsdus[12].endTx;
942  tStart = m_txPsdus[14].startTx;
943  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
944  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
945 
946  // A third STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
947  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[15].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
948  && m_txPsdus[15].psduMap.size () == 1
949  && m_txPsdus[15].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
950  true, "Expected a Block Ack");
951  tEnd = m_txPsdus[12].endTx;
952  tStart = m_txPsdus[15].startTx;
953  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
954  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
955 
956  // A fourth STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
957  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[16].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
958  && m_txPsdus[16].psduMap.size () == 1
959  && m_txPsdus[16].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
960  true, "Expected a Block Ack");
961  tEnd = m_txPsdus[12].endTx;
962  tStart = m_txPsdus[16].startTx;
963  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
964  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
965 
966  if (m_txopLimit > 0)
967  {
968  // DL MU PPDU's NAV
969  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[13].endTx, "Duration/ID in the DL MU PPDU is too short");
970  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[14].endTx, "Duration/ID in the DL MU PPDU is too short");
971  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[15].endTx, "Duration/ID in the DL MU PPDU is too short");
972  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[16].endTx, "Duration/ID in the DL MU PPDU is too short");
973  }
974  // MU-BAR Trigger Frame's NAV
975  navEnd = m_txPsdus[12].endTx + m_txPsdus[12].psduMap[SU_STA_ID]->GetDuration ();
976  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[13].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
977  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[14].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
978  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[15].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
979  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[16].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
980 
981  nTxPsdus = 17;
982  }
983  else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_AGGREGATE_TF)
984  {
985  /*
986  * |--------NAV------>|
987  * |------|-----------| |-----------|
988  * |PSDU 1|MU-BAR TF 1| |Block Ack 1|
989  * |------------------| |-----------|
990  * |PSDU 2|MU-BAR TF 2| |Block Ack 2|
991  * |------------------|<SIFS>|-----------|
992  * |PSDU 3|MU-BAR TF 3| |Block Ack 3|
993  * |------------------| |-----------|
994  * |PSDU 4|MU-BAR TF 4| |Block Ack 4|
995  * --------------------------------------------------
996  * From: AP
997  * To: AP
998  */
999  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 16, "Expected at least 16 packets");
1000 
1001  // The last MPDU in each PSDU is a MU-BAR Trigger Frame
1002  for (auto& psdu : m_txPsdus[11].psduMap)
1003  {
1004  NS_TEST_EXPECT_MSG_EQ ((*(--psdu.second->end ()))->GetHeader ().IsTrigger (), true,
1005  "Expected an aggregated MU-BAR Trigger Frame");
1006  }
1007 
1008  // A first STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1009  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[12].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1010  && m_txPsdus[12].psduMap.size () == 1
1011  && m_txPsdus[12].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1012  true, "Expected a Block Ack");
1013  tEnd = m_txPsdus[11].endTx;
1014  tStart = m_txPsdus[12].startTx;
1015  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1016  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1017  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[12].endTx, "Duration/ID in the DL MU PPDU is too short");
1018 
1019  // A second STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1020  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[13].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1021  && m_txPsdus[13].psduMap.size () == 1
1022  && m_txPsdus[13].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1023  true, "Expected a Block Ack");
1024  tEnd = m_txPsdus[11].endTx;
1025  tStart = m_txPsdus[13].startTx;
1026  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1027  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1028  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[13].endTx, "Duration/ID in the DL MU PPDU is too short");
1029 
1030  // A third STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1031  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[14].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1032  && m_txPsdus[14].psduMap.size () == 1
1033  && m_txPsdus[14].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1034  true, "Expected a Block Ack");
1035  tEnd = m_txPsdus[11].endTx;
1036  tStart = m_txPsdus[14].startTx;
1037  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1038  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1039  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[14].endTx, "Duration/ID in the DL MU PPDU is too short");
1040 
1041  // A fourth STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1042  NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[15].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1043  && m_txPsdus[15].psduMap.size () == 1
1044  && m_txPsdus[15].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1045  true, "Expected a Block Ack");
1046  tEnd = m_txPsdus[11].endTx;
1047  tStart = m_txPsdus[15].startTx;
1048  NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1049  NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1050  NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[15].endTx, "Duration/ID in the DL MU PPDU is too short");
1051 
1052  nTxPsdus = 16;
1053  }
1054 
1056  "Not all DL packets have been received");
1057 
1059  {
1060  // EDCA disabled, find the first PSDU transmitted by a station not in an
1061  // HE TB PPDU and check that it was not transmitted before the MU EDCA
1062  // timer expired
1063  for (std::size_t i = nTxPsdus; i < m_txPsdus.size (); ++i)
1064  {
1065  if (m_txPsdus[i].psduMap.size () == 1
1066  && m_txPsdus[i].psduMap.begin ()->second->GetHeader (0).GetAddr2 () != m_apDevice->GetAddress ()
1067  && !m_txPsdus[i].txVector.IsUlMu ())
1068  {
1069  NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus[i].startTx.GetMicroSeconds (),
1071  + m_muEdcaParameterSet.muTimer * 8192,
1072  "A station transmitted before the MU EDCA timer expired");
1073  break;
1074  }
1075  }
1076  }
1078  {
1079  // stations used worse access parameters after successful UL MU transmission
1080  for (const auto& cwValue : m_cwValues)
1081  {
1082  NS_TEST_EXPECT_MSG_EQ ((cwValue == 2 || cwValue >= m_muEdcaParameterSet.muCwMin),
1083  true, "A station did not set the correct MU CW min");
1084  }
1085  }
1086 
1087  m_txPsdus.clear ();
1088 }
1089 
1090 void
1092 {
1093  RngSeedManager::SetSeed (1);
1094  RngSeedManager::SetRun (1);
1095  int64_t streamNumber = 20;
1096 
1098  wifiApNode.Create (1);
1099 
1101  wifiStaNodes.Create (m_nStations);
1102 
1103  Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
1104  Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
1105  spectrumChannel->AddPropagationLossModel (lossModel);
1106  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
1107  spectrumChannel->SetPropagationDelayModel (delayModel);
1108 
1110  phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
1111  phy.SetErrorRateModel ("ns3::NistErrorRateModel");
1112  phy.SetChannel (spectrumChannel);
1113  switch (m_channelWidth)
1114  {
1115  case 20:
1116  phy.Set ("ChannelNumber", UintegerValue (36));
1117  break;
1118  case 40:
1119  phy.Set ("ChannelNumber", UintegerValue (38));
1120  break;
1121  case 80:
1122  phy.Set ("ChannelNumber", UintegerValue (42));
1123  break;
1124  case 160:
1125  phy.Set ("ChannelNumber", UintegerValue (50));
1126  break;
1127  default:
1128  NS_ABORT_MSG ("Invalid channel bandwidth (must be 20, 40, 80 or 160)");
1129  }
1130  phy.Set ("ChannelWidth", UintegerValue (m_channelWidth));
1131 
1132  Config::SetDefault ("ns3::HeConfiguration::MuBeAifsn",
1134  Config::SetDefault ("ns3::HeConfiguration::MuBeCwMin",
1136  Config::SetDefault ("ns3::HeConfiguration::MuBeCwMax",
1138  Config::SetDefault ("ns3::HeConfiguration::BeMuEdcaTimer",
1140  // MU EDCA timers must be either all null or all non-null
1141  Config::SetDefault ("ns3::HeConfiguration::BkMuEdcaTimer",
1143  Config::SetDefault ("ns3::HeConfiguration::ViMuEdcaTimer",
1145  Config::SetDefault ("ns3::HeConfiguration::VoMuEdcaTimer",
1147 
1148  // increase MSDU lifetime so that it does not expire before the MU EDCA timer ends
1149  Config::SetDefault ("ns3::WifiMacQueue::MaxDelay", TimeValue (Seconds (2)));
1150 
1151  WifiHelper wifi;
1152  wifi.SetStandard (WIFI_STANDARD_80211ax_5GHZ);
1153  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
1154 
1156  Ssid ssid = Ssid ("ns-3-ssid");
1157  mac.SetType ("ns3::StaWifiMac",
1158  "BE_MaxAmsduSize", UintegerValue (0),
1159  "BE_MaxAmpduSize", UintegerValue (0),
1160  "Ssid", SsidValue (ssid),
1161  /* setting blockack threshold for sta's BE queue */
1162  "BE_BlockAckThreshold", UintegerValue (2),
1163  "ActiveProbing", BooleanValue (false));
1164 
1165  m_staDevices = wifi.Install (phy, mac, wifiStaNodes);
1166 
1167  mac.SetType ("ns3::ApWifiMac",
1168  "BE_MaxAmsduSize", UintegerValue (0),
1169  "BE_MaxAmpduSize", UintegerValue (0),
1170  "Ssid", SsidValue (ssid),
1171  "BeaconGeneration", BooleanValue (true));
1172  mac.SetMultiUserScheduler ("ns3::TestMultiUserScheduler");
1173  mac.SetAckManager ("ns3::WifiDefaultAckManager", "DlMuAckSequenceType", EnumValue (m_dlMuAckType));
1174 
1175  m_apDevice = wifi.Install (phy, mac, wifiApNode).Get (0);
1176 
1177  // Assign fixed streams to random variables in use
1178  streamNumber += wifi.AssignStreams (NetDeviceContainer (m_apDevice), streamNumber);
1179  streamNumber += wifi.AssignStreams (m_staDevices, streamNumber);
1180 
1182  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
1183 
1184  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
1185  positionAlloc->Add (Vector (1.0, 0.0, 0.0));
1186  positionAlloc->Add (Vector (0.0, 1.0, 0.0));
1187  positionAlloc->Add (Vector (-1.0, 0.0, 0.0));
1188  positionAlloc->Add (Vector (-1.0, -1.0, 0.0));
1189  mobility.SetPositionAllocator (positionAlloc);
1190 
1191  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
1192  mobility.Install (wifiApNode);
1193  mobility.Install (wifiStaNodes);
1194 
1195  Ptr<WifiNetDevice> dev;
1196 
1197  // Set maximum A-MPDU size
1198  for (uint32_t i = 0; i < m_staDevices.GetN (); i++)
1199  {
1200  dev = DynamicCast<WifiNetDevice> (m_staDevices.Get (i));
1201  dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (m_maxAmpduSize));
1202  }
1203  dev = DynamicCast<WifiNetDevice> (m_apDevice);
1204  dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (m_maxAmpduSize));
1205 
1206  PointerValue ptr;
1207  dev->GetMac ()->GetAttribute ("BE_Txop", ptr);
1208  Ptr<QosTxop> apBeQosTxop = ptr.Get<QosTxop> ();
1209  // set the TXOP limit on BE AC
1210  apBeQosTxop->SetTxopLimit (MicroSeconds (m_txopLimit));
1211 
1212  PacketSocketHelper packetSocket;
1213  packetSocket.Install (wifiApNode);
1214  packetSocket.Install (wifiStaNodes);
1215 
1216  // DL Traffic
1217  for (uint16_t i = 0; i < m_nStations; i++)
1218  {
1219  PacketSocketAddress socket;
1220  socket.SetSingleDevice (m_apDevice->GetIfIndex ());
1221  socket.SetPhysicalAddress (m_staDevices.Get (i)->GetAddress ());
1222  socket.SetProtocol (1);
1223 
1224  // the first client application generates two packets in order
1225  // to trigger the establishment of a Block Ack agreement
1226  Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient> ();
1227  client1->SetAttribute ("PacketSize", UintegerValue (1400));
1228  client1->SetAttribute ("MaxPackets", UintegerValue (2));
1229  client1->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1230  client1->SetRemote (socket);
1231  wifiApNode.Get (0)->AddApplication (client1);
1232  client1->SetStartTime (Seconds (1) + i * MilliSeconds (1));
1233  client1->SetStopTime (Seconds (2.0));
1234 
1235  // the second client application generates the selected number of packets,
1236  // which are sent in DL MU PPDUs.
1237  Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient> ();
1238  client2->SetAttribute ("PacketSize", UintegerValue (1400 + i * 100));
1239  client2->SetAttribute ("MaxPackets", UintegerValue (m_nPktsPerSta));
1240  client2->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1241  client2->SetRemote (socket);
1242  wifiApNode.Get (0)->AddApplication (client2);
1243  client2->SetStartTime (Seconds (1.5));
1244  client2->SetStopTime (Seconds (2.5));
1245 
1246  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
1247  server->SetLocal (socket);
1248  wifiStaNodes.Get (i)->AddApplication (server);
1249  server->SetStartTime (Seconds (0.0));
1250  server->SetStopTime (Seconds (3.0));
1251  }
1252 
1253  // UL Traffic
1254  for (uint16_t i = 0; i < m_nStations; i++)
1255  {
1256  PacketSocketAddress socket;
1257  socket.SetSingleDevice (m_staDevices.Get (i)->GetIfIndex ());
1259  socket.SetProtocol (1);
1260 
1261  // the first client application generates two packets in order
1262  // to trigger the establishment of a Block Ack agreement
1263  Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient> ();
1264  client1->SetAttribute ("PacketSize", UintegerValue (1400));
1265  client1->SetAttribute ("MaxPackets", UintegerValue (2));
1266  client1->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1267  client1->SetRemote (socket);
1268  wifiStaNodes.Get (i)->AddApplication (client1);
1269  client1->SetStartTime (Seconds (1.005) + i * MilliSeconds (1));
1270  client1->SetStopTime (Seconds (2.0));
1271 
1272  // the second client application generates the selected number of packets,
1273  // which are sent in HE TB PPDUs.
1274  Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient> ();
1275  client2->SetAttribute ("PacketSize", UintegerValue (1400 + i * 100));
1276  client2->SetAttribute ("MaxPackets", UintegerValue (m_nPktsPerSta));
1277  client2->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1278  client2->SetRemote (socket);
1279  wifiStaNodes.Get (i)->AddApplication (client2);
1280  client2->SetStartTime (Seconds (1.50011)); // start before sending QoS Null frames
1281  client2->SetStopTime (Seconds (2.5));
1282 
1283  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
1284  server->SetLocal (socket);
1285  wifiApNode.Get (0)->AddApplication (server);
1286  server->SetStartTime (Seconds (0.0));
1287  server->SetStopTime (Seconds (3.0));
1288  }
1289 
1290  Config::Connect ("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx",
1292  // Trace PSDUs passed to the PHY on all devices
1293  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
1295 
1296  Simulator::Stop (Seconds (3));
1297  Simulator::Run ();
1298 
1299  CheckResults (dev->GetMac ()->GetWifiPhy ()->GetSifs (), dev->GetMac ()->GetWifiPhy ()->GetSlot (),
1300  apBeQosTxop->GetAifsn ());
1301 
1302  Simulator::Destroy ();
1303 }
1304 
1305 
1313 {
1314 public:
1316 };
1317 
1319  : TestSuite ("wifi-mac-ofdma", UNIT)
1320 {
1321  using MuEdcaParams = std::initializer_list<OfdmaAckSequenceTest::MuEdcaParameterSet>;
1322 
1323  for (auto& muEdcaParameterSet : MuEdcaParams {{0, 0, 0, 0} /* no MU EDCA */,
1324  {0, 127, 2047, 100} /* EDCA disabled */,
1325  {10, 127, 2047, 100} /* worse parameters */})
1326  {
1327  AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1328  AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_AGGREGATE_TF, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1329  AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_TF_MU_BAR, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1330  AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1331  AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_AGGREGATE_TF, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1332  AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_TF_MU_BAR, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1333  }
1334 }
1335 
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:543
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:391
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:335
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:390
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:1091
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:434
OfdmaAckSequenceTest::m_staDevices
NetDeviceContainer m_staDevices
stations' devices
Definition: wifi-mac-ofdma-test.cc:395
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:323
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:333
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:396
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:401
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:1313
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:331
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:406
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:332
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:397
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:400
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:302
ns3::Ptr< WifiMacQueueItem >
OfdmaAckSequenceTest::m_muEdcaParameterSet
MuEdcaParameterSet m_muEdcaParameterSet
MU EDCA Parameter Set.
Definition: wifi-mac-ofdma-test.cc:403
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:394
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:387
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:389
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:388
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:1318
OfdmaAckSequenceTest::m_received
uint16_t m_received
number of packets received by the stations
Definition: wifi-mac-ofdma-test.cc:404
OfdmaAckSequenceTest::MuEdcaParameterSet::muCwMax
uint16_t muCwMax
MU CW max.
Definition: wifi-mac-ofdma-test.cc:334
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:407
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:429
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:330
OfdmaAckSequenceTest::m_dlMuAckType
WifiAcknowledgment::Method m_dlMuAckType
DL MU ack sequence type.
Definition: wifi-mac-ofdma-test.cc:399
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:402
OfdmaAckSequenceTest
Test OFDMA acknowledgment sequences.
Definition: wifi-mac-ofdma-test.cc:325
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:443
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:410
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:1336
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:295
TestMultiUserScheduler::ComputeWifiTxVector
void ComputeWifiTxVector(void)
Compute the TX vector to use for MU PPDUs.
Definition: wifi-mac-ofdma-test.cc:242
OfdmaAckSequenceTest::m_flushed
uint16_t m_flushed
number of DL packets flushed after DL MU PPDU
Definition: wifi-mac-ofdma-test.cc:405
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:398
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:454
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