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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8
9#include "wifi-mac.h"
10
13#include "mac-rx-middle.h"
14#include "mac-tx-middle.h"
15#include "mgt-action-headers.h"
16#include "qos-txop.h"
17#include "ssid.h"
18#include "wifi-mac-queue.h"
19#include "wifi-net-device.h"
20
21#include "ns3/eht-configuration.h"
22#include "ns3/eht-frame-exchange-manager.h"
23#include "ns3/he-configuration.h"
24#include "ns3/ht-configuration.h"
25#include "ns3/log.h"
26#include "ns3/object-vector.h"
27#include "ns3/packet.h"
28#include "ns3/pointer.h"
29#include "ns3/shuffle.h"
30#include "ns3/socket.h"
31#include "ns3/string.h"
32#include "ns3/vht-configuration.h"
33
34#include <algorithm>
35#include <cmath>
36#include <iterator>
37#include <sstream>
38
39namespace ns3
40{
41
43
45
47 : m_qosSupported(false)
48{
49 NS_LOG_FUNCTION(this);
50
52 m_rxMiddle->SetForwardCallback(MakeCallback(&WifiMac::Receive, this));
53
55}
56
61
64{
65 static TypeId tid =
66 TypeId("ns3::WifiMac")
68 .SetGroupName("Wifi")
69 .AddAttribute("Ssid",
70 "The ssid we want to belong to.",
71 SsidValue(Ssid("default")),
74 .AddAttribute("QosSupported",
75 "This Boolean attribute is set to enable 802.11e/WMM-style QoS support "
76 "at this STA.",
78 TypeId::ATTR_CONSTRUCT, // prevent setting after construction
79 BooleanValue(false),
82 .AddAttribute("CtsToSelfSupported",
83 "Use CTS to Self when using a rate that is not in the basic rate set.",
84 BooleanValue(false),
87 .AddAttribute(
88 "ShortSlotTimeSupported",
89 "Whether or not short slot time is supported (only used by ERP APs or STAs).",
90 BooleanValue(true),
94 .AddAttribute("Txop",
95 "The Txop object.",
97 TypeId::ATTR_CONSTRUCT, // prevent setting after construction
101 .AddAttribute("VO_Txop",
102 "Queue that manages packets belonging to AC_VO access class.",
104 TypeId::ATTR_CONSTRUCT, // prevent setting after construction
105 PointerValue(),
108 .AddAttribute("VI_Txop",
109 "Queue that manages packets belonging to AC_VI access class.",
111 TypeId::ATTR_CONSTRUCT, // prevent setting after construction
112 PointerValue(),
115 .AddAttribute("BE_Txop",
116 "Queue that manages packets belonging to AC_BE access class.",
118 TypeId::ATTR_CONSTRUCT, // prevent setting after construction
119 PointerValue(),
122 .AddAttribute("BK_Txop",
123 "Queue that manages packets belonging to AC_BK access class.",
125 TypeId::ATTR_CONSTRUCT, // prevent setting after construction
126 PointerValue(),
129 .AddAttribute(
130 "ChannelAccessManagers",
131 "The Channel Access Manager(s) attached to this device.",
135 .AddAttribute(
136 "FrameExchangeManagers",
137 "The Frame Exchange Manager(s) attached to this device.",
141 .AddAttribute(
142 "MpduBufferSize",
143 "The size (in number of MPDUs) of the buffer used for each BlockAck "
144 "agreement in which this node is a recipient. The provided value is "
145 "capped to the maximum allowed value based on the supported standard.",
146 UintegerValue(1024),
149 .AddAttribute(
150 "FrameRetryLimit",
151 "The maximum number of transmission attempts of a frame that are made before a "
152 "failure condition is indicated. This corresponds to the dot11ShortRetryLimit "
153 "parameter in the standard.",
154 UintegerValue(7),
157 .AddAttribute("VO_MaxAmsduSize",
158 "Maximum length in bytes of an A-MSDU for AC_VO access class "
159 "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
160 "Value 0 means A-MSDU aggregation is disabled for that AC.",
161 UintegerValue(0),
164 .AddAttribute("VI_MaxAmsduSize",
165 "Maximum length in bytes of an A-MSDU for AC_VI access class "
166 "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
167 "Value 0 means A-MSDU aggregation is disabled for that AC.",
168 UintegerValue(0),
171 .AddAttribute("BE_MaxAmsduSize",
172 "Maximum length in bytes of an A-MSDU for AC_BE access class "
173 "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
174 "Value 0 means A-MSDU aggregation is disabled for that AC.",
175 UintegerValue(0),
178 .AddAttribute("BK_MaxAmsduSize",
179 "Maximum length in bytes of an A-MSDU for AC_BK access class "
180 "(capped to 7935 for HT PPDUs and 11398 for VHT/HE/EHT PPDUs). "
181 "Value 0 means A-MSDU aggregation is disabled for that AC.",
182 UintegerValue(0),
185 .AddAttribute(
186 "VO_MaxAmpduSize",
187 "Maximum length in bytes of an A-MPDU for AC_VO access class "
188 "(capped to 65535 for HT PPDUs, 1048575 for VHT PPDUs, 6500631 for HE PPDUs "
189 "and 15523200 for EHT PPDUs). "
190 "Value 0 means A-MPDU aggregation is disabled for that AC.",
191 UintegerValue(0),
194 .AddAttribute(
195 "VI_MaxAmpduSize",
196 "Maximum length in bytes of an A-MPDU for AC_VI access class "
197 "(capped to 65535 for HT PPDUs, 1048575 for VHT PPDUs, 6500631 for HE PPDUs "
198 "and 15523200 for EHT PPDUs). "
199 "Value 0 means A-MPDU aggregation is disabled for that AC.",
200 UintegerValue(65535),
203 .AddAttribute(
204 "BE_MaxAmpduSize",
205 "Maximum length in bytes of an A-MPDU for AC_BE access class "
206 "(capped to 65535 for HT PPDUs, 1048575 for VHT PPDUs, 6500631 for HE PPDUs "
207 "and 15523200 for EHT PPDUs). "
208 "Value 0 means A-MPDU aggregation is disabled for that AC.",
209 UintegerValue(65535),
212 .AddAttribute(
213 "BK_MaxAmpduSize",
214 "Maximum length in bytes of an A-MPDU for AC_BK access class "
215 "(capped to 65535 for HT PPDUs, 1048575 for VHT PPDUs, 6500631 for HE PPDUs "
216 "and 15523200 for EHT PPDUs). "
217 "Value 0 means A-MPDU aggregation is disabled for that AC.",
218 UintegerValue(0),
221 .AddAttribute(
222 "VO_BlockAckThreshold",
223 "If number of packets in VO queue reaches this value, "
224 "block ack mechanism is used. If this value is 0, block ack is never used."
225 "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
226 UintegerValue(0),
229 .AddAttribute(
230 "VI_BlockAckThreshold",
231 "If number of packets in VI queue reaches this value, "
232 "block ack mechanism is used. If this value is 0, block ack is never used."
233 "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
234 UintegerValue(0),
237 .AddAttribute(
238 "BE_BlockAckThreshold",
239 "If number of packets in BE queue reaches this value, "
240 "block ack mechanism is used. If this value is 0, block ack is never used."
241 "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
242 UintegerValue(0),
245 .AddAttribute(
246 "BK_BlockAckThreshold",
247 "If number of packets in BK queue reaches this value, "
248 "block ack mechanism is used. If this value is 0, block ack is never used."
249 "When A-MPDU is enabled, block ack mechanism is used regardless of this value.",
250 UintegerValue(0),
253 .AddAttribute(
254 "VO_BlockAckInactivityTimeout",
255 "Represents max time (blocks of 1024 microseconds) allowed for block ack"
256 "inactivity for AC_VO. If this value isn't equal to 0 a timer start after that a"
257 "block ack setup is completed and will be reset every time that a block ack"
258 "frame is received. If this value is 0, block ack inactivity timeout won't be "
259 "used.",
260 UintegerValue(0),
263 .AddAttribute(
264 "VI_BlockAckInactivityTimeout",
265 "Represents max time (blocks of 1024 microseconds) allowed for block ack"
266 "inactivity for AC_VI. If this value isn't equal to 0 a timer start after that a"
267 "block ack setup is completed and will be reset every time that a block ack"
268 "frame is received. If this value is 0, block ack inactivity timeout won't be "
269 "used.",
270 UintegerValue(0),
273 .AddAttribute(
274 "BE_BlockAckInactivityTimeout",
275 "Represents max time (blocks of 1024 microseconds) allowed for block ack"
276 "inactivity for AC_BE. If this value isn't equal to 0 a timer start after that a"
277 "block ack setup is completed and will be reset every time that a block ack"
278 "frame is received. If this value is 0, block ack inactivity timeout won't be "
279 "used.",
280 UintegerValue(0),
283 .AddAttribute(
284 "BK_BlockAckInactivityTimeout",
285 "Represents max time (blocks of 1024 microseconds) allowed for block ack"
286 "inactivity for AC_BK. If this value isn't equal to 0 a timer start after that a"
287 "block ack setup is completed and will be reset every time that a block ack"
288 "frame is received. If this value is 0, block ack inactivity timeout won't be "
289 "used.",
290 UintegerValue(0),
293 .AddAttribute("RobustAVStreamingSupported",
294 "Whether or not Robust Audio Video Streaming is supported (only allowed "
295 "for AP STAs or non-AP that are HT capable).",
296 BooleanValue(false),
300 .AddTraceSource(
301 "MacTx",
302 "A packet has been received by the WifiNetDevice and is about to be enqueued; "
303 "it has a LlcSnapHeader prepended but not yet a WifiMacHeader.",
305 "ns3::Packet::TracedCallback")
306 .AddTraceSource(
307 "MacTxDrop",
308 "A packet has been dropped in the MAC layer before being queued for transmission. "
309 "This trace source is fired, e.g., when an AP's MAC receives from the upper layer "
310 "a packet destined to a station that is not associated with the AP or a STA's MAC "
311 "receives a packet from the upper layer while it is not associated with any AP.",
313 "ns3::Packet::TracedCallback")
314 .AddTraceSource(
315 "MacPromiscRx",
316 "A packet has been received by this device, has been passed up from the physical "
317 "layer "
318 "and is being forwarded up the local protocol stack. This is a promiscuous trace.",
320 "ns3::Packet::TracedCallback")
321 .AddTraceSource("MacRx",
322 "A packet has been received by this device, has been passed up from "
323 "the physical layer "
324 "and is being forwarded up the local protocol stack. This is a "
325 "non-promiscuous trace.",
327 "ns3::Packet::TracedCallback")
328 .AddTraceSource("MacRxDrop",
329 "A packet has been dropped in the MAC layer after it has been passed "
330 "up from the physical layer.",
332 "ns3::Packet::TracedCallback")
333 .AddTraceSource("AckedMpdu",
334 "An MPDU that was successfully acknowledged, via either a "
335 "Normal Ack or a Block Ack.",
337 "ns3::WifiMpdu::TracedCallback")
338 .AddTraceSource("NAckedMpdu",
339 "An MPDU that was negatively acknowledged via a Block Ack.",
341 "ns3::WifiMpdu::TracedCallback")
342 .AddTraceSource(
343 "DroppedMpdu",
344 "An MPDU that was dropped for the given reason (see WifiMacDropReason).",
346 "ns3::WifiMac::DroppedMpduCallback")
347 .AddTraceSource(
348 "MpduResponseTimeout",
349 "An MPDU whose response was not received before the timeout, along with "
350 "an identifier of the type of timeout (see WifiTxTimer::Reason) and the "
351 "TXVECTOR used to transmit the MPDU. This trace source is fired when a "
352 "CTS is missing after an RTS, when all CTS frames are missing after an MU-RTS, "
353 "or when a Normal Ack is missing after an MPDU or after a DL MU PPDU "
354 "acknowledged in SU format.",
356 "ns3::WifiMac::MpduResponseTimeoutCallback")
357 .AddTraceSource(
358 "PsduResponseTimeout",
359 "A PSDU whose response was not received before the timeout, along with "
360 "an identifier of the type of timeout (see WifiTxTimer::Reason) and the "
361 "TXVECTOR used to transmit the PSDU. This trace source is fired when a "
362 "BlockAck is missing after an A-MPDU, a BlockAckReq (possibly in the "
363 "context of the acknowledgment of a DL MU PPDU in SU format) or a TB PPDU "
364 "(in the latter case the missing BlockAck is a Multi-STA BlockAck).",
366 "ns3::WifiMac::PsduResponseTimeoutCallback")
367 .AddTraceSource(
368 "PsduMapResponseTimeout",
369 "A PSDU map for which not all the responses were received before the timeout, "
370 "along with an identifier of the type of timeout (see WifiTxTimer::Reason), "
371 "the set of MAC addresses of the stations that did not respond and the total "
372 "number of stations that had to respond. This trace source is fired when not "
373 "all the addressed stations responded to an MU-BAR Trigger frame (either sent as "
374 "a SU frame or aggregated to PSDUs in the DL MU PPDU), a Basic Trigger Frame or "
375 "a BSRP Trigger Frame.",
377 "ns3::WifiMac::PsduMapResponseTimeoutCallback")
378 .AddTraceSource("IcfDropReason",
379 "An ICF is dropped by an EMLSR client for the given reason on the "
380 "link with the given ID. This trace source is actually fed by the "
381 "EHT Frame Exchange Manager through the m_icfDropCallback member "
382 "variable.",
384 "ns3::WifiMac::IcfDropCallback");
385 return tid;
386}
387
388int64_t
390{
391 NS_LOG_FUNCTION(this << stream);
392 if (GetNLinks() > 1)
393 {
394 m_shuffleLinkIdsGen.GetRv()->SetStream(stream);
395 return 1;
396 }
397 return 0;
398}
399
400void
402{
403 NS_LOG_FUNCTION(this);
404
405 if (!m_qosSupported)
406 {
408 return;
409 }
410
411 for (const auto& [aci, ac] : wifiAcList)
412 {
413 SetupEdcaQueue(aci);
414 }
415}
416
417void
419{
420 NS_LOG_FUNCTION(this);
421
422 if (m_txop)
423 {
425 }
426
427 for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
428 {
429 it->second->Initialize();
430 }
431
432 for (const auto& [id, link] : m_links)
433 {
434 if (auto cam = link->channelAccessManager)
435 {
436 cam->Initialize();
437 }
438 }
439}
440
441void
443{
444 NS_LOG_FUNCTION(this);
445
446 m_rxMiddle = nullptr;
447 m_txMiddle = nullptr;
448 m_links.clear();
449
450 if (m_txop)
451 {
452 m_txop->Dispose();
453 }
454 m_txop = nullptr;
455
456 for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
457 {
458 it->second->Dispose();
459 it->second = nullptr;
460 }
461
462 m_device = nullptr;
463 if (m_scheduler != nullptr)
464 {
465 m_scheduler->Dispose();
466 }
467 m_scheduler = nullptr;
468}
469
471{
472 // WifiMac owns pointers to ChannelAccessManager and FrameExchangeManager
474 {
475 channelAccessManager->Dispose();
476 }
477 if (feManager)
478 {
479 feManager->Dispose();
480 }
481}
482
483void
485{
486 NS_LOG_FUNCTION(this << type);
487 m_typeOfStation = type;
488}
489
492{
493 return m_typeOfStation;
494}
495
496void
498{
499 m_device = device;
500 if (device->GetHtConfiguration())
501 {
502 // the configured BlockAck buffer size can now be capped
504 }
505}
506
509{
510 return m_device;
511}
512
513void
515{
516 NS_LOG_FUNCTION(this << address);
517 m_address = address;
518}
519
522{
523 return m_address;
524}
525
526void
528{
529 NS_LOG_FUNCTION(this << ssid);
530 m_ssid = ssid;
531}
532
533Ssid
535{
536 return m_ssid;
537}
538
539void
540WifiMac::SetBssid(Mac48Address bssid, uint8_t linkId)
541{
542 NS_LOG_FUNCTION(this << bssid << +linkId);
543 GetLink(linkId).feManager->SetBssid(bssid);
544}
545
547WifiMac::GetBssid(uint8_t linkId) const
548{
549 return GetLink(linkId).feManager->GetBssid();
550}
551
552void
554{
555 for (auto& [id, link] : m_links)
556 {
557 link->feManager->SetPromisc();
558 }
559}
560
561void
563{
564 NS_LOG_FUNCTION(this << dcf);
565 if (!m_qosSupported)
566 {
567 m_txop = dcf;
568 }
569}
570
573{
574 return m_txop;
575}
576
577void
579{
580 NS_LOG_FUNCTION(this << edca);
581 if (m_qosSupported)
582 {
583 m_edca.emplace(AC_VO, edca);
584 }
585}
586
587void
589{
590 NS_LOG_FUNCTION(this << edca);
591 if (m_qosSupported)
592 {
593 m_edca.emplace(AC_VI, edca);
594 }
595}
596
597void
599{
600 NS_LOG_FUNCTION(this << edca);
601 if (m_qosSupported)
602 {
603 m_edca.emplace(AC_BE, edca);
604 }
605}
606
607void
609{
610 NS_LOG_FUNCTION(this << edca);
611 if (m_qosSupported)
612 {
613 m_edca.emplace(AC_BK, edca);
614 }
615}
616
619{
620 // Use std::find_if() instead of std::map::find() because the latter compares
621 // the given AC index with the AC index of an element in the map by using the
622 // operator< defined for AcIndex, which aborts if an operand is not a QoS AC
623 // (the AC index passed to this method may not be a QoS AC).
624 // The performance penalty is limited because std::map::find() performs 3
625 // comparisons in the worst case, while std::find_if() performs 4 comparisons
626 // in the worst case.
627 const auto it = std::find_if(m_edca.cbegin(), m_edca.cend(), [ac](const auto& pair) {
628 return pair.first == ac;
629 });
630 return (it == m_edca.cend() ? nullptr : it->second);
631}
632
634WifiMac::GetQosTxop(uint8_t tid) const
635{
636 return GetQosTxop(QosUtilsMapTidToAc(tid));
637}
638
641{
642 return (m_qosSupported ? GetQosTxop(AC_VO) : nullptr);
643}
644
647{
648 return (m_qosSupported ? GetQosTxop(AC_VI) : nullptr);
649}
650
653{
654 return (m_qosSupported ? GetQosTxop(AC_BE) : nullptr);
655}
656
659{
660 return (m_qosSupported ? GetQosTxop(AC_BK) : nullptr);
661}
662
665{
666 Ptr<Txop> txop = (ac == AC_BE_NQOS ? m_txop : StaticCast<Txop>(GetQosTxop(ac)));
667 return (txop ? txop->GetWifiMacQueue() : nullptr);
668}
669
670bool
672{
673 if (m_txop && m_txop->HasFramesToTransmit(linkId))
674 {
675 return true;
676 }
677 for (const auto& [aci, qosTxop] : m_edca)
678 {
679 if (qosTxop->HasFramesToTransmit(linkId))
680 {
681 return true;
682 }
683 }
684 return false;
685}
686
687void
689{
690 m_scheduler = scheduler;
691 m_scheduler->SetWifiMac(this);
692}
693
696{
697 return m_scheduler;
698}
699
700void
702{
703 NS_LOG_FUNCTION(this << +linkId);
704
705 // we may have changed PHY band, in which case it is necessary to re-configure
706 // the PHY dependent parameters. In any case, this makes no harm
708
709 // Reset remote station manager
710 GetLink(linkId).stationManager->Reset();
711}
712
713void
715{
716 m_macTxTrace(packet);
717}
718
719void
724
725void
727{
728 m_macRxTrace(packet);
729}
730
731void
736
737void
742
743void
745{
746 NS_LOG_FUNCTION(this);
748
751 MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
752}
753
754void
756{
757 NS_LOG_FUNCTION(this << ac);
758
759 auto edcaIt = m_edca.find(ac);
760 NS_ASSERT(edcaIt != m_edca.cend());
761
762 edcaIt->second->SetTxMiddle(m_txMiddle);
763 edcaIt->second->GetBaManager()->SetTxOkCallback(
764 MakeCallback(&MpduTracedCallback::operator(), &m_ackedMpduCallback));
765 edcaIt->second->GetBaManager()->SetTxFailedCallback(
766 MakeCallback(&MpduTracedCallback::operator(), &m_nackedMpduCallback));
767 edcaIt->second->SetDroppedMpduCallback(
768 MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
769 edcaIt->second->GetWifiMacQueue()->TraceConnectWithoutContext(
770 "Expired",
772}
773
774void
776{
777 std::list<bool> isDsssOnly;
778 for (const auto& [id, link] : m_links)
779 {
780 isDsssOnly.push_back(link->dsssSupported && !link->erpSupported);
781 }
782
783 if (m_txop)
784 {
785 // The special value of AC_BE_NQOS which exists in the Access
786 // Category enumeration allows us to configure plain old DCF.
787 ConfigureDcf(m_txop, cwMin, cwMax, isDsssOnly, AC_BE_NQOS);
788 }
789
790 // Now we configure the EDCA functions
791 for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
792 {
793 ConfigureDcf(it->second, cwMin, cwMax, isDsssOnly, it->first);
794 }
795}
796
797void
799 uint32_t cwmin,
800 uint32_t cwmax,
801 std::list<bool> isDsss,
802 AcIndex ac)
803{
804 NS_LOG_FUNCTION(this << dcf << cwmin << cwmax << +ac);
805
806 uint32_t cwMinValue = 0;
807 uint32_t cwMaxValue = 0;
808 uint8_t aifsnValue = 0;
809 Time txopLimitDsss(0);
810 Time txopLimitNoDsss(0);
811
812 /* see IEEE 802.11-2020 Table 9-155 "Default EDCA Parameter Set element parameter values" */
813 switch (ac)
814 {
815 case AC_VO:
816 cwMinValue = (cwmin + 1) / 4 - 1;
817 cwMaxValue = (cwmin + 1) / 2 - 1;
818 aifsnValue = 2;
819 txopLimitDsss = MicroSeconds(3264);
820 txopLimitNoDsss = MicroSeconds(2080);
821 break;
822 case AC_VI:
823 cwMinValue = (cwmin + 1) / 2 - 1;
824 cwMaxValue = cwmin;
825 aifsnValue = 2;
826 txopLimitDsss = MicroSeconds(6016);
827 txopLimitNoDsss = MicroSeconds(4096);
828 break;
829 case AC_BE:
830 cwMinValue = cwmin;
831 cwMaxValue = cwmax;
832 aifsnValue = 3;
833 txopLimitDsss = MicroSeconds(0); // TODO should be MicroSeconds (3264)
834 txopLimitNoDsss = MicroSeconds(0); // TODO should be MicroSeconds (2528)
835 break;
836 case AC_BK:
837 cwMinValue = cwmin;
838 cwMaxValue = cwmax;
839 aifsnValue = 7;
840 txopLimitDsss = MicroSeconds(0); // TODO should be MicroSeconds (3264)
841 txopLimitNoDsss = MicroSeconds(0); // TODO should be MicroSeconds (2528)
842 break;
843 case AC_BE_NQOS:
844 cwMinValue = cwmin;
845 cwMaxValue = cwmax;
846 aifsnValue = 2;
847 txopLimitDsss = txopLimitNoDsss = MicroSeconds(0);
848 break;
849 case AC_BEACON:
850 // done by ApWifiMac
851 break;
852 case AC_UNDEF:
853 NS_FATAL_ERROR("I don't know what to do with this");
854 break;
855 }
856
857 const auto& userDefinedParams = dcf->GetUserAccessParams();
858
859 dcf->SetMinCws(!userDefinedParams.cwMins.empty()
860 ? userDefinedParams.cwMins
861 : std::vector<uint32_t>(m_links.size(), cwMinValue));
862 dcf->SetMaxCws(!userDefinedParams.cwMaxs.empty()
863 ? userDefinedParams.cwMaxs
864 : std::vector<uint32_t>(m_links.size(), cwMaxValue));
865 dcf->SetAifsns(!userDefinedParams.aifsns.empty()
866 ? userDefinedParams.aifsns
867 : std::vector<uint8_t>(m_links.size(), aifsnValue));
868
869 if (!userDefinedParams.txopLimits.empty())
870 {
871 dcf->SetTxopLimits(userDefinedParams.txopLimits);
872 }
873 else
874 {
875 std::vector<Time> txopLimitValues(m_links.size());
876 std::transform(isDsss.begin(),
877 isDsss.end(),
878 txopLimitValues.begin(),
879 [&txopLimitDsss, &txopLimitNoDsss](bool dsss) {
880 return (dsss ? txopLimitDsss : txopLimitNoDsss);
881 });
882 dcf->SetTxopLimits(txopLimitValues);
883 }
884}
885
886void
888{
889 NS_ASSERT_MSG(!m_links.empty(), "CompleteConfig cannot be called before creating links");
890
891 const auto& link = *m_links.cbegin()->second;
892
893 if (!link.phy || !link.stationManager || !link.channelAccessManager || !link.feManager)
894 {
895 return;
896 }
897
898 NS_LOG_FUNCTION(this);
899
900 for (auto& [id, link] : m_links)
901 {
903 !link->phy || !link->phy->GetOperatingChannel().IsSet(),
904 "[LinkID " << +id
905 << "] PHY must have been set and an operating channel must have been set");
906
907 NS_ABORT_MSG_IF(!link->channelAccessManager,
908 "[LinkID " << +id << "] A channel access manager must have been set");
909
910 NS_ABORT_MSG_IF(!link->feManager,
911 "[LinkID " << +id << "] A frame exchange manager must have been set");
912
913 link->channelAccessManager->SetupPhyListener(link->phy);
914 link->channelAccessManager->SetupFrameExchangeManager(link->feManager);
915
916 link->feManager->SetWifiPhy(link->phy);
917 link->feManager->SetMacTxMiddle(m_txMiddle);
918 link->feManager->SetMacRxMiddle(m_rxMiddle);
919
921 {
922 m_txop->SetWifiMac(this);
923 link->channelAccessManager->Add(m_txop);
924 }
925 for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
926 {
927 it->second->SetWifiMac(this);
928 link->channelAccessManager->Add(it->second);
929 }
930
932 }
933
935}
936
937void
939{
940 NS_LOG_FUNCTION(this << +linkId);
941
942 WifiStandard standard = GetLink(linkId).phy->GetStandard();
943
944 uint32_t cwmin = (standard == WIFI_STANDARD_80211b ? 31 : 15);
945 uint32_t cwmax = 1023;
947 SetDsssSupported(standard == WIFI_STANDARD_80211b, linkId);
949 m_links[linkId]->phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ,
950 linkId);
951
952 ConfigureContentionWindow(cwmin, cwmax);
953}
954
955bool
957{
958 if (!m_links.empty())
959 {
960 return false;
961 }
962
963 for (std::size_t i = 0; i < nLinks; i++)
964 {
965 m_links.emplace(i, CreateLinkEntity());
966 m_linkIds.insert(i);
967 }
968 return true;
969}
970
971void
973{
974 NS_LOG_FUNCTION(this);
975
976 if (!CreateLinksIfNeeded(feManagers.size()))
977 {
978 NS_ABORT_MSG_IF(feManagers.size() != m_links.size(),
979 "The number of provided Frame Exchange Manager objects ("
980 << feManagers.size() << ") must match the number of existing links ("
981 << m_links.size() << ")");
982 }
983
984 for (auto managerIt = feManagers.cbegin(); auto& [id, link] : m_links)
985 {
986 link->feManager = *managerIt++;
987 link->feManager->SetWifiMac(this);
988 link->feManager->SetLinkId(id);
989 // connect callbacks
990 link->feManager->GetWifiTxTimer().SetMpduResponseTimeoutCallback(
991 MakeCallback(&MpduResponseTimeoutTracedCallback::operator(),
993 link->feManager->GetWifiTxTimer().SetPsduResponseTimeoutCallback(
994 MakeCallback(&PsduResponseTimeoutTracedCallback::operator(),
996 link->feManager->GetWifiTxTimer().SetPsduMapResponseTimeoutCallback(
997 MakeCallback(&PsduMapResponseTimeoutTracedCallback::operator(),
999 link->feManager->SetDroppedMpduCallback(
1000 MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
1001 link->feManager->SetAckedMpduCallback(
1002 MakeCallback(&MpduTracedCallback::operator(), &m_ackedMpduCallback));
1003 if (auto ehtFem = DynamicCast<EhtFrameExchangeManager>(link->feManager))
1004 {
1005 ehtFem->m_icfDropCallback.ConnectWithoutContext(
1006 MakeCallback(&IcfDropTracedCallback::operator(), &m_icfDropCallback));
1007 }
1008 }
1009
1011}
1012
1015{
1016 return GetLink(linkId).feManager;
1017}
1018
1019void
1021{
1022 NS_LOG_FUNCTION(this);
1023
1024 if (!CreateLinksIfNeeded(caManagers.size()))
1025 {
1026 NS_ABORT_MSG_IF(caManagers.size() != m_links.size(),
1027 "The number of provided Channel Access Manager objects ("
1028 << caManagers.size() << ") must match the number of existing links ("
1029 << m_links.size() << ")");
1030 }
1031
1032 for (auto managerIt = caManagers.cbegin(); auto& [id, link] : m_links)
1033 {
1034 link->channelAccessManager = *managerIt++;
1035 link->channelAccessManager->SetLinkId(id);
1036 }
1037
1039}
1040
1043{
1044 return GetLink(linkId).channelAccessManager;
1045}
1046
1047void
1049{
1050 NS_LOG_FUNCTION(this << stationManager);
1051 SetWifiRemoteStationManagers({stationManager});
1052}
1053
1054void
1056 const std::vector<Ptr<WifiRemoteStationManager>>& stationManagers)
1057{
1058 NS_LOG_FUNCTION(this);
1059
1060 if (!CreateLinksIfNeeded(stationManagers.size()))
1061 {
1062 NS_ABORT_MSG_IF(stationManagers.size() != m_links.size(),
1063 "The number of provided Remote Manager objects ("
1064 << stationManagers.size()
1065 << ") must match the number of existing links (" << m_links.size()
1066 << ")");
1067 }
1068
1069 for (auto managerIt = stationManagers.cbegin(); auto& [id, link] : m_links)
1070 {
1071 link->stationManager = *managerIt++;
1072 link->stationManager->SetLinkId(id);
1073 }
1074
1076}
1077
1080{
1081 return GetLink(linkId).stationManager;
1082}
1083
1084std::unique_ptr<WifiMac::LinkEntity>
1086{
1087 return std::make_unique<LinkEntity>();
1088}
1089
1090const std::map<uint8_t, std::unique_ptr<WifiMac::LinkEntity>>&
1092{
1093 return m_links;
1094}
1095
1097WifiMac::GetLink(uint8_t linkId) const
1098{
1099 auto it = m_links.find(linkId);
1100 NS_ASSERT(it != m_links.cend());
1101 NS_ASSERT(it->second); // check that the pointer owns an object
1102 return *it->second;
1103}
1104
1105uint8_t
1107{
1108 return m_links.size();
1109}
1110
1111const std::set<uint8_t>&
1113{
1114 return m_linkIds;
1115}
1116
1117void
1119{
1120 NS_LOG_FUNCTION(this << id);
1121
1122 auto& link = GetLink(id);
1123 if (link.feManager)
1124 {
1125 link.feManager->SetLinkId(id);
1126 }
1127 if (link.channelAccessManager)
1128 {
1129 link.channelAccessManager->SetLinkId(id);
1130 }
1131 if (link.stationManager)
1132 {
1133 link.stationManager->SetLinkId(id);
1134 }
1135}
1136
1137std::optional<uint8_t>
1139{
1140 for (const auto& [id, link] : m_links)
1141 {
1142 if (link->feManager->GetAddress() == address)
1143 {
1144 return id;
1145 }
1146 }
1147 return std::nullopt;
1148}
1149
1150std::optional<uint8_t>
1152{
1153 for (const auto& [id, link] : m_links)
1154 {
1155 if (link->phy == phy)
1156 {
1157 return id;
1158 }
1159 }
1160 return std::nullopt;
1161}
1162
1163std::optional<uint8_t>
1164WifiMac::GetLinkForPhy(std::size_t phyId) const
1165{
1166 NS_ABORT_UNLESS(phyId < m_device->GetNPhys());
1167 auto phy = m_device->GetPhy(phyId);
1168 return GetLinkForPhy(phy);
1169}
1170
1171void
1172WifiMac::SwapLinks(std::map<uint8_t, uint8_t> links)
1173{
1174 NS_LOG_FUNCTION(this);
1175
1176 // save the initial mapping between link IDs and link Entities
1177 std::map<uint8_t, std::reference_wrapper<const LinkEntity>> origLinkRefMap;
1178 for (const auto& [id, link] : m_links)
1179 {
1180 origLinkRefMap.insert_or_assign(id, *link.get());
1181 }
1182
1183 while (!links.empty())
1184 {
1185 auto from = links.cbegin()->first;
1186 auto to = links.cbegin()->second;
1187
1188 if (from == to)
1189 {
1190 // nothing to do
1191 links.erase(links.cbegin());
1192 continue;
1193 }
1194
1195 std::unique_ptr<LinkEntity> linkToMove;
1196 NS_ASSERT(m_links.contains(from));
1197 linkToMove.swap(m_links.at(from)); // from is now out of m_links
1198 auto empty = from; // track empty cell in m_links
1199
1200 do
1201 {
1202 auto [it, inserted] =
1203 m_links.emplace(to, nullptr); // insert an element with key to if not present
1204 m_links[to].swap(linkToMove); // to is the link to move now
1205 links.erase(from);
1206 if (!linkToMove)
1207 {
1208 if (inserted)
1209 {
1210 m_links.erase(empty);
1211 }
1212 break;
1213 }
1214
1215 auto nextTo = links.find(to);
1216 if (nextTo == links.cend())
1217 {
1218 // no new position specified for 'to', use the current empty cell
1219 m_links[empty].swap(linkToMove);
1220 break;
1221 }
1222
1223 from = to;
1224 to = nextTo->second;
1225 } while (true);
1226 }
1227
1228 m_linkIds.clear();
1229 for (const auto& [id, link] : m_links)
1230 {
1231 m_linkIds.insert(id);
1232 }
1233
1234 std::map<uint8_t, uint8_t> actualPairs;
1235 for (const auto& [from, ref] : origLinkRefMap)
1236 {
1237 // find the pointer in the current link map
1238 for (const auto& [to, link] : m_links)
1239 {
1240 if (link.get() == &ref.get())
1241 {
1242 actualPairs[from] = to; // link 'from' became link 'to'
1243 UpdateLinkId(to);
1244 break;
1245 }
1246 }
1247 }
1248 NS_ASSERT_MSG(actualPairs.size() == m_links.size(), "Missing some link(s)");
1249
1250 if (m_txop)
1251 {
1252 m_txop->SwapLinks(actualPairs);
1253 }
1254 for (auto& [ac, edca] : m_edca)
1255 {
1256 edca->SwapLinks(actualPairs);
1257 }
1258}
1259
1260bool
1261WifiMac::Is6GhzBand(uint8_t linkId) const
1262{
1263 auto phy = GetLink(linkId).phy;
1264 NS_ASSERT(phy);
1265 return phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ;
1266}
1267
1268void
1271 const WifiTidLinkMapping& mapping)
1272{
1273 NS_LOG_FUNCTION(this << mldAddr);
1274
1276 "DL and UL directions for TID-to-Link mapping must be set separately");
1277
1279
1280 auto [it, inserted] = mappings.emplace(mldAddr, mapping);
1281
1282 if (inserted)
1283 {
1284 // we are done
1285 return;
1286 }
1287
1288 // a previous mapping is stored for this MLD
1289 if (mapping.empty())
1290 {
1291 // the default mapping has been now negotiated
1292 it->second.clear();
1293 return;
1294 }
1295
1296 for (const auto& [tid, linkSet] : mapping)
1297 {
1298 it->second[tid] = linkSet;
1299 }
1300}
1301
1302std::optional<std::reference_wrapper<const WifiTidLinkMapping>>
1304{
1306 "Cannot request TID-to-Link mapping for both directions");
1307
1308 const auto& mappings =
1310
1311 if (const auto it = mappings.find(mldAddr); it != mappings.cend())
1312 {
1313 return it->second;
1314 }
1315 return std::nullopt;
1316}
1317
1318bool
1319WifiMac::TidMappedOnLink(Mac48Address mldAddr, WifiDirection dir, uint8_t tid, uint8_t linkId) const
1320{
1322 "Cannot request TID-to-Link mapping for both directions");
1323
1324 if (!GetWifiRemoteStationManager(linkId)->GetMldAddress(mldAddr).has_value())
1325 {
1326 // the link has not been setup
1327 return false;
1328 }
1329
1330 const auto& mappings =
1332
1333 const auto it = mappings.find(mldAddr);
1334
1335 if (it == mappings.cend())
1336 {
1337 // TID-to-link mapping was not negotiated, TIDs are mapped to all setup links
1338 return true;
1339 }
1340
1341 auto linkSetIt = it->second.find(tid);
1342
1343 if (linkSetIt == it->second.cend())
1344 {
1345 // If there is no successfully negotiated TID-to-link mapping for a TID, then the TID
1346 // is mapped to all setup links for DL and UL (Sec. 35.3.7.1.3 of 802.11be D3.1)
1347 return true;
1348 }
1349
1350 return std::find(linkSetIt->second.cbegin(), linkSetIt->second.cend(), linkId) !=
1351 linkSetIt->second.cend();
1352}
1353
1354void
1355WifiMac::SetWifiPhys(const std::vector<Ptr<WifiPhy>>& phys)
1356{
1357 NS_LOG_FUNCTION(this);
1358 ResetWifiPhys();
1359
1360 if (!CreateLinksIfNeeded(phys.size()))
1361 {
1362 NS_ABORT_MSG_IF(phys.size() != m_links.size(),
1363 "The number of provided PHY objects ("
1364 << phys.size() << ") must match the number of existing links ("
1365 << m_links.size() << ")");
1366 }
1367
1368 for (auto phyIt = phys.cbegin(); auto& [id, link] : m_links)
1369 {
1370 link->phy = *phyIt++;
1371 }
1372
1374}
1375
1377WifiMac::GetWifiPhy(uint8_t linkId) const
1378{
1379 return GetLink(linkId).phy;
1380}
1381
1382void
1384{
1385 NS_LOG_FUNCTION(this);
1386 for (auto& [id, link] : m_links)
1387 {
1388 if (link->feManager)
1389 {
1390 link->feManager->ResetPhy();
1391 }
1392 if (link->channelAccessManager)
1393 {
1394 link->channelAccessManager->RemovePhyListener(link->phy);
1395 }
1396 link->phy = nullptr;
1397 }
1398}
1399
1400void
1402{
1403 NS_LOG_FUNCTION(this << enable);
1405 m_qosSupported = enable;
1406}
1407
1408bool
1410{
1411 return m_qosSupported;
1412}
1413
1414bool
1415WifiMac::GetErpSupported(uint8_t linkId) const
1416{
1417 return GetLink(linkId).erpSupported;
1418}
1419
1420void
1421WifiMac::SetErpSupported(bool enable, uint8_t linkId)
1422{
1423 NS_LOG_FUNCTION(this << enable << +linkId);
1424 if (enable)
1425 {
1426 SetDsssSupported(true, linkId);
1427 }
1428 GetLink(linkId).erpSupported = enable;
1429}
1430
1431void
1432WifiMac::SetDsssSupported(bool enable, uint8_t linkId)
1433{
1434 NS_LOG_FUNCTION(this << enable << +linkId);
1435 GetLink(linkId).dsssSupported = enable;
1436}
1437
1438bool
1439WifiMac::GetDsssSupported(uint8_t linkId) const
1440{
1441 return GetLink(linkId).dsssSupported;
1442}
1443
1444void
1446{
1447 NS_LOG_FUNCTION(this);
1448 m_ctsToSelfSupported = enable;
1449}
1450
1451void
1453{
1454 NS_LOG_FUNCTION(this << enable);
1455 m_shortSlotTimeSupported = enable;
1456}
1457
1458bool
1463
1464bool
1466{
1467 return false;
1468}
1469
1470void
1472{
1473 NS_LOG_FUNCTION(this);
1474 m_forwardUp = upCallback;
1475}
1476
1477void
1479{
1480 NS_LOG_FUNCTION(this);
1481 m_linkUp = linkUp;
1482}
1483
1484void
1486{
1487 NS_LOG_FUNCTION(this);
1488 m_linkDown = linkDown;
1489}
1490
1491void
1493{
1494 NS_LOG_FUNCTION(this << mldAddr);
1495
1498 "This method can be used to enforce TID-to-Link mapping for one direction at a time");
1499
1500 const auto& mappings =
1502
1503 auto it = mappings.find(mldAddr);
1504
1505 if (it == mappings.cend())
1506 {
1507 // no mapping has been ever negotiated with the given MLD, the default mapping is used
1508 return;
1509 }
1510
1511 std::set<uint8_t> setupLinks;
1512
1513 // find the IDs of the links setup with the given MLD
1514 for (const auto& [id, link] : m_links)
1515 {
1516 if (link->stationManager->GetMldAddress(mldAddr))
1517 {
1518 setupLinks.insert(id);
1519 }
1520 }
1521
1522 auto linkMapping = it->second;
1523
1524 if (linkMapping.empty())
1525 {
1526 // default link mapping, each TID mapped on all setup links
1527 for (uint8_t tid = 0; tid < 8; tid++)
1528 {
1529 linkMapping.emplace(tid, setupLinks);
1530 }
1531 }
1532
1533 for (const auto& [tid, linkSet] : linkMapping)
1534 {
1535 decltype(setupLinks) mappedLinks; // empty
1536 auto notMappedLinks = setupLinks; // all setup links
1537
1538 for (const auto id : linkSet)
1539 {
1540 if (setupLinks.find(id) != setupLinks.cend())
1541 {
1542 // link is mapped
1543 mappedLinks.insert(id);
1544 notMappedLinks.erase(id);
1545 }
1546 }
1547
1548 // unblock mapped links
1549 NS_ABORT_MSG_IF(mappedLinks.empty(), "Every TID must be mapped to at least a link");
1550
1552 QosUtilsMapTidToAc(tid),
1554 mldAddr,
1555 GetAddress(),
1556 {tid},
1557 mappedLinks);
1558
1559 // block unmapped links
1560 if (!notMappedLinks.empty())
1561 {
1563 QosUtilsMapTidToAc(tid),
1565 mldAddr,
1566 GetAddress(),
1567 {tid},
1568 notMappedLinks);
1569 }
1570 }
1571}
1572
1573void
1575 const Mac48Address& address,
1576 const std::set<uint8_t>& linkIds)
1577{
1578 std::stringstream ss;
1579 if (g_log.IsEnabled(ns3::LOG_FUNCTION))
1580 {
1581 std::copy(linkIds.cbegin(), linkIds.cend(), std::ostream_iterator<uint16_t>(ss, " "));
1582 }
1583 NS_LOG_FUNCTION(this << reason << address << ss.str());
1585
1586 for (const auto linkId : linkIds)
1587 {
1588 auto& link = GetLink(linkId);
1589 auto linkAddr = link.stationManager->GetAffiliatedStaAddress(address).value_or(address);
1590
1591 if (link.stationManager->GetMldAddress(address) == address && linkAddr == address)
1592 {
1593 NS_LOG_DEBUG("Link " << +linkId << " has not been setup with the MLD, skip");
1594 continue;
1595 }
1596
1597 for (const auto& [acIndex, ac] : wifiAcList)
1598 {
1599 // block queues storing QoS data frames and control frames that use MLD addresses
1600 m_scheduler->BlockQueues(reason,
1601 acIndex,
1603 address,
1604 GetAddress(),
1605 {ac.GetLowTid(), ac.GetHighTid()},
1606 {linkId});
1607 // block queues storing management and control frames that use link addresses
1608 m_scheduler->BlockQueues(reason,
1609 acIndex,
1611 linkAddr,
1612 link.feManager->GetAddress(),
1613 {},
1614 {linkId});
1615 }
1616 }
1617}
1618
1619void
1621 const Mac48Address& address,
1622 const std::set<uint8_t>& linkIds)
1623{
1625
1626 // shuffle link IDs not to unblock links always in the same order
1627 std::vector<uint8_t> shuffledLinkIds(linkIds.cbegin(), linkIds.cend());
1628 Shuffle(shuffledLinkIds.begin(), shuffledLinkIds.end(), m_shuffleLinkIdsGen.GetRv());
1629
1630 std::stringstream ss;
1631 if (g_log.IsEnabled(ns3::LOG_FUNCTION))
1632 {
1633 std::copy(shuffledLinkIds.cbegin(),
1634 shuffledLinkIds.cend(),
1635 std::ostream_iterator<uint16_t>(ss, " "));
1636 }
1637 NS_LOG_FUNCTION(this << reason << address << ss.str());
1638
1639 for (const auto linkId : shuffledLinkIds)
1640 {
1641 auto& link = GetLink(linkId);
1642 auto linkAddr = link.stationManager->GetAffiliatedStaAddress(address).value_or(address);
1643
1644 if (link.stationManager->GetMldAddress(address) == address && linkAddr == address)
1645 {
1646 NS_LOG_DEBUG("Link " << +linkId << " has not been setup with the MLD, skip");
1647 continue;
1648 }
1649
1650 for (const auto& [acIndex, ac] : wifiAcList)
1651 {
1652 // save the status of the AC queues before unblocking the requested queues
1653 auto hasFramesToTransmit = GetQosTxop(acIndex)->HasFramesToTransmit(linkId);
1654
1655 // unblock queues storing QoS data frames and control frames that use MLD addresses
1656 m_scheduler->UnblockQueues(reason,
1657 acIndex,
1659 address,
1660 GetAddress(),
1661 {ac.GetLowTid(), ac.GetHighTid()},
1662 {linkId});
1663 // unblock queues storing management and control frames that use link addresses
1664 m_scheduler->UnblockQueues(reason,
1665 acIndex,
1667 linkAddr,
1668 link.feManager->GetAddress(),
1669 {},
1670 {linkId});
1671 // request channel access if needed (schedule now because multiple invocations
1672 // of this method may be done in a loop at the caller)
1674 GetQosTxop(acIndex),
1675 linkId,
1676 hasFramesToTransmit,
1677 Txop::CHECK_MEDIUM_BUSY); // generate backoff if medium busy
1678 }
1679 }
1680}
1681
1682bool
1684 const WifiContainerQueueId& queueId,
1685 uint8_t linkId,
1686 WifiQueueBlockedReason reason) const
1687{
1688 auto mask = m_scheduler->GetQueueLinkMask(ac, queueId, linkId);
1689
1690 if (!mask.has_value())
1691 {
1692 return true; // the link may have not been setup
1693 }
1695 {
1696 return mask->any();
1697 }
1698 return mask->test(static_cast<std::size_t>(reason));
1699}
1700
1701void
1703{
1704 NS_LOG_FUNCTION(this << *mpdu);
1705
1706 const auto& hdr = mpdu->GetHeader();
1707 const auto remoteAddr = hdr.GetAddr1();
1708
1709 if (remoteAddr.IsGroup() || hdr.IsCtl() || !hdr.IsRetry() || mpdu->IsInFlight())
1710 {
1711 return; // nothing to do
1712 }
1713
1714 std::optional<Mac48Address> optAddr;
1715 for (const auto& [id, link] : m_links)
1716 {
1717 if (link->stationManager->GetMldAddress(remoteAddr) == remoteAddr)
1718 {
1719 // this is a link setup with a remote MLD and remoteAddr is the MLD address
1720 optAddr = link->feManager->GetAddress(); // use local address of this setup link
1721 }
1722 }
1723
1724 const auto localAddr =
1725 optAddr.value_or(GetNLinks() == 1 ? m_address : DoGetLocalAddress(remoteAddr));
1726 const auto linkId = GetLinkIdByAddress(localAddr);
1727 NS_ASSERT_MSG(linkId.has_value(), "No link with address " << localAddr);
1728
1729 GetLink(*linkId).stationManager->ReportFinalDataFailed(mpdu);
1730}
1731
1732void
1734{
1735 NS_LOG_FUNCTION(this << packet << to);
1736 // We're sending this packet with a from address that is our own. We
1737 // get that address from the lower MAC and make use of the
1738 // from-spoofing Enqueue() method to avoid duplicated code.
1739 Enqueue(packet, to, GetAddress());
1740}
1741
1742void
1744{
1745 NS_LOG_FUNCTION(this << packet << to << from);
1746
1747 // If we are not a QoS AP then we definitely want to use AC_BE to
1748 // transmit the packet. A TID of zero will map to AC_BE (through \c
1749 // QosUtilsMapTidToAc()), so we use that as our default here.
1750 uint8_t tid = 0;
1751
1753 if (packet->RemovePacketTag(qos) && qos.GetPriority() < 8)
1754 {
1755 tid = qos.GetPriority();
1756 }
1757
1758 Enqueue(packet, to, from, tid);
1759}
1760
1761void
1763{
1764 NS_LOG_FUNCTION(this << packet << to << from << tid);
1765
1767 "This Mac does not support forwarding frames");
1768
1769 if (!CanForwardPacketsTo(to))
1770 {
1771 NotifyTxDrop(packet);
1772 NotifyDropPacketToEnqueue(packet, to);
1773 return;
1774 }
1775
1776 WifiMacHeader hdr;
1777
1778 // For now, an AP that supports QoS does not support non-QoS
1779 // associations, and vice versa. In future the AP model should
1780 // support simultaneously associated QoS and non-QoS STAs, at which
1781 // point there will need to be per-association QoS state maintained
1782 // by the association state machine, and consulted here.
1783 if (GetQosSupported())
1784 {
1787 hdr.SetQosNoEosp();
1788 hdr.SetQosNoAmsdu();
1789 hdr.SetQosTid(tid);
1790 hdr.SetNoOrder(); // explicitly set to 0 for the time being since HT control field is not
1791 // yet implemented (set it to 1 when implemented)
1792 }
1793 else
1794 {
1796 }
1797
1798 // create an MPDU and pass it to subclasses to finalize MAC header
1799 Enqueue(Create<WifiMpdu>(packet, hdr), to, from);
1800}
1801
1802void
1804{
1805 NS_LOG_FUNCTION(this << packet << to);
1806}
1807
1808void
1810{
1811 NS_LOG_FUNCTION(this << packet << from << to);
1812 m_forwardUp(packet, from, to);
1813}
1814
1815void
1817{
1818 NS_LOG_FUNCTION(this << *mpdu << linkId);
1819
1820 const auto& hdr = mpdu->GetOriginal()->GetHeader();
1821 const auto to = hdr.GetAddr1();
1822 const auto myAddr = hdr.IsData() ? Mac48Address::ConvertFrom(GetDevice()->GetAddress())
1823 : GetFrameExchangeManager(linkId)->GetAddress();
1824
1825 // We don't know how to deal with any frame that is not addressed to
1826 // us (and odds are there is nothing sensible we could do anyway),
1827 // so we ignore such frames.
1828 //
1829 // The derived class may also do some such filtering, but it doesn't
1830 // hurt to have it here too as a backstop.
1831 if (to != myAddr)
1832 {
1833 return;
1834 }
1835
1836 // Nothing to do with (QoS) Null Data frames or management frames
1837 if ((hdr.IsData() && !hdr.HasData()) || hdr.IsMgt())
1838 {
1839 return;
1840 }
1841
1842 NS_FATAL_ERROR("Don't know how to handle frame (type=" << hdr.GetType());
1843}
1844
1845void
1847{
1848 NS_LOG_FUNCTION(this << *mpdu);
1849 for (auto& msduPair : *PeekPointer(mpdu))
1850 {
1851 ForwardUp(msduPair.first,
1852 msduPair.second.GetSourceAddr(),
1853 msduPair.second.GetDestinationAddr());
1854 }
1855}
1856
1857std::optional<Mac48Address>
1858WifiMac::GetMldAddress(const Mac48Address& remoteAddr) const
1859{
1860 for (const auto& [id, link] : m_links)
1861 {
1862 if (auto mldAddress = link->stationManager->GetMldAddress(remoteAddr))
1863 {
1864 return *mldAddress;
1865 }
1866 }
1867 return std::nullopt;
1868}
1869
1872{
1873 for (const auto& [id, link] : m_links)
1874 {
1875 if (auto mldAddress = link->stationManager->GetMldAddress(remoteAddr))
1876 {
1877 // this is a link setup with remote MLD
1878 if (mldAddress != remoteAddr)
1879 {
1880 // the remote address is the address of a STA affiliated with the remote MLD
1881 return link->feManager->GetAddress();
1882 }
1883 // we have to return our MLD address
1884 return m_address;
1885 }
1886 }
1887 // we get here if no ML setup was established between this device and the remote device,
1888 // i.e., they are not both multi-link devices
1889 if (GetNLinks() == 1)
1890 {
1891 // this is a single link device
1892 return m_address;
1893 }
1894 // this is an MLD (hence the remote device is single link or unknown)
1895 return DoGetLocalAddress(remoteAddr);
1896}
1897
1899WifiMac::DoGetLocalAddress(const Mac48Address& remoteAddr [[maybe_unused]]) const
1900{
1901 return m_address;
1902}
1903
1906 uint8_t tid,
1907 std::optional<Mac48Address> gcrGroupAddr) const
1908{
1909 // BA agreements are indexed by the MLD address if ML setup was performed
1910 recipient = GetMldAddress(recipient).value_or(recipient);
1911
1912 auto agreement =
1913 GetQosTxop(tid)->GetBaManager()->GetAgreementAsOriginator(recipient, tid, gcrGroupAddr);
1914 if (!agreement || !agreement->get().IsEstablished())
1915 {
1916 return std::nullopt;
1917 }
1918 return agreement;
1919}
1920
1923 uint8_t tid,
1924 std::optional<Mac48Address> gcrGroupAddr) const
1925{
1926 // BA agreements are indexed by the MLD address if ML setup was performed
1927 originator = GetMldAddress(originator).value_or(originator);
1928 return GetQosTxop(tid)->GetBaManager()->GetAgreementAsRecipient(originator, tid, gcrGroupAddr);
1929}
1930
1932WifiMac::GetBaTypeAsOriginator(const Mac48Address& recipient, uint8_t tid) const
1933{
1934 auto agreement = GetBaAgreementEstablishedAsOriginator(recipient, tid);
1935 NS_ABORT_MSG_IF(!agreement,
1936 "No existing Block Ack agreement with " << recipient << " TID: " << +tid);
1937 return agreement->get().GetBlockAckType();
1938}
1939
1941WifiMac::GetBarTypeAsOriginator(const Mac48Address& recipient, uint8_t tid) const
1942{
1943 auto agreement = GetBaAgreementEstablishedAsOriginator(recipient, tid);
1944 NS_ABORT_MSG_IF(!agreement,
1945 "No existing Block Ack agreement with " << recipient << " TID: " << +tid);
1946 return agreement->get().GetBlockAckReqType();
1947}
1948
1950WifiMac::GetBaTypeAsRecipient(Mac48Address originator, uint8_t tid) const
1951{
1952 auto agreement = GetBaAgreementEstablishedAsRecipient(originator, tid);
1953 NS_ABORT_MSG_IF(!agreement,
1954 "No existing Block Ack agreement with " << originator << " TID: " << +tid);
1955 return agreement->get().GetBlockAckType();
1956}
1957
1959WifiMac::GetBarTypeAsRecipient(Mac48Address originator, uint8_t tid) const
1960{
1961 auto agreement = GetBaAgreementEstablishedAsRecipient(originator, tid);
1962 NS_ABORT_MSG_IF(!agreement,
1963 "No existing Block Ack agreement with " << originator << " TID: " << +tid);
1964 return agreement->get().GetBlockAckReqType();
1965}
1966
1969{
1970 return GetDevice()->GetHtConfiguration();
1971}
1972
1975{
1976 return GetDevice()->GetVhtConfiguration();
1977}
1978
1981{
1982 return GetDevice()->GetHeConfiguration();
1983}
1984
1987{
1988 return GetDevice()->GetEhtConfiguration();
1989}
1990
1991bool
1992WifiMac::GetHtSupported(uint8_t linkId) const
1993{
1994 return (GetDevice()->GetHtConfiguration() &&
1995 GetWifiPhy(linkId)->GetPhyBand() != WIFI_PHY_BAND_6GHZ);
1996}
1997
1998bool
1999WifiMac::GetVhtSupported(uint8_t linkId) const
2000{
2001 return (GetDevice()->GetVhtConfiguration() &&
2002 GetWifiPhy(linkId)->GetPhyBand() != WIFI_PHY_BAND_2_4GHZ &&
2003 GetWifiPhy(linkId)->GetPhyBand() != WIFI_PHY_BAND_6GHZ);
2004}
2005
2006bool
2008{
2009 return bool(GetDevice()->GetHeConfiguration());
2010}
2011
2012bool
2014{
2015 return bool(GetDevice()->GetEhtConfiguration());
2016}
2017
2018bool
2020{
2021 for (const auto& [id, link] : m_links)
2022 {
2023 if (link->stationManager->GetHtSupported(address))
2024 {
2025 return true;
2026 }
2027 }
2028 return false;
2029}
2030
2031bool
2033{
2034 for (const auto& [id, link] : m_links)
2035 {
2036 if (link->stationManager->GetVhtSupported(address))
2037 {
2038 return true;
2039 }
2040 }
2041 return false;
2042}
2043
2044bool
2046{
2047 for (const auto& [id, link] : m_links)
2048 {
2049 if (link->stationManager->GetHeSupported(address))
2050 {
2051 return true;
2052 }
2053 }
2054 return false;
2055}
2056
2057bool
2059{
2060 for (const auto& [id, link] : m_links)
2061 {
2062 if (link->stationManager->GetEhtSupported(address))
2063 {
2064 return true;
2065 }
2066 }
2067 return false;
2068}
2069
2070uint16_t
2071WifiMac::GetMaxBaBufferSize(std::optional<Mac48Address> address) const
2072{
2073 if (address ? GetEhtSupported(*address) : GetEhtSupported())
2074 {
2075 return 1024;
2076 }
2077 if (address ? GetHeSupported(*address) : GetHeSupported())
2078 {
2079 return 256;
2080 }
2081 NS_ASSERT(address ? GetHtSupported(*address) : static_cast<bool>(GetHtConfiguration()));
2082 return 64;
2083}
2084
2085void
2087{
2088 NS_LOG_FUNCTION(this << size);
2089
2090 // the cap can be computed if the device has been configured
2091 m_mpduBufferSize = m_device ? std::min(size, GetMaxBaBufferSize()) : size;
2092}
2093
2094uint16_t
2096{
2097 return m_mpduBufferSize;
2098}
2099
2100void
2102{
2103 NS_LOG_FUNCTION(this << limit);
2104 m_frameRetryLimit = limit;
2105}
2106
2109{
2110 return m_frameRetryLimit;
2111}
2112
2113void
2115{
2116 NS_LOG_FUNCTION(this << +threshold);
2117 if (m_qosSupported)
2118 {
2119 GetVOQueue()->SetBlockAckThreshold(threshold);
2120 }
2121}
2122
2123void
2125{
2126 NS_LOG_FUNCTION(this << +threshold);
2127 if (m_qosSupported)
2128 {
2129 GetVIQueue()->SetBlockAckThreshold(threshold);
2130 }
2131}
2132
2133void
2135{
2136 NS_LOG_FUNCTION(this << +threshold);
2137 if (m_qosSupported)
2138 {
2139 GetBEQueue()->SetBlockAckThreshold(threshold);
2140 }
2141}
2142
2143void
2145{
2146 NS_LOG_FUNCTION(this << +threshold);
2147 if (m_qosSupported)
2148 {
2149 GetBKQueue()->SetBlockAckThreshold(threshold);
2150 }
2151}
2152
2153void
2162
2163void
2172
2173void
2182
2183void
2192
2195{
2196 ExtendedCapabilities capabilities;
2198 return capabilities;
2199}
2200
2202WifiMac::GetHtCapabilities(uint8_t linkId) const
2203{
2204 NS_ASSERT(GetHtSupported(linkId));
2205 HtCapabilities capabilities;
2206
2207 auto phy = GetWifiPhy(linkId);
2208 Ptr<HtConfiguration> htConfiguration = GetHtConfiguration();
2209 bool sgiSupported = htConfiguration->m_sgiSupported;
2210 capabilities.SetLdpc(htConfiguration->m_ldpcSupported);
2211 capabilities.SetSupportedChannelWidth(htConfiguration->m_40MHzSupported ? 1 : 0);
2212 capabilities.SetShortGuardInterval20(sgiSupported);
2213 capabilities.SetShortGuardInterval40(sgiSupported);
2214 // Set Maximum A-MSDU Length subfield
2215 uint16_t maxAmsduSize =
2217 if (maxAmsduSize <= 3839)
2218 {
2219 capabilities.SetMaxAmsduLength(3839);
2220 }
2221 else
2222 {
2223 capabilities.SetMaxAmsduLength(7935);
2224 }
2225 uint32_t maxAmpduLength =
2227 // round to the next power of two minus one
2228 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2229 // The maximum A-MPDU length in HT capabilities elements ranges from 2^13-1 to 2^16-1
2230 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 65535U));
2231
2232 capabilities.SetLSigProtectionSupport(true);
2233 uint64_t maxSupportedRate = 0; // in bit/s
2234 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HT))
2235 {
2236 capabilities.SetRxMcsBitmask(mcs.GetMcsValue());
2237 uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
2238 NS_ASSERT(nss > 0 && nss < 5);
2239 uint64_t dataRate =
2240 mcs.GetDataRate(htConfiguration->m_40MHzSupported ? MHz_u{40} : MHz_u{20},
2241 NanoSeconds(sgiSupported ? 400 : 800),
2242 nss);
2243 if (dataRate > maxSupportedRate)
2244 {
2245 maxSupportedRate = dataRate;
2246 NS_LOG_DEBUG("Updating maxSupportedRate to " << maxSupportedRate);
2247 }
2248 }
2249 capabilities.SetRxHighestSupportedDataRate(
2250 static_cast<uint16_t>(maxSupportedRate / 1e6)); // in Mbit/s
2251 capabilities.SetTxMcsSetDefined(phy->GetNMcs() > 0);
2252 capabilities.SetTxMaxNSpatialStreams(phy->GetMaxSupportedTxSpatialStreams());
2253 // we do not support unequal modulations
2254 capabilities.SetTxRxMcsSetUnequal(0);
2255 capabilities.SetTxUnequalModulation(0);
2256
2257 return capabilities;
2258}
2259
2261WifiMac::GetVhtCapabilities(uint8_t linkId) const
2262{
2263 NS_ASSERT(GetVhtSupported(linkId));
2264 VhtCapabilities capabilities;
2265
2266 auto phy = GetWifiPhy(linkId);
2267 Ptr<HtConfiguration> htConfiguration = GetHtConfiguration();
2268 NS_ABORT_MSG_IF(!htConfiguration->m_40MHzSupported,
2269 "VHT stations have to support 40 MHz operation");
2270 Ptr<VhtConfiguration> vhtConfiguration = GetVhtConfiguration();
2271 bool sgiSupported = htConfiguration->m_sgiSupported;
2272 capabilities.SetSupportedChannelWidthSet(vhtConfiguration->m_160MHzSupported ? 1 : 0);
2273 // Set Maximum MPDU Length subfield
2274 uint16_t maxAmsduSize =
2276 if (maxAmsduSize <= 3839)
2277 {
2278 capabilities.SetMaxMpduLength(3895);
2279 }
2280 else if (maxAmsduSize <= 7935)
2281 {
2282 capabilities.SetMaxMpduLength(7991);
2283 }
2284 else
2285 {
2286 capabilities.SetMaxMpduLength(11454);
2287 }
2288 uint32_t maxAmpduLength =
2290 // round to the next power of two minus one
2291 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2292 // The maximum A-MPDU length in VHT capabilities elements ranges from 2^13-1 to 2^20-1
2293 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 1048575U));
2294
2295 capabilities.SetRxLdpc(htConfiguration->m_ldpcSupported);
2296 capabilities.SetShortGuardIntervalFor80Mhz(sgiSupported);
2297 capabilities.SetShortGuardIntervalFor160Mhz(sgiSupported);
2298 uint8_t maxMcs = 0;
2299 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
2300 {
2301 if (mcs.GetMcsValue() > maxMcs)
2302 {
2303 maxMcs = mcs.GetMcsValue();
2304 }
2305 }
2306 // Support same MaxMCS for each spatial stream
2307 for (uint8_t nss = 1; nss <= phy->GetMaxSupportedRxSpatialStreams(); nss++)
2308 {
2309 capabilities.SetRxMcsMap(maxMcs, nss);
2310 }
2311 for (uint8_t nss = 1; nss <= phy->GetMaxSupportedTxSpatialStreams(); nss++)
2312 {
2313 capabilities.SetTxMcsMap(maxMcs, nss);
2314 }
2315 uint64_t maxSupportedRateLGI = 0; // in bit/s
2316 const auto maxWidth = vhtConfiguration->m_160MHzSupported ? MHz_u{160} : MHz_u{80};
2317 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
2318 {
2319 if (!mcs.IsAllowed(maxWidth, 1))
2320 {
2321 continue;
2322 }
2323 if (mcs.GetDataRate(maxWidth) > maxSupportedRateLGI)
2324 {
2325 maxSupportedRateLGI = mcs.GetDataRate(maxWidth);
2326 NS_LOG_DEBUG("Updating maxSupportedRateLGI to " << maxSupportedRateLGI);
2327 }
2328 }
2330 static_cast<uint16_t>(maxSupportedRateLGI / 1e6)); // in Mbit/s
2332 static_cast<uint16_t>(maxSupportedRateLGI / 1e6)); // in Mbit/s
2333 // To be filled in once supported
2334 capabilities.SetRxStbc(0);
2335 capabilities.SetTxStbc(0);
2336
2337 return capabilities;
2338}
2339
2341WifiMac::GetHeCapabilities(uint8_t linkId) const
2342{
2344 HeCapabilities capabilities;
2345
2346 Ptr<WifiPhy> phy = GetLink(linkId).phy;
2347 Ptr<HtConfiguration> htConfiguration = GetHtConfiguration();
2348 Ptr<VhtConfiguration> vhtConfiguration = GetVhtConfiguration();
2349 Ptr<HeConfiguration> heConfiguration = GetHeConfiguration();
2350 uint8_t channelWidthSet = 0;
2351 if ((htConfiguration->m_40MHzSupported) && (phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ))
2352 {
2353 channelWidthSet |= 0x01;
2354 }
2355 // we assume that HE stations support 80 MHz operations
2356 if ((phy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) || (phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ))
2357 {
2358 channelWidthSet |= 0x02;
2359 }
2360 if ((vhtConfiguration->m_160MHzSupported) &&
2361 ((phy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) || (phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ)))
2362 {
2363 channelWidthSet |= 0x04;
2364 }
2365 capabilities.SetChannelWidthSet(channelWidthSet);
2366 capabilities.SetLdpcCodingInPayload(htConfiguration->m_ldpcSupported);
2367 if (heConfiguration->GetGuardInterval().GetNanoSeconds() == 800)
2368 {
2369 // todo: We assume for now that if we support 800ns GI then 1600ns GI is supported as well
2370 // todo: Assuming reception support for both 1x HE LTF and 4x HE LTF 800 ns
2371 capabilities.SetHeSuPpdu1xHeLtf800nsGi(true);
2372 capabilities.SetHePpdu4xHeLtf800nsGi(true);
2373 }
2374
2375 uint32_t maxAmpduLength =
2377 // round to the next power of two minus one
2378 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2379 // The maximum A-MPDU length in HE capabilities elements ranges from 2^20-1 to 2^23-1
2380 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 1048575U), 8388607U));
2381
2382 uint8_t maxMcs = 0;
2383 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HE))
2384 {
2385 if (mcs.GetMcsValue() > maxMcs)
2386 {
2387 maxMcs = mcs.GetMcsValue();
2388 }
2389 }
2390 capabilities.SetHighestMcsSupported(maxMcs);
2391 capabilities.SetHighestNssSupported(phy->GetMaxSupportedTxSpatialStreams());
2392
2393 return capabilities;
2394}
2395
2398{
2399 auto phy = GetLink(linkId).phy;
2400 NS_ASSERT_MSG(phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ,
2401 "Getting HE 6 GHz band capabilities on band different than 6 GHz");
2402
2403 He6GhzBandCapabilities capabilities;
2404
2405 // Set Maximum MPDU Length subfield
2406 const auto maxAmsduSize =
2408 if (maxAmsduSize <= 3839)
2409 {
2410 capabilities.SetMaxMpduLength(3895);
2411 }
2412 else if (maxAmsduSize <= 7935)
2413 {
2414 capabilities.SetMaxMpduLength(7991);
2415 }
2416 else
2417 {
2418 capabilities.SetMaxMpduLength(11454);
2419 }
2420
2421 auto maxAmpduLength =
2423 // round to the next power of two minus one
2424 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2425 // The maximum A-MPDU length in HE 6 GHz Band Capabilities elements ranges from 2^13-1 to 2^20-1
2426 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 1048575U));
2427
2428 return capabilities;
2429}
2430
2432WifiMac::GetEhtCapabilities(uint8_t linkId) const
2433{
2435 EhtCapabilities capabilities;
2436
2437 Ptr<WifiPhy> phy = GetLink(linkId).phy;
2438
2439 // Set Maximum MPDU Length subfield (Reserved when transmitted in 5 GHz or 6 GHz band)
2440 if (phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
2441 {
2442 uint16_t maxAmsduSize =
2444 // Table 9-34—Maximum data unit sizes (in octets) and durations (in microseconds)
2445 if (maxAmsduSize <= 3839)
2446 {
2447 capabilities.SetMaxMpduLength(3895);
2448 }
2449 else if (maxAmsduSize <= 7935)
2450 {
2451 capabilities.SetMaxMpduLength(7991);
2452 }
2453 else
2454 {
2455 capabilities.SetMaxMpduLength(11454);
2456 }
2457 }
2458
2459 // Set Maximum A-MPDU Length Exponent Extension subfield
2460 uint32_t maxAmpduLength =
2462 // round to the next power of two minus one
2463 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2464 // The maximum A-MPDU length in EHT capabilities elements ranges from 2^23-1 to 2^24-1
2465 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8388607U), 16777215U));
2466
2467 // Set the PHY capabilities
2468 const bool support4096Qam = phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, 12);
2470 support4096Qam ? 1 : 0;
2472 support4096Qam ? 1 : 0;
2473
2474 const uint8_t maxTxNss = phy->GetMaxSupportedTxSpatialStreams();
2475 const uint8_t maxRxNss = phy->GetMaxSupportedRxSpatialStreams();
2476 if (auto htConfig = GetHtConfiguration(); !htConfig->m_40MHzSupported)
2477 {
2478 for (auto maxMcs : {7, 9, 11, 13})
2479 {
2480 capabilities.SetSupportedRxEhtMcsAndNss(
2482 maxMcs,
2483 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2484 capabilities.SetSupportedTxEhtMcsAndNss(
2486 maxMcs,
2487 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2488 }
2489 }
2490 else
2491 {
2492 for (auto maxMcs : {9, 11, 13})
2493 {
2494 capabilities.SetSupportedRxEhtMcsAndNss(
2496 maxMcs,
2497 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2498 capabilities.SetSupportedTxEhtMcsAndNss(
2500 maxMcs,
2501 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2502 }
2503 }
2504 if (auto vhtConfig = GetVhtConfiguration(); vhtConfig->m_160MHzSupported)
2505 {
2506 for (auto maxMcs : {9, 11, 13})
2507 {
2508 capabilities.SetSupportedRxEhtMcsAndNss(
2510 maxMcs,
2511 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2512 capabilities.SetSupportedTxEhtMcsAndNss(
2514 maxMcs,
2515 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2516 }
2517 }
2518 // 320 MHz not supported yet
2519
2520 return capabilities;
2521}
2522
2525{
2526 uint32_t maxSize = 0;
2527 switch (ac)
2528 {
2529 case AC_BE:
2530 maxSize = m_beMaxAmpduSize;
2531 break;
2532 case AC_BK:
2533 maxSize = m_bkMaxAmpduSize;
2534 break;
2535 case AC_VI:
2536 maxSize = m_viMaxAmpduSize;
2537 break;
2538 case AC_VO:
2539 maxSize = m_voMaxAmpduSize;
2540 break;
2541 default:
2542 NS_ABORT_MSG("Unknown AC " << ac);
2543 return 0;
2544 }
2545 return maxSize;
2546}
2547
2548uint16_t
2550{
2551 uint16_t maxSize = 0;
2552 switch (ac)
2553 {
2554 case AC_BE:
2555 maxSize = m_beMaxAmsduSize;
2556 break;
2557 case AC_BK:
2558 maxSize = m_bkMaxAmsduSize;
2559 break;
2560 case AC_VI:
2561 maxSize = m_viMaxAmsduSize;
2562 break;
2563 case AC_VO:
2564 maxSize = m_voMaxAmsduSize;
2565 break;
2566 default:
2567 NS_ABORT_MSG("Unknown AC " << ac);
2568 return 0;
2569 }
2570 return maxSize;
2571}
2572
2573void
2575{
2576 NS_LOG_FUNCTION(this << enable);
2578}
2579
2580bool
2582{
2584 "Robust AV Streaming requires STA to be HT-capable");
2586}
2587
2588} // 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.
uint8_t m_robustAvStreaming
Robust AV Streaming.
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.
an EUI-48 address
static Mac48Address ConvertFrom(const Address &address)
A base class which provides memory management and object aggregation.
Definition object.h:78
void Initialize()
Invoke DoInitialize on all Objects aggregated to this one.
Definition object.cc:203
void Dispose()
Dispose of this Object.
Definition object.cc:247
bool IsInitialized() const
Check if the object has been initialized.
Definition object.cc:240
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
Ptr< BlockAckManager > GetBaManager()
Get the Block Ack Manager associated with this QosTxop.
Definition qos-txop.cc:285
void SetBlockAckThreshold(uint8_t threshold)
Set threshold for block ack mechanism.
Definition qos-txop.cc:768
void SetBlockAckInactivityTimeout(uint16_t timeout)
Set the BlockAck inactivity timeout.
Definition qos-txop.cc:776
bool HasFramesToTransmit(uint8_t linkId) override
Check if the Txop has frames to transmit over the given link.
Definition qos-txop.cc:336
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:594
indicates whether the socket has a priority set.
Definition socket.h:1307
uint8_t GetPriority() const
Get the tag's priority.
Definition socket.cc:849
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
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:705
virtual bool HasFramesToTransmit(uint8_t linkId)
Check if the Txop has frames to transmit over the given link.
Definition txop.cc:626
virtual void SetWifiMac(const Ptr< WifiMac > mac)
Set the wifi MAC this Txop is associated to.
Definition txop.cc:242
void SwapLinks(std::map< uint8_t, uint8_t > links)
Swap the links based on the information included in the given map.
Definition txop.cc:218
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set MacTxMiddle this Txop is associated to.
Definition txop.cc:235
virtual void SetDroppedMpduCallback(DroppedMpdu callback)
Definition txop.cc:253
static constexpr bool CHECK_MEDIUM_BUSY
generation of backoff (also) depends on the busy/idle state of the medium
Definition txop.h:411
a unique identifier for an interface.
Definition type-id.h:49
@ ATTR_GET
The attribute can be read.
Definition type-id.h:54
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
Definition type-id.h:56
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
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.
Implements the IEEE 802.11 MAC header.
void SetQosAckPolicy(QosAckPolicy policy)
Set the QoS Ack policy in the QoS control field.
void SetNoOrder()
Unset order bit in the frame control field.
void SetQosNoAmsdu()
Set that A-MSDU is not present.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetQosNoEosp()
Un-set the end of service period (EOSP) bit in the QoS control field.
virtual void DoCompleteConfig()=0
Allow subclasses to complete the configuration of the MAC layer components.
RecipientAgreementOptConstRef GetBaAgreementEstablishedAsRecipient(Mac48Address originator, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr=std::nullopt) const
Definition wifi-mac.cc:1922
uint16_t GetMaxAmsduSize(AcIndex ac) const
Return the maximum A-MSDU size of the given Access Category.
Definition wifi-mac.cc:2549
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:1014
Ptr< QosTxop > GetBEQueue() const
Accessor for the AC_BE channel access function.
Definition wifi-mac.cc:652
virtual void NotifyChannelSwitching(uint8_t linkId)
Notify that channel on the given link has been switched.
Definition wifi-mac.cc:701
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition wifi-mac.cc:1858
virtual void SetMacQueueScheduler(Ptr< WifiMacQueueScheduler > scheduler)
Set the wifi MAC queue scheduler.
Definition wifi-mac.cc:688
Mac48Address GetBssid(uint8_t linkId) const
Definition wifi-mac.cc:547
uint16_t m_viMaxAmsduSize
maximum A-MSDU size for AC_VI (in bytes)
Definition wifi-mac.h:1235
bool m_shortSlotTimeSupported
flag whether short slot time is supported
Definition wifi-mac.h:1213
void ConfigurePhyDependentParameters(uint8_t linkId)
Configure PHY dependent parameters such as CWmin and CWmax on the given link.
Definition wifi-mac.cc:938
Ptr< HeConfiguration > GetHeConfiguration() const
Definition wifi-mac.cc:1980
DroppedMpduTracedCallback m_droppedMpduCallback
This trace indicates that an MPDU was dropped for the given reason.
Definition wifi-mac.h:1310
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition wifi-mac.cc:491
uint32_t GetFrameRetryLimit() const
Definition wifi-mac.cc:2108
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:1211
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:608
const std::map< uint8_t, std::unique_ptr< LinkEntity > > & GetLinks() const
Definition wifi-mac.cc:1091
Ptr< Txop > GetTxop() const
Accessor for the Txop object.
Definition wifi-mac.cc:572
VhtCapabilities GetVhtCapabilities(uint8_t linkId) const
Return the VHT capabilities of the device for the given link.
Definition wifi-mac.cc:2261
Callback< void > m_linkDown
Callback when a link is down.
Definition wifi-mac.h:974
bool GetQosSupported() const
Return whether the device supports QoS.
Definition wifi-mac.cc:1409
virtual void SetAddress(Mac48Address address)
Definition wifi-mac.cc:514
void SetFrameExchangeManagers(const std::vector< Ptr< FrameExchangeManager > > &feManagers)
Definition wifi-mac.cc:972
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:956
Ptr< Txop > m_txop
TXOP used for transmission of frames to non-QoS peers.
Definition wifi-mac.h:970
void SetQosSupported(bool enable)
Enable or disable QoS support for the device.
Definition wifi-mac.cc:1401
Mac48Address m_address
MAC address of this station.
Definition wifi-mac.h:1222
std::set< uint8_t > m_linkIds
IDs of the links in use.
Definition wifi-mac.h:1220
Ptr< WifiMacQueueScheduler > GetMacQueueScheduler() const
Get the wifi MAC queue scheduler.
Definition wifi-mac.cc:695
uint16_t GetMpduBufferSize() const
Definition wifi-mac.cc:2095
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition wifi-mac.cc:1106
BlockAckType GetBaTypeAsRecipient(Mac48Address originator, uint8_t tid) const
Definition wifi-mac.cc:1950
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:1172
void Enqueue(Ptr< Packet > packet, Mac48Address to)
Definition wifi-mac.cc:1733
uint16_t m_voMaxAmsduSize
maximum A-MSDU size for AC_VO (in bytes)
Definition wifi-mac.h:1234
Ptr< MacRxMiddle > m_rxMiddle
RX middle (defragmentation etc.)
Definition wifi-mac.h:968
Ptr< WifiMacQueueScheduler > m_scheduler
wifi MAC queue scheduler
Definition wifi-mac.h:971
void DoInitialize() override
Initialize() implementation.
Definition wifi-mac.cc:418
TypeOfStation m_typeOfStation
the type of station
Definition wifi-mac.h:1216
uint16_t m_mpduBufferSize
BlockAck buffer size (in number of MPDUs)
Definition wifi-mac.h:1244
uint32_t m_beMaxAmpduSize
maximum A-MPDU size for AC_BE (in bytes)
Definition wifi-mac.h:1241
void SetChannelAccessManagers(const std::vector< Ptr< ChannelAccessManager > > &caManagers)
Definition wifi-mac.cc:1020
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:1319
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:1620
Ssid GetSsid() const
Definition wifi-mac.cc:534
void SetWifiRemoteStationManagers(const std::vector< Ptr< WifiRemoteStationManager > > &stationManagers)
Definition wifi-mac.cc:1055
void SetBeBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_BE.
Definition wifi-mac.cc:2134
bool GetErpSupported(uint8_t linkId) const
Return whether the device supports ERP on the given link.
Definition wifi-mac.cc:1415
void ResetWifiPhys()
Remove currently attached WifiPhy objects from this MAC.
Definition wifi-mac.cc:1383
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:1264
void SetErpSupported(bool enable, uint8_t linkId)
Enable or disable ERP support for the given link.
Definition wifi-mac.cc:1421
bool GetTxBlockedOnLink(AcIndex ac, const WifiContainerQueueId &queueId, uint8_t linkId, WifiQueueBlockedReason reason=WifiQueueBlockedReason::REASONS_COUNT) const
Check whether the transmission of the packets in the given container queue of the given Access Catego...
Definition wifi-mac.cc:1683
uint32_t m_voMaxAmpduSize
maximum A-MPDU size for AC_VO (in bytes)
Definition wifi-mac.h:1239
void ConfigureDcf(Ptr< Txop > dcf, uint32_t cwmin, uint32_t cwmax, std::list< bool > isDsss, AcIndex ac)
Definition wifi-mac.cc:798
Ptr< WifiNetDevice > m_device
Pointer to the device.
Definition wifi-mac.h:1218
bool GetRobustAVStreamingSupported() const
Return whether the device supports Robust AV Streaming.
Definition wifi-mac.cc:2581
void SetSsid(Ssid ssid)
Definition wifi-mac.cc:527
virtual void NotifyDropPacketToEnqueue(Ptr< Packet > packet, Mac48Address to)
Allow subclasses to take actions when a packet to enqueue has been dropped.
Definition wifi-mac.cc:1803
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:1118
IcfDropTracedCallback m_icfDropCallback
traced callback for ICF drop events
Definition wifi-mac.h:1394
Ptr< QosTxop > GetVOQueue() const
Accessor for the AC_VO channel access function.
Definition wifi-mac.cc:640
void SetTypeOfStation(TypeOfStation type)
This method is invoked by a subclass to specify what type of station it is implementing.
Definition wifi-mac.cc:484
MpduTracedCallback m_ackedMpduCallback
ack'ed MPDU callback
Definition wifi-mac.h:1315
void NotifyRsmOfExpiredMpdu(Ptr< const WifiMpdu > mpdu)
Notify the remote station manager if the given expired (hence dropped) MPDU is a management or data f...
Definition wifi-mac.cc:1702
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition wifi-mac.cc:1377
void SetMpduBufferSize(uint16_t size)
Definition wifi-mac.cc:2086
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:1574
MpduTracedCallback m_nackedMpduCallback
nack'ed MPDU callback
Definition wifi-mac.h:1316
bool GetEhtSupported() const
Return whether the device supports EHT.
Definition wifi-mac.cc:2013
void SetTxop(Ptr< Txop > dcf)
Set the Txop object.
Definition wifi-mac.cc:562
bool GetHeSupported() const
Return whether the device supports HE.
Definition wifi-mac.cc:2007
HtCapabilities GetHtCapabilities(uint8_t linkId) const
Return the HT capabilities of the device for the given link.
Definition wifi-mac.cc:2202
void SetBkBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_BK.
Definition wifi-mac.cc:2144
void SetVoBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_VO.
Definition wifi-mac.cc:2114
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:1138
std::optional< std::reference_wrapper< const RecipientBlockAckAgreement > > RecipientAgreementOptConstRef
optional const reference to RecipientBlockAckAgreement
Definition wifi-mac.h:684
void NotifyPromiscRx(Ptr< const Packet > packet)
Definition wifi-mac.cc:732
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:1252
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:578
virtual bool HasFramesToTransmit(uint8_t linkId)
Check if the MAC has frames to transmit over the given link.
Definition wifi-mac.cc:671
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > stationManager)
Definition wifi-mac.cc:1048
UniformRandomBitGenerator m_shuffleLinkIdsGen
random number generator to shuffle link IDs
Definition wifi-mac.h:1247
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:1492
void CompleteConfig()
Complete the configuration of the MAC layer components.
Definition wifi-mac.cc:887
void SetBeBlockAckInactivityTimeout(uint16_t timeout)
Set BE block ack inactivity timeout.
Definition wifi-mac.cc:2174
Ptr< EhtConfiguration > GetEhtConfiguration() const
Definition wifi-mac.cc:1986
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:1287
bool GetVhtSupported(uint8_t linkId) const
Return whether the device supports VHT on the given link.
Definition wifi-mac.cc:1999
void SetDsssSupported(bool enable, uint8_t linkId)
Enable or disable DSSS support for the given link.
Definition wifi-mac.cc:1432
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:1271
Ptr< MacTxMiddle > m_txMiddle
TX middle (aggregation etc.)
Definition wifi-mac.h:969
void NotifyTx(Ptr< const Packet > packet)
Definition wifi-mac.cc:714
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:389
static TypeId GetTypeId()
Get the type ID.
Definition wifi-mac.cc:63
Ptr< HtConfiguration > GetHtConfiguration() const
Definition wifi-mac.cc:1968
void SetFrameRetryLimit(uint32_t limit)
Set the frame retry limit.
Definition wifi-mac.cc:2101
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:1303
uint32_t GetMaxAmpduSize(AcIndex ac) const
Return the maximum A-MPDU size of the given Access Category.
Definition wifi-mac.cc:2524
BlockAckReqType GetBarTypeAsRecipient(Mac48Address originator, uint8_t tid) const
Definition wifi-mac.cc:1959
Ssid m_ssid
Service Set ID (SSID)
Definition wifi-mac.h:1223
std::map< uint8_t, std::unique_ptr< LinkEntity > > m_links
ID-indexed map of Link objects.
Definition wifi-mac.h:1219
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:1846
Ptr< QosTxop > GetVIQueue() const
Accessor for the AC_VI channel access function.
Definition wifi-mac.cc:646
void SetBssid(Mac48Address bssid, uint8_t linkId)
Definition wifi-mac.cc:540
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition wifi-mac.cc:508
void NotifyRx(Ptr< const Packet > packet)
Definition wifi-mac.cc:726
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:1294
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:1269
BlockAckType GetBaTypeAsOriginator(const Mac48Address &recipient, uint8_t tid) const
Definition wifi-mac.cc:1932
MpduResponseTimeoutTracedCallback m_mpduResponseTimeoutCallback
MPDU response timeout traced callback.
Definition wifi-mac.h:1337
void SetForwardUpCallback(ForwardUpCallback upCallback)
Definition wifi-mac.cc:1471
PsduMapResponseTimeoutTracedCallback m_psduMapResponseTimeoutCallback
PSDU map response timeout traced callback.
Definition wifi-mac.h:1381
OriginatorAgreementOptConstRef GetBaAgreementEstablishedAsOriginator(Mac48Address recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr=std::nullopt) const
Definition wifi-mac.cc:1905
ExtendedCapabilities GetExtendedCapabilities() const
Return the extended capabilities of the device.
Definition wifi-mac.cc:2194
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:1279
uint16_t m_bkMaxAmsduSize
maximum A-MSDU size for AC_BK (in bytes)
Definition wifi-mac.h:1237
void SetBkBlockAckInactivityTimeout(uint16_t timeout)
Set BK block ack inactivity timeout.
Definition wifi-mac.cc:2184
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:1254
virtual bool SupportsSendFrom() const
Definition wifi-mac.cc:1465
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:2397
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:2071
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:664
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:1151
void SetViBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_VI.
Definition wifi-mac.cc:2124
void SetViBlockAckInactivityTimeout(uint16_t timeout)
Set VI block ack inactivity timeout.
Definition wifi-mac.cc:2164
bool GetShortSlotTimeSupported() const
Definition wifi-mac.cc:1459
BlockAckReqType GetBarTypeAsOriginator(const Mac48Address &recipient, uint8_t tid) const
Definition wifi-mac.cc:1941
void NotifyConstructionCompleted() override
Notifier called once the ObjectBase is fully constructed.
Definition wifi-mac.cc:401
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:755
void SetLinkDownCallback(Callback< void > linkDown)
Definition wifi-mac.cc:1485
bool m_robustAVStreamingSupported
flag whether robust AV streaming is supported
Definition wifi-mac.h:1249
Ptr< QosTxop > GetBKQueue() const
Accessor for the AC_BK channel access function.
Definition wifi-mac.cc:658
~WifiMac() override
Definition wifi-mac.cc:57
void SetPromisc()
Sets the interface in promiscuous mode.
Definition wifi-mac.cc:553
Ptr< VhtConfiguration > GetVhtConfiguration() const
Definition wifi-mac.cc:1974
void NotifyRxDrop(Ptr< const Packet > packet)
Definition wifi-mac.cc:738
virtual void SetLinkUpCallback(Callback< void > linkUp)
Definition wifi-mac.cc:1478
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition wifi-mac.cc:1079
const std::set< uint8_t > & GetLinkIds() const
Definition wifi-mac.cc:1112
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition wifi-mac.cc:497
void SetCtsToSelfSupported(bool enable)
Enable or disable CTS-to-self feature.
Definition wifi-mac.cc:1445
Mac48Address GetLocalAddress(const Mac48Address &remoteAddr) const
Get the local MAC address used to communicate with a remote STA.
Definition wifi-mac.cc:1871
EdcaQueues m_edca
This is a map from Access Category index to the corresponding channel access function.
Definition wifi-mac.h:1232
uint32_t m_bkMaxAmpduSize
maximum A-MPDU size for AC_BK (in bytes)
Definition wifi-mac.h:1242
bool GetHtSupported(uint8_t linkId) const
Return whether the device supports HT on the given link.
Definition wifi-mac.cc:1992
void ForwardUp(Ptr< const Packet > packet, Mac48Address from, Mac48Address to)
Forward the packet up to the device.
Definition wifi-mac.cc:1809
virtual void ConfigureContentionWindow(uint32_t cwMin, uint32_t cwMax)
Definition wifi-mac.cc:775
bool Is6GhzBand(uint8_t linkId) const
Indicate if a given link is on the 6 GHz band.
Definition wifi-mac.cc:1261
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:1816
std::optional< std::reference_wrapper< const OriginatorBlockAckAgreement > > OriginatorAgreementOptConstRef
optional const reference to OriginatorBlockAckAgreement
Definition wifi-mac.h:681
Mac48Address GetAddress() const
Definition wifi-mac.cc:521
ForwardUpCallback m_forwardUp
Callback to forward packet up the stack.
Definition wifi-mac.h:1256
EhtCapabilities GetEhtCapabilities(uint8_t linkId) const
Return the EHT capabilities of the device for the given link.
Definition wifi-mac.cc:2432
Callback< void > m_linkUp
Callback when a link is up.
Definition wifi-mac.h:973
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition wifi-mac.cc:1097
void SetupDcfQueue()
This method is a private utility invoked to configure the channel access function for devices that do...
Definition wifi-mac.cc:744
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:598
HeCapabilities GetHeCapabilities(uint8_t linkId) const
Return the HE capabilities of the device for the given link.
Definition wifi-mac.cc:2341
virtual bool CanForwardPacketsTo(Mac48Address to) const =0
Return true if packets can be forwarded to the given destination, false otherwise.
virtual void SetWifiPhys(const std::vector< Ptr< WifiPhy > > &phys)
Definition wifi-mac.cc:1355
PsduResponseTimeoutTracedCallback m_psduResponseTimeoutCallback
PSDU response timeout traced callback.
Definition wifi-mac.h:1358
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition wifi-mac.cc:618
void NotifyTxDrop(Ptr< const Packet > packet)
Definition wifi-mac.cc:720
void DoDispose() override
Destructor implementation.
Definition wifi-mac.cc:442
void SetRobustAVStreamingSupported(bool enable)
Enable or disable Robust AV Streaming support for the device.
Definition wifi-mac.cc:2574
uint32_t m_frameRetryLimit
the frame retry limit
Definition wifi-mac.h:1245
bool GetDsssSupported(uint8_t linkId) const
Return whether the device supports DSSS on the given link.
Definition wifi-mac.cc:1439
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:1042
void SetVoBlockAckInactivityTimeout(uint16_t timeout)
Set VO block ack inactivity timeout.
Definition wifi-mac.cc:2154
virtual std::unique_ptr< LinkEntity > CreateLinkEntity() const
Create a LinkEntity object.
Definition wifi-mac.cc:1085
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:588
void SetShortSlotTimeSupported(bool enable)
Enable or disable short slot time feature.
Definition wifi-mac.cc:1452
bool m_ctsToSelfSupported
flag indicating whether CTS-To-Self is supported
Definition wifi-mac.h:1214
uint16_t m_beMaxAmsduSize
maximum A-MSDU size for AC_BE (in bytes)
Definition wifi-mac.h:1236
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:1899
uint32_t m_viMaxAmpduSize
maximum A-MPDU size for AC_VI (in bytes)
Definition wifi-mac.h:1240
WifiStandard GetStandard() const
Get the configured Wi-Fi standard.
Definition wifi-phy.cc:1075
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#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:75
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_UNLESS(cond)
Abnormal program termination if a condition is false.
Definition abort.h:118
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1368
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1380
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:58
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:123
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:62
@ WIFI_STANDARD_80211g
@ WIFI_STANDARD_80211b
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ 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:72
@ AC_BE
Best Effort.
Definition qos-utils.h:64
@ AC_VO
Voice.
Definition qos-utils.h:70
@ AC_VI
Video.
Definition qos-utils.h:68
@ AC_BK
Background.
Definition qos-utils.h:66
@ AC_UNDEF
Total number of ACs.
Definition qos-utils.h:76
@ AC_BEACON
Beacon queue.
Definition qos-utils.h:74
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeChecker > MakeSsidChecker()
Definition ssid.cc:102
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:443
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
std:: tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
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:684
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeAccessor > MakeSsidAccessor(T1 a1)
Definition ssid.h:85
Ptr< const AttributeChecker > MakeObjectVectorChecker()
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
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:67
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:48
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:115
@ WIFI_MAC_DATA
@ WIFI_MAC_QOSDATA
WifiDirection
Wifi direction.
Definition wifi-utils.h:36
@ LOG_FUNCTION
Function tracing for non-trivial function calls.
Definition log.h:95
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition boolean.h:70
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