A Discrete-Event Network Simulator
API
wifi-mac.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18  */
19 
20 #include "wifi-mac.h"
21 
22 #include "channel-access-manager.h"
23 #include "extended-capabilities.h"
24 #include "mac-rx-middle.h"
25 #include "mac-tx-middle.h"
26 #include "mgt-headers.h"
27 #include "qos-txop.h"
28 #include "ssid.h"
30 #include "wifi-mac-queue.h"
31 #include "wifi-net-device.h"
32 
33 #include "ns3/eht-configuration.h"
34 #include "ns3/eht-frame-exchange-manager.h"
35 #include "ns3/he-configuration.h"
36 #include "ns3/ht-configuration.h"
37 #include "ns3/log.h"
38 #include "ns3/packet.h"
39 #include "ns3/pointer.h"
40 #include "ns3/vht-configuration.h"
41 
42 namespace ns3
43 {
44 
45 NS_LOG_COMPONENT_DEFINE("WifiMac");
46 
48 
50  : m_qosSupported(false)
51 {
52  NS_LOG_FUNCTION(this);
53 
54  m_rxMiddle = Create<MacRxMiddle>();
55  m_rxMiddle->SetForwardCallback(MakeCallback(&WifiMac::Receive, this));
56 
57  m_txMiddle = Create<MacTxMiddle>();
58 }
59 
61 {
62  NS_LOG_FUNCTION(this);
63 }
64 
65 TypeId
67 {
68  static TypeId tid =
69  TypeId("ns3::WifiMac")
70  .SetParent<Object>()
71  .SetGroupName("Wifi")
72  .AddAttribute("Ssid",
73  "The ssid we want to belong to.",
74  SsidValue(Ssid("default")),
75  MakeSsidAccessor(&WifiMac::GetSsid, &WifiMac::SetSsid),
76  MakeSsidChecker())
77  .AddAttribute("QosSupported",
78  "This Boolean attribute is set to enable 802.11e/WMM-style QoS support "
79  "at this STA.",
81  TypeId::ATTR_CONSTRUCT, // prevent setting after construction
82  BooleanValue(false),
85  .AddAttribute("CtsToSelfSupported",
86  "Use CTS to Self when using a rate that is not in the basic rate set.",
87  BooleanValue(false),
90  .AddAttribute(
91  "ShortSlotTimeSupported",
92  "Whether or not short slot time is supported (only used by ERP APs or STAs).",
93  BooleanValue(true),
97  .AddAttribute("Txop",
98  "The Txop object.",
99  PointerValue(),
101  MakePointerChecker<Txop>())
102  .AddAttribute("VO_Txop",
103  "Queue that manages packets belonging to AC_VO access class.",
104  PointerValue(),
106  MakePointerChecker<QosTxop>())
107  .AddAttribute("VI_Txop",
108  "Queue that manages packets belonging to AC_VI access class.",
109  PointerValue(),
111  MakePointerChecker<QosTxop>())
112  .AddAttribute("BE_Txop",
113  "Queue that manages packets belonging to AC_BE access class.",
114  PointerValue(),
116  MakePointerChecker<QosTxop>())
117  .AddAttribute("BK_Txop",
118  "Queue that manages packets belonging to AC_BK access class.",
119  PointerValue(),
121  MakePointerChecker<QosTxop>())
122  .AddAttribute("VO_MaxAmsduSize",
123  "Maximum length in bytes of an A-MSDU for AC_VO access class "
124  "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
125  "Value 0 means A-MSDU aggregation is disabled for that AC.",
126  UintegerValue(0),
128  MakeUintegerChecker<uint16_t>(0, 11398))
129  .AddAttribute("VI_MaxAmsduSize",
130  "Maximum length in bytes of an A-MSDU for AC_VI access class "
131  "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
132  "Value 0 means A-MSDU aggregation is disabled for that AC.",
133  UintegerValue(0),
135  MakeUintegerChecker<uint16_t>(0, 11398))
136  .AddAttribute("BE_MaxAmsduSize",
137  "Maximum length in bytes of an A-MSDU for AC_BE access class "
138  "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
139  "Value 0 means A-MSDU aggregation is disabled for that AC.",
140  UintegerValue(0),
142  MakeUintegerChecker<uint16_t>(0, 11398))
143  .AddAttribute("BK_MaxAmsduSize",
144  "Maximum length in bytes of an A-MSDU for AC_BK access class "
145  "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
146  "Value 0 means A-MSDU aggregation is disabled for that AC.",
147  UintegerValue(0),
149  MakeUintegerChecker<uint16_t>(0, 11398))
150  .AddAttribute(
151  "VO_MaxAmpduSize",
152  "Maximum length in bytes of an A-MPDU for AC_VO access class "
153  "(capped to 65535 for HT PPDUs, 1048575 for VHT PPDUs, 6500631 for HE PPDUs "
154  "and 15523200 for EHT PPDUs). "
155  "Value 0 means A-MPDU aggregation is disabled for that AC.",
156  UintegerValue(0),
158  MakeUintegerChecker<uint32_t>(0, 15523200))
159  .AddAttribute(
160  "VI_MaxAmpduSize",
161  "Maximum length in bytes of an A-MPDU for AC_VI access class "
162  "(capped to 65535 for HT PPDUs, 1048575 for VHT PPDUs, 6500631 for HE PPDUs "
163  "and 15523200 for EHT PPDUs). "
164  "Value 0 means A-MPDU aggregation is disabled for that AC.",
165  UintegerValue(65535),
167  MakeUintegerChecker<uint32_t>(0, 15523200))
168  .AddAttribute(
169  "BE_MaxAmpduSize",
170  "Maximum length in bytes of an A-MPDU for AC_BE access class "
171  "(capped to 65535 for HT PPDUs, 1048575 for VHT PPDUs, 6500631 for HE PPDUs "
172  "and 15523200 for EHT PPDUs). "
173  "Value 0 means A-MPDU aggregation is disabled for that AC.",
174  UintegerValue(65535),
176  MakeUintegerChecker<uint32_t>(0, 15523200))
177  .AddAttribute(
178  "BK_MaxAmpduSize",
179  "Maximum length in bytes of an A-MPDU for AC_BK access class "
180  "(capped to 65535 for HT PPDUs, 1048575 for VHT PPDUs, 6500631 for HE PPDUs "
181  "and 15523200 for EHT PPDUs). "
182  "Value 0 means A-MPDU aggregation is disabled for that AC.",
183  UintegerValue(0),
185  MakeUintegerChecker<uint32_t>(0, 15523200))
186  .AddAttribute(
187  "VO_BlockAckThreshold",
188  "If number of packets in VO queue reaches this value, "
189  "block ack mechanism is used. If this value is 0, block ack is never used."
190  "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
191  UintegerValue(0),
193  MakeUintegerChecker<uint8_t>(0, 64))
194  .AddAttribute(
195  "VI_BlockAckThreshold",
196  "If number of packets in VI queue reaches this value, "
197  "block ack mechanism is used. If this value is 0, block ack is never used."
198  "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
199  UintegerValue(0),
201  MakeUintegerChecker<uint8_t>(0, 64))
202  .AddAttribute(
203  "BE_BlockAckThreshold",
204  "If number of packets in BE queue reaches this value, "
205  "block ack mechanism is used. If this value is 0, block ack is never used."
206  "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
207  UintegerValue(0),
209  MakeUintegerChecker<uint8_t>(0, 64))
210  .AddAttribute(
211  "BK_BlockAckThreshold",
212  "If number of packets in BK queue reaches this value, "
213  "block ack mechanism is used. If this value is 0, block ack is never used."
214  "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
215  UintegerValue(0),
217  MakeUintegerChecker<uint8_t>(0, 64))
218  .AddAttribute(
219  "VO_BlockAckInactivityTimeout",
220  "Represents max time (blocks of 1024 microseconds) allowed for block ack"
221  "inactivity for AC_VO. If this value isn't equal to 0 a timer start after that a"
222  "block ack setup is completed and will be reset every time that a block ack"
223  "frame is received. If this value is 0, block ack inactivity timeout won't be "
224  "used.",
225  UintegerValue(0),
227  MakeUintegerChecker<uint16_t>())
228  .AddAttribute(
229  "VI_BlockAckInactivityTimeout",
230  "Represents max time (blocks of 1024 microseconds) allowed for block ack"
231  "inactivity for AC_VI. If this value isn't equal to 0 a timer start after that a"
232  "block ack setup is completed and will be reset every time that a block ack"
233  "frame is received. If this value is 0, block ack inactivity timeout won't be "
234  "used.",
235  UintegerValue(0),
237  MakeUintegerChecker<uint16_t>())
238  .AddAttribute(
239  "BE_BlockAckInactivityTimeout",
240  "Represents max time (blocks of 1024 microseconds) allowed for block ack"
241  "inactivity for AC_BE. If this value isn't equal to 0 a timer start after that a"
242  "block ack setup is completed and will be reset every time that a block ack"
243  "frame is received. If this value is 0, block ack inactivity timeout won't be "
244  "used.",
245  UintegerValue(0),
247  MakeUintegerChecker<uint16_t>())
248  .AddAttribute(
249  "BK_BlockAckInactivityTimeout",
250  "Represents max time (blocks of 1024 microseconds) allowed for block ack"
251  "inactivity for AC_BK. If this value isn't equal to 0 a timer start after that a"
252  "block ack setup is completed and will be reset every time that a block ack"
253  "frame is received. If this value is 0, block ack inactivity timeout won't be "
254  "used.",
255  UintegerValue(0),
257  MakeUintegerChecker<uint16_t>())
258  .AddTraceSource("MacTx",
259  "A packet has been received from higher layers and is being processed "
260  "in preparation for "
261  "queueing for transmission.",
263  "ns3::Packet::TracedCallback")
264  .AddTraceSource(
265  "MacTxDrop",
266  "A packet has been dropped in the MAC layer before being queued for transmission. "
267  "This trace source is fired, e.g., when an AP's MAC receives from the upper layer "
268  "a packet destined to a station that is not associated with the AP or a STA's MAC "
269  "receives a packet from the upper layer while it is not associated with any AP.",
271  "ns3::Packet::TracedCallback")
272  .AddTraceSource(
273  "MacPromiscRx",
274  "A packet has been received by this device, has been passed up from the physical "
275  "layer "
276  "and is being forwarded up the local protocol stack. This is a promiscuous trace.",
278  "ns3::Packet::TracedCallback")
279  .AddTraceSource("MacRx",
280  "A packet has been received by this device, has been passed up from "
281  "the physical layer "
282  "and is being forwarded up the local protocol stack. This is a "
283  "non-promiscuous trace.",
285  "ns3::Packet::TracedCallback")
286  .AddTraceSource("MacRxDrop",
287  "A packet has been dropped in the MAC layer after it has been passed "
288  "up from the physical layer.",
290  "ns3::Packet::TracedCallback")
291  .AddTraceSource("TxOkHeader",
292  "The header of successfully transmitted packet.",
294  "ns3::WifiMacHeader::TracedCallback",
296  "Use the AckedMpdu trace instead.")
297  .AddTraceSource("TxErrHeader",
298  "The header of unsuccessfuly transmitted packet.",
300  "ns3::WifiMacHeader::TracedCallback",
302  "Depending on the failure type, use the NAckedMpdu trace, the "
303  "DroppedMpdu trace or one of the traces associated with TX timeouts.")
304  .AddTraceSource("AckedMpdu",
305  "An MPDU that was successfully acknowledged, via either a "
306  "Normal Ack or a Block Ack.",
308  "ns3::WifiMpdu::TracedCallback")
309  .AddTraceSource("NAckedMpdu",
310  "An MPDU that was negatively acknowledged via a Block Ack.",
312  "ns3::WifiMpdu::TracedCallback")
313  .AddTraceSource(
314  "DroppedMpdu",
315  "An MPDU that was dropped for the given reason (see WifiMacDropReason).",
317  "ns3::WifiMac::DroppedMpduCallback")
318  .AddTraceSource(
319  "MpduResponseTimeout",
320  "An MPDU whose response was not received before the timeout, along with "
321  "an identifier of the type of timeout (see WifiTxTimer::Reason) and the "
322  "TXVECTOR used to transmit the MPDU. This trace source is fired when a "
323  "CTS is missing after an RTS, when all CTS frames are missing after an MU-RTS, "
324  "or when a Normal Ack is missing after an MPDU or after a DL MU PPDU "
325  "acknowledged in SU format.",
327  "ns3::WifiMac::MpduResponseTimeoutCallback")
328  .AddTraceSource(
329  "PsduResponseTimeout",
330  "A PSDU whose response was not received before the timeout, along with "
331  "an identifier of the type of timeout (see WifiTxTimer::Reason) and the "
332  "TXVECTOR used to transmit the PSDU. This trace source is fired when a "
333  "BlockAck is missing after an A-MPDU, a BlockAckReq (possibly in the "
334  "context of the acknowledgment of a DL MU PPDU in SU format) or a TB PPDU "
335  "(in the latter case the missing BlockAck is a Multi-STA BlockAck).",
337  "ns3::WifiMac::PsduResponseTimeoutCallback")
338  .AddTraceSource(
339  "PsduMapResponseTimeout",
340  "A PSDU map for which not all the responses were received before the timeout, "
341  "along with an identifier of the type of timeout (see WifiTxTimer::Reason), "
342  "the set of MAC addresses of the stations that did not respond and the total "
343  "number of stations that had to respond. This trace source is fired when not "
344  "all the addressed stations responded to an MU-BAR Trigger frame (either sent as "
345  "a SU frame or aggregated to PSDUs in the DL MU PPDU), a Basic Trigger Frame or "
346  "a BSRP Trigger Frame.",
348  "ns3::WifiMac::PsduMapResponseTimeoutCallback");
349  return tid;
350 }
351 
352 void
354 {
355  NS_LOG_FUNCTION(this);
356 
357  if (m_txop)
358  {
359  m_txop->Initialize();
360  }
361 
362  for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
363  {
364  it->second->Initialize();
365  }
366 }
367 
368 void
370 {
371  NS_LOG_FUNCTION(this);
372 
373  m_rxMiddle = nullptr;
374  m_txMiddle = nullptr;
375  m_links.clear();
376 
377  if (m_txop)
378  {
379  m_txop->Dispose();
380  }
381  m_txop = nullptr;
382 
383  for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
384  {
385  it->second->Dispose();
386  it->second = nullptr;
387  }
388 
389  m_device = nullptr;
390  if (m_scheduler != nullptr)
391  {
392  m_scheduler->Dispose();
393  }
394  m_scheduler = nullptr;
395 }
396 
398 {
399  // WifiMac owns pointers to ChannelAccessManager and FrameExchangeManager
401  {
403  }
404  if (feManager)
405  {
406  feManager->Dispose();
407  }
408 }
409 
410 void
412 {
413  NS_LOG_FUNCTION(this << type);
415 }
416 
419 {
420  return m_typeOfStation;
421 }
422 
423 void
425 {
426  m_device = device;
427 }
428 
431 {
432  return m_device;
433 }
434 
435 void
437 {
438  NS_LOG_FUNCTION(this << address);
439  m_address = address;
440 }
441 
444 {
445  return m_address;
446 }
447 
448 void
450 {
451  NS_LOG_FUNCTION(this << ssid);
452  m_ssid = ssid;
453 }
454 
455 Ssid
457 {
458  return m_ssid;
459 }
460 
461 void
462 WifiMac::SetBssid(Mac48Address bssid, uint8_t linkId)
463 {
464  NS_LOG_FUNCTION(this << bssid << +linkId);
465  GetLink(linkId).feManager->SetBssid(bssid);
466 }
467 
469 WifiMac::GetBssid(uint8_t linkId) const
470 {
471  return GetLink(linkId).feManager->GetBssid();
472 }
473 
474 void
476 {
477  for (auto& link : m_links)
478  {
479  link->feManager->SetPromisc();
480  }
481 }
482 
483 Ptr<Txop>
485 {
486  return m_txop;
487 }
488 
491 {
492  // Use std::find_if() instead of std::map::find() because the latter compares
493  // the given AC index with the AC index of an element in the map by using the
494  // operator< defined for AcIndex, which aborts if an operand is not a QoS AC
495  // (the AC index passed to this method may not be a QoS AC).
496  // The performance penalty is limited because std::map::find() performs 3
497  // comparisons in the worst case, while std::find_if() performs 4 comparisons
498  // in the worst case.
499  const auto it = std::find_if(m_edca.cbegin(), m_edca.cend(), [ac](const auto& pair) {
500  return pair.first == ac;
501  });
502  return (it == m_edca.cend() ? nullptr : it->second);
503 }
504 
506 WifiMac::GetQosTxop(uint8_t tid) const
507 {
508  return GetQosTxop(QosUtilsMapTidToAc(tid));
509 }
510 
513 {
514  return (m_qosSupported ? GetQosTxop(AC_VO) : nullptr);
515 }
516 
519 {
520  return (m_qosSupported ? GetQosTxop(AC_VI) : nullptr);
521 }
522 
525 {
526  return (m_qosSupported ? GetQosTxop(AC_BE) : nullptr);
527 }
528 
531 {
532  return (m_qosSupported ? GetQosTxop(AC_BK) : nullptr);
533 }
534 
537 {
538  Ptr<Txop> txop = (ac == AC_BE_NQOS ? m_txop : StaticCast<Txop>(GetQosTxop(ac)));
539  return (txop ? txop->GetWifiMacQueue() : nullptr);
540 }
541 
542 void
544 {
545  m_scheduler = scheduler;
546  m_scheduler->SetWifiMac(this);
547 }
548 
551 {
552  return m_scheduler;
553 }
554 
555 void
557 {
558  NS_LOG_FUNCTION(this << +linkId);
559 
560  // we may have changed PHY band, in which case it is necessary to re-configure
561  // the PHY dependent parameters. In any case, this makes no harm
563 
564  // SetupPhy not only resets the remote station manager, but also sets the
565  // default TX mode and MCS, which is required when switching to a channel
566  // in a different band
567  GetLink(linkId).stationManager->SetupPhy(GetLink(linkId).phy);
568 }
569 
570 void
572 {
573  m_macTxTrace(packet);
574 }
575 
576 void
578 {
579  m_macTxDropTrace(packet);
580 }
581 
582 void
584 {
585  m_macRxTrace(packet);
586 }
587 
588 void
590 {
591  m_macPromiscRxTrace(packet);
592 }
593 
594 void
596 {
597  m_macRxDropTrace(packet);
598 }
599 
600 void
602 {
603  NS_LOG_FUNCTION(this << ac);
604 
605  // Our caller shouldn't be attempting to setup a queue that is
606  // already configured.
607  NS_ASSERT(m_edca.find(ac) == m_edca.end());
608 
609  Ptr<QosTxop> edca = CreateObject<QosTxop>(ac);
610  edca->SetTxMiddle(m_txMiddle);
611  edca->GetBaManager()->SetTxOkCallback(
612  MakeCallback(&MpduTracedCallback::operator(), &m_ackedMpduCallback));
613  edca->GetBaManager()->SetTxFailedCallback(
614  MakeCallback(&MpduTracedCallback::operator(), &m_nackedMpduCallback));
616  MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
617 
618  m_edca.insert(std::make_pair(ac, edca));
619 }
620 
621 void
622 WifiMac::ConfigureContentionWindow(uint32_t cwMin, uint32_t cwMax)
623 {
624  std::list<bool> isDsssOnly;
625  for (const auto& link : m_links)
626  {
627  isDsssOnly.push_back(link->dsssSupported && !link->erpSupported);
628  }
629 
630  if (m_txop)
631  {
632  // The special value of AC_BE_NQOS which exists in the Access
633  // Category enumeration allows us to configure plain old DCF.
634  ConfigureDcf(m_txop, cwMin, cwMax, isDsssOnly, AC_BE_NQOS);
635  }
636 
637  // Now we configure the EDCA functions
638  for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
639  {
640  ConfigureDcf(it->second, cwMin, cwMax, isDsssOnly, it->first);
641  }
642 }
643 
644 void
646  uint32_t cwmin,
647  uint32_t cwmax,
648  std::list<bool> isDsss,
649  AcIndex ac)
650 {
651  NS_LOG_FUNCTION(this << dcf << cwmin << cwmax << +ac);
652 
653  uint32_t cwMinValue = 0;
654  uint32_t cwMaxValue = 0;
655  uint8_t aifsnValue = 0;
656  Time txopLimitDsss(0);
657  Time txopLimitNoDsss(0);
658 
659  /* see IEEE 802.11-2020 Table 9-155 "Default EDCA Parameter Set element parameter values" */
660  switch (ac)
661  {
662  case AC_VO:
663  cwMinValue = (cwmin + 1) / 4 - 1;
664  cwMaxValue = (cwmin + 1) / 2 - 1;
665  aifsnValue = 2;
666  txopLimitDsss = MicroSeconds(3264);
667  txopLimitNoDsss = MicroSeconds(2080);
668  break;
669  case AC_VI:
670  cwMinValue = (cwmin + 1) / 2 - 1;
671  cwMaxValue = cwmin;
672  aifsnValue = 2;
673  txopLimitDsss = MicroSeconds(6016);
674  txopLimitNoDsss = MicroSeconds(4096);
675  break;
676  case AC_BE:
677  cwMinValue = cwmin;
678  cwMaxValue = cwmax;
679  aifsnValue = 3;
680  txopLimitDsss = MicroSeconds(0); // TODO should be MicroSeconds (3264)
681  txopLimitNoDsss = MicroSeconds(0); // TODO should be MicroSeconds (2528)
682  break;
683  case AC_BK:
684  cwMinValue = cwmin;
685  cwMaxValue = cwmax;
686  aifsnValue = 7;
687  txopLimitDsss = MicroSeconds(0); // TODO should be MicroSeconds (3264)
688  txopLimitNoDsss = MicroSeconds(0); // TODO should be MicroSeconds (2528)
689  break;
690  case AC_BE_NQOS:
691  cwMinValue = cwmin;
692  cwMaxValue = cwmax;
693  aifsnValue = 2;
694  txopLimitDsss = txopLimitNoDsss = MicroSeconds(0);
695  break;
696  case AC_BEACON:
697  // done by ApWifiMac
698  break;
699  case AC_UNDEF:
700  NS_FATAL_ERROR("I don't know what to do with this");
701  break;
702  }
703 
704  std::vector<uint32_t> cwValues(m_links.size());
705  std::vector<uint8_t> aifsnValues(m_links.size());
706  std::vector<Time> txopLimitValues(m_links.size());
707 
708  std::fill(cwValues.begin(), cwValues.end(), cwMinValue);
709  dcf->SetMinCws(cwValues);
710  std::fill(cwValues.begin(), cwValues.end(), cwMaxValue);
711  dcf->SetMaxCws(cwValues);
712  std::fill(aifsnValues.begin(), aifsnValues.end(), aifsnValue);
713  dcf->SetAifsns(aifsnValues);
714  std::transform(isDsss.begin(),
715  isDsss.end(),
716  txopLimitValues.begin(),
717  [&txopLimitDsss, &txopLimitNoDsss](bool dsss) {
718  return (dsss ? txopLimitDsss : txopLimitNoDsss);
719  });
720  dcf->SetTxopLimits(txopLimitValues);
721 }
722 
723 void
725 {
726  NS_LOG_FUNCTION(this << standard);
728  NS_ABORT_MSG_IF(m_links.empty(), "No PHY configured yet");
729 
730  for (auto& link : m_links)
731  {
733  !link->phy || !link->phy->GetOperatingChannel().IsSet(),
734  "[LinkID " << link->id
735  << "] PHY must have been set and an operating channel must have been set");
736 
737  // do not create a ChannelAccessManager and a FrameExchangeManager if they
738  // already exist (this function may be called after ResetWifiPhys)
739  if (!link->channelAccessManager)
740  {
741  link->channelAccessManager = CreateObject<ChannelAccessManager>();
742  }
743  link->channelAccessManager->SetupPhyListener(link->phy);
744 
745  if (!link->feManager)
746  {
747  link->feManager = SetupFrameExchangeManager(standard);
748  }
749  link->feManager->SetWifiPhy(link->phy);
750  link->feManager->SetWifiMac(this);
751  link->feManager->SetLinkId(link->id);
752  link->channelAccessManager->SetLinkId(link->id);
753  link->channelAccessManager->SetupFrameExchangeManager(link->feManager);
754 
755  if (m_txop)
756  {
757  m_txop->SetWifiMac(this);
758  link->channelAccessManager->Add(m_txop);
759  }
760  for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
761  {
762  it->second->SetWifiMac(this);
763  link->channelAccessManager->Add(it->second);
764  }
765 
767  }
768 }
769 
770 void
772 {
773  NS_LOG_FUNCTION(this << +linkId);
774 
775  WifiStandard standard = GetLink(linkId).phy->GetStandard();
776 
777  uint32_t cwmin = (standard == WIFI_STANDARD_80211b ? 31 : 15);
778  uint32_t cwmax = 1023;
779 
780  SetDsssSupported(standard == WIFI_STANDARD_80211b, linkId);
782  m_links[linkId]->phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ,
783  linkId);
784 
785  ConfigureContentionWindow(cwmin, cwmax);
786 }
787 
790 {
791  NS_LOG_FUNCTION(this << standard);
792  NS_ABORT_MSG_IF(standard == WIFI_STANDARD_UNSPECIFIED, "Wifi standard not set");
793  Ptr<FrameExchangeManager> feManager;
794 
795  if (standard >= WIFI_STANDARD_80211be)
796  {
797  feManager = CreateObject<EhtFrameExchangeManager>();
798  }
799  else if (standard >= WIFI_STANDARD_80211ax)
800  {
801  feManager = CreateObject<HeFrameExchangeManager>();
802  }
803  else if (standard >= WIFI_STANDARD_80211ac)
804  {
805  feManager = CreateObject<VhtFrameExchangeManager>();
806  }
807  else if (standard >= WIFI_STANDARD_80211n)
808  {
809  feManager = CreateObject<HtFrameExchangeManager>();
810  }
811  else if (m_qosSupported)
812  {
813  feManager = CreateObject<QosFrameExchangeManager>();
814  }
815  else
816  {
817  feManager = CreateObject<FrameExchangeManager>();
818  }
819 
820  feManager->SetMacTxMiddle(m_txMiddle);
821  feManager->SetMacRxMiddle(m_rxMiddle);
822  feManager->SetAddress(GetAddress());
823  feManager->GetWifiTxTimer().SetMpduResponseTimeoutCallback(
824  MakeCallback(&MpduResponseTimeoutTracedCallback::operator(),
826  feManager->GetWifiTxTimer().SetPsduResponseTimeoutCallback(
827  MakeCallback(&PsduResponseTimeoutTracedCallback::operator(),
829  feManager->GetWifiTxTimer().SetPsduMapResponseTimeoutCallback(
830  MakeCallback(&PsduMapResponseTimeoutTracedCallback::operator(),
832  feManager->SetDroppedMpduCallback(
833  MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
834  feManager->SetAckedMpduCallback(
835  MakeCallback(&MpduTracedCallback::operator(), &m_ackedMpduCallback));
836  return feManager;
837 }
838 
840 WifiMac::GetFrameExchangeManager(uint8_t linkId) const
841 {
842  return GetLink(linkId).feManager;
843 }
844 
846 WifiMac::GetChannelAccessManager(uint8_t linkId) const
847 {
848  return GetLink(linkId).channelAccessManager;
849 }
850 
851 void
853 {
854  NS_LOG_FUNCTION(this << stationManager);
855  SetWifiRemoteStationManagers({stationManager});
856 }
857 
858 void
860  const std::vector<Ptr<WifiRemoteStationManager>>& stationManagers)
861 {
862  NS_LOG_FUNCTION(this);
863 
864  NS_ABORT_MSG_UNLESS(m_links.empty() || m_links.size() == stationManagers.size(),
865  "If links have been already created, the number of provided "
866  "Remote Manager objects ("
867  << stationManagers.size()
868  << ") must "
869  "match the number of links ("
870  << m_links.size() << ")");
871 
872  for (std::size_t i = 0; i < stationManagers.size(); i++)
873  {
874  // the link may already exist in case PHY objects were configured first
875  if (i == m_links.size())
876  {
877  m_links.push_back(CreateLinkEntity());
878  m_links.back()->id = i;
879  }
880  NS_ABORT_IF(i != m_links[i]->id);
881  m_links[i]->stationManager = stationManagers[i];
882  }
883 }
884 
887 {
888  return GetLink(linkId).stationManager;
889 }
890 
891 std::unique_ptr<WifiMac::LinkEntity>
893 {
894  return std::make_unique<LinkEntity>();
895 }
896 
898 WifiMac::GetLink(uint8_t linkId) const
899 {
900  NS_ASSERT(linkId < m_links.size());
901  NS_ASSERT(m_links.at(linkId)); // check that the pointer owns an object
902  return *m_links.at(linkId);
903 }
904 
905 uint8_t
907 {
908  return m_links.size();
909 }
910 
911 std::optional<uint8_t>
913 {
914  for (std::size_t ret = 0; ret < m_links.size(); ++ret)
915  {
916  if (m_links[ret]->feManager->GetAddress() == address)
917  {
918  return ret;
919  }
920  }
921  return std::nullopt;
922 }
923 
924 void
925 WifiMac::SetWifiPhys(const std::vector<Ptr<WifiPhy>>& phys)
926 {
927  NS_LOG_FUNCTION(this);
928  ResetWifiPhys();
929 
930  NS_ABORT_MSG_UNLESS(m_links.empty() || m_links.size() == phys.size(),
931  "If links have been already created, the number of provided "
932  "PHY objects ("
933  << phys.size()
934  << ") must match the number "
935  "of links ("
936  << m_links.size() << ")");
937 
938  for (std::size_t i = 0; i < phys.size(); i++)
939  {
940  // the link may already exist in case we are setting new PHY objects
941  // (ResetWifiPhys just nullified the PHY(s) but left the links)
942  // or the remote station managers were configured first
943  if (i == m_links.size())
944  {
945  m_links.push_back(CreateLinkEntity());
946  m_links.back()->id = i;
947  }
948  NS_ABORT_IF(i != m_links[i]->id);
949  m_links[i]->phy = phys[i];
950  }
951 }
952 
954 WifiMac::GetWifiPhy(uint8_t linkId) const
955 {
956  NS_LOG_FUNCTION(this << +linkId);
957  return GetLink(linkId).phy;
958 }
959 
960 void
962 {
963  NS_LOG_FUNCTION(this);
964  for (auto& link : m_links)
965  {
966  if (link->feManager)
967  {
968  link->feManager->ResetPhy();
969  }
970  if (link->channelAccessManager)
971  {
972  link->channelAccessManager->RemovePhyListener(link->phy);
973  }
974  link->phy = nullptr;
975  }
976 }
977 
978 void
980 {
981  NS_LOG_FUNCTION(this << enable);
983  m_qosSupported = enable;
984 
985  if (!m_qosSupported)
986  {
987  // create a non-QoS TXOP
988  m_txop = CreateObject<Txop>();
991  MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
992  }
993  else
994  {
995  // Construct the EDCAFs. The ordering is important - highest
996  // priority (Table 9-1 UP-to-AC mapping; IEEE 802.11-2012) must be created
997  // first.
1002  }
1003 }
1004 
1005 bool
1007 {
1008  return m_qosSupported;
1009 }
1010 
1011 bool
1012 WifiMac::GetErpSupported(uint8_t linkId) const
1013 {
1014  return GetLink(linkId).erpSupported;
1015 }
1016 
1017 void
1018 WifiMac::SetErpSupported(bool enable, uint8_t linkId)
1019 {
1020  NS_LOG_FUNCTION(this << enable << +linkId);
1021  if (enable)
1022  {
1023  SetDsssSupported(true, linkId);
1024  }
1025  GetLink(linkId).erpSupported = enable;
1026 }
1027 
1028 void
1029 WifiMac::SetDsssSupported(bool enable, uint8_t linkId)
1030 {
1031  NS_LOG_FUNCTION(this << enable << +linkId);
1032  GetLink(linkId).dsssSupported = enable;
1033 }
1034 
1035 bool
1036 WifiMac::GetDsssSupported(uint8_t linkId) const
1037 {
1038  return GetLink(linkId).dsssSupported;
1039 }
1040 
1041 void
1043 {
1044  NS_LOG_FUNCTION(this);
1045  m_ctsToSelfSupported = enable;
1046 }
1047 
1048 void
1050 {
1051  NS_LOG_FUNCTION(this << enable);
1052  m_shortSlotTimeSupported = enable;
1053 }
1054 
1055 bool
1057 {
1058  return m_shortSlotTimeSupported;
1059 }
1060 
1061 bool
1063 {
1064  return false;
1065 }
1066 
1067 void
1069 {
1070  NS_LOG_FUNCTION(this);
1071  m_forwardUp = upCallback;
1072 }
1073 
1074 void
1076 {
1077  NS_LOG_FUNCTION(this);
1078  m_linkUp = linkUp;
1079 }
1080 
1081 void
1083 {
1084  NS_LOG_FUNCTION(this);
1085  m_linkDown = linkDown;
1086 }
1087 
1088 void
1090 {
1091  // We expect WifiMac subclasses which do support forwarding (e.g.,
1092  // AP) to override this method. Therefore, we throw a fatal error if
1093  // someone tries to invoke this method on a class which has not done
1094  // this.
1095  NS_FATAL_ERROR("This MAC entity (" << this << ", " << GetAddress()
1096  << ") does not support Enqueue() with from address");
1097 }
1098 
1099 void
1101 {
1102  NS_LOG_FUNCTION(this << packet << from << to);
1103  m_forwardUp(packet, from, to);
1104 }
1105 
1106 void
1108 {
1109  NS_LOG_FUNCTION(this << *mpdu << linkId);
1110 
1111  const WifiMacHeader* hdr = &mpdu->GetOriginal()->GetHeader();
1112  Mac48Address to = hdr->GetAddr1();
1113  Mac48Address from = hdr->GetAddr2();
1114  auto myAddr = hdr->IsData() ? Mac48Address::ConvertFrom(GetDevice()->GetAddress())
1115  : GetFrameExchangeManager(linkId)->GetAddress();
1116 
1117  // We don't know how to deal with any frame that is not addressed to
1118  // us (and odds are there is nothing sensible we could do anyway),
1119  // so we ignore such frames.
1120  //
1121  // The derived class may also do some such filtering, but it doesn't
1122  // hurt to have it here too as a backstop.
1123  if (to != myAddr)
1124  {
1125  return;
1126  }
1127 
1128  if (hdr->IsMgt() && hdr->IsAction())
1129  {
1130  // There is currently only any reason for Management Action
1131  // frames to be flying about if we are a QoS STA.
1133 
1134  auto& link = GetLink(linkId);
1135  WifiActionHeader actionHdr;
1136  Ptr<Packet> packet = mpdu->GetPacket()->Copy();
1137  packet->RemoveHeader(actionHdr);
1138 
1139  switch (actionHdr.GetCategory())
1140  {
1142 
1143  switch (actionHdr.GetAction().blockAck)
1144  {
1146  MgtAddBaRequestHeader reqHdr;
1147  packet->RemoveHeader(reqHdr);
1148 
1149  // We've received an ADDBA Request. Our policy here is
1150  // to automatically accept it, so we get the ADDBA
1151  // Response on it's way immediately.
1152  NS_ASSERT(link.feManager);
1153  auto htFem = DynamicCast<HtFrameExchangeManager>(link.feManager);
1154  if (htFem)
1155  {
1156  htFem->SendAddBaResponse(&reqHdr, from);
1157  }
1158  // This frame is now completely dealt with, so we're done.
1159  return;
1160  }
1162  MgtAddBaResponseHeader respHdr;
1163  packet->RemoveHeader(respHdr);
1164 
1165  // We've received an ADDBA Response. We assume that it
1166  // indicates success after an ADDBA Request we have
1167  // sent (we could, in principle, check this, but it
1168  // seems a waste given the level of the current model)
1169  // and act by locally establishing the agreement on
1170  // the appropriate queue.
1171  auto recipientMld = link.stationManager->GetMldAddress(from);
1172  auto recipient = (recipientMld ? *recipientMld : from);
1173  GetQosTxop(respHdr.GetTid())->GotAddBaResponse(respHdr, recipient);
1174  auto htFem = DynamicCast<HtFrameExchangeManager>(link.feManager);
1175  if (htFem)
1176  {
1177  GetQosTxop(respHdr.GetTid())
1178  ->GetBaManager()
1179  ->SetBlockAckInactivityCallback(
1181  }
1182  // This frame is now completely dealt with, so we're done.
1183  return;
1184  }
1186  MgtDelBaHeader delBaHdr;
1187  packet->RemoveHeader(delBaHdr);
1188  auto recipientMld = link.stationManager->GetMldAddress(from);
1189  auto recipient = (recipientMld ? *recipientMld : from);
1190 
1191  if (delBaHdr.IsByOriginator())
1192  {
1193  // This DELBA frame was sent by the originator, so
1194  // this means that an ingoing established
1195  // agreement exists in BlockAckManager and we need to
1196  // destroy it.
1197  GetQosTxop(delBaHdr.GetTid())
1198  ->GetBaManager()
1199  ->DestroyRecipientAgreement(recipient, delBaHdr.GetTid());
1200  }
1201  else
1202  {
1203  // We must have been the originator. We need to
1204  // tell the correct queue that the agreement has
1205  // been torn down
1206  GetQosTxop(delBaHdr.GetTid())->GotDelBaFrame(&delBaHdr, recipient);
1207  }
1208  // This frame is now completely dealt with, so we're done.
1209  return;
1210  }
1211  default:
1212  NS_FATAL_ERROR("Unsupported Action field in Block Ack Action frame");
1213  return;
1214  }
1215  default:
1216  NS_FATAL_ERROR("Unsupported Action frame received");
1217  return;
1218  }
1219  }
1220  NS_FATAL_ERROR("Don't know how to handle frame (type=" << hdr->GetType());
1221 }
1222 
1223 void
1225 {
1226  NS_LOG_FUNCTION(this << *mpdu);
1227  for (auto& msduPair : *PeekPointer(mpdu))
1228  {
1229  ForwardUp(msduPair.first,
1230  msduPair.second.GetSourceAddr(),
1231  msduPair.second.GetDestinationAddr());
1232  }
1233 }
1234 
1235 std::optional<Mac48Address>
1236 WifiMac::GetMldAddress(const Mac48Address& remoteAddr) const
1237 {
1238  for (std::size_t linkId = 0; linkId < m_links.size(); linkId++)
1239  {
1240  if (auto mldAddress = m_links[linkId]->stationManager->GetMldAddress(remoteAddr))
1241  {
1242  return *mldAddress;
1243  }
1244  }
1245  return std::nullopt;
1246 }
1247 
1249 WifiMac::GetLocalAddress(const Mac48Address& remoteAddr) const
1250 {
1251  for (const auto& link : m_links)
1252  {
1253  if (auto mldAddress = link->stationManager->GetMldAddress(remoteAddr))
1254  {
1255  // this is a link setup with remote MLD
1256  if (mldAddress != remoteAddr)
1257  {
1258  // the remote address is the address of a STA affiliated with the remote MLD
1259  return link->feManager->GetAddress();
1260  }
1261  // we have to return our MLD address
1262  return m_address;
1263  }
1264  }
1265  // we get here if no ML setup was established between this device and the remote device,
1266  // i.e., they are not both multi-link devices
1267  if (GetNLinks() == 1)
1268  {
1269  // this is a single link device
1270  return m_address;
1271  }
1272  // this is an MLD (hence the remote device is single link)
1273  return DoGetLocalAddress(remoteAddr);
1274 }
1275 
1277 WifiMac::DoGetLocalAddress(const Mac48Address& remoteAddr [[maybe_unused]]) const
1278 {
1279  return m_address;
1280 }
1281 
1284 {
1285  // BA agreements are indexed by the MLD address if ML setup was performed
1286  recipient = GetMldAddress(recipient).value_or(recipient);
1287 
1288  auto agreement = GetQosTxop(tid)->GetBaManager()->GetAgreementAsOriginator(recipient, tid);
1289  if (!agreement || !agreement->get().IsEstablished())
1290  {
1291  return std::nullopt;
1292  }
1293  return agreement;
1294 }
1295 
1298 {
1299  // BA agreements are indexed by the MLD address if ML setup was performed
1300  originator = GetMldAddress(originator).value_or(originator);
1301  return GetQosTxop(tid)->GetBaManager()->GetAgreementAsRecipient(originator, tid);
1302 }
1303 
1305 WifiMac::GetBaTypeAsOriginator(const Mac48Address& recipient, uint8_t tid) const
1306 {
1307  auto agreement = GetBaAgreementEstablishedAsOriginator(recipient, tid);
1308  NS_ABORT_MSG_IF(!agreement,
1309  "No existing Block Ack agreement with " << recipient << " TID: " << +tid);
1310  return agreement->get().GetBlockAckType();
1311 }
1312 
1314 WifiMac::GetBarTypeAsOriginator(const Mac48Address& recipient, uint8_t tid) const
1315 {
1316  auto agreement = GetBaAgreementEstablishedAsOriginator(recipient, tid);
1317  NS_ABORT_MSG_IF(!agreement,
1318  "No existing Block Ack agreement with " << recipient << " TID: " << +tid);
1319  return agreement->get().GetBlockAckReqType();
1320 }
1321 
1323 WifiMac::GetBaTypeAsRecipient(Mac48Address originator, uint8_t tid) const
1324 {
1325  auto agreement = GetBaAgreementEstablishedAsRecipient(originator, tid);
1326  NS_ABORT_MSG_IF(!agreement,
1327  "No existing Block Ack agreement with " << originator << " TID: " << +tid);
1328  return agreement->get().GetBlockAckType();
1329 }
1330 
1332 WifiMac::GetBarTypeAsRecipient(Mac48Address originator, uint8_t tid) const
1333 {
1334  auto agreement = GetBaAgreementEstablishedAsRecipient(originator, tid);
1335  NS_ABORT_MSG_IF(!agreement,
1336  "No existing Block Ack agreement with " << originator << " TID: " << +tid);
1337  return agreement->get().GetBlockAckReqType();
1338 }
1339 
1342 {
1343  return GetDevice()->GetHtConfiguration();
1344 }
1345 
1348 {
1349  return GetDevice()->GetVhtConfiguration();
1350 }
1351 
1354 {
1355  return GetDevice()->GetHeConfiguration();
1356 }
1357 
1360 {
1361  return GetDevice()->GetEhtConfiguration();
1362 }
1363 
1364 bool
1366 {
1367  return bool(GetDevice()->GetHtConfiguration());
1368 }
1369 
1370 bool
1371 WifiMac::GetVhtSupported(uint8_t linkId) const
1372 {
1373  return (GetDevice()->GetVhtConfiguration() &&
1374  GetWifiPhy(linkId)->GetPhyBand() != WIFI_PHY_BAND_2_4GHZ);
1375 }
1376 
1377 bool
1379 {
1380  return bool(GetDevice()->GetHeConfiguration());
1381 }
1382 
1383 bool
1385 {
1386  return bool(GetDevice()->GetEhtConfiguration());
1387 }
1388 
1389 bool
1391 {
1392  for (const auto& link : m_links)
1393  {
1394  if (link->stationManager->GetHtSupported(address))
1395  {
1396  return true;
1397  }
1398  }
1399  return false;
1400 }
1401 
1402 bool
1404 {
1405  for (const auto& link : m_links)
1406  {
1407  if (link->stationManager->GetVhtSupported(address))
1408  {
1409  return true;
1410  }
1411  }
1412  return false;
1413 }
1414 
1415 bool
1417 {
1418  for (const auto& link : m_links)
1419  {
1420  if (link->stationManager->GetHeSupported(address))
1421  {
1422  return true;
1423  }
1424  }
1425  return false;
1426 }
1427 
1428 bool
1430 {
1431  for (const auto& link : m_links)
1432  {
1433  if (link->stationManager->GetEhtSupported(address))
1434  {
1435  return true;
1436  }
1437  }
1438  return false;
1439 }
1440 
1441 void
1443 {
1444  NS_LOG_FUNCTION(this << +threshold);
1445  if (m_qosSupported)
1446  {
1447  GetVOQueue()->SetBlockAckThreshold(threshold);
1448  }
1449 }
1450 
1451 void
1453 {
1454  NS_LOG_FUNCTION(this << +threshold);
1455  if (m_qosSupported)
1456  {
1457  GetVIQueue()->SetBlockAckThreshold(threshold);
1458  }
1459 }
1460 
1461 void
1463 {
1464  NS_LOG_FUNCTION(this << +threshold);
1465  if (m_qosSupported)
1466  {
1467  GetBEQueue()->SetBlockAckThreshold(threshold);
1468  }
1469 }
1470 
1471 void
1473 {
1474  NS_LOG_FUNCTION(this << +threshold);
1475  if (m_qosSupported)
1476  {
1477  GetBKQueue()->SetBlockAckThreshold(threshold);
1478  }
1479 }
1480 
1481 void
1483 {
1484  NS_LOG_FUNCTION(this << timeout);
1485  if (m_qosSupported)
1486  {
1488  }
1489 }
1490 
1491 void
1493 {
1494  NS_LOG_FUNCTION(this << timeout);
1495  if (m_qosSupported)
1496  {
1498  }
1499 }
1500 
1501 void
1503 {
1504  NS_LOG_FUNCTION(this << timeout);
1505  if (m_qosSupported)
1506  {
1508  }
1509 }
1510 
1511 void
1513 {
1514  NS_LOG_FUNCTION(this << timeout);
1515  if (m_qosSupported)
1516  {
1518  }
1519 }
1520 
1523 {
1524  NS_LOG_FUNCTION(this);
1525  ExtendedCapabilities capabilities;
1526  capabilities.SetHtSupported(GetHtSupported());
1528  // TODO: to be completed
1529  return capabilities;
1530 }
1531 
1533 WifiMac::GetHtCapabilities(uint8_t linkId) const
1534 {
1535  NS_LOG_FUNCTION(this << +linkId);
1537  HtCapabilities capabilities;
1538 
1539  auto phy = GetWifiPhy(linkId);
1540  Ptr<HtConfiguration> htConfiguration = GetHtConfiguration();
1541  bool sgiSupported = htConfiguration->GetShortGuardIntervalSupported();
1542  capabilities.SetLdpc(htConfiguration->GetLdpcSupported());
1543  capabilities.SetSupportedChannelWidth(htConfiguration->Get40MHzOperationSupported() ? 1 : 0);
1544  capabilities.SetShortGuardInterval20(sgiSupported);
1545  capabilities.SetShortGuardInterval40(phy->GetChannelWidth() >= 40 && sgiSupported);
1546  // Set Maximum A-MSDU Length subfield
1547  uint16_t maxAmsduSize =
1549  if (maxAmsduSize <= 3839)
1550  {
1551  capabilities.SetMaxAmsduLength(3839);
1552  }
1553  else
1554  {
1555  capabilities.SetMaxAmsduLength(7935);
1556  }
1557  uint32_t maxAmpduLength =
1559  // round to the next power of two minus one
1560  maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
1561  // The maximum A-MPDU length in HT capabilities elements ranges from 2^13-1 to 2^16-1
1562  capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 65535U));
1563 
1564  capabilities.SetLSigProtectionSupport(true);
1565  uint64_t maxSupportedRate = 0; // in bit/s
1566  for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HT))
1567  {
1568  capabilities.SetRxMcsBitmask(mcs.GetMcsValue());
1569  uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
1570  NS_ASSERT(nss > 0 && nss < 5);
1571  uint64_t dataRate = mcs.GetDataRate(phy->GetChannelWidth(), sgiSupported ? 400 : 800, nss);
1572  if (dataRate > maxSupportedRate)
1573  {
1574  maxSupportedRate = dataRate;
1575  NS_LOG_DEBUG("Updating maxSupportedRate to " << maxSupportedRate);
1576  }
1577  }
1578  capabilities.SetRxHighestSupportedDataRate(
1579  static_cast<uint16_t>(maxSupportedRate / 1e6)); // in Mbit/s
1580  capabilities.SetTxMcsSetDefined(phy->GetNMcs() > 0);
1581  capabilities.SetTxMaxNSpatialStreams(phy->GetMaxSupportedTxSpatialStreams());
1582  // we do not support unequal modulations
1583  capabilities.SetTxRxMcsSetUnequal(0);
1584  capabilities.SetTxUnequalModulation(0);
1585 
1586  return capabilities;
1587 }
1588 
1590 WifiMac::GetVhtCapabilities(uint8_t linkId) const
1591 {
1592  NS_LOG_FUNCTION(this << +linkId);
1593  NS_ASSERT(GetVhtSupported(linkId));
1594  VhtCapabilities capabilities;
1595 
1596  auto phy = GetWifiPhy(linkId);
1597  Ptr<HtConfiguration> htConfiguration = GetHtConfiguration();
1598  NS_ABORT_MSG_IF(!htConfiguration->Get40MHzOperationSupported(),
1599  "VHT stations have to support 40 MHz operation");
1600  Ptr<VhtConfiguration> vhtConfiguration = GetVhtConfiguration();
1601  bool sgiSupported = htConfiguration->GetShortGuardIntervalSupported();
1602  capabilities.SetSupportedChannelWidthSet(vhtConfiguration->Get160MHzOperationSupported() ? 1
1603  : 0);
1604  // Set Maximum MPDU Length subfield
1605  uint16_t maxAmsduSize =
1607  if (maxAmsduSize <= 3839)
1608  {
1609  capabilities.SetMaxMpduLength(3895);
1610  }
1611  else if (maxAmsduSize <= 7935)
1612  {
1613  capabilities.SetMaxMpduLength(7991);
1614  }
1615  else
1616  {
1617  capabilities.SetMaxMpduLength(11454);
1618  }
1619  uint32_t maxAmpduLength =
1621  // round to the next power of two minus one
1622  maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
1623  // The maximum A-MPDU length in VHT capabilities elements ranges from 2^13-1 to 2^20-1
1624  capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 1048575U));
1625 
1626  capabilities.SetRxLdpc(htConfiguration->GetLdpcSupported());
1627  capabilities.SetShortGuardIntervalFor80Mhz((phy->GetChannelWidth() == 80) && sgiSupported);
1628  capabilities.SetShortGuardIntervalFor160Mhz((phy->GetChannelWidth() == 160) && sgiSupported);
1629  uint8_t maxMcs = 0;
1630  for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
1631  {
1632  if (mcs.GetMcsValue() > maxMcs)
1633  {
1634  maxMcs = mcs.GetMcsValue();
1635  }
1636  }
1637  // Support same MaxMCS for each spatial stream
1638  for (uint8_t nss = 1; nss <= phy->GetMaxSupportedRxSpatialStreams(); nss++)
1639  {
1640  capabilities.SetRxMcsMap(maxMcs, nss);
1641  }
1642  for (uint8_t nss = 1; nss <= phy->GetMaxSupportedTxSpatialStreams(); nss++)
1643  {
1644  capabilities.SetTxMcsMap(maxMcs, nss);
1645  }
1646  uint64_t maxSupportedRateLGI = 0; // in bit/s
1647  for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
1648  {
1649  if (!mcs.IsAllowed(phy->GetChannelWidth(), 1))
1650  {
1651  continue;
1652  }
1653  if (mcs.GetDataRate(phy->GetChannelWidth()) > maxSupportedRateLGI)
1654  {
1655  maxSupportedRateLGI = mcs.GetDataRate(phy->GetChannelWidth());
1656  NS_LOG_DEBUG("Updating maxSupportedRateLGI to " << maxSupportedRateLGI);
1657  }
1658  }
1659  capabilities.SetRxHighestSupportedLgiDataRate(
1660  static_cast<uint16_t>(maxSupportedRateLGI / 1e6)); // in Mbit/s
1661  capabilities.SetTxHighestSupportedLgiDataRate(
1662  static_cast<uint16_t>(maxSupportedRateLGI / 1e6)); // in Mbit/s
1663  // To be filled in once supported
1664  capabilities.SetRxStbc(0);
1665  capabilities.SetTxStbc(0);
1666 
1667  return capabilities;
1668 }
1669 
1671 WifiMac::GetHeCapabilities(uint8_t linkId) const
1672 {
1673  NS_LOG_FUNCTION(this << +linkId);
1675  HeCapabilities capabilities;
1676 
1677  Ptr<WifiPhy> phy = GetLink(linkId).phy;
1678  Ptr<HtConfiguration> htConfiguration = GetHtConfiguration();
1679  Ptr<HeConfiguration> heConfiguration = GetHeConfiguration();
1680  uint8_t channelWidthSet = 0;
1681  if ((phy->GetChannelWidth() >= 40) && (phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ))
1682  {
1683  channelWidthSet |= 0x01;
1684  }
1685  if (((phy->GetChannelWidth() >= 80) || GetEhtSupported()) &&
1686  ((phy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) || (phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ)))
1687  {
1688  channelWidthSet |= 0x02;
1689  }
1690  if ((phy->GetChannelWidth() >= 160) &&
1691  ((phy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) || (phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ)))
1692  {
1693  channelWidthSet |= 0x04;
1694  }
1695  capabilities.SetChannelWidthSet(channelWidthSet);
1696  capabilities.SetLdpcCodingInPayload(htConfiguration->GetLdpcSupported());
1697  if (heConfiguration->GetGuardInterval() == NanoSeconds(800))
1698  {
1699  // todo: We assume for now that if we support 800ns GI then 1600ns GI is supported as well
1700  // todo: Assuming reception support for both 1x HE LTF and 4x HE LTF 800 ns
1701  capabilities.SetHeSuPpdu1xHeLtf800nsGi(true);
1702  capabilities.SetHePpdu4xHeLtf800nsGi(true);
1703  }
1704 
1705  uint32_t maxAmpduLength =
1707  // round to the next power of two minus one
1708  maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
1709  // The maximum A-MPDU length in HE capabilities elements ranges from 2^20-1 to 2^23-1
1710  capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 1048575U), 8388607U));
1711 
1712  uint8_t maxMcs = 0;
1713  for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HE))
1714  {
1715  if (mcs.GetMcsValue() > maxMcs)
1716  {
1717  maxMcs = mcs.GetMcsValue();
1718  }
1719  }
1720  capabilities.SetHighestMcsSupported(maxMcs);
1721  capabilities.SetHighestNssSupported(phy->GetMaxSupportedTxSpatialStreams());
1722 
1723  return capabilities;
1724 }
1725 
1727 WifiMac::GetEhtCapabilities(uint8_t linkId) const
1728 {
1729  NS_LOG_FUNCTION(this << +linkId);
1731  EhtCapabilities capabilities;
1732 
1733  Ptr<WifiPhy> phy = GetLink(linkId).phy;
1734 
1735  // Set Maximum MPDU Length subfield (Reserved when transmitted in 5 GHz or 6 GHz band)
1736  if (phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
1737  {
1738  uint16_t maxAmsduSize =
1740  // Table 9-34—Maximum data unit sizes (in octets) and durations (in microseconds)
1741  if (maxAmsduSize <= 3839)
1742  {
1743  capabilities.SetMaxMpduLength(3895);
1744  }
1745  else if (maxAmsduSize <= 7935)
1746  {
1747  capabilities.SetMaxMpduLength(7991);
1748  }
1749  else
1750  {
1751  capabilities.SetMaxMpduLength(11454);
1752  }
1753  }
1754 
1755  // Set Maximum A-MPDU Length Exponent Extension subfield
1756  uint32_t maxAmpduLength =
1758  // round to the next power of two minus one
1759  maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
1760  // The maximum A-MPDU length in EHT capabilities elements ranges from 2^23-1 to 2^24-1
1761  capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8388607U), 16777215U));
1762 
1763  // Set the PHY capabilities
1764  const bool support4096Qam = phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, 12);
1766  support4096Qam ? 1 : 0;
1768  support4096Qam ? 1 : 0;
1769 
1770  const uint8_t maxTxNss = phy->GetMaxSupportedTxSpatialStreams();
1771  const uint8_t maxRxNss = phy->GetMaxSupportedRxSpatialStreams();
1772  if (phy->GetChannelWidth() == 20)
1773  {
1774  for (auto maxMcs : {7, 9, 11, 13})
1775  {
1776  capabilities.SetSupportedRxEhtMcsAndNss(
1778  maxMcs,
1779  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
1780  capabilities.SetSupportedTxEhtMcsAndNss(
1782  maxMcs,
1783  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
1784  }
1785  }
1786  else
1787  {
1788  for (auto maxMcs : {9, 11, 13})
1789  {
1790  capabilities.SetSupportedRxEhtMcsAndNss(
1792  maxMcs,
1793  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
1794  capabilities.SetSupportedTxEhtMcsAndNss(
1796  maxMcs,
1797  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
1798  }
1799  }
1800  if (phy->GetChannelWidth() >= 160)
1801  {
1802  for (auto maxMcs : {9, 11, 13})
1803  {
1804  capabilities.SetSupportedRxEhtMcsAndNss(
1806  maxMcs,
1807  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
1808  capabilities.SetSupportedTxEhtMcsAndNss(
1810  maxMcs,
1811  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
1812  }
1813  }
1814  // 320 MHz not supported yet
1815 
1816  return capabilities;
1817 }
1818 
1819 uint32_t
1821 {
1822  uint32_t maxSize = 0;
1823  switch (ac)
1824  {
1825  case AC_BE:
1826  maxSize = m_beMaxAmpduSize;
1827  break;
1828  case AC_BK:
1829  maxSize = m_bkMaxAmpduSize;
1830  break;
1831  case AC_VI:
1832  maxSize = m_viMaxAmpduSize;
1833  break;
1834  case AC_VO:
1835  maxSize = m_voMaxAmpduSize;
1836  break;
1837  default:
1838  NS_ABORT_MSG("Unknown AC " << ac);
1839  return 0;
1840  }
1841  return maxSize;
1842 }
1843 
1844 uint16_t
1846 {
1847  uint16_t maxSize = 0;
1848  switch (ac)
1849  {
1850  case AC_BE:
1851  maxSize = m_beMaxAmsduSize;
1852  break;
1853  case AC_BK:
1854  maxSize = m_bkMaxAmsduSize;
1855  break;
1856  case AC_VI:
1857  maxSize = m_viMaxAmsduSize;
1858  break;
1859  case AC_VO:
1860  maxSize = m_voMaxAmsduSize;
1861  break;
1862  default:
1863  NS_ABORT_MSG("Unknown AC " << ac);
1864  return 0;
1865  }
1866  return maxSize;
1867 }
1868 
1869 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
#define max(a, b)
Definition: 80211b.c:43
AttributeValue implementation for Boolean.
Definition: boolean.h:37
The IEEE 802.11be EHT Capabilities.
void SetMaxMpduLength(uint16_t length)
Set the maximum MPDU length.
void SetSupportedTxEhtMcsAndNss(EhtMcsAndNssSet::EhtMcsMapType mapType, uint8_t upperMcs, uint8_t maxNss)
Set a subfield of the Supported EHT-MCS And NSS Set.
EhtPhyCapabilities m_phyCapabilities
EHT PHY Capabilities Info subfield.
void SetMaxAmpduLength(uint32_t maxAmpduLength)
Set the maximum A-MPDU length.
void SetSupportedRxEhtMcsAndNss(EhtMcsAndNssSet::EhtMcsMapType mapType, uint8_t upperMcs, uint8_t maxNss)
Set a subfield of the Supported EHT-MCS And NSS Set.
The Extended Capabilities Information Element.
void SetHtSupported(uint8_t htSupported)
Set the HT Supported flag.
void SetVhtSupported(uint8_t vhtSupported)
Set the VHT Supported flag.
The IEEE 802.11ax HE Capabilities.
void SetHeSuPpdu1xHeLtf800nsGi(bool heSuPpdu1xHeLtf800nsGi)
Set 1xHE-LTF and 800ns GI in HE SU PPDU reception support.
void SetLdpcCodingInPayload(uint8_t ldpcCodingInPayload)
Set indication whether the transmission and reception of LDPC encoded packets is supported.
void SetHePpdu4xHeLtf800nsGi(bool heSuPpdu4xHeLtf800nsGi)
Set 4xHE-LTF and 800ns GI in HE SU PPDU and HE MU PPDU reception support.
void SetHighestNssSupported(uint8_t nss)
Set highest NSS supported.
void SetMaxAmpduLength(uint32_t maxAmpduLength)
Set the maximum AMPDU length.
void SetChannelWidthSet(uint8_t channelWidthSet)
Set channel width set.
void SetHighestMcsSupported(uint8_t mcs)
Set highest MCS supported.
The HT Capabilities Information Element.
void SetLdpc(uint8_t ldpc)
Set the LDPC field.
void SetTxRxMcsSetUnequal(uint8_t txRxMcsSetUnequal)
Set the transmit / receive MCS set unequal.
void SetRxHighestSupportedDataRate(uint16_t maxSupportedRate)
Set the receive highest supported data rate.
void SetLSigProtectionSupport(uint8_t lSigProtection)
Set the LSIG protection support.
void SetMaxAmsduLength(uint16_t maxAmsduLength)
Set the maximum AMSDU length.
void SetTxMaxNSpatialStreams(uint8_t maxTxSpatialStreams)
Set the transmit maximum N spatial streams.
void SetShortGuardInterval20(uint8_t shortGuardInterval)
Set the short guard interval 20 field.
void SetTxUnequalModulation(uint8_t txUnequalModulation)
Set the transmit unequal modulation.
void SetTxMcsSetDefined(uint8_t txMcsSetDefined)
Set the transmit MCS set defined.
void SetRxMcsBitmask(uint8_t index)
Set the receive MCS bitmask.
void SetSupportedChannelWidth(uint8_t supportedChannelWidth)
Set the supported channel width field.
void SetMaxAmpduLength(uint32_t maxAmpduLength)
Set the maximum AMPDU length.
void SetShortGuardInterval40(uint8_t shortGuardInterval)
Set the short guard interval 40 field.
void SendDelbaFrame(Mac48Address addr, uint8_t tid, bool byOriginator)
Sends DELBA frame to cancel a block ack agreement with STA addressed by addr for TID tid.
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address ConvertFrom(const Address &address)
Implement the header for management frames of type Add Block Ack request.
Definition: mgt-headers.h:1511
Implement the header for management frames of type Add Block Ack response.
Definition: mgt-headers.h:1642
uint8_t GetTid() const
Return the Traffic ID (TID).
Implement the header for management frames of type Delete Block Ack.
Definition: mgt-headers.h:1761
uint8_t GetTid() const
Return the Traffic ID (TID).
bool IsByOriginator() const
Check if the initiator bit in the DELBA is set.
A base class which provides memory management and object aggregation.
Definition: object.h:89
void Initialize()
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:186
void Dispose()
Dispose of this Object.
Definition: object.cc:219
bool IsInitialized() const
Check if the object has been initialized.
Definition: object.cc:212
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< BlockAckManager > GetBaManager()
Get the Block Ack Manager associated with this QosTxop.
Definition: qos-txop.cc:261
void SetDroppedMpduCallback(DroppedMpdu callback) override
Definition: qos-txop.cc:165
void GotAddBaResponse(const MgtAddBaResponseHeader &respHdr, Mac48Address recipient)
Event handler when an ADDBA response is received.
Definition: qos-txop.cc:607
void SetBlockAckThreshold(uint8_t threshold)
Set threshold for block ack mechanism.
Definition: qos-txop.cc:678
void GotDelBaFrame(const MgtDelBaHeader *delBaHdr, Mac48Address recipient)
Event handler when a DELBA frame is received.
Definition: qos-txop.cc:642
void SetBlockAckInactivityTimeout(uint16_t timeout)
Set the BlockAck inactivity timeout.
Definition: qos-txop.cc:686
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:220
virtual void SetWifiMac(const Ptr< WifiMac > mac)
Set the wifi MAC this Txop is associated to.
Definition: txop.cc:195
void SetMaxCws(std::vector< uint32_t > maxCws)
Set the maximum contention window size for each link.
Definition: txop.cc:262
void SetTxopLimits(const std::vector< Time > &txopLimits)
Set the TXOP limit for each link.
Definition: txop.cc:382
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set MacTxMiddle this Txop is associated to.
Definition: txop.cc:188
void SetMinCws(std::vector< uint32_t > minCws)
Set the minimum contention window size for each link.
Definition: txop.cc:233
virtual void SetDroppedMpduCallback(DroppedMpdu callback)
Definition: txop.cc:209
void SetAifsns(std::vector< uint8_t > aifsns)
Set the number of slots that make up an AIFS for each link.
Definition: txop.cc:359
a unique identifier for an interface.
Definition: type-id.h:60
@ ATTR_GET
The attribute can be read.
Definition: type-id.h:65
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
Definition: type-id.h:67
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
@ OBSOLETE
Attribute or trace source is not used anymore; simulation fails.
Definition: type-id.h:77
Hold an unsigned integer type.
Definition: uinteger.h:45
The IEEE 802.11ac VHT Capabilities.
void SetRxHighestSupportedLgiDataRate(uint16_t supportedDatarate)
Set the receive highest supported LGI data rate.
void SetSupportedChannelWidthSet(uint8_t channelWidthSet)
Set the supported channel width set.
void SetMaxMpduLength(uint16_t length)
Set the maximum MPDU length.
void SetRxLdpc(uint8_t rxLdpc)
Set the receive LDPC.
void SetTxStbc(uint8_t txStbc)
Set the transmit STBC.
void SetTxMcsMap(uint8_t mcs, uint8_t nss)
void SetShortGuardIntervalFor80Mhz(uint8_t shortGuardInterval)
Set the short guard interval 80 MHz.
void SetTxHighestSupportedLgiDataRate(uint16_t supportedDatarate)
Set the transmit highest supported LGI data rate.
void SetShortGuardIntervalFor160Mhz(uint8_t shortGuardInterval)
Set the short guard interval 160 MHz.
void SetMaxAmpduLength(uint32_t maxAmpduLength)
Set the maximum AMPDU length.
void SetRxMcsMap(uint8_t mcs, uint8_t nss)
void SetRxStbc(uint8_t rxStbc)
Set the receive STBC.
bool Get160MHzOperationSupported() const
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
Definition: mgt-headers.h:1279
CategoryValue GetCategory() const
Return the category value.
ActionValue GetAction() const
Return the action value.
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
WifiMacType GetType() const
Return the type (enum WifiMacType)
bool IsMgt() const
Return true if the Type is Management.
bool IsAction() const
Return true if the header is an Action header.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
bool IsData() const
Return true if the Type is DATA.
uint16_t GetMaxAmsduSize(AcIndex ac) const
Return the maximum A-MSDU size of the given Access Category.
Definition: wifi-mac.cc:1845
Ptr< FrameExchangeManager > GetFrameExchangeManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Frame Exchange Manager associated with the given link.
Definition: wifi-mac.cc:840
Ptr< QosTxop > GetBEQueue() const
Accessor for the AC_BE channel access function.
Definition: wifi-mac.cc:524
virtual void NotifyChannelSwitching(uint8_t linkId)
Notify that channel on the given link has been switched.
Definition: wifi-mac.cc:556
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition: wifi-mac.cc:1236
virtual void SetMacQueueScheduler(Ptr< WifiMacQueueScheduler > scheduler)
Set the wifi MAC queue scheduler.
Definition: wifi-mac.cc:543
Mac48Address GetBssid(uint8_t linkId) const
Definition: wifi-mac.cc:469
uint16_t m_viMaxAmsduSize
maximum A-MSDU size for AC_VI (in bytes)
Definition: wifi-mac.h:918
bool m_shortSlotTimeSupported
flag whether short slot time is supported
Definition: wifi-mac.h:897
void ConfigurePhyDependentParameters(uint8_t linkId)
Configure PHY dependent parameters such as CWmin and CWmax on the given link.
Definition: wifi-mac.cc:771
Ptr< HeConfiguration > GetHeConfiguration() const
Definition: wifi-mac.cc:1353
DroppedMpduTracedCallback m_droppedMpduCallback
This trace indicates that an MPDU was dropped for the given reason.
Definition: wifi-mac.h:984
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition: wifi-mac.cc:418
bool m_qosSupported
This Boolean is set true iff this WifiMac is to model 802.11e/WMM style Quality of Service.
Definition: wifi-mac.h:895
Ptr< Txop > GetTxop() const
Accessor for the Txop object.
Definition: wifi-mac.cc:484
VhtCapabilities GetVhtCapabilities(uint8_t linkId) const
Return the VHT capabilities of the device for the given link.
Definition: wifi-mac.cc:1590
Callback< void > m_linkDown
Callback when a link is down.
Definition: wifi-mac.h:757
bool GetQosSupported() const
Return whether the device supports QoS.
Definition: wifi-mac.cc:1006
std::optional< std::reference_wrapper< const RecipientBlockAckAgreement > > RecipientAgreementOptConstRef
optional const reference to RecipientBlockAckAgreement
Definition: wifi-mac.h:562
virtual void SetAddress(Mac48Address address)
Definition: wifi-mac.cc:436
Ptr< Txop > m_txop
TXOP used for transmission of frames to non-QoS peers.
Definition: wifi-mac.h:753
void SetQosSupported(bool enable)
Enable or disable QoS support for the device.
Definition: wifi-mac.cc:979
Mac48Address m_address
MAC address of this station.
Definition: wifi-mac.h:905
Ptr< WifiMacQueueScheduler > GetMacQueueScheduler() const
Get the wifi MAC queue scheduler.
Definition: wifi-mac.cc:550
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition: wifi-mac.cc:906
BlockAckType GetBaTypeAsRecipient(Mac48Address originator, uint8_t tid) const
Definition: wifi-mac.cc:1323
uint16_t m_voMaxAmsduSize
maximum A-MSDU size for AC_VO (in bytes)
Definition: wifi-mac.h:917
Ptr< MacRxMiddle > m_rxMiddle
RX middle (defragmentation etc.)
Definition: wifi-mac.h:751
Ptr< WifiMacQueueScheduler > m_scheduler
wifi MAC queue scheduler
Definition: wifi-mac.h:754
void DoInitialize() override
Initialize() implementation.
Definition: wifi-mac.cc:353
std::vector< std::unique_ptr< LinkEntity > > m_links
vector of Link objects
Definition: wifi-mac.h:903
TypeOfStation m_typeOfStation
the type of station
Definition: wifi-mac.h:900
uint32_t m_beMaxAmpduSize
maximum A-MPDU size for AC_BE (in bytes)
Definition: wifi-mac.h:924
virtual void ConfigureStandard(WifiStandard standard)
Definition: wifi-mac.cc:724
Ssid GetSsid() const
Definition: wifi-mac.cc:456
void SetBeBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_BE.
Definition: wifi-mac.cc:1462
bool GetErpSupported(uint8_t linkId) const
Return whether the device supports ERP on the given link.
Definition: wifi-mac.cc:1012
bool GetHtSupported() const
Return whether the device supports HT.
Definition: wifi-mac.cc:1365
void ResetWifiPhys()
Remove currently attached WifiPhy objects from this MAC.
Definition: wifi-mac.cc:961
TracedCallback< Ptr< const Packet > > m_macTxTrace
The trace source fired when packets come into the "top" of the device at the L3/L2 transition,...
Definition: wifi-mac.h:935
void SetErpSupported(bool enable, uint8_t linkId)
Enable or disable ERP support for the given link.
Definition: wifi-mac.cc:1018
uint32_t m_voMaxAmpduSize
maximum A-MPDU size for AC_VO (in bytes)
Definition: wifi-mac.h:922
void ConfigureDcf(Ptr< Txop > dcf, uint32_t cwmin, uint32_t cwmax, std::list< bool > isDsss, AcIndex ac)
Definition: wifi-mac.cc:645
Ptr< WifiNetDevice > m_device
Pointer to the device.
Definition: wifi-mac.h:902
void SetSsid(Ssid ssid)
Definition: wifi-mac.cc:449
Ptr< QosTxop > GetVOQueue() const
Accessor for the AC_VO channel access function.
Definition: wifi-mac.cc:512
void SetTypeOfStation(TypeOfStation type)
This method is invoked by a subclass to specify what type of station it is implementing.
Definition: wifi-mac.cc:411
MpduTracedCallback m_ackedMpduCallback
ack'ed MPDU callback
Definition: wifi-mac.h:989
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:954
MpduTracedCallback m_nackedMpduCallback
nack'ed MPDU callback
Definition: wifi-mac.h:990
bool GetEhtSupported() const
Return whether the device supports EHT.
Definition: wifi-mac.cc:1384
bool GetHeSupported() const
Return whether the device supports HE.
Definition: wifi-mac.cc:1378
HtCapabilities GetHtCapabilities(uint8_t linkId) const
Return the HT capabilities of the device for the given link.
Definition: wifi-mac.cc:1533
void SetBkBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_BK.
Definition: wifi-mac.cc:1472
void SetVoBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_VO.
Definition: wifi-mac.cc:1442
virtual std::optional< uint8_t > GetLinkIdByAddress(const Mac48Address &address) const
Get the ID of the link having the given MAC address, if any.
Definition: wifi-mac.cc:912
void NotifyPromiscRx(Ptr< const Packet > packet)
Definition: wifi-mac.cc:589
virtual void SetWifiPhys(const std::vector< Ptr< WifiPhy >> &phys)
Definition: wifi-mac.cc:925
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > stationManager)
Definition: wifi-mac.cc:852
RecipientAgreementOptConstRef GetBaAgreementEstablishedAsRecipient(Mac48Address originator, uint8_t tid) const
Definition: wifi-mac.cc:1297
void SetBeBlockAckInactivityTimeout(uint16_t timeout)
Set BE block ack inactivity timeout.
Definition: wifi-mac.cc:1502
Ptr< EhtConfiguration > GetEhtConfiguration() const
Definition: wifi-mac.cc:1359
TracedCallback< Ptr< const Packet > > m_macRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
Definition: wifi-mac.h:958
bool GetVhtSupported(uint8_t linkId) const
Return whether the device supports VHT on the given link.
Definition: wifi-mac.cc:1371
void SetDsssSupported(bool enable, uint8_t linkId)
Enable or disable DSSS support for the given link.
Definition: wifi-mac.cc:1029
TracedCallback< Ptr< const Packet > > m_macTxDropTrace
The trace source fired when packets coming into the "top" of the device are dropped at the MAC layer ...
Definition: wifi-mac.h:942
Ptr< MacTxMiddle > m_txMiddle
TX middle (aggregation etc.)
Definition: wifi-mac.h:752
void NotifyTx(Ptr< const Packet > packet)
Definition: wifi-mac.cc:571
static TypeId GetTypeId()
Get the type ID.
Definition: wifi-mac.cc:66
Ptr< HtConfiguration > GetHtConfiguration() const
Definition: wifi-mac.cc:1341
uint32_t GetMaxAmpduSize(AcIndex ac) const
Return the maximum A-MPDU size of the given Access Category.
Definition: wifi-mac.cc:1820
BlockAckReqType GetBarTypeAsRecipient(Mac48Address originator, uint8_t tid) const
Definition: wifi-mac.cc:1332
Ssid m_ssid
Service Set ID (SSID)
Definition: wifi-mac.h:906
virtual void DeaggregateAmsduAndForward(Ptr< const WifiMpdu > mpdu)
This method can be called to de-aggregate an A-MSDU and forward the constituent packets up the stack.
Definition: wifi-mac.cc:1224
Ptr< QosTxop > GetVIQueue() const
Accessor for the AC_VI channel access function.
Definition: wifi-mac.cc:518
void SetBssid(Mac48Address bssid, uint8_t linkId)
Definition: wifi-mac.cc:462
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition: wifi-mac.cc:430
Ptr< FrameExchangeManager > SetupFrameExchangeManager(WifiStandard standard)
Create a Frame Exchange Manager depending on the supported version of the standard.
Definition: wifi-mac.cc:789
virtual void Enqueue(Ptr< Packet > packet, Mac48Address to, Mac48Address from)
Definition: wifi-mac.cc:1089
void NotifyRx(Ptr< const Packet > packet)
Definition: wifi-mac.cc:583
TracedCallback< Ptr< const Packet > > m_macRxDropTrace
The trace source fired when packets coming into the "top" of the device are dropped at the MAC layer ...
Definition: wifi-mac.h:965
BlockAckType GetBaTypeAsOriginator(const Mac48Address &recipient, uint8_t tid) const
Definition: wifi-mac.cc:1305
MpduResponseTimeoutTracedCallback m_mpduResponseTimeoutCallback
MPDU response timeout traced callback.
Definition: wifi-mac.h:1011
void SetForwardUpCallback(ForwardUpCallback upCallback)
Definition: wifi-mac.cc:1068
PsduMapResponseTimeoutTracedCallback m_psduMapResponseTimeoutCallback
PSDU map response timeout traced callback.
Definition: wifi-mac.h:1055
ExtendedCapabilities GetExtendedCapabilities() const
Return the extended capabilities of the device.
Definition: wifi-mac.cc:1522
TracedCallback< Ptr< const Packet > > m_macPromiscRxTrace
The trace source fired for packets successfully received by the device immediately before being forwa...
Definition: wifi-mac.h:950
uint16_t m_bkMaxAmsduSize
maximum A-MSDU size for AC_BK (in bytes)
Definition: wifi-mac.h:920
void SetBkBlockAckInactivityTimeout(uint16_t timeout)
Set BK block ack inactivity timeout.
Definition: wifi-mac.cc:1512
std::optional< std::reference_wrapper< const OriginatorBlockAckAgreement > > OriginatorAgreementOptConstRef
optional const reference to OriginatorBlockAckAgreement
Definition: wifi-mac.h:559
virtual bool SupportsSendFrom() const
Definition: wifi-mac.cc:1062
virtual Ptr< WifiMacQueue > GetTxopQueue(AcIndex ac) const
Get the wifi MAC queue of the (Qos)Txop associated with the given AC, if such (Qos)Txop is installed,...
Definition: wifi-mac.cc:536
void SetWifiRemoteStationManagers(const std::vector< Ptr< WifiRemoteStationManager >> &stationManagers)
Definition: wifi-mac.cc:859
void SetViBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_VI.
Definition: wifi-mac.cc:1452
void SetViBlockAckInactivityTimeout(uint16_t timeout)
Set VI block ack inactivity timeout.
Definition: wifi-mac.cc:1492
bool GetShortSlotTimeSupported() const
Definition: wifi-mac.cc:1056
BlockAckReqType GetBarTypeAsOriginator(const Mac48Address &recipient, uint8_t tid) const
Definition: wifi-mac.cc:1314
void SetupEdcaQueue(AcIndex ac)
This method is a private utility invoked to configure the channel access function for the specified A...
Definition: wifi-mac.cc:601
void SetLinkDownCallback(Callback< void > linkDown)
Definition: wifi-mac.cc:1082
Ptr< QosTxop > GetBKQueue() const
Accessor for the AC_BK channel access function.
Definition: wifi-mac.cc:530
~WifiMac() override
Definition: wifi-mac.cc:60
void SetPromisc()
Sets the interface in promiscuous mode.
Definition: wifi-mac.cc:475
Ptr< VhtConfiguration > GetVhtConfiguration() const
Definition: wifi-mac.cc:1347
void NotifyRxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:595
virtual void SetLinkUpCallback(Callback< void > linkUp)
Definition: wifi-mac.cc:1075
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:886
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-mac.cc:424
void SetCtsToSelfSupported(bool enable)
Enable or disable CTS-to-self feature.
Definition: wifi-mac.cc:1042
Mac48Address GetLocalAddress(const Mac48Address &remoteAddr) const
Get the local MAC address used to communicate with a remote STA.
Definition: wifi-mac.cc:1249
EdcaQueues m_edca
This is a map from Access Category index to the corresponding channel access function.
Definition: wifi-mac.h:915
uint32_t m_bkMaxAmpduSize
maximum A-MPDU size for AC_BK (in bytes)
Definition: wifi-mac.h:925
void ForwardUp(Ptr< const Packet > packet, Mac48Address from, Mac48Address to)
Forward the packet up to the device.
Definition: wifi-mac.cc:1100
virtual void ConfigureContentionWindow(uint32_t cwMin, uint32_t cwMax)
Definition: wifi-mac.cc:622
OriginatorAgreementOptConstRef GetBaAgreementEstablishedAsOriginator(Mac48Address recipient, uint8_t tid) const
Definition: wifi-mac.cc:1283
virtual void Receive(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
This method acts as the MacRxMiddle receive callback and is invoked to notify us that a frame has bee...
Definition: wifi-mac.cc:1107
Mac48Address GetAddress() const
Definition: wifi-mac.cc:443
TracedCallback< const WifiMacHeader & > m_txErrCallback
transmit error callback
Definition: wifi-mac.h:968
ForwardUpCallback m_forwardUp
Callback to forward packet up the stack.
Definition: wifi-mac.h:927
EhtCapabilities GetEhtCapabilities(uint8_t linkId) const
Return the EHT capabilities of the device for the given link.
Definition: wifi-mac.cc:1727
Callback< void > m_linkUp
Callback when a link is up.
Definition: wifi-mac.h:756
TracedCallback< const WifiMacHeader & > m_txOkCallback
transmit OK callback
Definition: wifi-mac.h:967
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: wifi-mac.cc:898
HeCapabilities GetHeCapabilities(uint8_t linkId) const
Return the HE capabilities of the device for the given link.
Definition: wifi-mac.cc:1671
PsduResponseTimeoutTracedCallback m_psduResponseTimeoutCallback
PSDU response timeout traced callback.
Definition: wifi-mac.h:1032
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:490
void NotifyTxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:577
void DoDispose() override
Destructor implementation.
Definition: wifi-mac.cc:369
bool GetDsssSupported(uint8_t linkId) const
Return whether the device supports DSSS on the given link.
Definition: wifi-mac.cc:1036
Ptr< ChannelAccessManager > GetChannelAccessManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Channel Access Manager associated with the given link.
Definition: wifi-mac.cc:846
void SetVoBlockAckInactivityTimeout(uint16_t timeout)
Set VO block ack inactivity timeout.
Definition: wifi-mac.cc:1482
virtual std::unique_ptr< LinkEntity > CreateLinkEntity() const
Create a LinkEntity object.
Definition: wifi-mac.cc:892
void SetShortSlotTimeSupported(bool enable)
Enable or disable short slot time feature.
Definition: wifi-mac.cc:1049
bool m_ctsToSelfSupported
flag indicating whether CTS-To-Self is supported
Definition: wifi-mac.h:898
uint16_t m_beMaxAmsduSize
maximum A-MSDU size for AC_BE (in bytes)
Definition: wifi-mac.h:919
virtual Mac48Address DoGetLocalAddress(const Mac48Address &remoteAddr) const
This method is called if this device is an MLD to determine the MAC address of the affiliated STA use...
Definition: wifi-mac.cc:1277
uint32_t m_viMaxAmpduSize
maximum A-MPDU size for AC_VI (in bytes)
Definition: wifi-mac.h:923
Ptr< VhtConfiguration > GetVhtConfiguration() const
Ptr< EhtConfiguration > GetEhtConfiguration() const
Ptr< HtConfiguration > GetHtConfiguration() const
Ptr< HeConfiguration > GetHeConfiguration() const
WifiStandard GetStandard() const
Get the configured Wi-Fi standard.
Definition: wifi-phy.cc:1002
virtual void SetupPhy(const Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: pointer.h:231
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:46
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:76
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition: qos-utils.cc:134
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:72
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211g
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_UNSPECIFIED
@ WIFI_STANDARD_80211ac
@ WIFI_STANDARD_80211b
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
Definition: wifi-phy-band.h:39
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ AC_BE_NQOS
Non-QoS.
Definition: qos-utils.h:82
@ AC_BE
Best Effort.
Definition: qos-utils.h:74
@ AC_VO
Voice.
Definition: qos-utils.h:80
@ AC_VI
Video.
Definition: qos-utils.h:78
@ AC_BK
Background.
Definition: qos-utils.h:76
@ AC_UNDEF
Total number of ACs.
Definition: qos-utils.h:86
@ AC_BEACON
Beacon queue.
Definition: qos-utils.h:84
address
Definition: first.py:40
Every class exported by the ns3 library is enclosed in the ns3 namespace.
TypeOfStation
Enumeration for type of station.
Definition: wifi-mac.h:61
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
Definition: wifi-utils.h:140
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:488
ssid
Definition: third.py:86
phy
Definition: third.py:82
ns3::Time timeout
The different BlockAckRequest variants.
The different BlockAck variants.
uint8_t supportTx1024And4096QamForRuSmallerThan242Tones
Tx 1024-QAM And 4096-QAM < 242-tone RU Support.
uint8_t supportRx1024And4096QamForRuSmallerThan242Tones
Rx 1024-QAM And 4096-QAM < 242-tone RU Support.
BlockAckActionValue blockAck
block ack
Definition: mgt-headers.h:1446