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  m_trigger = CtrlTriggerHeader (ulTriggerType, m_txVector);
140 
141  WifiTxVector txVector = m_txVector;
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;
151  std::tie (length, duration) = HePhy::ConvertHeTbPpduDurationToLSigLength (duration,
152  m_trigger.GetHeTbTxVector (m_trigger.begin ()->GetAid12 ()),
153  m_apMac->GetWifiPhy ()->GetPhyBand ());
154  m_trigger.SetUlLength (length);
155 
156  Ptr<Packet> packet = Create<Packet> ();
157  packet->AddHeader (m_trigger);
158 
160  m_triggerHdr.SetAddr1 (Mac48Address::GetBroadcast ());
161  m_triggerHdr.SetAddr2 (m_apMac->GetAddress ());
164 
165  auto item = Create<WifiMacQueueItem> (packet, m_triggerHdr);
166 
167  m_txParams.Clear ();
168  // set the TXVECTOR used to send the Trigger Frame
169  m_txParams.m_txVector = m_apMac->GetWifiRemoteStationManager ()->GetRtsTxVector (m_triggerHdr.GetAddr1 ());
170 
171  if (!m_heFem->TryAddMpdu (item, m_txParams, m_availableTime)
172  || (m_availableTime != Time::Min ()
173  && m_txParams.m_protection->protectionTime
174  + m_txParams.m_txDuration // TF tx time
175  + m_apMac->GetWifiPhy ()->GetSifs ()
176  + duration
177  + m_txParams.m_acknowledgment->acknowledgmentTime
178  > m_availableTime ))
179  {
180  NS_LOG_DEBUG ("Remaining TXOP duration is not enough for BSRP TF exchange");
181  return SU_TX;
182  }
183 
185  m_ulTriggerType = ulTriggerType;
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_triggerHdr, 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 = 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 = 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 ("ChannelSettings", StringValue ("{36, 20, BAND_5GHZ, 0}"));
1117  break;
1118  case 40:
1119  phy.Set ("ChannelSettings", StringValue ("{38, 40, BAND_5GHZ, 0}"));
1120  break;
1121  case 80:
1122  phy.Set ("ChannelSettings", StringValue ("{42, 80, BAND_5GHZ, 0}"));
1123  break;
1124  case 160:
1125  phy.Set ("ChannelSettings", StringValue ("{50, 160, BAND_5GHZ, 0}"));
1126  break;
1127  default:
1128  NS_ABORT_MSG ("Invalid channel bandwidth (must be 20, 40, 80 or 160)");
1129  }
1130 
1131  Config::SetDefault ("ns3::HeConfiguration::MuBeAifsn",
1133  Config::SetDefault ("ns3::HeConfiguration::MuBeCwMin",
1135  Config::SetDefault ("ns3::HeConfiguration::MuBeCwMax",
1137  Config::SetDefault ("ns3::HeConfiguration::BeMuEdcaTimer",
1139  // MU EDCA timers must be either all null or all non-null
1140  Config::SetDefault ("ns3::HeConfiguration::BkMuEdcaTimer",
1142  Config::SetDefault ("ns3::HeConfiguration::ViMuEdcaTimer",
1144  Config::SetDefault ("ns3::HeConfiguration::VoMuEdcaTimer",
1146 
1147  // increase MSDU lifetime so that it does not expire before the MU EDCA timer ends
1148  Config::SetDefault ("ns3::WifiMacQueue::MaxDelay", TimeValue (Seconds (2)));
1149 
1150  WifiHelper wifi;
1151  wifi.SetStandard (WIFI_STANDARD_80211ax);
1152  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
1153 
1155  Ssid ssid = Ssid ("ns-3-ssid");
1156  mac.SetType ("ns3::StaWifiMac",
1157  "BE_MaxAmsduSize", UintegerValue (0),
1158  "BE_MaxAmpduSize", UintegerValue (0),
1159  "Ssid", SsidValue (ssid),
1160  /* setting blockack threshold for sta's BE queue */
1161  "BE_BlockAckThreshold", UintegerValue (2),
1162  "ActiveProbing", BooleanValue (false));
1163 
1164  m_staDevices = wifi.Install (phy, mac, wifiStaNodes);
1165 
1166  mac.SetType ("ns3::ApWifiMac",
1167  "BE_MaxAmsduSize", UintegerValue (0),
1168  "BE_MaxAmpduSize", UintegerValue (0),
1169  "Ssid", SsidValue (ssid),
1170  "BeaconGeneration", BooleanValue (true));
1171  mac.SetMultiUserScheduler ("ns3::TestMultiUserScheduler");
1172  mac.SetAckManager ("ns3::WifiDefaultAckManager", "DlMuAckSequenceType", EnumValue (m_dlMuAckType));
1173 
1174  m_apDevice = wifi.Install (phy, mac, wifiApNode).Get (0);
1175 
1176  // Assign fixed streams to random variables in use
1177  streamNumber += wifi.AssignStreams (NetDeviceContainer (m_apDevice), streamNumber);
1178  streamNumber += wifi.AssignStreams (m_staDevices, streamNumber);
1179 
1181  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
1182 
1183  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
1184  positionAlloc->Add (Vector (1.0, 0.0, 0.0));
1185  positionAlloc->Add (Vector (0.0, 1.0, 0.0));
1186  positionAlloc->Add (Vector (-1.0, 0.0, 0.0));
1187  positionAlloc->Add (Vector (-1.0, -1.0, 0.0));
1188  mobility.SetPositionAllocator (positionAlloc);
1189 
1190  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
1191  mobility.Install (wifiApNode);
1192  mobility.Install (wifiStaNodes);
1193 
1194  Ptr<WifiNetDevice> dev;
1195 
1196  // Set maximum A-MPDU size
1197  for (uint32_t i = 0; i < m_staDevices.GetN (); i++)
1198  {
1199  dev = DynamicCast<WifiNetDevice> (m_staDevices.Get (i));
1200  dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (m_maxAmpduSize));
1201  }
1202  dev = DynamicCast<WifiNetDevice> (m_apDevice);
1203  dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (m_maxAmpduSize));
1204 
1205  PointerValue ptr;
1206  dev->GetMac ()->GetAttribute ("BE_Txop", ptr);
1207  Ptr<QosTxop> apBeQosTxop = ptr.Get<QosTxop> ();
1208  // set the TXOP limit on BE AC
1209  apBeQosTxop->SetTxopLimit (MicroSeconds (m_txopLimit));
1210 
1211  PacketSocketHelper packetSocket;
1212  packetSocket.Install (wifiApNode);
1213  packetSocket.Install (wifiStaNodes);
1214 
1215  // DL Traffic
1216  for (uint16_t i = 0; i < m_nStations; i++)
1217  {
1218  PacketSocketAddress socket;
1219  socket.SetSingleDevice (m_apDevice->GetIfIndex ());
1220  socket.SetPhysicalAddress (m_staDevices.Get (i)->GetAddress ());
1221  socket.SetProtocol (1);
1222 
1223  // the first client application generates two packets in order
1224  // to trigger the establishment of a Block Ack agreement
1225  Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient> ();
1226  client1->SetAttribute ("PacketSize", UintegerValue (1400));
1227  client1->SetAttribute ("MaxPackets", UintegerValue (2));
1228  client1->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1229  client1->SetRemote (socket);
1230  wifiApNode.Get (0)->AddApplication (client1);
1231  client1->SetStartTime (Seconds (1) + i * MilliSeconds (1));
1232  client1->SetStopTime (Seconds (2.0));
1233 
1234  // the second client application generates the selected number of packets,
1235  // which are sent in DL MU PPDUs.
1236  Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient> ();
1237  client2->SetAttribute ("PacketSize", UintegerValue (1400 + i * 100));
1238  client2->SetAttribute ("MaxPackets", UintegerValue (m_nPktsPerSta));
1239  client2->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1240  client2->SetRemote (socket);
1241  wifiApNode.Get (0)->AddApplication (client2);
1242  client2->SetStartTime (Seconds (1.5));
1243  client2->SetStopTime (Seconds (2.5));
1244 
1245  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
1246  server->SetLocal (socket);
1247  wifiStaNodes.Get (i)->AddApplication (server);
1248  server->SetStartTime (Seconds (0.0));
1249  server->SetStopTime (Seconds (3.0));
1250  }
1251 
1252  // UL Traffic
1253  for (uint16_t i = 0; i < m_nStations; i++)
1254  {
1255  PacketSocketAddress socket;
1256  socket.SetSingleDevice (m_staDevices.Get (i)->GetIfIndex ());
1258  socket.SetProtocol (1);
1259 
1260  // the first client application generates two packets in order
1261  // to trigger the establishment of a Block Ack agreement
1262  Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient> ();
1263  client1->SetAttribute ("PacketSize", UintegerValue (1400));
1264  client1->SetAttribute ("MaxPackets", UintegerValue (2));
1265  client1->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1266  client1->SetRemote (socket);
1267  wifiStaNodes.Get (i)->AddApplication (client1);
1268  client1->SetStartTime (Seconds (1.005) + i * MilliSeconds (1));
1269  client1->SetStopTime (Seconds (2.0));
1270 
1271  // the second client application generates the selected number of packets,
1272  // which are sent in HE TB PPDUs.
1273  Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient> ();
1274  client2->SetAttribute ("PacketSize", UintegerValue (1400 + i * 100));
1275  client2->SetAttribute ("MaxPackets", UintegerValue (m_nPktsPerSta));
1276  client2->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1277  client2->SetRemote (socket);
1278  wifiStaNodes.Get (i)->AddApplication (client2);
1279  client2->SetStartTime (Seconds (1.50011)); // start before sending QoS Null frames
1280  client2->SetStopTime (Seconds (2.5));
1281 
1282  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
1283  server->SetLocal (socket);
1284  wifiApNode.Get (0)->AddApplication (server);
1285  server->SetStartTime (Seconds (0.0));
1286  server->SetStopTime (Seconds (3.0));
1287  }
1288 
1289  Config::Connect ("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx",
1291  // Trace PSDUs passed to the PHY on all devices
1292  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
1294 
1295  Simulator::Stop (Seconds (3));
1296  Simulator::Run ();
1297 
1298  CheckResults (dev->GetMac ()->GetWifiPhy ()->GetSifs (), dev->GetMac ()->GetWifiPhy ()->GetSlot (),
1299  apBeQosTxop->GetAifsn ());
1300 
1301  Simulator::Destroy ();
1302 }
1303 
1304 
1312 {
1313 public:
1315 };
1316 
1318  : TestSuite ("wifi-mac-ofdma", UNIT)
1319 {
1320  using MuEdcaParams = std::initializer_list<OfdmaAckSequenceTest::MuEdcaParameterSet>;
1321 
1322  for (auto& muEdcaParameterSet : MuEdcaParams {{0, 0, 0, 0} /* no MU EDCA */,
1323  {0, 127, 2047, 100} /* EDCA disabled */,
1324  {10, 127, 2047, 100} /* worse parameters */})
1325  {
1326  AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1327  AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_AGGREGATE_TF, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1328  AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_TF_MU_BAR, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1329  AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1330  AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_AGGREGATE_TF, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1331  AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_TF_MU_BAR, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1332  }
1333 }
1334 
#define Min(a, b)
Test OFDMA acknowledgment sequences.
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
Time m_edcaDisabledStartTime
time when disabling EDCA started
uint16_t m_flushed
number of DL packets flushed after DL MU PPDU
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when FrameExchangeManager passes PSDUs to the PHY.
OfdmaAckSequenceTest(uint16_t width, WifiAcknowledgment::Method dlType, uint32_t maxAmpduSize, uint16_t txopLimit, uint16_t nPktsPerSta, MuEdcaParameterSet muEdcaParameterSet)
Constructor.
uint16_t m_received
number of packets received by the stations
void CheckResults(Time sifs, Time slotTime, uint8_t aifsn)
Check correctness of transmitted frames.
WifiAcknowledgment::Method m_dlMuAckType
DL MU ack sequence type.
Ptr< NetDevice > m_apDevice
AP's device.
uint16_t m_nPktsPerSta
number of packets to send to each station
NetDeviceContainer m_staDevices
stations' devices
uint16_t m_txopLimit
TXOP limit in microseconds.
void L7Receive(std::string context, Ptr< const Packet > p, const Address &addr)
Function to trace packets received by the server application.
uint16_t m_channelWidth
PHY channel bandwidth in MHz.
uint32_t m_maxAmpduSize
maximum A-MPDU size in bytes
std::vector< uint32_t > m_cwValues
CW used by stations after MU exchange.
void DoRun(void) override
Implementation to actually run this TestCase.
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.
uint16_t m_nStations
number of stations
MuEdcaParameterSet m_muEdcaParameterSet
MU EDCA Parameter Set.
Dummy Multi User Scheduler used to test OFDMA ack sequences.
TxFormat SelectTxFormat(void) override
Select the format of the next transmission.
WifiPsduMap m_psduMap
the DL MU PPDU to transmit
TxFormat m_txFormat
the format of next transmission
WifiTxVector m_txVector
the TX vector for MU PPDUs
UlMuInfo ComputeUlMuInfo(void) override
Prepare the information required to solicit an UL MU transmission.
static TypeId GetTypeId(void)
Get the type ID.
TriggerFrameType m_ulTriggerType
Trigger Frame type for UL MU.
WifiTxParameters m_txParams
TX parameters.
DlMuInfo ComputeDlMuInfo(void) override
Compute the information required to perform a DL MU transmission.
void ComputeWifiTxVector(void)
Compute the TX vector to use for MU PPDUs.
WifiMacHeader m_triggerHdr
MAC header for Trigger Frame.
CtrlTriggerHeader m_trigger
Trigger Frame to send.
wifi MAC OFDMA Test Suite
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAck response.
Definition: ctrl-headers.h:202
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...
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.
bool IsMultiSta(void) const
Check if the BlockAck frame variant is Multi-STA Block Ack.
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...
Headers for Trigger frames.
Definition: ctrl-headers.h:886
ConstIterator begin(void) const
Get a const iterator pointing to the first User Info field in the list.
bool IsBsrp(void) const
Check if this is a Buffer Status Report Poll Trigger frame.
WifiTxVector GetHeTbTxVector(uint16_t staId) const
Get the TX vector that the station with the given STA-ID will use to send the HE TB PPDU solicited by...
std::size_t GetNUserInfoFields(void) const
Get the number of User Info fields in this Trigger Frame.
bool IsBasic(void) const
Check if this is a Basic Trigger frame.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
uint16_t GetGuardInterval(void) const
Get the guard interval duration (in nanoseconds) of the solicited HE TB PPDU.
Hold variables of type enum.
Definition: enum.h:55
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:42
an EUI-48 address
Definition: mac48-address.h:44
Helper class used to assign positions and mobility models to nodes.
MultiUserScheduler is an abstract base class defining the API that APs supporting at least VHT can us...
bool m_initialFrame
true if a TXOP is being started
Ptr< ApWifiMac > m_apMac
the AP wifi MAC
Time m_availableTime
the time available for frame exchange
Ptr< HeFrameExchangeManager > m_heFem
HE Frame Exchange Manager.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(void) const
Get the station manager attached to the AP.
uint32_t m_sizeOf8QosNull
size in bytes of 8 QoS Null frames
TxFormat
Enumeration of the possible transmission formats.
holds a vector of ns3::NetDevice pointers
uint32_t GetN(void) const
Get the number of Ptr<NetDevice> stored in this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
virtual Address GetAddress(void) const =0
virtual uint32_t GetIfIndex(void) const =0
keep track of a set of node pointers.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get(void) const
Definition: pointer.h:201
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:72
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
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
Definition: ssid.h:105
Hold variables of type string.
Definition: string.h:41
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:387
AttributeValue implementation for Time.
Definition: nstime.h:1308
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:154
void SetTxopLimit(Time txopLimit)
Set the TXOP limit.
Definition: txop.cc:254
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
helps to create WifiNetDevice objects
Definition: wifi-helper.h:274
Implements the IEEE 802.11 MAC header.
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
uint8_t GetQosQueueSize(void) const
Get the Queue Size subfield in the QoS control field.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
create MAC layers for a ns3::WifiNetDevice.
represent a single transmission mode
Definition: wifi-mode.h:48
Ptr< WifiMac > GetMac(void) const
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
void Clear(void)
Reset the TX parameters.
std::unique_ptr< WifiProtection > m_protection
protection method
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
Time m_txDuration
TX duration of the frame.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType(void) const
bool IsMu(void) const
Return true if this TX vector is used for a multi-user transmission.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
#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:935
#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:785
#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:748
#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:899
#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:240
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1268
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:561
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ AC_BE
Best Effort.
Definition: qos-utils.h:73
@ BASIC_TRIGGER
Definition: ctrl-headers.h:562
@ BSRP_TRIGGER
Definition: ctrl-headers.h:566
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Time GetPpduMaxTime(WifiPreamble preamble)
Get the maximum PPDU duration (see Section 10.14 of 802.11-2016) for the PHY layers defining the aPPD...
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_QOSDATA_NULL
std::unordered_map< uint16_t, Ptr< WifiPsdu > > WifiPsduMap
Map of PSDUs indexed by STA-ID.
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:1648
ssid
Definition: third.py:100
mac
Definition: third.py:99
wifi
Definition: third.py:96
wifiApNode
Definition: third.py:90
mobility
Definition: third.py:108
wifiStaNodes
Definition: third.py:88
phy
Definition: third.py:93
Information about transmitted frames.
WifiConstPsduMap psduMap
transmitted PSDU map
uint8_t muAifsn
MU AIFS (0 to disable EDCA)
uint8_t muTimer
MU EDCA Timer in units of 8192 microseconds (0 not to use MU EDCA)
Information to be provided in case of DL MU transmission.
Information to be provided in case of UL MU transmission.
Method
Available acknowledgment methods.
static WifiMacOfdmaTestSuite g_wifiMacOfdmaTestSuite
the test suite
#define SU_STA_ID
Definition: wifi-mode.h:32