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-action-headers.h"
27 #include "qos-txop.h"
28 #include "ssid.h"
29 #include "wifi-mac-queue.h"
30 #include "wifi-net-device.h"
31 
32 #include "ns3/eht-configuration.h"
33 #include "ns3/eht-frame-exchange-manager.h"
34 #include "ns3/he-configuration.h"
35 #include "ns3/ht-configuration.h"
36 #include "ns3/log.h"
37 #include "ns3/packet.h"
38 #include "ns3/pointer.h"
39 #include "ns3/vht-configuration.h"
40 
41 #include <algorithm>
42 
43 namespace ns3
44 {
45 
46 NS_LOG_COMPONENT_DEFINE("WifiMac");
47 
49 
51  : m_qosSupported(false)
52 {
53  NS_LOG_FUNCTION(this);
54 
55  m_rxMiddle = Create<MacRxMiddle>();
56  m_rxMiddle->SetForwardCallback(MakeCallback(&WifiMac::Receive, this));
57 
58  m_txMiddle = Create<MacTxMiddle>();
59 }
60 
62 {
63  NS_LOG_FUNCTION(this);
64 }
65 
66 TypeId
68 {
69  static TypeId tid =
70  TypeId("ns3::WifiMac")
71  .SetParent<Object>()
72  .SetGroupName("Wifi")
73  .AddAttribute("Ssid",
74  "The ssid we want to belong to.",
75  SsidValue(Ssid("default")),
76  MakeSsidAccessor(&WifiMac::GetSsid, &WifiMac::SetSsid),
77  MakeSsidChecker())
78  .AddAttribute("QosSupported",
79  "This Boolean attribute is set to enable 802.11e/WMM-style QoS support "
80  "at this STA.",
82  TypeId::ATTR_CONSTRUCT, // prevent setting after construction
83  BooleanValue(false),
86  .AddAttribute("CtsToSelfSupported",
87  "Use CTS to Self when using a rate that is not in the basic rate set.",
88  BooleanValue(false),
91  .AddAttribute(
92  "ShortSlotTimeSupported",
93  "Whether or not short slot time is supported (only used by ERP APs or STAs).",
94  BooleanValue(true),
98  .AddAttribute("Txop",
99  "The Txop object.",
100  PointerValue(),
102  MakePointerChecker<Txop>())
103  .AddAttribute("VO_Txop",
104  "Queue that manages packets belonging to AC_VO access class.",
105  PointerValue(),
107  MakePointerChecker<QosTxop>())
108  .AddAttribute("VI_Txop",
109  "Queue that manages packets belonging to AC_VI access class.",
110  PointerValue(),
112  MakePointerChecker<QosTxop>())
113  .AddAttribute("BE_Txop",
114  "Queue that manages packets belonging to AC_BE access class.",
115  PointerValue(),
117  MakePointerChecker<QosTxop>())
118  .AddAttribute("BK_Txop",
119  "Queue that manages packets belonging to AC_BK access class.",
120  PointerValue(),
122  MakePointerChecker<QosTxop>())
123  .AddAttribute(
124  "MpduBufferSize",
125  "The size (in number of MPDUs) of the buffer used for each BlockAck "
126  "agreement in which this node is a recipient. The provided value is "
127  "capped to the maximum allowed value based on the supported standard.",
128  UintegerValue(1024),
130  MakeUintegerChecker<uint16_t>(1, 1024))
131  .AddAttribute("VO_MaxAmsduSize",
132  "Maximum length in bytes of an A-MSDU for AC_VO access class "
133  "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
134  "Value 0 means A-MSDU aggregation is disabled for that AC.",
135  UintegerValue(0),
137  MakeUintegerChecker<uint16_t>(0, 11398))
138  .AddAttribute("VI_MaxAmsduSize",
139  "Maximum length in bytes of an A-MSDU for AC_VI access class "
140  "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
141  "Value 0 means A-MSDU aggregation is disabled for that AC.",
142  UintegerValue(0),
144  MakeUintegerChecker<uint16_t>(0, 11398))
145  .AddAttribute("BE_MaxAmsduSize",
146  "Maximum length in bytes of an A-MSDU for AC_BE access class "
147  "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
148  "Value 0 means A-MSDU aggregation is disabled for that AC.",
149  UintegerValue(0),
151  MakeUintegerChecker<uint16_t>(0, 11398))
152  .AddAttribute("BK_MaxAmsduSize",
153  "Maximum length in bytes of an A-MSDU for AC_BK access class "
154  "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
155  "Value 0 means A-MSDU aggregation is disabled for that AC.",
156  UintegerValue(0),
158  MakeUintegerChecker<uint16_t>(0, 11398))
159  .AddAttribute(
160  "VO_MaxAmpduSize",
161  "Maximum length in bytes of an A-MPDU for AC_VO 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(0),
167  MakeUintegerChecker<uint32_t>(0, 15523200))
168  .AddAttribute(
169  "VI_MaxAmpduSize",
170  "Maximum length in bytes of an A-MPDU for AC_VI 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  "BE_MaxAmpduSize",
179  "Maximum length in bytes of an A-MPDU for AC_BE 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(65535),
185  MakeUintegerChecker<uint32_t>(0, 15523200))
186  .AddAttribute(
187  "BK_MaxAmpduSize",
188  "Maximum length in bytes of an A-MPDU for AC_BK access class "
189  "(capped to 65535 for HT PPDUs, 1048575 for VHT PPDUs, 6500631 for HE PPDUs "
190  "and 15523200 for EHT PPDUs). "
191  "Value 0 means A-MPDU aggregation is disabled for that AC.",
192  UintegerValue(0),
194  MakeUintegerChecker<uint32_t>(0, 15523200))
195  .AddAttribute(
196  "VO_BlockAckThreshold",
197  "If number of packets in VO queue reaches this value, "
198  "block ack mechanism is used. If this value is 0, block ack is never used."
199  "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
200  UintegerValue(0),
202  MakeUintegerChecker<uint8_t>(0, 64))
203  .AddAttribute(
204  "VI_BlockAckThreshold",
205  "If number of packets in VI queue reaches this value, "
206  "block ack mechanism is used. If this value is 0, block ack is never used."
207  "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
208  UintegerValue(0),
210  MakeUintegerChecker<uint8_t>(0, 64))
211  .AddAttribute(
212  "BE_BlockAckThreshold",
213  "If number of packets in BE queue reaches this value, "
214  "block ack mechanism is used. If this value is 0, block ack is never used."
215  "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
216  UintegerValue(0),
218  MakeUintegerChecker<uint8_t>(0, 64))
219  .AddAttribute(
220  "BK_BlockAckThreshold",
221  "If number of packets in BK queue reaches this value, "
222  "block ack mechanism is used. If this value is 0, block ack is never used."
223  "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
224  UintegerValue(0),
226  MakeUintegerChecker<uint8_t>(0, 64))
227  .AddAttribute(
228  "VO_BlockAckInactivityTimeout",
229  "Represents max time (blocks of 1024 microseconds) allowed for block ack"
230  "inactivity for AC_VO. If this value isn't equal to 0 a timer start after that a"
231  "block ack setup is completed and will be reset every time that a block ack"
232  "frame is received. If this value is 0, block ack inactivity timeout won't be "
233  "used.",
234  UintegerValue(0),
236  MakeUintegerChecker<uint16_t>())
237  .AddAttribute(
238  "VI_BlockAckInactivityTimeout",
239  "Represents max time (blocks of 1024 microseconds) allowed for block ack"
240  "inactivity for AC_VI. If this value isn't equal to 0 a timer start after that a"
241  "block ack setup is completed and will be reset every time that a block ack"
242  "frame is received. If this value is 0, block ack inactivity timeout won't be "
243  "used.",
244  UintegerValue(0),
246  MakeUintegerChecker<uint16_t>())
247  .AddAttribute(
248  "BE_BlockAckInactivityTimeout",
249  "Represents max time (blocks of 1024 microseconds) allowed for block ack"
250  "inactivity for AC_BE. If this value isn't equal to 0 a timer start after that a"
251  "block ack setup is completed and will be reset every time that a block ack"
252  "frame is received. If this value is 0, block ack inactivity timeout won't be "
253  "used.",
254  UintegerValue(0),
256  MakeUintegerChecker<uint16_t>())
257  .AddAttribute(
258  "BK_BlockAckInactivityTimeout",
259  "Represents max time (blocks of 1024 microseconds) allowed for block ack"
260  "inactivity for AC_BK. If this value isn't equal to 0 a timer start after that a"
261  "block ack setup is completed and will be reset every time that a block ack"
262  "frame is received. If this value is 0, block ack inactivity timeout won't be "
263  "used.",
264  UintegerValue(0),
266  MakeUintegerChecker<uint16_t>())
267  .AddTraceSource("MacTx",
268  "A packet has been received from higher layers and is being processed "
269  "in preparation for "
270  "queueing for transmission.",
272  "ns3::Packet::TracedCallback")
273  .AddTraceSource(
274  "MacTxDrop",
275  "A packet has been dropped in the MAC layer before being queued for transmission. "
276  "This trace source is fired, e.g., when an AP's MAC receives from the upper layer "
277  "a packet destined to a station that is not associated with the AP or a STA's MAC "
278  "receives a packet from the upper layer while it is not associated with any AP.",
280  "ns3::Packet::TracedCallback")
281  .AddTraceSource(
282  "MacPromiscRx",
283  "A packet has been received by this device, has been passed up from the physical "
284  "layer "
285  "and is being forwarded up the local protocol stack. This is a promiscuous trace.",
287  "ns3::Packet::TracedCallback")
288  .AddTraceSource("MacRx",
289  "A packet has been received by this device, has been passed up from "
290  "the physical layer "
291  "and is being forwarded up the local protocol stack. This is a "
292  "non-promiscuous trace.",
294  "ns3::Packet::TracedCallback")
295  .AddTraceSource("MacRxDrop",
296  "A packet has been dropped in the MAC layer after it has been passed "
297  "up from the physical layer.",
299  "ns3::Packet::TracedCallback")
300  .AddTraceSource("AckedMpdu",
301  "An MPDU that was successfully acknowledged, via either a "
302  "Normal Ack or a Block Ack.",
304  "ns3::WifiMpdu::TracedCallback")
305  .AddTraceSource("NAckedMpdu",
306  "An MPDU that was negatively acknowledged via a Block Ack.",
308  "ns3::WifiMpdu::TracedCallback")
309  .AddTraceSource(
310  "DroppedMpdu",
311  "An MPDU that was dropped for the given reason (see WifiMacDropReason).",
313  "ns3::WifiMac::DroppedMpduCallback")
314  .AddTraceSource(
315  "MpduResponseTimeout",
316  "An MPDU whose response was not received before the timeout, along with "
317  "an identifier of the type of timeout (see WifiTxTimer::Reason) and the "
318  "TXVECTOR used to transmit the MPDU. This trace source is fired when a "
319  "CTS is missing after an RTS, when all CTS frames are missing after an MU-RTS, "
320  "or when a Normal Ack is missing after an MPDU or after a DL MU PPDU "
321  "acknowledged in SU format.",
323  "ns3::WifiMac::MpduResponseTimeoutCallback")
324  .AddTraceSource(
325  "PsduResponseTimeout",
326  "A PSDU whose response was not received before the timeout, along with "
327  "an identifier of the type of timeout (see WifiTxTimer::Reason) and the "
328  "TXVECTOR used to transmit the PSDU. This trace source is fired when a "
329  "BlockAck is missing after an A-MPDU, a BlockAckReq (possibly in the "
330  "context of the acknowledgment of a DL MU PPDU in SU format) or a TB PPDU "
331  "(in the latter case the missing BlockAck is a Multi-STA BlockAck).",
333  "ns3::WifiMac::PsduResponseTimeoutCallback")
334  .AddTraceSource(
335  "PsduMapResponseTimeout",
336  "A PSDU map for which not all the responses were received before the timeout, "
337  "along with an identifier of the type of timeout (see WifiTxTimer::Reason), "
338  "the set of MAC addresses of the stations that did not respond and the total "
339  "number of stations that had to respond. This trace source is fired when not "
340  "all the addressed stations responded to an MU-BAR Trigger frame (either sent as "
341  "a SU frame or aggregated to PSDUs in the DL MU PPDU), a Basic Trigger Frame or "
342  "a BSRP Trigger Frame.",
344  "ns3::WifiMac::PsduMapResponseTimeoutCallback");
345  return tid;
346 }
347 
348 void
350 {
351  NS_LOG_FUNCTION(this);
352 
353  if (m_txop)
354  {
355  m_txop->Initialize();
356  }
357 
358  for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
359  {
360  it->second->Initialize();
361  }
362 
363  for (const auto& [id, link] : m_links)
364  {
365  if (auto cam = link->channelAccessManager)
366  {
367  cam->Initialize();
368  }
369  }
370 }
371 
372 void
374 {
375  NS_LOG_FUNCTION(this);
376 
377  m_rxMiddle = nullptr;
378  m_txMiddle = nullptr;
379  m_links.clear();
380 
381  if (m_txop)
382  {
383  m_txop->Dispose();
384  }
385  m_txop = nullptr;
386 
387  for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
388  {
389  it->second->Dispose();
390  it->second = nullptr;
391  }
392 
393  m_device = nullptr;
394  if (m_scheduler != nullptr)
395  {
396  m_scheduler->Dispose();
397  }
398  m_scheduler = nullptr;
399 }
400 
402 {
403  // WifiMac owns pointers to ChannelAccessManager and FrameExchangeManager
405  {
407  }
408  if (feManager)
409  {
410  feManager->Dispose();
411  }
412 }
413 
414 void
416 {
417  NS_LOG_FUNCTION(this << type);
419 }
420 
423 {
424  return m_typeOfStation;
425 }
426 
427 void
429 {
430  m_device = device;
431  if (GetHtSupported())
432  {
433  // the configured BlockAck buffer size can now be capped
435  }
436 }
437 
440 {
441  return m_device;
442 }
443 
444 void
446 {
447  NS_LOG_FUNCTION(this << address);
448  m_address = address;
449 }
450 
453 {
454  return m_address;
455 }
456 
457 void
459 {
460  NS_LOG_FUNCTION(this << ssid);
461  m_ssid = ssid;
462 }
463 
464 Ssid
466 {
467  return m_ssid;
468 }
469 
470 void
471 WifiMac::SetBssid(Mac48Address bssid, uint8_t linkId)
472 {
473  NS_LOG_FUNCTION(this << bssid << +linkId);
474  GetLink(linkId).feManager->SetBssid(bssid);
475 }
476 
478 WifiMac::GetBssid(uint8_t linkId) const
479 {
480  return GetLink(linkId).feManager->GetBssid();
481 }
482 
483 void
485 {
486  for (auto& [id, link] : m_links)
487  {
488  link->feManager->SetPromisc();
489  }
490 }
491 
492 Ptr<Txop>
494 {
495  return m_txop;
496 }
497 
500 {
501  // Use std::find_if() instead of std::map::find() because the latter compares
502  // the given AC index with the AC index of an element in the map by using the
503  // operator< defined for AcIndex, which aborts if an operand is not a QoS AC
504  // (the AC index passed to this method may not be a QoS AC).
505  // The performance penalty is limited because std::map::find() performs 3
506  // comparisons in the worst case, while std::find_if() performs 4 comparisons
507  // in the worst case.
508  const auto it = std::find_if(m_edca.cbegin(), m_edca.cend(), [ac](const auto& pair) {
509  return pair.first == ac;
510  });
511  return (it == m_edca.cend() ? nullptr : it->second);
512 }
513 
515 WifiMac::GetQosTxop(uint8_t tid) const
516 {
517  return GetQosTxop(QosUtilsMapTidToAc(tid));
518 }
519 
522 {
523  return (m_qosSupported ? GetQosTxop(AC_VO) : nullptr);
524 }
525 
528 {
529  return (m_qosSupported ? GetQosTxop(AC_VI) : nullptr);
530 }
531 
534 {
535  return (m_qosSupported ? GetQosTxop(AC_BE) : nullptr);
536 }
537 
540 {
541  return (m_qosSupported ? GetQosTxop(AC_BK) : nullptr);
542 }
543 
546 {
547  Ptr<Txop> txop = (ac == AC_BE_NQOS ? m_txop : StaticCast<Txop>(GetQosTxop(ac)));
548  return (txop ? txop->GetWifiMacQueue() : nullptr);
549 }
550 
551 bool
553 {
554  if (m_txop && m_txop->HasFramesToTransmit(linkId))
555  {
556  return true;
557  }
558  for (const auto& [aci, qosTxop] : m_edca)
559  {
560  if (qosTxop->HasFramesToTransmit(linkId))
561  {
562  return true;
563  }
564  }
565  return false;
566 }
567 
568 void
570 {
571  m_scheduler = scheduler;
572  m_scheduler->SetWifiMac(this);
573 }
574 
577 {
578  return m_scheduler;
579 }
580 
581 void
583 {
584  NS_LOG_FUNCTION(this << +linkId);
585 
586  // we may have changed PHY band, in which case it is necessary to re-configure
587  // the PHY dependent parameters. In any case, this makes no harm
589 
590  // Reset remote station manager
591  GetLink(linkId).stationManager->Reset();
592 }
593 
594 void
596 {
597  m_macTxTrace(packet);
598 }
599 
600 void
602 {
603  m_macTxDropTrace(packet);
604 }
605 
606 void
608 {
609  m_macRxTrace(packet);
610 }
611 
612 void
614 {
615  m_macPromiscRxTrace(packet);
616 }
617 
618 void
620 {
621  m_macRxDropTrace(packet);
622 }
623 
624 void
626 {
627  NS_LOG_FUNCTION(this << ac);
628 
629  // Our caller shouldn't be attempting to setup a queue that is
630  // already configured.
631  NS_ASSERT(m_edca.find(ac) == m_edca.end());
632 
633  Ptr<QosTxop> edca = CreateObject<QosTxop>(ac);
634  edca->SetTxMiddle(m_txMiddle);
635  edca->GetBaManager()->SetTxOkCallback(
636  MakeCallback(&MpduTracedCallback::operator(), &m_ackedMpduCallback));
637  edca->GetBaManager()->SetTxFailedCallback(
638  MakeCallback(&MpduTracedCallback::operator(), &m_nackedMpduCallback));
640  MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
641 
642  m_edca.insert(std::make_pair(ac, edca));
643 }
644 
645 void
646 WifiMac::ConfigureContentionWindow(uint32_t cwMin, uint32_t cwMax)
647 {
648  std::list<bool> isDsssOnly;
649  for (const auto& [id, link] : m_links)
650  {
651  isDsssOnly.push_back(link->dsssSupported && !link->erpSupported);
652  }
653 
654  if (m_txop)
655  {
656  // The special value of AC_BE_NQOS which exists in the Access
657  // Category enumeration allows us to configure plain old DCF.
658  ConfigureDcf(m_txop, cwMin, cwMax, isDsssOnly, AC_BE_NQOS);
659  }
660 
661  // Now we configure the EDCA functions
662  for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
663  {
664  ConfigureDcf(it->second, cwMin, cwMax, isDsssOnly, it->first);
665  }
666 }
667 
668 void
670  uint32_t cwmin,
671  uint32_t cwmax,
672  std::list<bool> isDsss,
673  AcIndex ac)
674 {
675  NS_LOG_FUNCTION(this << dcf << cwmin << cwmax << +ac);
676 
677  uint32_t cwMinValue = 0;
678  uint32_t cwMaxValue = 0;
679  uint8_t aifsnValue = 0;
680  Time txopLimitDsss(0);
681  Time txopLimitNoDsss(0);
682 
683  /* see IEEE 802.11-2020 Table 9-155 "Default EDCA Parameter Set element parameter values" */
684  switch (ac)
685  {
686  case AC_VO:
687  cwMinValue = (cwmin + 1) / 4 - 1;
688  cwMaxValue = (cwmin + 1) / 2 - 1;
689  aifsnValue = 2;
690  txopLimitDsss = MicroSeconds(3264);
691  txopLimitNoDsss = MicroSeconds(2080);
692  break;
693  case AC_VI:
694  cwMinValue = (cwmin + 1) / 2 - 1;
695  cwMaxValue = cwmin;
696  aifsnValue = 2;
697  txopLimitDsss = MicroSeconds(6016);
698  txopLimitNoDsss = MicroSeconds(4096);
699  break;
700  case AC_BE:
701  cwMinValue = cwmin;
702  cwMaxValue = cwmax;
703  aifsnValue = 3;
704  txopLimitDsss = MicroSeconds(0); // TODO should be MicroSeconds (3264)
705  txopLimitNoDsss = MicroSeconds(0); // TODO should be MicroSeconds (2528)
706  break;
707  case AC_BK:
708  cwMinValue = cwmin;
709  cwMaxValue = cwmax;
710  aifsnValue = 7;
711  txopLimitDsss = MicroSeconds(0); // TODO should be MicroSeconds (3264)
712  txopLimitNoDsss = MicroSeconds(0); // TODO should be MicroSeconds (2528)
713  break;
714  case AC_BE_NQOS:
715  cwMinValue = cwmin;
716  cwMaxValue = cwmax;
717  aifsnValue = 2;
718  txopLimitDsss = txopLimitNoDsss = MicroSeconds(0);
719  break;
720  case AC_BEACON:
721  // done by ApWifiMac
722  break;
723  case AC_UNDEF:
724  NS_FATAL_ERROR("I don't know what to do with this");
725  break;
726  }
727 
728  std::vector<uint32_t> cwValues(m_links.size());
729  std::vector<uint8_t> aifsnValues(m_links.size());
730  std::vector<Time> txopLimitValues(m_links.size());
731 
732  std::fill(cwValues.begin(), cwValues.end(), cwMinValue);
733  dcf->SetMinCws(cwValues);
734  std::fill(cwValues.begin(), cwValues.end(), cwMaxValue);
735  dcf->SetMaxCws(cwValues);
736  std::fill(aifsnValues.begin(), aifsnValues.end(), aifsnValue);
737  dcf->SetAifsns(aifsnValues);
738  std::transform(isDsss.begin(),
739  isDsss.end(),
740  txopLimitValues.begin(),
741  [&txopLimitDsss, &txopLimitNoDsss](bool dsss) {
742  return (dsss ? txopLimitDsss : txopLimitNoDsss);
743  });
744  dcf->SetTxopLimits(txopLimitValues);
745 }
746 
747 void
749 {
750  NS_LOG_FUNCTION(this << standard);
752  NS_ABORT_MSG_IF(m_links.empty(), "No PHY configured yet");
753 
754  for (auto& [id, link] : m_links)
755  {
757  !link->phy || !link->phy->GetOperatingChannel().IsSet(),
758  "[LinkID " << +id
759  << "] PHY must have been set and an operating channel must have been set");
760 
761  // do not create a ChannelAccessManager and a FrameExchangeManager if they
762  // already exist (this function may be called after ResetWifiPhys)
763  if (!link->channelAccessManager)
764  {
765  link->channelAccessManager = CreateObject<ChannelAccessManager>();
766  }
767  link->channelAccessManager->SetupPhyListener(link->phy);
768 
769  if (!link->feManager)
770  {
771  link->feManager = SetupFrameExchangeManager(standard);
772  }
773  link->feManager->SetWifiPhy(link->phy);
774  link->feManager->SetWifiMac(this);
775  link->feManager->SetLinkId(id);
776  link->channelAccessManager->SetLinkId(id);
777  link->channelAccessManager->SetupFrameExchangeManager(link->feManager);
778 
779  if (m_txop)
780  {
781  m_txop->SetWifiMac(this);
782  link->channelAccessManager->Add(m_txop);
783  }
784  for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
785  {
786  it->second->SetWifiMac(this);
787  link->channelAccessManager->Add(it->second);
788  }
789 
791  }
792 }
793 
794 void
796 {
797  NS_LOG_FUNCTION(this << +linkId);
798 
799  WifiStandard standard = GetLink(linkId).phy->GetStandard();
800 
801  uint32_t cwmin = (standard == WIFI_STANDARD_80211b ? 31 : 15);
802  uint32_t cwmax = 1023;
803 
804  SetDsssSupported(standard == WIFI_STANDARD_80211b, linkId);
806  m_links[linkId]->phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ,
807  linkId);
808 
809  ConfigureContentionWindow(cwmin, cwmax);
810 }
811 
814 {
815  NS_LOG_FUNCTION(this << standard);
816  NS_ABORT_MSG_IF(standard == WIFI_STANDARD_UNSPECIFIED, "Wifi standard not set");
817  Ptr<FrameExchangeManager> feManager;
818 
819  if (standard >= WIFI_STANDARD_80211be)
820  {
821  feManager = CreateObject<EhtFrameExchangeManager>();
822  }
823  else if (standard >= WIFI_STANDARD_80211ax)
824  {
825  feManager = CreateObject<HeFrameExchangeManager>();
826  }
827  else if (standard >= WIFI_STANDARD_80211ac)
828  {
829  feManager = CreateObject<VhtFrameExchangeManager>();
830  }
831  else if (standard >= WIFI_STANDARD_80211n)
832  {
833  feManager = CreateObject<HtFrameExchangeManager>();
834  }
835  else if (m_qosSupported)
836  {
837  feManager = CreateObject<QosFrameExchangeManager>();
838  }
839  else
840  {
841  feManager = CreateObject<FrameExchangeManager>();
842  }
843 
844  feManager->SetMacTxMiddle(m_txMiddle);
845  feManager->SetMacRxMiddle(m_rxMiddle);
846  feManager->SetAddress(GetAddress());
847  feManager->GetWifiTxTimer().SetMpduResponseTimeoutCallback(
848  MakeCallback(&MpduResponseTimeoutTracedCallback::operator(),
850  feManager->GetWifiTxTimer().SetPsduResponseTimeoutCallback(
851  MakeCallback(&PsduResponseTimeoutTracedCallback::operator(),
853  feManager->GetWifiTxTimer().SetPsduMapResponseTimeoutCallback(
854  MakeCallback(&PsduMapResponseTimeoutTracedCallback::operator(),
856  feManager->SetDroppedMpduCallback(
857  MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
858  feManager->SetAckedMpduCallback(
859  MakeCallback(&MpduTracedCallback::operator(), &m_ackedMpduCallback));
860  return feManager;
861 }
862 
864 WifiMac::GetFrameExchangeManager(uint8_t linkId) const
865 {
866  return GetLink(linkId).feManager;
867 }
868 
870 WifiMac::GetChannelAccessManager(uint8_t linkId) const
871 {
872  return GetLink(linkId).channelAccessManager;
873 }
874 
875 void
877 {
878  NS_LOG_FUNCTION(this << stationManager);
879  SetWifiRemoteStationManagers({stationManager});
880 }
881 
882 void
884  const std::vector<Ptr<WifiRemoteStationManager>>& stationManagers)
885 {
886  NS_LOG_FUNCTION(this);
887 
888  NS_ABORT_MSG_UNLESS(m_links.empty() || m_links.size() == stationManagers.size(),
889  "If links have been already created, the number of provided "
890  "Remote Manager objects ("
891  << stationManagers.size()
892  << ") must "
893  "match the number of links ("
894  << m_links.size() << ")");
895 
896  for (std::size_t i = 0; i < stationManagers.size(); i++)
897  {
898  // the link may already exist in case PHY objects were configured first
899  auto [it, inserted] = m_links.emplace(i, CreateLinkEntity());
900  m_linkIds.insert(i);
901  it->second->stationManager = stationManagers[i];
902  }
903 }
904 
907 {
908  return GetLink(linkId).stationManager;
909 }
910 
911 std::unique_ptr<WifiMac::LinkEntity>
913 {
914  return std::make_unique<LinkEntity>();
915 }
916 
917 const std::map<uint8_t, std::unique_ptr<WifiMac::LinkEntity>>&
919 {
920  return m_links;
921 }
922 
924 WifiMac::GetLink(uint8_t linkId) const
925 {
926  auto it = m_links.find(linkId);
927  NS_ASSERT(it != m_links.cend());
928  NS_ASSERT(it->second); // check that the pointer owns an object
929  return *it->second;
930 }
931 
932 uint8_t
934 {
935  return m_links.size();
936 }
937 
938 const std::set<uint8_t>&
940 {
941  return m_linkIds;
942 }
943 
944 void
946 {
947  NS_LOG_FUNCTION(this << id);
948 
949  auto& link = GetLink(id);
950  if (link.feManager)
951  {
952  link.feManager->SetLinkId(id);
953  }
954  if (link.channelAccessManager)
955  {
956  link.channelAccessManager->SetLinkId(id);
957  }
958 }
959 
960 std::optional<uint8_t>
962 {
963  for (const auto& [id, link] : m_links)
964  {
965  if (link->feManager->GetAddress() == address)
966  {
967  return id;
968  }
969  }
970  return std::nullopt;
971 }
972 
973 std::optional<uint8_t>
975 {
976  for (const auto& [id, link] : m_links)
977  {
978  if (link->phy == phy)
979  {
980  return id;
981  }
982  }
983  return std::nullopt;
984 }
985 
986 std::optional<uint8_t>
987 WifiMac::GetLinkForPhy(std::size_t phyId) const
988 {
989  NS_ABORT_UNLESS(phyId < m_device->GetNPhys());
990  auto phy = m_device->GetPhy(phyId);
991  return GetLinkForPhy(phy);
992 }
993 
994 void
995 WifiMac::SwapLinks(std::map<uint8_t, uint8_t> links)
996 {
997  NS_LOG_FUNCTION(this);
998 
999  std::map<uint8_t, uint8_t> actualPairs;
1000 
1001  while (!links.empty())
1002  {
1003  auto from = links.cbegin()->first;
1004  auto to = links.cbegin()->second;
1005 
1006  if (from == to)
1007  {
1008  // nothing to do
1009  links.erase(links.cbegin());
1010  continue;
1011  }
1012 
1013  std::unique_ptr<LinkEntity> linkToMove;
1014  NS_ASSERT(m_links.find(from) != m_links.cend());
1015  linkToMove.swap(m_links.at(from)); // from is now out of m_links
1016  auto empty = from; // track empty cell in m_links
1017 
1018  do
1019  {
1020  auto [it, inserted] =
1021  m_links.emplace(to, nullptr); // insert an element with key to if not present
1022  m_links[to].swap(linkToMove); // to is the link to move now
1023  actualPairs.emplace(from, to);
1024  UpdateLinkId(to);
1025  links.erase(from);
1026  if (!linkToMove)
1027  {
1028  if (inserted)
1029  {
1030  m_links.erase(empty);
1031  }
1032  break;
1033  }
1034 
1035  auto nextTo = links.find(to);
1036  if (nextTo == links.cend())
1037  {
1038  // no new position specified for 'to', use the current empty cell
1039  m_links[empty].swap(linkToMove);
1040  actualPairs.emplace(to, empty);
1041  break;
1042  }
1043 
1044  from = to;
1045  to = nextTo->second;
1046  } while (true);
1047  }
1048 
1049  m_linkIds.clear();
1050  for (const auto& [id, link] : m_links)
1051  {
1052  m_linkIds.insert(id);
1053  }
1054 
1055  if (m_txop)
1056  {
1057  m_txop->SwapLinks(actualPairs);
1058  }
1059  for (auto& [ac, edca] : m_edca)
1060  {
1061  edca->SwapLinks(actualPairs);
1062  }
1063 }
1064 
1065 void
1068  const WifiTidLinkMapping& mapping)
1069 {
1070  NS_LOG_FUNCTION(this << mldAddr);
1071 
1073  "DL and UL directions for TID-to-Link mapping must be set separately");
1074 
1076 
1077  auto [it, inserted] = mappings.emplace(mldAddr, mapping);
1078 
1079  if (inserted)
1080  {
1081  // we are done
1082  return;
1083  }
1084 
1085  // a previous mapping is stored for this MLD
1086  if (mapping.empty())
1087  {
1088  // the default mapping has been now negotiated
1089  it->second.clear();
1090  return;
1091  }
1092 
1093  for (const auto& [tid, linkSet] : mapping)
1094  {
1095  it->second[tid] = linkSet;
1096  }
1097 }
1098 
1099 std::optional<std::reference_wrapper<const WifiTidLinkMapping>>
1101 {
1103  "Cannot request TID-to-Link mapping for both directions");
1104 
1105  const auto& mappings =
1107 
1108  if (const auto it = mappings.find(mldAddr); it != mappings.cend())
1109  {
1110  return it->second;
1111  }
1112  return std::nullopt;
1113 }
1114 
1115 bool
1116 WifiMac::TidMappedOnLink(Mac48Address mldAddr, WifiDirection dir, uint8_t tid, uint8_t linkId) const
1117 {
1119  "Cannot request TID-to-Link mapping for both directions");
1120 
1121  const auto& mappings =
1123 
1124  const auto it = mappings.find(mldAddr);
1125 
1126  if (it == mappings.cend())
1127  {
1128  // TID-to-link mapping was not negotiated, TIDs are mapped to all setup links
1129  return GetWifiRemoteStationManager(linkId)->GetMldAddress(mldAddr).has_value();
1130  }
1131 
1132  auto linkSetIt = it->second.find(tid);
1133 
1134  if (linkSetIt == it->second.cend())
1135  {
1136  // If there is no successfully negotiated TID-to-link mapping for a TID, then the TID
1137  // is mapped to all setup links for DL and UL (Sec. 35.3.7.1.3 of 802.11be D3.1)
1138  return GetWifiRemoteStationManager(linkId)->GetMldAddress(mldAddr).has_value();
1139  }
1140 
1141  return std::find(linkSetIt->second.cbegin(), linkSetIt->second.cend(), linkId) !=
1142  linkSetIt->second.cend();
1143 }
1144 
1145 void
1146 WifiMac::SetWifiPhys(const std::vector<Ptr<WifiPhy>>& phys)
1147 {
1148  NS_LOG_FUNCTION(this);
1149  ResetWifiPhys();
1150 
1151  NS_ABORT_MSG_UNLESS(m_links.empty() || m_links.size() == phys.size(),
1152  "If links have been already created, the number of provided "
1153  "PHY objects ("
1154  << phys.size()
1155  << ") must match the number "
1156  "of links ("
1157  << m_links.size() << ")");
1158 
1159  for (std::size_t i = 0; i < phys.size(); i++)
1160  {
1161  // the link may already exist in case we are setting new PHY objects
1162  // (ResetWifiPhys just nullified the PHY(s) but left the links)
1163  // or the remote station managers were configured first
1164  auto [it, inserted] = m_links.emplace(i, CreateLinkEntity());
1165  m_linkIds.insert(i);
1166  it->second->phy = phys[i];
1167  }
1168 }
1169 
1171 WifiMac::GetWifiPhy(uint8_t linkId) const
1172 {
1173  return GetLink(linkId).phy;
1174 }
1175 
1176 void
1178 {
1179  NS_LOG_FUNCTION(this);
1180  for (auto& [id, link] : m_links)
1181  {
1182  if (link->feManager)
1183  {
1184  link->feManager->ResetPhy();
1185  }
1186  if (link->channelAccessManager)
1187  {
1188  link->channelAccessManager->RemovePhyListener(link->phy);
1189  }
1190  link->phy = nullptr;
1191  }
1192 }
1193 
1194 void
1196 {
1197  NS_LOG_FUNCTION(this << enable);
1199  m_qosSupported = enable;
1200 
1201  if (!m_qosSupported)
1202  {
1203  // create a non-QoS TXOP
1204  m_txop = CreateObject<Txop>();
1207  MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
1208  }
1209  else
1210  {
1211  // Construct the EDCAFs. The ordering is important - highest
1212  // priority (Table 9-1 UP-to-AC mapping; IEEE 802.11-2012) must be created
1213  // first.
1218  }
1219 }
1220 
1221 bool
1223 {
1224  return m_qosSupported;
1225 }
1226 
1227 bool
1228 WifiMac::GetErpSupported(uint8_t linkId) const
1229 {
1230  return GetLink(linkId).erpSupported;
1231 }
1232 
1233 void
1234 WifiMac::SetErpSupported(bool enable, uint8_t linkId)
1235 {
1236  NS_LOG_FUNCTION(this << enable << +linkId);
1237  if (enable)
1238  {
1239  SetDsssSupported(true, linkId);
1240  }
1241  GetLink(linkId).erpSupported = enable;
1242 }
1243 
1244 void
1245 WifiMac::SetDsssSupported(bool enable, uint8_t linkId)
1246 {
1247  NS_LOG_FUNCTION(this << enable << +linkId);
1248  GetLink(linkId).dsssSupported = enable;
1249 }
1250 
1251 bool
1252 WifiMac::GetDsssSupported(uint8_t linkId) const
1253 {
1254  return GetLink(linkId).dsssSupported;
1255 }
1256 
1257 void
1259 {
1260  NS_LOG_FUNCTION(this);
1261  m_ctsToSelfSupported = enable;
1262 }
1263 
1264 void
1266 {
1267  NS_LOG_FUNCTION(this << enable);
1268  m_shortSlotTimeSupported = enable;
1269 }
1270 
1271 bool
1273 {
1274  return m_shortSlotTimeSupported;
1275 }
1276 
1277 bool
1279 {
1280  return false;
1281 }
1282 
1283 void
1285 {
1286  NS_LOG_FUNCTION(this);
1287  m_forwardUp = upCallback;
1288 }
1289 
1290 void
1292 {
1293  NS_LOG_FUNCTION(this);
1294  m_linkUp = linkUp;
1295 }
1296 
1297 void
1299 {
1300  NS_LOG_FUNCTION(this);
1301  m_linkDown = linkDown;
1302 }
1303 
1304 void
1306 {
1307  NS_LOG_FUNCTION(this << mldAddr);
1308 
1311  "This method can be used to enforce TID-to-Link mapping for one direction at a time");
1312 
1313  const auto& mappings =
1315 
1316  auto it = mappings.find(mldAddr);
1317 
1318  if (it == mappings.cend())
1319  {
1320  // no mapping has been ever negotiated with the given MLD, the default mapping is used
1321  return;
1322  }
1323 
1324  std::set<uint8_t> setupLinks;
1325 
1326  // find the IDs of the links setup with the given MLD
1327  for (const auto& [id, link] : m_links)
1328  {
1329  if (link->stationManager->GetMldAddress(mldAddr))
1330  {
1331  setupLinks.insert(id);
1332  }
1333  }
1334 
1335  auto linkMapping = it->second;
1336 
1337  if (linkMapping.empty())
1338  {
1339  // default link mapping, each TID mapped on all setup links
1340  for (uint8_t tid = 0; tid < 8; tid++)
1341  {
1342  linkMapping.emplace(tid, setupLinks);
1343  }
1344  }
1345 
1346  for (const auto& [tid, linkSet] : linkMapping)
1347  {
1348  decltype(setupLinks) mappedLinks; // empty
1349  auto notMappedLinks = setupLinks; // all setup links
1350 
1351  for (const auto id : linkSet)
1352  {
1353  if (setupLinks.find(id) != setupLinks.cend())
1354  {
1355  // link is mapped
1356  mappedLinks.insert(id);
1357  notMappedLinks.erase(id);
1358  }
1359  }
1360 
1361  // unblock mapped links
1362  NS_ABORT_MSG_IF(mappedLinks.empty(), "Every TID must be mapped to at least a link");
1363 
1365  QosUtilsMapTidToAc(tid),
1367  mldAddr,
1368  GetAddress(),
1369  {tid},
1370  mappedLinks);
1371 
1372  // block unmapped links
1373  if (!notMappedLinks.empty())
1374  {
1376  QosUtilsMapTidToAc(tid),
1378  mldAddr,
1379  GetAddress(),
1380  {tid},
1381  notMappedLinks);
1382  }
1383  }
1384 }
1385 
1386 void
1388  const Mac48Address& address,
1389  const std::set<uint8_t>& linkIds)
1390 {
1391  NS_LOG_FUNCTION(this << reason << address);
1393 
1394  for (const auto linkId : linkIds)
1395  {
1396  auto& link = GetLink(linkId);
1397  auto linkAddr = link.stationManager->GetAffiliatedStaAddress(address).value_or(address);
1398 
1399  if (link.stationManager->GetMldAddress(address) == address && linkAddr == address)
1400  {
1401  NS_LOG_DEBUG("Link " << +linkId << " has not been setup with the MLD, skip");
1402  continue;
1403  }
1404 
1405  for (const auto& [acIndex, ac] : wifiAcList)
1406  {
1407  // block queues storing QoS data frames and control frames that use MLD addresses
1408  m_scheduler->BlockQueues(reason,
1409  acIndex,
1411  address,
1412  GetAddress(),
1413  {ac.GetLowTid(), ac.GetHighTid()},
1414  {linkId});
1415  // block queues storing management and control frames that use link addresses
1416  m_scheduler->BlockQueues(reason,
1417  acIndex,
1419  linkAddr,
1420  link.feManager->GetAddress(),
1421  {},
1422  {linkId});
1423  }
1424  }
1425 }
1426 
1427 void
1429  const Mac48Address& address,
1430  const std::set<uint8_t>& linkIds)
1431 {
1432  NS_LOG_FUNCTION(this << reason << address);
1434 
1435  for (const auto linkId : linkIds)
1436  {
1437  auto& link = GetLink(linkId);
1438  auto linkAddr = link.stationManager->GetAffiliatedStaAddress(address).value_or(address);
1439 
1440  if (link.stationManager->GetMldAddress(address) == address && linkAddr == address)
1441  {
1442  NS_LOG_DEBUG("Link " << +linkId << " has not been setup with the MLD, skip");
1443  continue;
1444  }
1445 
1446  for (const auto& [acIndex, ac] : wifiAcList)
1447  {
1448  // save the status of the AC queues before unblocking the requested queues
1449  auto hasFramesToTransmit = GetQosTxop(acIndex)->HasFramesToTransmit(linkId);
1450 
1451  // unblock queues storing QoS data frames and control frames that use MLD addresses
1452  m_scheduler->UnblockQueues(reason,
1453  acIndex,
1455  address,
1456  GetAddress(),
1457  {ac.GetLowTid(), ac.GetHighTid()},
1458  {linkId});
1459  // unblock queues storing management and control frames that use link addresses
1460  m_scheduler->UnblockQueues(reason,
1461  acIndex,
1463  linkAddr,
1464  link.feManager->GetAddress(),
1465  {},
1466  {linkId});
1467  // request channel access if needed (schedule now because multiple invocations
1468  // of this method may be done in a loop at the caller)
1470  GetQosTxop(acIndex),
1471  linkId,
1472  hasFramesToTransmit,
1473  Txop::CHECK_MEDIUM_BUSY); // generate backoff if medium busy
1474  }
1475  }
1476 }
1477 
1478 void
1480 {
1481  // We expect WifiMac subclasses which do support forwarding (e.g.,
1482  // AP) to override this method. Therefore, we throw a fatal error if
1483  // someone tries to invoke this method on a class which has not done
1484  // this.
1485  NS_FATAL_ERROR("This MAC entity (" << this << ", " << GetAddress()
1486  << ") does not support Enqueue() with from address");
1487 }
1488 
1489 void
1491 {
1492  NS_LOG_FUNCTION(this << packet << from << to);
1493  m_forwardUp(packet, from, to);
1494 }
1495 
1496 void
1498 {
1499  NS_LOG_FUNCTION(this << *mpdu << linkId);
1500 
1501  const WifiMacHeader* hdr = &mpdu->GetOriginal()->GetHeader();
1502  Mac48Address to = hdr->GetAddr1();
1503  Mac48Address from = hdr->GetAddr2();
1504  auto myAddr = hdr->IsData() ? Mac48Address::ConvertFrom(GetDevice()->GetAddress())
1505  : GetFrameExchangeManager(linkId)->GetAddress();
1506 
1507  // We don't know how to deal with any frame that is not addressed to
1508  // us (and odds are there is nothing sensible we could do anyway),
1509  // so we ignore such frames.
1510  //
1511  // The derived class may also do some such filtering, but it doesn't
1512  // hurt to have it here too as a backstop.
1513  if (to != myAddr)
1514  {
1515  return;
1516  }
1517 
1518  // Nothing to do with (QoS) Null Data frames
1519  if (hdr->IsData() && !hdr->HasData())
1520  {
1521  return;
1522  }
1523 
1524  if (hdr->IsMgt() && hdr->IsAction())
1525  {
1526  // There is currently only any reason for Management Action
1527  // frames to be flying about if we are a QoS STA.
1529 
1530  auto& link = GetLink(linkId);
1531  WifiActionHeader actionHdr;
1532  Ptr<Packet> packet = mpdu->GetPacket()->Copy();
1533  packet->RemoveHeader(actionHdr);
1534 
1535  switch (actionHdr.GetCategory())
1536  {
1538 
1539  switch (actionHdr.GetAction().blockAck)
1540  {
1542  MgtAddBaRequestHeader reqHdr;
1543  packet->RemoveHeader(reqHdr);
1544 
1545  // We've received an ADDBA Request. Our policy here is
1546  // to automatically accept it, so we get the ADDBA
1547  // Response on it's way immediately.
1548  NS_ASSERT(link.feManager);
1549  auto htFem = DynamicCast<HtFrameExchangeManager>(link.feManager);
1550  if (htFem)
1551  {
1552  htFem->SendAddBaResponse(&reqHdr, from);
1553  }
1554  // This frame is now completely dealt with, so we're done.
1555  return;
1556  }
1558  MgtAddBaResponseHeader respHdr;
1559  packet->RemoveHeader(respHdr);
1560 
1561  // We've received an ADDBA Response. We assume that it
1562  // indicates success after an ADDBA Request we have
1563  // sent (we could, in principle, check this, but it
1564  // seems a waste given the level of the current model)
1565  // and act by locally establishing the agreement on
1566  // the appropriate queue.
1567  auto recipientMld = link.stationManager->GetMldAddress(from);
1568  auto recipient = (recipientMld ? *recipientMld : from);
1569  GetQosTxop(respHdr.GetTid())->GotAddBaResponse(respHdr, recipient);
1570  auto htFem = DynamicCast<HtFrameExchangeManager>(link.feManager);
1571  if (htFem)
1572  {
1573  GetQosTxop(respHdr.GetTid())
1574  ->GetBaManager()
1575  ->SetBlockAckInactivityCallback(
1577  }
1578  // This frame is now completely dealt with, so we're done.
1579  return;
1580  }
1582  MgtDelBaHeader delBaHdr;
1583  packet->RemoveHeader(delBaHdr);
1584  auto recipientMld = link.stationManager->GetMldAddress(from);
1585  auto recipient = (recipientMld ? *recipientMld : from);
1586 
1587  if (delBaHdr.IsByOriginator())
1588  {
1589  // This DELBA frame was sent by the originator, so
1590  // this means that an ingoing established
1591  // agreement exists in BlockAckManager and we need to
1592  // destroy it.
1593  GetQosTxop(delBaHdr.GetTid())
1594  ->GetBaManager()
1595  ->DestroyRecipientAgreement(recipient, delBaHdr.GetTid());
1596  }
1597  else
1598  {
1599  // We must have been the originator. We need to
1600  // tell the correct queue that the agreement has
1601  // been torn down
1602  GetQosTxop(delBaHdr.GetTid())->GotDelBaFrame(&delBaHdr, recipient);
1603  }
1604  // This frame is now completely dealt with, so we're done.
1605  return;
1606  }
1607  default:
1608  NS_FATAL_ERROR("Unsupported Action field in Block Ack Action frame");
1609  return;
1610  }
1611  default:
1612  NS_FATAL_ERROR("Unsupported Action frame received");
1613  return;
1614  }
1615  }
1616  NS_FATAL_ERROR("Don't know how to handle frame (type=" << hdr->GetType());
1617 }
1618 
1619 void
1621 {
1622  NS_LOG_FUNCTION(this << *mpdu);
1623  for (auto& msduPair : *PeekPointer(mpdu))
1624  {
1625  ForwardUp(msduPair.first,
1626  msduPair.second.GetSourceAddr(),
1627  msduPair.second.GetDestinationAddr());
1628  }
1629 }
1630 
1631 std::optional<Mac48Address>
1632 WifiMac::GetMldAddress(const Mac48Address& remoteAddr) const
1633 {
1634  for (const auto& [id, link] : m_links)
1635  {
1636  if (auto mldAddress = link->stationManager->GetMldAddress(remoteAddr))
1637  {
1638  return *mldAddress;
1639  }
1640  }
1641  return std::nullopt;
1642 }
1643 
1645 WifiMac::GetLocalAddress(const Mac48Address& remoteAddr) const
1646 {
1647  for (const auto& [id, link] : m_links)
1648  {
1649  if (auto mldAddress = link->stationManager->GetMldAddress(remoteAddr))
1650  {
1651  // this is a link setup with remote MLD
1652  if (mldAddress != remoteAddr)
1653  {
1654  // the remote address is the address of a STA affiliated with the remote MLD
1655  return link->feManager->GetAddress();
1656  }
1657  // we have to return our MLD address
1658  return m_address;
1659  }
1660  }
1661  // we get here if no ML setup was established between this device and the remote device,
1662  // i.e., they are not both multi-link devices
1663  if (GetNLinks() == 1)
1664  {
1665  // this is a single link device
1666  return m_address;
1667  }
1668  // this is an MLD (hence the remote device is single link)
1669  return DoGetLocalAddress(remoteAddr);
1670 }
1671 
1673 WifiMac::DoGetLocalAddress(const Mac48Address& remoteAddr [[maybe_unused]]) const
1674 {
1675  return m_address;
1676 }
1677 
1680 {
1681  // BA agreements are indexed by the MLD address if ML setup was performed
1682  recipient = GetMldAddress(recipient).value_or(recipient);
1683 
1684  auto agreement = GetQosTxop(tid)->GetBaManager()->GetAgreementAsOriginator(recipient, tid);
1685  if (!agreement || !agreement->get().IsEstablished())
1686  {
1687  return std::nullopt;
1688  }
1689  return agreement;
1690 }
1691 
1694 {
1695  // BA agreements are indexed by the MLD address if ML setup was performed
1696  originator = GetMldAddress(originator).value_or(originator);
1697  return GetQosTxop(tid)->GetBaManager()->GetAgreementAsRecipient(originator, tid);
1698 }
1699 
1701 WifiMac::GetBaTypeAsOriginator(const Mac48Address& recipient, uint8_t tid) const
1702 {
1703  auto agreement = GetBaAgreementEstablishedAsOriginator(recipient, tid);
1704  NS_ABORT_MSG_IF(!agreement,
1705  "No existing Block Ack agreement with " << recipient << " TID: " << +tid);
1706  return agreement->get().GetBlockAckType();
1707 }
1708 
1710 WifiMac::GetBarTypeAsOriginator(const Mac48Address& recipient, uint8_t tid) const
1711 {
1712  auto agreement = GetBaAgreementEstablishedAsOriginator(recipient, tid);
1713  NS_ABORT_MSG_IF(!agreement,
1714  "No existing Block Ack agreement with " << recipient << " TID: " << +tid);
1715  return agreement->get().GetBlockAckReqType();
1716 }
1717 
1719 WifiMac::GetBaTypeAsRecipient(Mac48Address originator, uint8_t tid) const
1720 {
1721  auto agreement = GetBaAgreementEstablishedAsRecipient(originator, tid);
1722  NS_ABORT_MSG_IF(!agreement,
1723  "No existing Block Ack agreement with " << originator << " TID: " << +tid);
1724  return agreement->get().GetBlockAckType();
1725 }
1726 
1728 WifiMac::GetBarTypeAsRecipient(Mac48Address originator, uint8_t tid) const
1729 {
1730  auto agreement = GetBaAgreementEstablishedAsRecipient(originator, tid);
1731  NS_ABORT_MSG_IF(!agreement,
1732  "No existing Block Ack agreement with " << originator << " TID: " << +tid);
1733  return agreement->get().GetBlockAckReqType();
1734 }
1735 
1738 {
1739  return GetDevice()->GetHtConfiguration();
1740 }
1741 
1744 {
1745  return GetDevice()->GetVhtConfiguration();
1746 }
1747 
1750 {
1751  return GetDevice()->GetHeConfiguration();
1752 }
1753 
1756 {
1757  return GetDevice()->GetEhtConfiguration();
1758 }
1759 
1760 bool
1762 {
1763  return bool(GetDevice()->GetHtConfiguration());
1764 }
1765 
1766 bool
1767 WifiMac::GetVhtSupported(uint8_t linkId) const
1768 {
1769  return (GetDevice()->GetVhtConfiguration() &&
1770  GetWifiPhy(linkId)->GetPhyBand() != WIFI_PHY_BAND_2_4GHZ);
1771 }
1772 
1773 bool
1775 {
1776  return bool(GetDevice()->GetHeConfiguration());
1777 }
1778 
1779 bool
1781 {
1782  return bool(GetDevice()->GetEhtConfiguration());
1783 }
1784 
1785 bool
1787 {
1788  for (const auto& [id, link] : m_links)
1789  {
1790  if (link->stationManager->GetHtSupported(address))
1791  {
1792  return true;
1793  }
1794  }
1795  return false;
1796 }
1797 
1798 bool
1800 {
1801  for (const auto& [id, link] : m_links)
1802  {
1803  if (link->stationManager->GetVhtSupported(address))
1804  {
1805  return true;
1806  }
1807  }
1808  return false;
1809 }
1810 
1811 bool
1813 {
1814  for (const auto& [id, link] : m_links)
1815  {
1816  if (link->stationManager->GetHeSupported(address))
1817  {
1818  return true;
1819  }
1820  }
1821  return false;
1822 }
1823 
1824 bool
1826 {
1827  for (const auto& [id, link] : m_links)
1828  {
1829  if (link->stationManager->GetEhtSupported(address))
1830  {
1831  return true;
1832  }
1833  }
1834  return false;
1835 }
1836 
1837 uint16_t
1838 WifiMac::GetMaxBaBufferSize(std::optional<Mac48Address> address) const
1839 {
1841  {
1842  return 1024;
1843  }
1845  {
1846  return 256;
1847  }
1849  return 64;
1850 }
1851 
1852 void
1854 {
1855  NS_LOG_FUNCTION(this << size);
1856 
1857  // the cap can be computed if the device has been configured
1859 }
1860 
1861 uint16_t
1863 {
1864  return m_mpduBufferSize;
1865 }
1866 
1867 void
1869 {
1870  NS_LOG_FUNCTION(this << +threshold);
1871  if (m_qosSupported)
1872  {
1873  GetVOQueue()->SetBlockAckThreshold(threshold);
1874  }
1875 }
1876 
1877 void
1879 {
1880  NS_LOG_FUNCTION(this << +threshold);
1881  if (m_qosSupported)
1882  {
1883  GetVIQueue()->SetBlockAckThreshold(threshold);
1884  }
1885 }
1886 
1887 void
1889 {
1890  NS_LOG_FUNCTION(this << +threshold);
1891  if (m_qosSupported)
1892  {
1893  GetBEQueue()->SetBlockAckThreshold(threshold);
1894  }
1895 }
1896 
1897 void
1899 {
1900  NS_LOG_FUNCTION(this << +threshold);
1901  if (m_qosSupported)
1902  {
1903  GetBKQueue()->SetBlockAckThreshold(threshold);
1904  }
1905 }
1906 
1907 void
1909 {
1910  NS_LOG_FUNCTION(this << timeout);
1911  if (m_qosSupported)
1912  {
1914  }
1915 }
1916 
1917 void
1919 {
1920  NS_LOG_FUNCTION(this << timeout);
1921  if (m_qosSupported)
1922  {
1924  }
1925 }
1926 
1927 void
1929 {
1930  NS_LOG_FUNCTION(this << timeout);
1931  if (m_qosSupported)
1932  {
1934  }
1935 }
1936 
1937 void
1939 {
1940  NS_LOG_FUNCTION(this << timeout);
1941  if (m_qosSupported)
1942  {
1944  }
1945 }
1946 
1949 {
1950  NS_LOG_FUNCTION(this);
1951  ExtendedCapabilities capabilities;
1952  capabilities.SetHtSupported(GetHtSupported());
1954  // TODO: to be completed
1955  return capabilities;
1956 }
1957 
1959 WifiMac::GetHtCapabilities(uint8_t linkId) const
1960 {
1961  NS_LOG_FUNCTION(this << +linkId);
1963  HtCapabilities capabilities;
1964 
1965  auto phy = GetWifiPhy(linkId);
1966  Ptr<HtConfiguration> htConfiguration = GetHtConfiguration();
1967  bool sgiSupported = htConfiguration->GetShortGuardIntervalSupported();
1968  capabilities.SetLdpc(htConfiguration->GetLdpcSupported());
1969  capabilities.SetSupportedChannelWidth(htConfiguration->Get40MHzOperationSupported() ? 1 : 0);
1970  capabilities.SetShortGuardInterval20(sgiSupported);
1971  capabilities.SetShortGuardInterval40(sgiSupported);
1972  // Set Maximum A-MSDU Length subfield
1973  uint16_t maxAmsduSize =
1975  if (maxAmsduSize <= 3839)
1976  {
1977  capabilities.SetMaxAmsduLength(3839);
1978  }
1979  else
1980  {
1981  capabilities.SetMaxAmsduLength(7935);
1982  }
1983  uint32_t maxAmpduLength =
1985  // round to the next power of two minus one
1986  maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
1987  // The maximum A-MPDU length in HT capabilities elements ranges from 2^13-1 to 2^16-1
1988  capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 65535U));
1989 
1990  capabilities.SetLSigProtectionSupport(true);
1991  uint64_t maxSupportedRate = 0; // in bit/s
1992  for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HT))
1993  {
1994  capabilities.SetRxMcsBitmask(mcs.GetMcsValue());
1995  uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
1996  NS_ASSERT(nss > 0 && nss < 5);
1997  uint64_t dataRate = mcs.GetDataRate(htConfiguration->Get40MHzOperationSupported() ? 40 : 20,
1998  sgiSupported ? 400 : 800,
1999  nss);
2000  if (dataRate > maxSupportedRate)
2001  {
2002  maxSupportedRate = dataRate;
2003  NS_LOG_DEBUG("Updating maxSupportedRate to " << maxSupportedRate);
2004  }
2005  }
2006  capabilities.SetRxHighestSupportedDataRate(
2007  static_cast<uint16_t>(maxSupportedRate / 1e6)); // in Mbit/s
2008  capabilities.SetTxMcsSetDefined(phy->GetNMcs() > 0);
2009  capabilities.SetTxMaxNSpatialStreams(phy->GetMaxSupportedTxSpatialStreams());
2010  // we do not support unequal modulations
2011  capabilities.SetTxRxMcsSetUnequal(0);
2012  capabilities.SetTxUnequalModulation(0);
2013 
2014  return capabilities;
2015 }
2016 
2018 WifiMac::GetVhtCapabilities(uint8_t linkId) const
2019 {
2020  NS_LOG_FUNCTION(this << +linkId);
2021  NS_ASSERT(GetVhtSupported(linkId));
2022  VhtCapabilities capabilities;
2023 
2024  auto phy = GetWifiPhy(linkId);
2025  Ptr<HtConfiguration> htConfiguration = GetHtConfiguration();
2026  NS_ABORT_MSG_IF(!htConfiguration->Get40MHzOperationSupported(),
2027  "VHT stations have to support 40 MHz operation");
2028  Ptr<VhtConfiguration> vhtConfiguration = GetVhtConfiguration();
2029  bool sgiSupported = htConfiguration->GetShortGuardIntervalSupported();
2030  capabilities.SetSupportedChannelWidthSet(vhtConfiguration->Get160MHzOperationSupported() ? 1
2031  : 0);
2032  // Set Maximum MPDU Length subfield
2033  uint16_t maxAmsduSize =
2035  if (maxAmsduSize <= 3839)
2036  {
2037  capabilities.SetMaxMpduLength(3895);
2038  }
2039  else if (maxAmsduSize <= 7935)
2040  {
2041  capabilities.SetMaxMpduLength(7991);
2042  }
2043  else
2044  {
2045  capabilities.SetMaxMpduLength(11454);
2046  }
2047  uint32_t maxAmpduLength =
2049  // round to the next power of two minus one
2050  maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2051  // The maximum A-MPDU length in VHT capabilities elements ranges from 2^13-1 to 2^20-1
2052  capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 1048575U));
2053 
2054  capabilities.SetRxLdpc(htConfiguration->GetLdpcSupported());
2055  capabilities.SetShortGuardIntervalFor80Mhz(sgiSupported);
2056  capabilities.SetShortGuardIntervalFor160Mhz(sgiSupported);
2057  uint8_t maxMcs = 0;
2058  for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
2059  {
2060  if (mcs.GetMcsValue() > maxMcs)
2061  {
2062  maxMcs = mcs.GetMcsValue();
2063  }
2064  }
2065  // Support same MaxMCS for each spatial stream
2066  for (uint8_t nss = 1; nss <= phy->GetMaxSupportedRxSpatialStreams(); nss++)
2067  {
2068  capabilities.SetRxMcsMap(maxMcs, nss);
2069  }
2070  for (uint8_t nss = 1; nss <= phy->GetMaxSupportedTxSpatialStreams(); nss++)
2071  {
2072  capabilities.SetTxMcsMap(maxMcs, nss);
2073  }
2074  uint64_t maxSupportedRateLGI = 0; // in bit/s
2075  uint16_t maxWidth = vhtConfiguration->Get160MHzOperationSupported() ? 160 : 80;
2076  for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
2077  {
2078  if (!mcs.IsAllowed(maxWidth, 1))
2079  {
2080  continue;
2081  }
2082  if (mcs.GetDataRate(maxWidth) > maxSupportedRateLGI)
2083  {
2084  maxSupportedRateLGI = mcs.GetDataRate(maxWidth);
2085  NS_LOG_DEBUG("Updating maxSupportedRateLGI to " << maxSupportedRateLGI);
2086  }
2087  }
2088  capabilities.SetRxHighestSupportedLgiDataRate(
2089  static_cast<uint16_t>(maxSupportedRateLGI / 1e6)); // in Mbit/s
2090  capabilities.SetTxHighestSupportedLgiDataRate(
2091  static_cast<uint16_t>(maxSupportedRateLGI / 1e6)); // in Mbit/s
2092  // To be filled in once supported
2093  capabilities.SetRxStbc(0);
2094  capabilities.SetTxStbc(0);
2095 
2096  return capabilities;
2097 }
2098 
2100 WifiMac::GetHeCapabilities(uint8_t linkId) const
2101 {
2102  NS_LOG_FUNCTION(this << +linkId);
2104  HeCapabilities capabilities;
2105 
2106  Ptr<WifiPhy> phy = GetLink(linkId).phy;
2107  Ptr<HtConfiguration> htConfiguration = GetHtConfiguration();
2108  Ptr<VhtConfiguration> vhtConfiguration = GetVhtConfiguration();
2109  Ptr<HeConfiguration> heConfiguration = GetHeConfiguration();
2110  uint8_t channelWidthSet = 0;
2111  if ((htConfiguration->Get40MHzOperationSupported()) &&
2112  (phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ))
2113  {
2114  channelWidthSet |= 0x01;
2115  }
2116  // we assume that HE stations support 80 MHz operations
2117  if ((phy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) || (phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ))
2118  {
2119  channelWidthSet |= 0x02;
2120  }
2121  if ((vhtConfiguration->Get160MHzOperationSupported()) &&
2122  ((phy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) || (phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ)))
2123  {
2124  channelWidthSet |= 0x04;
2125  }
2126  capabilities.SetChannelWidthSet(channelWidthSet);
2127  capabilities.SetLdpcCodingInPayload(htConfiguration->GetLdpcSupported());
2128  if (heConfiguration->GetGuardInterval() == NanoSeconds(800))
2129  {
2130  // todo: We assume for now that if we support 800ns GI then 1600ns GI is supported as well
2131  // todo: Assuming reception support for both 1x HE LTF and 4x HE LTF 800 ns
2132  capabilities.SetHeSuPpdu1xHeLtf800nsGi(true);
2133  capabilities.SetHePpdu4xHeLtf800nsGi(true);
2134  }
2135 
2136  uint32_t maxAmpduLength =
2138  // round to the next power of two minus one
2139  maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2140  // The maximum A-MPDU length in HE capabilities elements ranges from 2^20-1 to 2^23-1
2141  capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 1048575U), 8388607U));
2142 
2143  uint8_t maxMcs = 0;
2144  for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HE))
2145  {
2146  if (mcs.GetMcsValue() > maxMcs)
2147  {
2148  maxMcs = mcs.GetMcsValue();
2149  }
2150  }
2151  capabilities.SetHighestMcsSupported(maxMcs);
2152  capabilities.SetHighestNssSupported(phy->GetMaxSupportedTxSpatialStreams());
2153 
2154  return capabilities;
2155 }
2156 
2158 WifiMac::GetEhtCapabilities(uint8_t linkId) const
2159 {
2160  NS_LOG_FUNCTION(this << +linkId);
2162  EhtCapabilities capabilities;
2163 
2164  Ptr<WifiPhy> phy = GetLink(linkId).phy;
2165 
2166  // Set Maximum MPDU Length subfield (Reserved when transmitted in 5 GHz or 6 GHz band)
2167  if (phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
2168  {
2169  uint16_t maxAmsduSize =
2171  // Table 9-34—Maximum data unit sizes (in octets) and durations (in microseconds)
2172  if (maxAmsduSize <= 3839)
2173  {
2174  capabilities.SetMaxMpduLength(3895);
2175  }
2176  else if (maxAmsduSize <= 7935)
2177  {
2178  capabilities.SetMaxMpduLength(7991);
2179  }
2180  else
2181  {
2182  capabilities.SetMaxMpduLength(11454);
2183  }
2184  }
2185 
2186  // Set Maximum A-MPDU Length Exponent Extension subfield
2187  uint32_t maxAmpduLength =
2189  // round to the next power of two minus one
2190  maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2191  // The maximum A-MPDU length in EHT capabilities elements ranges from 2^23-1 to 2^24-1
2192  capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8388607U), 16777215U));
2193 
2194  // Set the PHY capabilities
2195  const bool support4096Qam = phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, 12);
2197  support4096Qam ? 1 : 0;
2199  support4096Qam ? 1 : 0;
2200 
2201  const uint8_t maxTxNss = phy->GetMaxSupportedTxSpatialStreams();
2202  const uint8_t maxRxNss = phy->GetMaxSupportedRxSpatialStreams();
2203  if (auto htConfig = GetHtConfiguration(); !htConfig->Get40MHzOperationSupported())
2204  {
2205  for (auto maxMcs : {7, 9, 11, 13})
2206  {
2207  capabilities.SetSupportedRxEhtMcsAndNss(
2209  maxMcs,
2210  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2211  capabilities.SetSupportedTxEhtMcsAndNss(
2213  maxMcs,
2214  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2215  }
2216  }
2217  else
2218  {
2219  for (auto maxMcs : {9, 11, 13})
2220  {
2221  capabilities.SetSupportedRxEhtMcsAndNss(
2223  maxMcs,
2224  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2225  capabilities.SetSupportedTxEhtMcsAndNss(
2227  maxMcs,
2228  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2229  }
2230  }
2231  if (auto vhtConfig = GetVhtConfiguration(); vhtConfig->Get160MHzOperationSupported())
2232  {
2233  for (auto maxMcs : {9, 11, 13})
2234  {
2235  capabilities.SetSupportedRxEhtMcsAndNss(
2237  maxMcs,
2238  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2239  capabilities.SetSupportedTxEhtMcsAndNss(
2241  maxMcs,
2242  phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2243  }
2244  }
2245  // 320 MHz not supported yet
2246 
2247  return capabilities;
2248 }
2249 
2250 uint32_t
2252 {
2253  uint32_t maxSize = 0;
2254  switch (ac)
2255  {
2256  case AC_BE:
2257  maxSize = m_beMaxAmpduSize;
2258  break;
2259  case AC_BK:
2260  maxSize = m_bkMaxAmpduSize;
2261  break;
2262  case AC_VI:
2263  maxSize = m_viMaxAmpduSize;
2264  break;
2265  case AC_VO:
2266  maxSize = m_voMaxAmpduSize;
2267  break;
2268  default:
2269  NS_ABORT_MSG("Unknown AC " << ac);
2270  return 0;
2271  }
2272  return maxSize;
2273 }
2274 
2275 uint16_t
2277 {
2278  uint16_t maxSize = 0;
2279  switch (ac)
2280  {
2281  case AC_BE:
2282  maxSize = m_beMaxAmsduSize;
2283  break;
2284  case AC_BK:
2285  maxSize = m_bkMaxAmsduSize;
2286  break;
2287  case AC_VI:
2288  maxSize = m_viMaxAmsduSize;
2289  break;
2290  case AC_VO:
2291  maxSize = m_voMaxAmsduSize;
2292  break;
2293  default:
2294  NS_ABORT_MSG("Unknown AC " << ac);
2295  return 0;
2296  }
2297  return maxSize;
2298 }
2299 
2300 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:41
#define max(a, b)
Definition: 80211b.c:42
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.
Implement the header for management frames of type Add Block Ack response.
uint8_t GetTid() const
Return the Traffic ID (TID).
Implement the header for management frames of type Delete Block Ack.
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:286
void SetDroppedMpduCallback(DroppedMpdu callback) override
Definition: qos-txop.cc:190
void GotAddBaResponse(const MgtAddBaResponseHeader &respHdr, Mac48Address recipient)
Event handler when an ADDBA response is received.
Definition: qos-txop.cc:652
void SetBlockAckThreshold(uint8_t threshold)
Set threshold for block ack mechanism.
Definition: qos-txop.cc:712
void GotDelBaFrame(const MgtDelBaHeader *delBaHdr, Mac48Address recipient)
Event handler when a DELBA frame is received.
Definition: qos-txop.cc:683
void SetBlockAckInactivityTimeout(uint16_t timeout)
Set the BlockAck inactivity timeout.
Definition: qos-txop.cc:720
bool HasFramesToTransmit(uint8_t linkId) override
Check if the Txop has frames to transmit over the given link.
Definition: qos-txop.cc:333
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
void StartAccessAfterEvent(uint8_t linkId, bool hadFramesToTransmit, bool checkMediumBusy)
Request channel access on the given link after the occurrence of an event that possibly requires to g...
Definition: txop.cc:572
virtual bool HasFramesToTransmit(uint8_t linkId)
Check if the Txop has frames to transmit over the given link.
Definition: txop.cc:514
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:231
virtual void SetWifiMac(const Ptr< WifiMac > mac)
Set the wifi MAC this Txop is associated to.
Definition: txop.cc:209
void SetMaxCws(std::vector< uint32_t > maxCws)
Set the maximum contention window size for each link.
Definition: txop.cc:273
void SetTxopLimits(const std::vector< Time > &txopLimits)
Set the TXOP limit for each link.
Definition: txop.cc:395
void SwapLinks(std::map< uint8_t, uint8_t > links)
Swap the links based on the information included in the given map.
Definition: txop.cc:185
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set MacTxMiddle this Txop is associated to.
Definition: txop.cc:202
void SetMinCws(std::vector< uint32_t > minCws)
Set the minimum contention window size for each link.
Definition: txop.cc:243
virtual void SetDroppedMpduCallback(DroppedMpdu callback)
Definition: txop.cc:220
void SetAifsns(std::vector< uint8_t > aifsns)
Set the number of slots that make up an AIFS for each link.
Definition: txop.cc:371
static constexpr bool CHECK_MEDIUM_BUSY
generation of backoff (also) depends on the busy/idle state of the medium
Definition: txop.h:419
a unique identifier for an interface.
Definition: type-id.h:59
@ ATTR_GET
The attribute can be read.
Definition: type-id.h:64
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
Definition: type-id.h:66
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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 |.
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.
virtual WifiMacType GetType() const
Return the type (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 HasData() const
Return true if the header type is DATA and is not DATA_NULL.
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:2276
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:864
Ptr< QosTxop > GetBEQueue() const
Accessor for the AC_BE channel access function.
Definition: wifi-mac.cc:533
virtual void NotifyChannelSwitching(uint8_t linkId)
Notify that channel on the given link has been switched.
Definition: wifi-mac.cc:582
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition: wifi-mac.cc:1632
virtual void SetMacQueueScheduler(Ptr< WifiMacQueueScheduler > scheduler)
Set the wifi MAC queue scheduler.
Definition: wifi-mac.cc:569
Mac48Address GetBssid(uint8_t linkId) const
Definition: wifi-mac.cc:478
uint16_t m_viMaxAmsduSize
maximum A-MSDU size for AC_VI (in bytes)
Definition: wifi-mac.h:1069
bool m_shortSlotTimeSupported
flag whether short slot time is supported
Definition: wifi-mac.h:1047
void ConfigurePhyDependentParameters(uint8_t linkId)
Configure PHY dependent parameters such as CWmin and CWmax on the given link.
Definition: wifi-mac.cc:795
Ptr< HeConfiguration > GetHeConfiguration() const
Definition: wifi-mac.cc:1749
DroppedMpduTracedCallback m_droppedMpduCallback
This trace indicates that an MPDU was dropped for the given reason.
Definition: wifi-mac.h:1139
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition: wifi-mac.cc:422
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:1045
const std::map< uint8_t, std::unique_ptr< LinkEntity > > & GetLinks() const
Definition: wifi-mac.cc:918
Ptr< Txop > GetTxop() const
Accessor for the Txop object.
Definition: wifi-mac.cc:493
VhtCapabilities GetVhtCapabilities(uint8_t linkId) const
Return the VHT capabilities of the device for the given link.
Definition: wifi-mac.cc:2018
Callback< void > m_linkDown
Callback when a link is down.
Definition: wifi-mac.h:898
bool GetQosSupported() const
Return whether the device supports QoS.
Definition: wifi-mac.cc:1222
std::optional< std::reference_wrapper< const RecipientBlockAckAgreement > > RecipientAgreementOptConstRef
optional const reference to RecipientBlockAckAgreement
Definition: wifi-mac.h:619
virtual void SetAddress(Mac48Address address)
Definition: wifi-mac.cc:445
Ptr< Txop > m_txop
TXOP used for transmission of frames to non-QoS peers.
Definition: wifi-mac.h:894
void SetQosSupported(bool enable)
Enable or disable QoS support for the device.
Definition: wifi-mac.cc:1195
Mac48Address m_address
MAC address of this station.
Definition: wifi-mac.h:1056
std::set< uint8_t > m_linkIds
IDs of the links in use.
Definition: wifi-mac.h:1054
Ptr< WifiMacQueueScheduler > GetMacQueueScheduler() const
Get the wifi MAC queue scheduler.
Definition: wifi-mac.cc:576
uint16_t GetMpduBufferSize() const
Definition: wifi-mac.cc:1862
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition: wifi-mac.cc:933
BlockAckType GetBaTypeAsRecipient(Mac48Address originator, uint8_t tid) const
Definition: wifi-mac.cc:1719
void SwapLinks(std::map< uint8_t, uint8_t > links)
Swap the links based on the information included in the given map.
Definition: wifi-mac.cc:995
uint16_t m_voMaxAmsduSize
maximum A-MSDU size for AC_VO (in bytes)
Definition: wifi-mac.h:1068
Ptr< MacRxMiddle > m_rxMiddle
RX middle (defragmentation etc.)
Definition: wifi-mac.h:892
Ptr< WifiMacQueueScheduler > m_scheduler
wifi MAC queue scheduler
Definition: wifi-mac.h:895
void DoInitialize() override
Initialize() implementation.
Definition: wifi-mac.cc:349
TypeOfStation m_typeOfStation
the type of station
Definition: wifi-mac.h:1050
uint16_t m_mpduBufferSize
BlockAck buffer size (in number of MPDUs)
Definition: wifi-mac.h:1078
uint32_t m_beMaxAmpduSize
maximum A-MPDU size for AC_BE (in bytes)
Definition: wifi-mac.h:1075
virtual void ConfigureStandard(WifiStandard standard)
Definition: wifi-mac.cc:748
bool TidMappedOnLink(Mac48Address mldAddr, WifiDirection dir, uint8_t tid, uint8_t linkId) const
Check whether the given TID is mapped on the given link in the given direction for the given MLD.
Definition: wifi-mac.cc:1116
void UnblockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Unblock the transmission on the given links of all unicast frames addressed to the station with the g...
Definition: wifi-mac.cc:1428
Ssid GetSsid() const
Definition: wifi-mac.cc:465
void SetBeBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_BE.
Definition: wifi-mac.cc:1888
bool GetErpSupported(uint8_t linkId) const
Return whether the device supports ERP on the given link.
Definition: wifi-mac.cc:1228
bool GetHtSupported() const
Return whether the device supports HT.
Definition: wifi-mac.cc:1761
void ResetWifiPhys()
Remove currently attached WifiPhy objects from this MAC.
Definition: wifi-mac.cc:1177
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:1093
void SetErpSupported(bool enable, uint8_t linkId)
Enable or disable ERP support for the given link.
Definition: wifi-mac.cc:1234
uint32_t m_voMaxAmpduSize
maximum A-MPDU size for AC_VO (in bytes)
Definition: wifi-mac.h:1073
void ConfigureDcf(Ptr< Txop > dcf, uint32_t cwmin, uint32_t cwmax, std::list< bool > isDsss, AcIndex ac)
Definition: wifi-mac.cc:669
Ptr< WifiNetDevice > m_device
Pointer to the device.
Definition: wifi-mac.h:1052
void SetSsid(Ssid ssid)
Definition: wifi-mac.cc:458
void UpdateLinkId(uint8_t id)
This method is intended to be called when a link changes ID in order to update the link ID stored by ...
Definition: wifi-mac.cc:945
Ptr< QosTxop > GetVOQueue() const
Accessor for the AC_VO channel access function.
Definition: wifi-mac.cc:521
void SetTypeOfStation(TypeOfStation type)
This method is invoked by a subclass to specify what type of station it is implementing.
Definition: wifi-mac.cc:415
MpduTracedCallback m_ackedMpduCallback
ack'ed MPDU callback
Definition: wifi-mac.h:1144
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:1171
void SetMpduBufferSize(uint16_t size)
Definition: wifi-mac.cc:1853
void BlockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Block the transmission on the given links of all unicast frames addressed to the station with the giv...
Definition: wifi-mac.cc:1387
MpduTracedCallback m_nackedMpduCallback
nack'ed MPDU callback
Definition: wifi-mac.h:1145
bool GetEhtSupported() const
Return whether the device supports EHT.
Definition: wifi-mac.cc:1780
bool GetHeSupported() const
Return whether the device supports HE.
Definition: wifi-mac.cc:1774
HtCapabilities GetHtCapabilities(uint8_t linkId) const
Return the HT capabilities of the device for the given link.
Definition: wifi-mac.cc:1959
void SetBkBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_BK.
Definition: wifi-mac.cc:1898
void SetVoBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_VO.
Definition: wifi-mac.cc:1868
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:961
void NotifyPromiscRx(Ptr< const Packet > packet)
Definition: wifi-mac.cc:613
std::unordered_map< Mac48Address, WifiTidLinkMapping, WifiAddressHash > m_dlTidLinkMappings
DL TID-to-Link Mapping negotiated with an MLD (identified by its MLD address)
Definition: wifi-mac.h:1081
virtual bool HasFramesToTransmit(uint8_t linkId)
Check if the MAC has frames to transmit over the given link.
Definition: wifi-mac.cc:552
virtual void SetWifiPhys(const std::vector< Ptr< WifiPhy >> &phys)
Definition: wifi-mac.cc:1146
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > stationManager)
Definition: wifi-mac.cc:876
void ApplyTidLinkMapping(const Mac48Address &mldAddr, WifiDirection dir)
Apply the TID-to-Link Mapping negotiated with the given MLD for the given direction by properly confi...
Definition: wifi-mac.cc:1305
RecipientAgreementOptConstRef GetBaAgreementEstablishedAsRecipient(Mac48Address originator, uint8_t tid) const
Definition: wifi-mac.cc:1693
void SetBeBlockAckInactivityTimeout(uint16_t timeout)
Set BE block ack inactivity timeout.
Definition: wifi-mac.cc:1928
Ptr< EhtConfiguration > GetEhtConfiguration() const
Definition: wifi-mac.cc:1755
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:1116
bool GetVhtSupported(uint8_t linkId) const
Return whether the device supports VHT on the given link.
Definition: wifi-mac.cc:1767
void SetDsssSupported(bool enable, uint8_t linkId)
Enable or disable DSSS support for the given link.
Definition: wifi-mac.cc:1245
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:1100
Ptr< MacTxMiddle > m_txMiddle
TX middle (aggregation etc.)
Definition: wifi-mac.h:893
void NotifyTx(Ptr< const Packet > packet)
Definition: wifi-mac.cc:595
static TypeId GetTypeId()
Get the type ID.
Definition: wifi-mac.cc:67
Ptr< HtConfiguration > GetHtConfiguration() const
Definition: wifi-mac.cc:1737
std::optional< std::reference_wrapper< const WifiTidLinkMapping > > GetTidToLinkMapping(Mac48Address mldAddr, WifiDirection dir) const
Get the TID-to-Link Mapping negotiated with the given MLD (if any) for the given direction.
Definition: wifi-mac.cc:1100
uint32_t GetMaxAmpduSize(AcIndex ac) const
Return the maximum A-MPDU size of the given Access Category.
Definition: wifi-mac.cc:2251
BlockAckReqType GetBarTypeAsRecipient(Mac48Address originator, uint8_t tid) const
Definition: wifi-mac.cc:1728
Ssid m_ssid
Service Set ID (SSID)
Definition: wifi-mac.h:1057
std::map< uint8_t, std::unique_ptr< LinkEntity > > m_links
ID-indexed map of Link objects.
Definition: wifi-mac.h:1053
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:1620
Ptr< QosTxop > GetVIQueue() const
Accessor for the AC_VI channel access function.
Definition: wifi-mac.cc:527
void SetBssid(Mac48Address bssid, uint8_t linkId)
Definition: wifi-mac.cc:471
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition: wifi-mac.cc:439
Ptr< FrameExchangeManager > SetupFrameExchangeManager(WifiStandard standard)
Create a Frame Exchange Manager depending on the supported version of the standard.
Definition: wifi-mac.cc:813
virtual void Enqueue(Ptr< Packet > packet, Mac48Address to, Mac48Address from)
Definition: wifi-mac.cc:1479
void NotifyRx(Ptr< const Packet > packet)
Definition: wifi-mac.cc:607
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:1123
void UpdateTidToLinkMapping(const Mac48Address &mldAddr, WifiDirection dir, const WifiTidLinkMapping &mapping)
Update the TID-to-Link Mappings for the given MLD in the given direction based on the given negotiate...
Definition: wifi-mac.cc:1066
BlockAckType GetBaTypeAsOriginator(const Mac48Address &recipient, uint8_t tid) const
Definition: wifi-mac.cc:1701
MpduResponseTimeoutTracedCallback m_mpduResponseTimeoutCallback
MPDU response timeout traced callback.
Definition: wifi-mac.h:1166
void SetForwardUpCallback(ForwardUpCallback upCallback)
Definition: wifi-mac.cc:1284
PsduMapResponseTimeoutTracedCallback m_psduMapResponseTimeoutCallback
PSDU map response timeout traced callback.
Definition: wifi-mac.h:1210
ExtendedCapabilities GetExtendedCapabilities() const
Return the extended capabilities of the device.
Definition: wifi-mac.cc:1948
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:1108
uint16_t m_bkMaxAmsduSize
maximum A-MSDU size for AC_BK (in bytes)
Definition: wifi-mac.h:1071
void SetBkBlockAckInactivityTimeout(uint16_t timeout)
Set BK block ack inactivity timeout.
Definition: wifi-mac.cc:1938
std::optional< std::reference_wrapper< const OriginatorBlockAckAgreement > > OriginatorAgreementOptConstRef
optional const reference to OriginatorBlockAckAgreement
Definition: wifi-mac.h:616
std::unordered_map< Mac48Address, WifiTidLinkMapping, WifiAddressHash > m_ulTidLinkMappings
UL TID-to-Link Mapping negotiated with an MLD (identified by its MLD address)
Definition: wifi-mac.h:1083
virtual bool SupportsSendFrom() const
Definition: wifi-mac.cc:1278
uint16_t GetMaxBaBufferSize(std::optional< Mac48Address > address=std::nullopt) const
Get the maximum Block Ack buffer size (in number of MPDUs) supported by the given device,...
Definition: wifi-mac.cc:1838
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:545
void SetWifiRemoteStationManagers(const std::vector< Ptr< WifiRemoteStationManager >> &stationManagers)
Definition: wifi-mac.cc:883
std::optional< uint8_t > GetLinkForPhy(Ptr< const WifiPhy > phy) const
Get the ID of the link (if any) on which the given PHY is operating.
Definition: wifi-mac.cc:974
void SetViBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_VI.
Definition: wifi-mac.cc:1878
void SetViBlockAckInactivityTimeout(uint16_t timeout)
Set VI block ack inactivity timeout.
Definition: wifi-mac.cc:1918
bool GetShortSlotTimeSupported() const
Definition: wifi-mac.cc:1272
BlockAckReqType GetBarTypeAsOriginator(const Mac48Address &recipient, uint8_t tid) const
Definition: wifi-mac.cc:1710
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:625
void SetLinkDownCallback(Callback< void > linkDown)
Definition: wifi-mac.cc:1298
Ptr< QosTxop > GetBKQueue() const
Accessor for the AC_BK channel access function.
Definition: wifi-mac.cc:539
~WifiMac() override
Definition: wifi-mac.cc:61
void SetPromisc()
Sets the interface in promiscuous mode.
Definition: wifi-mac.cc:484
Ptr< VhtConfiguration > GetVhtConfiguration() const
Definition: wifi-mac.cc:1743
void NotifyRxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:619
virtual void SetLinkUpCallback(Callback< void > linkUp)
Definition: wifi-mac.cc:1291
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:906
const std::set< uint8_t > & GetLinkIds() const
Definition: wifi-mac.cc:939
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-mac.cc:428
void SetCtsToSelfSupported(bool enable)
Enable or disable CTS-to-self feature.
Definition: wifi-mac.cc:1258
Mac48Address GetLocalAddress(const Mac48Address &remoteAddr) const
Get the local MAC address used to communicate with a remote STA.
Definition: wifi-mac.cc:1645
EdcaQueues m_edca
This is a map from Access Category index to the corresponding channel access function.
Definition: wifi-mac.h:1066
uint32_t m_bkMaxAmpduSize
maximum A-MPDU size for AC_BK (in bytes)
Definition: wifi-mac.h:1076
void ForwardUp(Ptr< const Packet > packet, Mac48Address from, Mac48Address to)
Forward the packet up to the device.
Definition: wifi-mac.cc:1490
virtual void ConfigureContentionWindow(uint32_t cwMin, uint32_t cwMax)
Definition: wifi-mac.cc:646
OriginatorAgreementOptConstRef GetBaAgreementEstablishedAsOriginator(Mac48Address recipient, uint8_t tid) const
Definition: wifi-mac.cc:1679
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:1497
Mac48Address GetAddress() const
Definition: wifi-mac.cc:452
ForwardUpCallback m_forwardUp
Callback to forward packet up the stack.
Definition: wifi-mac.h:1085
EhtCapabilities GetEhtCapabilities(uint8_t linkId) const
Return the EHT capabilities of the device for the given link.
Definition: wifi-mac.cc:2158
Callback< void > m_linkUp
Callback when a link is up.
Definition: wifi-mac.h:897
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: wifi-mac.cc:924
HeCapabilities GetHeCapabilities(uint8_t linkId) const
Return the HE capabilities of the device for the given link.
Definition: wifi-mac.cc:2100
PsduResponseTimeoutTracedCallback m_psduResponseTimeoutCallback
PSDU response timeout traced callback.
Definition: wifi-mac.h:1187
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:499
void NotifyTxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:601
void DoDispose() override
Destructor implementation.
Definition: wifi-mac.cc:373
bool GetDsssSupported(uint8_t linkId) const
Return whether the device supports DSSS on the given link.
Definition: wifi-mac.cc:1252
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:870
void SetVoBlockAckInactivityTimeout(uint16_t timeout)
Set VO block ack inactivity timeout.
Definition: wifi-mac.cc:1908
virtual std::unique_ptr< LinkEntity > CreateLinkEntity() const
Create a LinkEntity object.
Definition: wifi-mac.cc:912
void SetShortSlotTimeSupported(bool enable)
Enable or disable short slot time feature.
Definition: wifi-mac.cc:1265
bool m_ctsToSelfSupported
flag indicating whether CTS-To-Self is supported
Definition: wifi-mac.h:1048
uint16_t m_beMaxAmsduSize
maximum A-MSDU size for AC_BE (in bytes)
Definition: wifi-mac.h:1070
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:1673
uint32_t m_viMaxAmpduSize
maximum A-MPDU size for AC_VI (in bytes)
Definition: wifi-mac.h:1074
Ptr< VhtConfiguration > GetVhtConfiguration() const
Ptr< EhtConfiguration > GetEhtConfiguration() const
Ptr< HtConfiguration > GetHtConfiguration() const
Ptr< HeConfiguration > GetHeConfiguration() const
Ptr< WifiPhy > GetPhy() const
WifiStandard GetStandard() const
Get the configured Wi-Fi standard.
Definition: wifi-phy.cc:1027
#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
#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_UNLESS(cond)
Abnormal program termination if a condition is false.
Definition: abort.h:129
#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:1350
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
TypeOfStation
Enumeration for type of WiFi station.
Definition: wifi-mac.h:64
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
WifiQueueBlockedReason
Enumeration of the reasons to block container queues.
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:73
@ 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:83
@ AC_BE
Best Effort.
Definition: qos-utils.h:75
@ AC_VO
Voice.
Definition: qos-utils.h:81
@ AC_VI
Video.
Definition: qos-utils.h:79
@ AC_BK
Background.
Definition: qos-utils.h:77
@ AC_UNDEF
Total number of ACs.
Definition: qos-utils.h:87
@ AC_BEACON
Beacon queue.
Definition: qos-utils.h:85
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
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:704
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
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:192
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
const std::map< AcIndex, WifiAc > wifiAcList
Map containing the four ACs in increasing order of priority (according to Table 10-1 "UP-to-AC Mappin...
Definition: qos-utils.cc:126
WifiDirection
Wifi direction.
Definition: wifi-utils.h:43
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
std::map< uint8_t, std::set< uint8_t > > WifiTidLinkMapping
TID-indexed map of the link set to which the TID is mapped.
Definition: wifi-utils.h:74
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:449
ssid
Definition: third.py:93
phy
Definition: third.py:89
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.
std::string dir
BlockAckActionValue blockAck
block ack