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