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