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 sent by the given sender is dropped by an EMLSR client for "
380 "the given reason on the link with the given ID. This trace source "
381 "is actually fed by the EHT Frame Exchange Manager through the "
382 "m_icfDropCallback member 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 {
424 m_txop->Initialize();
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 auto txop = GetTxopFor(ac);
667 return (txop ? txop->GetWifiMacQueue() : nullptr);
668}
669
672{
673 if (auto txop = (ac == AC_BE_NQOS ? m_txop : StaticCast<Txop>(GetQosTxop(ac))))
674 {
675 return txop;
676 }
677 return nullptr;
678}
679
680bool
682{
683 if (m_txop && m_txop->HasFramesToTransmit(linkId))
684 {
685 return true;
686 }
687 for (const auto& [aci, qosTxop] : m_edca)
688 {
689 if (qosTxop->HasFramesToTransmit(linkId))
690 {
691 return true;
692 }
693 }
694 return false;
695}
696
697void
699{
700 m_scheduler = scheduler;
701 m_scheduler->SetWifiMac(this);
702}
703
706{
707 return m_scheduler;
708}
709
710void
712{
713 NS_LOG_FUNCTION(this << +linkId);
714
715 // we may have changed PHY band, in which case it is necessary to re-configure
716 // the PHY dependent parameters. In any case, this makes no harm
718
719 // Reset remote station manager
720 GetLink(linkId).stationManager->Reset();
721}
722
723void
725{
726 m_macTxTrace(packet);
727}
728
729void
734
735void
737{
738 m_macRxTrace(packet);
739}
740
741void
746
747void
752
753void
755{
756}
757
758void
760{
761}
762
763void
765{
766 NS_LOG_FUNCTION(this);
768
769 m_txop->SetTxMiddle(m_txMiddle);
770 m_txop->SetDroppedMpduCallback(
771 MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
772}
773
774void
776{
777 NS_LOG_FUNCTION(this << ac);
778
779 auto edcaIt = m_edca.find(ac);
780 NS_ASSERT(edcaIt != m_edca.cend());
781
782 edcaIt->second->SetTxMiddle(m_txMiddle);
783 edcaIt->second->GetBaManager()->SetTxOkCallback(
784 MakeCallback(&MpduTracedCallback::operator(), &m_ackedMpduCallback));
785 edcaIt->second->GetBaManager()->SetTxFailedCallback(
786 MakeCallback(&MpduTracedCallback::operator(), &m_nackedMpduCallback));
787 edcaIt->second->SetDroppedMpduCallback(
788 MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
789 edcaIt->second->GetWifiMacQueue()->TraceConnectWithoutContext(
790 "Expired",
792}
793
794void
796{
797 std::list<bool> isDsssOnly;
798 for (const auto& [id, link] : m_links)
799 {
800 isDsssOnly.push_back(link->dsssSupported && !link->erpSupported);
801 }
802
803 if (m_txop)
804 {
805 // The special value of AC_BE_NQOS which exists in the Access
806 // Category enumeration allows us to configure plain old DCF.
807 ConfigureDcf(m_txop, cwMin, cwMax, isDsssOnly, AC_BE_NQOS);
808 }
809
810 // Now we configure the EDCA functions
811 for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
812 {
813 ConfigureDcf(it->second, cwMin, cwMax, isDsssOnly, it->first);
814 }
815}
816
817void
819 uint32_t cwmin,
820 uint32_t cwmax,
821 std::list<bool> isDsss,
822 AcIndex ac)
823{
824 NS_LOG_FUNCTION(this << dcf << cwmin << cwmax << +ac);
825
826 uint32_t cwMinValue = 0;
827 uint32_t cwMaxValue = 0;
828 uint8_t aifsnValue = 0;
829 Time txopLimitDsss(0);
830 Time txopLimitNoDsss(0);
831
832 /* see IEEE 802.11-2020 Table 9-155 "Default EDCA Parameter Set element parameter values" */
833 switch (ac)
834 {
835 case AC_VO:
836 cwMinValue = (cwmin + 1) / 4 - 1;
837 cwMaxValue = (cwmin + 1) / 2 - 1;
838 aifsnValue = 2;
839 txopLimitDsss = MicroSeconds(3264);
840 txopLimitNoDsss = MicroSeconds(2080);
841 break;
842 case AC_VI:
843 cwMinValue = (cwmin + 1) / 2 - 1;
844 cwMaxValue = cwmin;
845 aifsnValue = 2;
846 txopLimitDsss = MicroSeconds(6016);
847 txopLimitNoDsss = MicroSeconds(4096);
848 break;
849 case AC_BE:
850 cwMinValue = cwmin;
851 cwMaxValue = cwmax;
852 aifsnValue = 3;
853 txopLimitDsss = MicroSeconds(0); // TODO should be MicroSeconds (3264)
854 txopLimitNoDsss = MicroSeconds(0); // TODO should be MicroSeconds (2528)
855 break;
856 case AC_BK:
857 cwMinValue = cwmin;
858 cwMaxValue = cwmax;
859 aifsnValue = 7;
860 txopLimitDsss = MicroSeconds(0); // TODO should be MicroSeconds (3264)
861 txopLimitNoDsss = MicroSeconds(0); // TODO should be MicroSeconds (2528)
862 break;
863 case AC_BE_NQOS:
864 cwMinValue = cwmin;
865 cwMaxValue = cwmax;
866 aifsnValue = 2;
867 txopLimitDsss = txopLimitNoDsss = MicroSeconds(0);
868 break;
869 case AC_BEACON:
870 // done by ApWifiMac
871 break;
872 case AC_UNDEF:
873 NS_FATAL_ERROR("I don't know what to do with this");
874 break;
875 }
876
877 const auto& userDefinedParams = dcf->GetUserAccessParams();
878
879 dcf->SetMinCws(!userDefinedParams.cwMins.empty()
880 ? userDefinedParams.cwMins
881 : std::vector<uint32_t>(m_links.size(), cwMinValue));
882 dcf->SetMaxCws(!userDefinedParams.cwMaxs.empty()
883 ? userDefinedParams.cwMaxs
884 : std::vector<uint32_t>(m_links.size(), cwMaxValue));
885 dcf->SetAifsns(!userDefinedParams.aifsns.empty()
886 ? userDefinedParams.aifsns
887 : std::vector<uint8_t>(m_links.size(), aifsnValue));
888
889 if (!userDefinedParams.txopLimits.empty())
890 {
891 dcf->SetTxopLimits(userDefinedParams.txopLimits);
892 }
893 else
894 {
895 std::vector<Time> txopLimitValues(m_links.size());
896 std::transform(isDsss.begin(),
897 isDsss.end(),
898 txopLimitValues.begin(),
899 [&txopLimitDsss, &txopLimitNoDsss](bool dsss) {
900 return (dsss ? txopLimitDsss : txopLimitNoDsss);
901 });
902 dcf->SetTxopLimits(txopLimitValues);
903 }
904}
905
906void
908{
909 NS_ASSERT_MSG(!m_links.empty(), "CompleteConfig cannot be called before creating links");
910
911 const auto& link = *m_links.cbegin()->second;
912
913 if (!link.phy || !link.stationManager || !link.channelAccessManager || !link.feManager)
914 {
915 return;
916 }
917
918 NS_LOG_FUNCTION(this);
919
920 for (auto& [id, link] : m_links)
921 {
923 !link->phy || !link->phy->GetOperatingChannel().IsSet(),
924 "[LinkID " << +id
925 << "] PHY must have been set and an operating channel must have been set");
926
927 NS_ABORT_MSG_IF(!link->channelAccessManager,
928 "[LinkID " << +id << "] A channel access manager must have been set");
929
930 NS_ABORT_MSG_IF(!link->feManager,
931 "[LinkID " << +id << "] A frame exchange manager must have been set");
932
933 link->channelAccessManager->SetupPhyListener(link->phy);
934 link->channelAccessManager->SetupFrameExchangeManager(link->feManager);
935
936 link->feManager->SetWifiPhy(link->phy);
937 link->feManager->SetMacTxMiddle(m_txMiddle);
938 link->feManager->SetMacRxMiddle(m_rxMiddle);
939
940 if (m_txop)
941 {
942 m_txop->SetWifiMac(this);
943 link->channelAccessManager->Add(m_txop);
944 }
945 for (auto it = m_edca.begin(); it != m_edca.end(); ++it)
946 {
947 it->second->SetWifiMac(this);
948 link->channelAccessManager->Add(it->second);
949 }
950
952 }
953
955}
956
957void
959{
960 NS_LOG_FUNCTION(this << +linkId);
961
962 WifiStandard standard = GetLink(linkId).phy->GetStandard();
963
964 uint32_t cwmin = (standard == WIFI_STANDARD_80211b ? 31 : 15);
965 uint32_t cwmax = 1023;
966
967 SetDsssSupported(standard == WIFI_STANDARD_80211b, linkId);
969 m_links[linkId]->phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ,
970 linkId);
971
972 ConfigureContentionWindow(cwmin, cwmax);
973}
974
975bool
977{
978 if (!m_links.empty())
979 {
980 return false;
981 }
982
983 for (std::size_t i = 0; i < nLinks; i++)
984 {
985 m_links.emplace(i, CreateLinkEntity());
986 m_linkIds.insert(i);
987 }
988 return true;
989}
990
991void
993{
994 NS_LOG_FUNCTION(this);
995
996 if (!CreateLinksIfNeeded(feManagers.size()))
997 {
998 NS_ABORT_MSG_IF(feManagers.size() != m_links.size(),
999 "The number of provided Frame Exchange Manager objects ("
1000 << feManagers.size() << ") must match the number of existing links ("
1001 << m_links.size() << ")");
1002 }
1003
1004 for (auto managerIt = feManagers.cbegin(); auto& [id, link] : m_links)
1005 {
1006 link->feManager = *managerIt++;
1007 link->feManager->SetWifiMac(this);
1008 link->feManager->SetLinkId(id);
1009 // connect callbacks
1010 link->feManager->GetWifiTxTimer().SetMpduResponseTimeoutCallback(
1011 MakeCallback(&MpduResponseTimeoutTracedCallback::operator(),
1013 link->feManager->GetWifiTxTimer().SetPsduResponseTimeoutCallback(
1014 MakeCallback(&PsduResponseTimeoutTracedCallback::operator(),
1016 link->feManager->GetWifiTxTimer().SetPsduMapResponseTimeoutCallback(
1017 MakeCallback(&PsduMapResponseTimeoutTracedCallback::operator(),
1019 link->feManager->SetDroppedMpduCallback(
1020 MakeCallback(&DroppedMpduTracedCallback::operator(), &m_droppedMpduCallback));
1021 link->feManager->SetAckedMpduCallback(
1022 MakeCallback(&MpduTracedCallback::operator(), &m_ackedMpduCallback));
1023 if (auto ehtFem = DynamicCast<EhtFrameExchangeManager>(link->feManager))
1024 {
1025 ehtFem->m_icfDropCallback.ConnectWithoutContext(
1026 MakeCallback(&IcfDropTracedCallback::operator(), &m_icfDropCallback));
1027 }
1028 }
1029
1031}
1032
1033Ptr<FrameExchangeManager>
1035{
1036 return GetLink(linkId).feManager;
1037}
1038
1039void
1041{
1042 NS_LOG_FUNCTION(this);
1043
1044 if (!CreateLinksIfNeeded(caManagers.size()))
1045 {
1046 NS_ABORT_MSG_IF(caManagers.size() != m_links.size(),
1047 "The number of provided Channel Access Manager objects ("
1048 << caManagers.size() << ") must match the number of existing links ("
1049 << m_links.size() << ")");
1050 }
1051
1052 for (auto managerIt = caManagers.cbegin(); auto& [id, link] : m_links)
1053 {
1054 link->channelAccessManager = *managerIt++;
1055 link->channelAccessManager->SetLinkId(id);
1056 }
1057
1059}
1060
1063{
1064 return GetLink(linkId).channelAccessManager;
1065}
1066
1067void
1069{
1070 NS_LOG_FUNCTION(this << stationManager);
1071 SetWifiRemoteStationManagers({stationManager});
1072}
1073
1074void
1076 const std::vector<Ptr<WifiRemoteStationManager>>& stationManagers)
1077{
1078 NS_LOG_FUNCTION(this);
1079
1080 if (!CreateLinksIfNeeded(stationManagers.size()))
1081 {
1082 NS_ABORT_MSG_IF(stationManagers.size() != m_links.size(),
1083 "The number of provided Remote Manager objects ("
1084 << stationManagers.size()
1085 << ") must match the number of existing links (" << m_links.size()
1086 << ")");
1087 }
1088
1089 for (auto managerIt = stationManagers.cbegin(); auto& [id, link] : m_links)
1090 {
1091 link->stationManager = *managerIt++;
1092 link->stationManager->SetLinkId(id);
1093 }
1094
1096}
1097
1100{
1101 return GetLink(linkId).stationManager;
1102}
1103
1104std::unique_ptr<WifiMac::LinkEntity>
1106{
1107 return std::make_unique<LinkEntity>();
1108}
1109
1110const std::map<uint8_t, std::unique_ptr<WifiMac::LinkEntity>>&
1112{
1113 return m_links;
1114}
1115
1117WifiMac::GetLink(uint8_t linkId) const
1118{
1119 auto it = m_links.find(linkId);
1120 NS_ASSERT(it != m_links.cend());
1121 NS_ASSERT(it->second); // check that the pointer owns an object
1122 return *it->second;
1123}
1124
1125uint8_t
1127{
1128 return m_links.size();
1129}
1130
1131const std::set<uint8_t>&
1133{
1134 return m_linkIds;
1135}
1136
1137void
1139{
1140 NS_LOG_FUNCTION(this << id);
1141
1142 auto& link = GetLink(id);
1143 if (link.feManager)
1144 {
1145 link.feManager->SetLinkId(id);
1146 }
1147 if (link.channelAccessManager)
1148 {
1149 link.channelAccessManager->SetLinkId(id);
1150 }
1151 if (link.stationManager)
1152 {
1153 link.stationManager->SetLinkId(id);
1154 }
1155}
1156
1157std::optional<uint8_t>
1159{
1160 for (const auto& [id, link] : m_links)
1161 {
1162 if (link->feManager->GetAddress() == address)
1163 {
1164 return id;
1165 }
1166 }
1167 return std::nullopt;
1168}
1169
1170std::optional<uint8_t>
1172{
1173 for (const auto& [id, link] : m_links)
1174 {
1175 if (link->phy == phy)
1176 {
1177 return id;
1178 }
1179 }
1180 return std::nullopt;
1181}
1182
1183std::optional<uint8_t>
1184WifiMac::GetLinkForPhy(std::size_t phyId) const
1185{
1186 NS_ABORT_UNLESS(phyId < m_device->GetNPhys());
1187 auto phy = m_device->GetPhy(phyId);
1188 return GetLinkForPhy(phy);
1189}
1190
1191void
1192WifiMac::SwapLinks(std::map<uint8_t, uint8_t> links)
1193{
1194 NS_LOG_FUNCTION(this);
1195
1196 // save the initial mapping between link IDs and link Entities
1197 std::map<uint8_t, std::reference_wrapper<const LinkEntity>> origLinkRefMap;
1198 for (const auto& [id, link] : m_links)
1199 {
1200 origLinkRefMap.insert_or_assign(id, *link.get());
1201 }
1202
1203 while (!links.empty())
1204 {
1205 auto from = links.cbegin()->first;
1206 auto to = links.cbegin()->second;
1207
1208 if (from == to)
1209 {
1210 // nothing to do
1211 links.erase(links.cbegin());
1212 continue;
1213 }
1214
1215 std::unique_ptr<LinkEntity> linkToMove;
1216 NS_ASSERT(m_links.contains(from));
1217 linkToMove.swap(m_links.at(from)); // from is now out of m_links
1218 auto empty = from; // track empty cell in m_links
1219
1220 do
1221 {
1222 auto [it, inserted] =
1223 m_links.emplace(to, nullptr); // insert an element with key to if not present
1224 m_links[to].swap(linkToMove); // to is the link to move now
1225 links.erase(from);
1226 if (!linkToMove)
1227 {
1228 if (inserted)
1229 {
1230 m_links.erase(empty);
1231 }
1232 break;
1233 }
1234
1235 auto nextTo = links.find(to);
1236 if (nextTo == links.cend())
1237 {
1238 // no new position specified for 'to', use the current empty cell
1239 m_links[empty].swap(linkToMove);
1240 break;
1241 }
1242
1243 from = to;
1244 to = nextTo->second;
1245 } while (true);
1246 }
1247
1248 m_linkIds.clear();
1249 for (const auto& [id, link] : m_links)
1250 {
1251 m_linkIds.insert(id);
1252 }
1253
1254 std::map<uint8_t, uint8_t> actualPairs;
1255 for (const auto& [from, ref] : origLinkRefMap)
1256 {
1257 // find the pointer in the current link map
1258 for (const auto& [to, link] : m_links)
1259 {
1260 if (link.get() == &ref.get())
1261 {
1262 actualPairs[from] = to; // link 'from' became link 'to'
1263 UpdateLinkId(to);
1264 break;
1265 }
1266 }
1267 }
1268 NS_ASSERT_MSG(actualPairs.size() == m_links.size(), "Missing some link(s)");
1269
1270 if (m_txop)
1271 {
1272 m_txop->SwapLinks(actualPairs);
1273 }
1274 for (auto& [ac, edca] : m_edca)
1275 {
1276 edca->SwapLinks(actualPairs);
1277 }
1278}
1279
1280bool
1281WifiMac::Is6GhzBand(uint8_t linkId) const
1282{
1283 auto phy = GetLink(linkId).phy;
1284 NS_ASSERT(phy);
1285 return phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ;
1286}
1287
1288void
1291 const WifiTidLinkMapping& mapping)
1292{
1293 NS_LOG_FUNCTION(this << mldAddr);
1294
1296 "DL and UL directions for TID-to-Link mapping must be set separately");
1297
1299
1300 auto [it, inserted] = mappings.emplace(mldAddr, mapping);
1301
1302 if (inserted)
1303 {
1304 // we are done
1305 return;
1306 }
1307
1308 // a previous mapping is stored for this MLD
1309 if (mapping.empty())
1310 {
1311 // the default mapping has been now negotiated
1312 it->second.clear();
1313 return;
1314 }
1315
1316 for (const auto& [tid, linkSet] : mapping)
1317 {
1318 it->second[tid] = linkSet;
1319 }
1320}
1321
1322std::optional<std::reference_wrapper<const WifiTidLinkMapping>>
1324{
1326 "Cannot request TID-to-Link mapping for both directions");
1327
1328 const auto& mappings =
1330
1331 if (const auto it = mappings.find(mldAddr); it != mappings.cend())
1332 {
1333 return it->second;
1334 }
1335 return std::nullopt;
1336}
1337
1338bool
1339WifiMac::TidMappedOnLink(Mac48Address mldAddr, WifiDirection dir, uint8_t tid, uint8_t linkId) const
1340{
1342 "Cannot request TID-to-Link mapping for both directions");
1343
1344 if (!GetWifiRemoteStationManager(linkId)->GetMldAddress(mldAddr).has_value())
1345 {
1346 // the link has not been setup
1347 return false;
1348 }
1349
1350 const auto& mappings =
1352
1353 const auto it = mappings.find(mldAddr);
1354
1355 if (it == mappings.cend())
1356 {
1357 // TID-to-link mapping was not negotiated, TIDs are mapped to all setup links
1358 return true;
1359 }
1360
1361 auto linkSetIt = it->second.find(tid);
1362
1363 if (linkSetIt == it->second.cend())
1364 {
1365 // If there is no successfully negotiated TID-to-link mapping for a TID, then the TID
1366 // is mapped to all setup links for DL and UL (Sec. 35.3.7.1.3 of 802.11be D3.1)
1367 return true;
1368 }
1369
1370 return std::find(linkSetIt->second.cbegin(), linkSetIt->second.cend(), linkId) !=
1371 linkSetIt->second.cend();
1372}
1373
1374void
1375WifiMac::SetWifiPhys(const std::vector<Ptr<WifiPhy>>& phys)
1376{
1377 NS_LOG_FUNCTION(this);
1378 ResetWifiPhys();
1379
1380 if (!CreateLinksIfNeeded(phys.size()))
1381 {
1382 NS_ABORT_MSG_IF(phys.size() != m_links.size(),
1383 "The number of provided PHY objects ("
1384 << phys.size() << ") must match the number of existing links ("
1385 << m_links.size() << ")");
1386 }
1387
1388 for (auto phyIt = phys.cbegin(); auto& [id, link] : m_links)
1389 {
1390 link->phy = *phyIt++;
1391 }
1392
1394}
1395
1397WifiMac::GetWifiPhy(uint8_t linkId) const
1398{
1399 return GetLink(linkId).phy;
1400}
1401
1402void
1404{
1405 NS_LOG_FUNCTION(this);
1406 for (auto& [id, link] : m_links)
1407 {
1408 if (link->feManager)
1409 {
1410 link->feManager->ResetPhy();
1411 }
1412 if (link->channelAccessManager)
1413 {
1414 link->channelAccessManager->RemovePhyListener(link->phy);
1415 }
1416 link->phy = nullptr;
1417 }
1418}
1419
1420void
1422{
1423 NS_LOG_FUNCTION(this << enable);
1425 m_qosSupported = enable;
1426}
1427
1428bool
1430{
1431 return m_qosSupported;
1432}
1433
1434bool
1435WifiMac::GetErpSupported(uint8_t linkId) const
1436{
1437 return GetLink(linkId).erpSupported;
1438}
1439
1440void
1441WifiMac::SetErpSupported(bool enable, uint8_t linkId)
1442{
1443 NS_LOG_FUNCTION(this << enable << +linkId);
1444 if (enable)
1445 {
1446 SetDsssSupported(true, linkId);
1447 }
1448 GetLink(linkId).erpSupported = enable;
1449}
1450
1451void
1452WifiMac::SetDsssSupported(bool enable, uint8_t linkId)
1453{
1454 NS_LOG_FUNCTION(this << enable << +linkId);
1455 GetLink(linkId).dsssSupported = enable;
1456}
1457
1458bool
1459WifiMac::GetDsssSupported(uint8_t linkId) const
1460{
1461 return GetLink(linkId).dsssSupported;
1462}
1463
1464void
1466{
1467 NS_LOG_FUNCTION(this);
1468 m_ctsToSelfSupported = enable;
1469}
1470
1471void
1473{
1474 NS_LOG_FUNCTION(this << enable);
1475 m_shortSlotTimeSupported = enable;
1476}
1477
1478bool
1483
1484bool
1486{
1487 return false;
1488}
1489
1490void
1492{
1493 NS_LOG_FUNCTION(this);
1494 m_forwardUp = upCallback;
1495}
1496
1497void
1499{
1500 NS_LOG_FUNCTION(this);
1501 m_linkUp = linkUp;
1502}
1503
1504void
1506{
1507 NS_LOG_FUNCTION(this);
1508 m_linkDown = linkDown;
1509}
1510
1511void
1513{
1514 NS_LOG_FUNCTION(this << mldAddr);
1515
1518 "This method can be used to enforce TID-to-Link mapping for one direction at a time");
1519
1520 const auto& mappings =
1522
1523 auto it = mappings.find(mldAddr);
1524
1525 if (it == mappings.cend())
1526 {
1527 // no mapping has been ever negotiated with the given MLD, the default mapping is used
1528 return;
1529 }
1530
1531 std::set<uint8_t> setupLinks;
1532
1533 // find the IDs of the links setup with the given MLD
1534 for (const auto& [id, link] : m_links)
1535 {
1536 if (link->stationManager->GetMldAddress(mldAddr))
1537 {
1538 setupLinks.insert(id);
1539 }
1540 }
1541
1542 auto linkMapping = it->second;
1543
1544 if (linkMapping.empty())
1545 {
1546 // default link mapping, each TID mapped on all setup links
1547 for (uint8_t tid = 0; tid < 8; tid++)
1548 {
1549 linkMapping.emplace(tid, setupLinks);
1550 }
1551 }
1552
1553 for (const auto& [tid, linkSet] : linkMapping)
1554 {
1555 decltype(setupLinks) mappedLinks; // empty
1556 auto notMappedLinks = setupLinks; // all setup links
1557
1558 for (const auto id : linkSet)
1559 {
1560 if (setupLinks.find(id) != setupLinks.cend())
1561 {
1562 // link is mapped
1563 mappedLinks.insert(id);
1564 notMappedLinks.erase(id);
1565 }
1566 }
1567
1568 // unblock mapped links
1569 NS_ABORT_MSG_IF(mappedLinks.empty(), "Every TID must be mapped to at least a link");
1570
1572 QosUtilsMapTidToAc(tid),
1574 mldAddr,
1575 GetAddress(),
1576 {tid},
1577 mappedLinks);
1578
1579 // block unmapped links
1580 if (!notMappedLinks.empty())
1581 {
1583 QosUtilsMapTidToAc(tid),
1585 mldAddr,
1586 GetAddress(),
1587 {tid},
1588 notMappedLinks);
1589 }
1590 }
1591}
1592
1593void
1595 Mac48Address address,
1596 const std::set<uint8_t>& linkIds)
1597{
1598 std::stringstream ss;
1599 if (g_log.IsEnabled(ns3::LOG_FUNCTION))
1600 {
1601 std::copy(linkIds.cbegin(), linkIds.cend(), std::ostream_iterator<uint16_t>(ss, " "));
1602 }
1603 NS_LOG_FUNCTION(this << reason << address << ss.str());
1605
1606 for (const auto linkId : linkIds)
1607 {
1608 auto& link = GetLink(linkId);
1609 auto linkAddr = link.stationManager->GetAffiliatedStaAddress(address);
1610
1611 if (link.stationManager->GetMldAddress(address) == address && !linkAddr.has_value())
1612 {
1613 NS_LOG_DEBUG("Link " << +linkId << " has not been setup with the MLD, skip");
1614 continue;
1615 }
1616
1617 for (const auto& [acIndex, ac] : wifiAcList)
1618 {
1619 // block queues storing QoS data frames and control frames that use MLD addresses
1620 m_scheduler->BlockQueues(reason,
1621 acIndex,
1623 address,
1624 GetLocalAddress(address),
1625 {ac.GetLowTid(), ac.GetHighTid()},
1626 {linkId});
1627 // block queues storing management and control frames that use link addresses
1628 m_scheduler->BlockQueues(reason,
1629 acIndex,
1631 linkAddr.value_or(address),
1632 link.feManager->GetAddress(),
1633 {},
1634 {linkId});
1635 }
1636 }
1637}
1638
1639void
1641 Mac48Address address,
1642 const std::set<uint8_t>& linkIds)
1643{
1645
1646 // shuffle link IDs not to unblock links always in the same order
1647 std::vector<uint8_t> shuffledLinkIds(linkIds.cbegin(), linkIds.cend());
1648 Shuffle(shuffledLinkIds.begin(), shuffledLinkIds.end(), m_shuffleLinkIdsGen.GetRv());
1649
1650 std::stringstream ss;
1651 if (g_log.IsEnabled(ns3::LOG_FUNCTION))
1652 {
1653 std::copy(shuffledLinkIds.cbegin(),
1654 shuffledLinkIds.cend(),
1655 std::ostream_iterator<uint16_t>(ss, " "));
1656 }
1657 NS_LOG_FUNCTION(this << reason << address << ss.str());
1658
1659 for (const auto linkId : shuffledLinkIds)
1660 {
1661 auto& link = GetLink(linkId);
1662 auto linkAddr = link.stationManager->GetAffiliatedStaAddress(address);
1663
1664 if (link.stationManager->GetMldAddress(address) == address && !linkAddr.has_value())
1665 {
1666 NS_LOG_DEBUG("Link " << +linkId << " has not been setup with the MLD, skip");
1667 continue;
1668 }
1669
1670 for (const auto& [acIndex, ac] : wifiAcList)
1671 {
1672 // save the status of the AC queues before unblocking the requested queues
1673 auto hasFramesToTransmit = GetQosTxop(acIndex)->HasFramesToTransmit(linkId);
1674
1675 // unblock queues storing QoS data frames and control frames that use MLD addresses
1676 m_scheduler->UnblockQueues(reason,
1677 acIndex,
1679 address,
1680 GetLocalAddress(address),
1681 {ac.GetLowTid(), ac.GetHighTid()},
1682 {linkId});
1683 // unblock queues storing management and control frames that use link addresses
1684 m_scheduler->UnblockQueues(reason,
1685 acIndex,
1687 linkAddr.value_or(address),
1688 link.feManager->GetAddress(),
1689 {},
1690 {linkId});
1691 // request channel access if needed (schedule now because multiple invocations
1692 // of this method may be done in a loop at the caller)
1694 GetQosTxop(acIndex),
1695 linkId,
1696 hasFramesToTransmit,
1697 Txop::CHECK_MEDIUM_BUSY); // generate backoff if medium busy
1698 }
1699 }
1700}
1701
1702bool
1704 const WifiContainerQueueId& queueId,
1705 uint8_t linkId,
1706 WifiQueueBlockedReason reason) const
1707{
1708 auto mask = m_scheduler->GetQueueLinkMask(ac, queueId, linkId);
1709
1710 if (!mask.has_value())
1711 {
1712 return true; // the link may have not been setup
1713 }
1715 {
1716 return mask->any();
1717 }
1718 return mask->test(static_cast<std::size_t>(reason));
1719}
1720
1721void
1723{
1724 NS_LOG_FUNCTION(this << *mpdu);
1725
1726 const auto& hdr = mpdu->GetHeader();
1727 const auto remoteAddr = hdr.GetAddr1();
1728
1729 if (remoteAddr.IsGroup() || hdr.IsCtl() || !hdr.IsRetry() || mpdu->IsInFlight())
1730 {
1731 return; // nothing to do
1732 }
1733
1734 std::optional<Mac48Address> optAddr;
1735 for (const auto& [id, link] : m_links)
1736 {
1737 if (link->stationManager->GetMldAddress(remoteAddr) == remoteAddr)
1738 {
1739 // this is a link setup with a remote MLD and remoteAddr is the MLD address
1740 optAddr = link->feManager->GetAddress(); // use local address of this setup link
1741 }
1742 }
1743
1744 const auto localAddr =
1745 optAddr.value_or(GetNLinks() == 1 ? m_address : DoGetLocalAddress(remoteAddr));
1746 const auto linkId = GetLinkIdByAddress(localAddr);
1747 NS_ASSERT_MSG(linkId.has_value(), "No link with address " << localAddr);
1748
1749 GetLink(*linkId).stationManager->ReportFinalDataFailed(mpdu);
1750}
1751
1752void
1754{
1755 NS_LOG_FUNCTION(this << packet << to);
1756 // We're sending this packet with a from address that is our own. We
1757 // get that address from the lower MAC and make use of the
1758 // from-spoofing Enqueue() method to avoid duplicated code.
1759 Enqueue(packet, to, GetAddress());
1760}
1761
1762void
1764{
1765 NS_LOG_FUNCTION(this << packet << to << from);
1766
1767 // If we are not a QoS AP then we definitely want to use AC_BE to
1768 // transmit the packet. A TID of zero will map to AC_BE (through \c
1769 // QosUtilsMapTidToAc()), so we use that as our default here.
1770 uint8_t tid = 0;
1771
1773 if (packet->RemovePacketTag(qos) && qos.GetPriority() < 8)
1774 {
1775 tid = qos.GetPriority();
1776 }
1777
1778 Enqueue(packet, to, from, tid);
1779}
1780
1781void
1783{
1784 NS_LOG_FUNCTION(this << packet << to << from << tid);
1785
1787 "This Mac does not support forwarding frames");
1788
1789 if (!CanForwardPacketsTo(to))
1790 {
1791 NotifyTxDrop(packet);
1792 NotifyDropPacketToEnqueue(packet, to);
1793 return;
1794 }
1795
1796 WifiMacHeader hdr;
1797
1798 // For now, an AP that supports QoS does not support non-QoS
1799 // associations, and vice versa. In future the AP model should
1800 // support simultaneously associated QoS and non-QoS STAs, at which
1801 // point there will need to be per-association QoS state maintained
1802 // by the association state machine, and consulted here.
1803 if (GetQosSupported())
1804 {
1807 hdr.SetQosNoEosp();
1808 hdr.SetQosNoAmsdu();
1809 hdr.SetQosTid(tid);
1810 hdr.SetNoOrder(); // explicitly set to 0 for the time being since HT control field is not
1811 // yet implemented (set it to 1 when implemented)
1812 }
1813 else
1814 {
1816 }
1817
1818 // create an MPDU and pass it to subclasses to finalize MAC header
1819 Enqueue(Create<WifiMpdu>(packet, hdr), to, from);
1820}
1821
1822void
1824{
1825 NS_LOG_FUNCTION(this << packet << to);
1826}
1827
1828void
1830{
1831 NS_LOG_FUNCTION(this << packet << from << to);
1832 m_forwardUp(packet, from, to);
1833}
1834
1835void
1837{
1838 NS_LOG_FUNCTION(this << *mpdu << linkId);
1839
1840 const auto& hdr = mpdu->GetOriginal()->GetHeader();
1841 const auto to = hdr.GetAddr1();
1842 const auto myAddr = hdr.IsData() ? Mac48Address::ConvertFrom(GetDevice()->GetAddress())
1843 : GetFrameExchangeManager(linkId)->GetAddress();
1844
1845 // We don't know how to deal with any frame that is not addressed to
1846 // us (and odds are there is nothing sensible we could do anyway),
1847 // so we ignore such frames.
1848 //
1849 // The derived class may also do some such filtering, but it doesn't
1850 // hurt to have it here too as a backstop.
1851 if (to != myAddr)
1852 {
1853 return;
1854 }
1855
1856 // Nothing to do with (QoS) Null Data frames or management frames
1857 if ((hdr.IsData() && !hdr.HasData()) || hdr.IsMgt())
1858 {
1859 return;
1860 }
1861
1862 NS_FATAL_ERROR("Don't know how to handle frame (type=" << hdr.GetType());
1863}
1864
1865void
1867{
1868 NS_LOG_FUNCTION(this << *mpdu);
1869 for (auto& msduPair : *PeekPointer(mpdu))
1870 {
1871 ForwardUp(msduPair.first,
1872 msduPair.second.GetSourceAddr(),
1873 msduPair.second.GetDestinationAddr());
1874 }
1875}
1876
1877std::optional<Mac48Address>
1878WifiMac::GetMldAddress(const Mac48Address& remoteAddr) const
1879{
1880 for (const auto& [id, link] : m_links)
1881 {
1882 if (auto mldAddress = link->stationManager->GetMldAddress(remoteAddr))
1883 {
1884 return *mldAddress;
1885 }
1886 }
1887 return std::nullopt;
1888}
1889
1892{
1893 for (const auto& [id, link] : m_links)
1894 {
1895 if (auto mldAddress = link->stationManager->GetMldAddress(remoteAddr))
1896 {
1897 // this is a link setup with remote MLD
1898 if (mldAddress != remoteAddr)
1899 {
1900 // the remote address is the address of a STA affiliated with the remote MLD
1901 return link->feManager->GetAddress();
1902 }
1903 // we have to return our MLD address
1904 return m_address;
1905 }
1906 }
1907 // we get here if no ML setup was established between this device and the remote device
1908 if (GetNLinks() == 1)
1909 {
1910 // this is a single link device
1911 return m_address;
1912 }
1913 // this is an MLD which performed legacy association with the remote device or the remote device
1914 // is unknown
1915 return DoGetLocalAddress(remoteAddr);
1916}
1917
1919WifiMac::DoGetLocalAddress(const Mac48Address& remoteAddr [[maybe_unused]]) const
1920{
1921 return m_address;
1922}
1923
1926 uint8_t tid,
1927 std::optional<Mac48Address> gcrGroupAddr) const
1928{
1929 // BA agreements are indexed by the MLD address if ML setup was performed
1930 recipient = GetMldAddress(recipient).value_or(recipient);
1931
1932 auto agreement =
1933 GetQosTxop(tid)->GetBaManager()->GetAgreementAsOriginator(recipient, tid, gcrGroupAddr);
1934 if (!agreement || !agreement->get().IsEstablished())
1935 {
1936 return std::nullopt;
1937 }
1938 return agreement;
1939}
1940
1943 uint8_t tid,
1944 std::optional<Mac48Address> gcrGroupAddr) const
1945{
1946 // BA agreements are indexed by the MLD address if ML setup was performed
1947 originator = GetMldAddress(originator).value_or(originator);
1948 return GetQosTxop(tid)->GetBaManager()->GetAgreementAsRecipient(originator, tid, gcrGroupAddr);
1949}
1950
1952WifiMac::GetBaTypeAsOriginator(const Mac48Address& recipient, uint8_t tid) const
1953{
1954 auto agreement = GetBaAgreementEstablishedAsOriginator(recipient, tid);
1955 NS_ABORT_MSG_IF(!agreement,
1956 "No existing Block Ack agreement with " << recipient << " TID: " << +tid);
1957 return agreement->get().GetBlockAckType();
1958}
1959
1961WifiMac::GetBarTypeAsOriginator(const Mac48Address& recipient, uint8_t tid) const
1962{
1963 auto agreement = GetBaAgreementEstablishedAsOriginator(recipient, tid);
1964 NS_ABORT_MSG_IF(!agreement,
1965 "No existing Block Ack agreement with " << recipient << " TID: " << +tid);
1966 return agreement->get().GetBlockAckReqType();
1967}
1968
1970WifiMac::GetBaTypeAsRecipient(Mac48Address originator, uint8_t tid) const
1971{
1972 auto agreement = GetBaAgreementEstablishedAsRecipient(originator, tid);
1973 NS_ABORT_MSG_IF(!agreement,
1974 "No existing Block Ack agreement with " << originator << " TID: " << +tid);
1975 return agreement->get().GetBlockAckType();
1976}
1977
1979WifiMac::GetBarTypeAsRecipient(Mac48Address originator, uint8_t tid) const
1980{
1981 auto agreement = GetBaAgreementEstablishedAsRecipient(originator, tid);
1982 NS_ABORT_MSG_IF(!agreement,
1983 "No existing Block Ack agreement with " << originator << " TID: " << +tid);
1984 return agreement->get().GetBlockAckReqType();
1985}
1986
1989{
1990 return GetDevice()->GetHtConfiguration();
1991}
1992
1995{
1996 return GetDevice()->GetVhtConfiguration();
1997}
1998
2001{
2002 return GetDevice()->GetHeConfiguration();
2003}
2004
2007{
2008 return GetDevice()->GetEhtConfiguration();
2009}
2010
2011bool
2012WifiMac::GetHtSupported(uint8_t linkId) const
2013{
2014 return (GetDevice()->GetHtConfiguration() &&
2015 GetWifiPhy(linkId)->GetPhyBand() != WIFI_PHY_BAND_6GHZ);
2016}
2017
2018bool
2019WifiMac::GetVhtSupported(uint8_t linkId) const
2020{
2021 return (GetDevice()->GetVhtConfiguration() &&
2022 GetWifiPhy(linkId)->GetPhyBand() != WIFI_PHY_BAND_2_4GHZ &&
2023 GetWifiPhy(linkId)->GetPhyBand() != WIFI_PHY_BAND_6GHZ);
2024}
2025
2026bool
2028{
2029 return bool(GetDevice()->GetHeConfiguration());
2030}
2031
2032bool
2034{
2035 return bool(GetDevice()->GetEhtConfiguration());
2036}
2037
2038bool
2040{
2041 for (const auto& [id, link] : m_links)
2042 {
2043 if (link->stationManager->GetHtSupported(address))
2044 {
2045 return true;
2046 }
2047 }
2048 return false;
2049}
2050
2051bool
2053{
2054 for (const auto& [id, link] : m_links)
2055 {
2056 if (link->stationManager->GetVhtSupported(address))
2057 {
2058 return true;
2059 }
2060 }
2061 return false;
2062}
2063
2064bool
2066{
2067 for (const auto& [id, link] : m_links)
2068 {
2069 if (link->stationManager->GetHeSupported(address))
2070 {
2071 return true;
2072 }
2073 }
2074 return false;
2075}
2076
2077bool
2079{
2080 for (const auto& [id, link] : m_links)
2081 {
2082 if (link->stationManager->GetEhtSupported(address))
2083 {
2084 return true;
2085 }
2086 }
2087 return false;
2088}
2089
2090uint16_t
2091WifiMac::GetMaxBaBufferSize(std::optional<Mac48Address> address) const
2092{
2093 if (address ? GetEhtSupported(*address) : GetEhtSupported())
2094 {
2095 return 1024;
2096 }
2097 if (address ? GetHeSupported(*address) : GetHeSupported())
2098 {
2099 return 256;
2100 }
2101 NS_ASSERT(address ? GetHtSupported(*address) : static_cast<bool>(GetHtConfiguration()));
2102 return 64;
2103}
2104
2105void
2107{
2108 NS_LOG_FUNCTION(this << size);
2109
2110 // the cap can be computed if the device has been configured
2111 m_mpduBufferSize = m_device ? std::min(size, GetMaxBaBufferSize()) : size;
2112}
2113
2114uint16_t
2116{
2117 return m_mpduBufferSize;
2118}
2119
2120void
2122{
2123 NS_LOG_FUNCTION(this << limit);
2124 m_frameRetryLimit = limit;
2125}
2126
2129{
2130 return m_frameRetryLimit;
2131}
2132
2133void
2135{
2136 NS_LOG_FUNCTION(this << +threshold);
2137 if (m_qosSupported)
2138 {
2139 GetVOQueue()->SetBlockAckThreshold(threshold);
2140 }
2141}
2142
2143void
2145{
2146 NS_LOG_FUNCTION(this << +threshold);
2147 if (m_qosSupported)
2148 {
2149 GetVIQueue()->SetBlockAckThreshold(threshold);
2150 }
2151}
2152
2153void
2155{
2156 NS_LOG_FUNCTION(this << +threshold);
2157 if (m_qosSupported)
2158 {
2159 GetBEQueue()->SetBlockAckThreshold(threshold);
2160 }
2161}
2162
2163void
2165{
2166 NS_LOG_FUNCTION(this << +threshold);
2167 if (m_qosSupported)
2168 {
2169 GetBKQueue()->SetBlockAckThreshold(threshold);
2170 }
2171}
2172
2173void
2175{
2176 NS_LOG_FUNCTION(this << timeout);
2177 if (m_qosSupported)
2178 {
2179 GetVOQueue()->SetBlockAckInactivityTimeout(timeout);
2180 }
2181}
2182
2183void
2185{
2186 NS_LOG_FUNCTION(this << timeout);
2187 if (m_qosSupported)
2188 {
2189 GetVIQueue()->SetBlockAckInactivityTimeout(timeout);
2190 }
2191}
2192
2193void
2195{
2196 NS_LOG_FUNCTION(this << timeout);
2197 if (m_qosSupported)
2198 {
2199 GetBEQueue()->SetBlockAckInactivityTimeout(timeout);
2200 }
2201}
2202
2203void
2205{
2206 NS_LOG_FUNCTION(this << timeout);
2207 if (m_qosSupported)
2208 {
2209 GetBKQueue()->SetBlockAckInactivityTimeout(timeout);
2210 }
2211}
2212
2215{
2216 ExtendedCapabilities capabilities;
2218 return capabilities;
2219}
2220
2222WifiMac::GetHtCapabilities(uint8_t linkId) const
2223{
2224 NS_ASSERT(GetHtSupported(linkId));
2225 HtCapabilities capabilities;
2226
2227 auto phy = GetWifiPhy(linkId);
2228 auto htConfiguration = GetHtConfiguration();
2229 bool sgiSupported = htConfiguration->m_sgiSupported;
2230 capabilities.SetLdpc(htConfiguration->m_ldpcSupported);
2231 const auto width = phy->GetChannelWidth();
2232 capabilities.SetSupportedChannelWidth((width < MHz_u{40}) ? 0 : 1);
2233 capabilities.SetShortGuardInterval20(sgiSupported);
2234 capabilities.SetShortGuardInterval40(sgiSupported);
2235 // Set Maximum A-MSDU Length subfield
2236 uint16_t maxAmsduSize =
2238 if (maxAmsduSize <= 3839)
2239 {
2240 capabilities.SetMaxAmsduLength(3839);
2241 }
2242 else
2243 {
2244 capabilities.SetMaxAmsduLength(7935);
2245 }
2246 uint32_t maxAmpduLength =
2248 // round to the next power of two minus one
2249 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2250 // The maximum A-MPDU length in HT capabilities elements ranges from 2^13-1 to 2^16-1
2251 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 65535U));
2252
2253 capabilities.SetLSigProtectionSupport(true);
2254 uint64_t maxSupportedRate = 0; // in bit/s
2255 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HT))
2256 {
2257 capabilities.SetRxMcsBitmask(mcs.GetMcsValue());
2258 uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
2259 NS_ASSERT(nss > 0 && nss < 5);
2260 uint64_t dataRate =
2261 mcs.GetDataRate(std::min(width, MHz_u{40}), NanoSeconds(sgiSupported ? 400 : 800), nss);
2262 if (dataRate > maxSupportedRate)
2263 {
2264 maxSupportedRate = dataRate;
2265 NS_LOG_DEBUG("Updating maxSupportedRate to " << maxSupportedRate);
2266 }
2267 }
2268 capabilities.SetRxHighestSupportedDataRate(
2269 static_cast<uint16_t>(maxSupportedRate / 1e6)); // in Mbit/s
2270 capabilities.SetTxMcsSetDefined(phy->GetNMcs() > 0);
2271 capabilities.SetTxMaxNSpatialStreams(phy->GetMaxSupportedTxSpatialStreams());
2272 // we do not support unequal modulations
2273 capabilities.SetTxRxMcsSetUnequal(0);
2274 capabilities.SetTxUnequalModulation(0);
2275
2276 return capabilities;
2277}
2278
2280WifiMac::GetVhtCapabilities(uint8_t linkId) const
2281{
2282 NS_ASSERT(GetVhtSupported(linkId));
2283 VhtCapabilities capabilities;
2284
2285 auto phy = GetWifiPhy(linkId);
2286 auto htConfiguration = GetHtConfiguration();
2287 const auto sgiSupported = htConfiguration->m_sgiSupported;
2288 const auto width = phy->GetChannelWidth();
2289 capabilities.SetSupportedChannelWidthSet((width < MHz_u{160}) ? 0 : 1);
2290 // Set Maximum MPDU Length subfield
2291 uint16_t maxAmsduSize =
2293 if (maxAmsduSize <= 3839)
2294 {
2295 capabilities.SetMaxMpduLength(3895);
2296 }
2297 else if (maxAmsduSize <= 7935)
2298 {
2299 capabilities.SetMaxMpduLength(7991);
2300 }
2301 else
2302 {
2303 capabilities.SetMaxMpduLength(11454);
2304 }
2305 uint32_t maxAmpduLength =
2307 // round to the next power of two minus one
2308 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2309 // The maximum A-MPDU length in VHT capabilities elements ranges from 2^13-1 to 2^20-1
2310 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 1048575U));
2311
2312 capabilities.SetRxLdpc(htConfiguration->m_ldpcSupported);
2313 capabilities.SetShortGuardIntervalFor80Mhz(sgiSupported);
2314 capabilities.SetShortGuardIntervalFor160Mhz(sgiSupported);
2315 uint8_t maxMcs = 0;
2316 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
2317 {
2318 if (mcs.GetMcsValue() > maxMcs)
2319 {
2320 maxMcs = mcs.GetMcsValue();
2321 }
2322 }
2323 // Support same MaxMCS for each spatial stream
2324 for (uint8_t nss = 1; nss <= phy->GetMaxSupportedRxSpatialStreams(); nss++)
2325 {
2326 capabilities.SetRxMcsMap(maxMcs, nss);
2327 }
2328 for (uint8_t nss = 1; nss <= phy->GetMaxSupportedTxSpatialStreams(); nss++)
2329 {
2330 capabilities.SetTxMcsMap(maxMcs, nss);
2331 }
2332 uint64_t maxSupportedRateLGI = 0; // in bit/s
2333 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
2334 {
2335 if (!mcs.IsAllowed(width, 1))
2336 {
2337 continue;
2338 }
2339 if (mcs.GetDataRate(width) > maxSupportedRateLGI)
2340 {
2341 maxSupportedRateLGI = mcs.GetDataRate(width);
2342 NS_LOG_DEBUG("Updating maxSupportedRateLGI to " << maxSupportedRateLGI);
2343 }
2344 }
2346 static_cast<uint16_t>(maxSupportedRateLGI / 1e6)); // in Mbit/s
2348 static_cast<uint16_t>(maxSupportedRateLGI / 1e6)); // in Mbit/s
2349 // To be filled in once supported
2350 capabilities.SetRxStbc(0);
2351 capabilities.SetTxStbc(0);
2352
2353 return capabilities;
2354}
2355
2357WifiMac::GetHeCapabilities(uint8_t linkId) const
2358{
2360 HeCapabilities capabilities;
2361
2362 auto phy = GetLink(linkId).phy;
2363 auto htConfiguration = GetHtConfiguration();
2364 auto heConfiguration = GetHeConfiguration();
2365 uint8_t channelWidthSet = 0;
2366 const auto width = phy->GetChannelWidth();
2367 if (const auto band = phy->GetPhyBand(); band == WIFI_PHY_BAND_2_4GHZ)
2368 {
2369 if (width >= MHz_u{40})
2370 {
2371 channelWidthSet |= 0x01;
2372 }
2373 }
2374 else if (band == WIFI_PHY_BAND_5GHZ || band == WIFI_PHY_BAND_6GHZ)
2375 {
2376 if (width >= MHz_u{40})
2377 {
2378 channelWidthSet |= 0x02;
2379 }
2380 if (width >= MHz_u{160})
2381 {
2382 channelWidthSet |= 0x04;
2383 if (phy->GetOperatingChannel().GetNSegments() > 1)
2384 {
2385 channelWidthSet |= 0x08;
2386 }
2387 }
2388 }
2389 capabilities.SetChannelWidthSet(channelWidthSet);
2390 capabilities.SetLdpcCodingInPayload(htConfiguration->m_ldpcSupported);
2391 if (heConfiguration->GetGuardInterval().GetNanoSeconds() == 800)
2392 {
2393 // todo: We assume for now that if we support 800ns GI then 1600ns GI is supported as well
2394 // todo: Assuming reception support for both 1x HE LTF and 4x HE LTF 800 ns
2395 capabilities.SetHeSuPpdu1xHeLtf800nsGi(true);
2396 capabilities.SetHePpdu4xHeLtf800nsGi(true);
2397 }
2398
2399 uint32_t maxAmpduLength =
2401 // round to the next power of two minus one
2402 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2403 // The maximum A-MPDU length in HE capabilities elements ranges from 2^20-1 to 2^23-1
2404 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 1048575U), 8388607U));
2405
2406 uint8_t maxMcs = 0;
2407 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HE))
2408 {
2409 if (mcs.GetMcsValue() > maxMcs)
2410 {
2411 maxMcs = mcs.GetMcsValue();
2412 }
2413 }
2414 capabilities.SetHighestMcsSupported(maxMcs);
2415 capabilities.SetHighestNssSupported(phy->GetMaxSupportedTxSpatialStreams());
2416
2417 return capabilities;
2418}
2419
2422{
2423 auto phy = GetLink(linkId).phy;
2424 NS_ASSERT_MSG(phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ,
2425 "Getting HE 6 GHz band capabilities on band different than 6 GHz");
2426
2427 He6GhzBandCapabilities capabilities;
2428
2429 // Set Maximum MPDU Length subfield
2430 const auto maxAmsduSize =
2432 if (maxAmsduSize <= 3839)
2433 {
2434 capabilities.SetMaxMpduLength(3895);
2435 }
2436 else if (maxAmsduSize <= 7935)
2437 {
2438 capabilities.SetMaxMpduLength(7991);
2439 }
2440 else
2441 {
2442 capabilities.SetMaxMpduLength(11454);
2443 }
2444
2445 auto maxAmpduLength =
2447 // round to the next power of two minus one
2448 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2449 // The maximum A-MPDU length in HE 6 GHz Band Capabilities elements ranges from 2^13-1 to 2^20-1
2450 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8191U), 1048575U));
2451
2452 return capabilities;
2453}
2454
2456WifiMac::GetEhtCapabilities(uint8_t linkId) const
2457{
2459 EhtCapabilities capabilities;
2460
2461 Ptr<WifiPhy> phy = GetLink(linkId).phy;
2462
2463 // Set Maximum MPDU Length subfield (Reserved when transmitted in 5 GHz or 6 GHz band)
2464 if (phy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
2465 {
2466 uint16_t maxAmsduSize =
2468 // Table 9-34—Maximum data unit sizes (in octets) and durations (in microseconds)
2469 if (maxAmsduSize <= 3839)
2470 {
2471 capabilities.SetMaxMpduLength(3895);
2472 }
2473 else if (maxAmsduSize <= 7935)
2474 {
2475 capabilities.SetMaxMpduLength(7991);
2476 }
2477 else
2478 {
2479 capabilities.SetMaxMpduLength(11454);
2480 }
2481 }
2482
2483 // Set Maximum A-MPDU Length Exponent Extension subfield
2484 uint32_t maxAmpduLength =
2486 // round to the next power of two minus one
2487 maxAmpduLength = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduLength + 1)))) - 1;
2488 // The maximum A-MPDU length in EHT capabilities elements ranges from 2^23-1 to 2^24-1
2489 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduLength, 8388607U), 16777215U));
2490
2491 // Set the PHY capabilities
2492 const auto support4096Qam = phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, 12);
2494 support4096Qam ? 1 : 0;
2496 support4096Qam ? 1 : 0;
2497
2498 const auto maxTxNss = phy->GetMaxSupportedTxSpatialStreams();
2499 const auto maxRxNss = phy->GetMaxSupportedRxSpatialStreams();
2500 const auto width = phy->GetChannelWidth();
2501 if (width == MHz_u{20})
2502 {
2503 for (auto maxMcs : {7, 9, 11, 13})
2504 {
2505 capabilities.SetSupportedRxEhtMcsAndNss(
2507 maxMcs,
2508 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2509 capabilities.SetSupportedTxEhtMcsAndNss(
2511 maxMcs,
2512 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2513 }
2514 }
2515 else
2516 {
2517 for (auto maxMcs : {9, 11, 13})
2518 {
2519 capabilities.SetSupportedRxEhtMcsAndNss(
2521 maxMcs,
2522 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2523 capabilities.SetSupportedTxEhtMcsAndNss(
2525 maxMcs,
2526 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2527 }
2528 }
2529 if (width >= MHz_u{160})
2530 {
2531 for (auto maxMcs : {9, 11, 13})
2532 {
2533 capabilities.SetSupportedRxEhtMcsAndNss(
2535 maxMcs,
2536 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2537 capabilities.SetSupportedTxEhtMcsAndNss(
2539 maxMcs,
2540 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2541 }
2542 }
2543 if (width >= MHz_u{320})
2544 {
2545 capabilities.m_phyCapabilities.support320MhzIn6Ghz = true;
2546 for (auto maxMcs : {9, 11, 13})
2547 {
2548 capabilities.SetSupportedRxEhtMcsAndNss(
2550 maxMcs,
2551 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxRxNss : 0);
2552 capabilities.SetSupportedTxEhtMcsAndNss(
2554 maxMcs,
2555 phy->IsMcsSupported(WIFI_MOD_CLASS_EHT, maxMcs) ? maxTxNss : 0);
2556 }
2557 }
2558 return capabilities;
2559}
2560
2563{
2564 uint32_t maxSize = 0;
2565 switch (ac)
2566 {
2567 case AC_BE:
2568 maxSize = m_beMaxAmpduSize;
2569 break;
2570 case AC_BK:
2571 maxSize = m_bkMaxAmpduSize;
2572 break;
2573 case AC_VI:
2574 maxSize = m_viMaxAmpduSize;
2575 break;
2576 case AC_VO:
2577 maxSize = m_voMaxAmpduSize;
2578 break;
2579 default:
2580 NS_ABORT_MSG("Unknown AC " << ac);
2581 return 0;
2582 }
2583 return maxSize;
2584}
2585
2586uint16_t
2588{
2589 uint16_t maxSize = 0;
2590 switch (ac)
2591 {
2592 case AC_BE:
2593 maxSize = m_beMaxAmsduSize;
2594 break;
2595 case AC_BK:
2596 maxSize = m_bkMaxAmsduSize;
2597 break;
2598 case AC_VI:
2599 maxSize = m_viMaxAmsduSize;
2600 break;
2601 case AC_VO:
2602 maxSize = m_voMaxAmsduSize;
2603 break;
2604 default:
2605 NS_ABORT_MSG("Unknown AC " << ac);
2606 return 0;
2607 }
2608 return maxSize;
2609}
2610
2611void
2613{
2614 NS_LOG_FUNCTION(this << enable);
2616}
2617
2618bool
2620{
2622 "Robust AV Streaming requires STA to be HT-capable");
2624}
2625
2626void
2627WifiMac::RecordCapabilities(const MgtFrameType& frame, const Mac48Address& from, uint8_t linkId)
2628{
2629 NS_LOG_FUNCTION(this << frame.index() << from << linkId);
2630 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
2631 auto phy = GetWifiPhy(linkId);
2632
2633 // lambda processing Information Elements included in all frame types
2634 auto recordFromIes = [&](auto&& frame) {
2635 NS_ASSERT(frame.template Get<SupportedRates>());
2636 const auto rates = AllSupportedRates{*frame.template Get<SupportedRates>(),
2637 frame.template Get<ExtendedSupportedRatesIE>()};
2638 for (const auto& mode : phy->GetModeList())
2639 {
2640 if (rates.IsSupportedRate(mode.GetDataRate(phy->GetChannelWidth())))
2641 {
2642 remoteStationManager->AddSupportedMode(from, mode);
2643 if (rates.IsBasicRate(mode.GetDataRate(phy->GetChannelWidth())))
2644 {
2645 remoteStationManager->AddBasicMode(mode);
2646 }
2647 }
2648 }
2649
2650 // we do not return if HT is not supported because HE STAs operating in
2651 // the 6 GHz band do not support VHT
2652 if (GetHtSupported(linkId))
2653 {
2654 /* HT station */
2655 if (const auto& htCapabilities = frame.template Get<HtCapabilities>())
2656 {
2657 remoteStationManager->AddStationHtCapabilities(from, *htCapabilities);
2658 }
2659 if (const auto& extendedCapabilities = frame.template Get<ExtendedCapabilities>())
2660 {
2661 remoteStationManager->AddStationExtendedCapabilities(from, *extendedCapabilities);
2662 }
2663 }
2664
2665 // we do not return if VHT is not supported because HE STAs operating in
2666 // the 2.4 GHz or 6 GHz band do not support VHT
2667 if (GetVhtSupported(linkId))
2668 {
2669 const auto& vhtCapabilities = frame.template Get<VhtCapabilities>();
2670 // we will always fill in RxHighestSupportedLgiDataRate field at TX, so this can be used
2671 // to check whether it supports VHT
2672 if (vhtCapabilities.has_value() &&
2673 vhtCapabilities->GetRxHighestSupportedLgiDataRate() > 0)
2674 {
2675 remoteStationManager->AddStationVhtCapabilities(from, *vhtCapabilities);
2676 }
2677 }
2678
2679 if (!GetHeSupported())
2680 {
2681 return;
2682 }
2683
2684 const auto& heCapabilities = frame.template Get<HeCapabilities>();
2685 if (heCapabilities.has_value() && heCapabilities->GetSupportedMcsAndNss() != 0)
2686 {
2687 remoteStationManager->AddStationHeCapabilities(from, *heCapabilities);
2688 }
2689
2690 if (Is6GhzBand(linkId))
2691 {
2692 if (const auto& he6GhzCapabilities = frame.template Get<He6GhzBandCapabilities>())
2693 {
2694 remoteStationManager->AddStationHe6GhzCapabilities(from, *he6GhzCapabilities);
2695 }
2696 }
2697
2698 if (!GetEhtSupported())
2699 {
2700 return;
2701 }
2702
2703 if (const auto& ehtCapabilities = frame.template Get<EhtCapabilities>())
2704 {
2705 remoteStationManager->AddStationEhtCapabilities(from, *ehtCapabilities);
2706 }
2707 };
2708
2709 // process Information Elements included in the current frame variant
2710 std::visit(recordFromIes, frame);
2711}
2712
2713} // namespace ns3
AttributeValue implementation for Boolean.
Definition boolean.h:26
Callback template class.
Definition callback.h:428
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)
Object()
Caller graph was not generated because of its size.
Definition object.cc:93
bool IsInitialized() const
Check if the object has been initialized.
Definition object.cc:237
AttributeValue implementation for Pointer.
Definition pointer.h:37
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:614
indicates whether the socket has a priority set.
Definition socket.h:1308
uint8_t GetPriority() const
Get the tag's priority.
Definition socket.cc:849
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
AttributeValue implementation for Ssid.
Definition ssid.h:85
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
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:664
static constexpr bool CHECK_MEDIUM_BUSY
generation of backoff (also) depends on the busy/idle state of the medium
Definition txop.h:413
a unique identifier for an interface.
Definition type-id.h:50
@ ATTR_GET
The attribute can be read.
Definition type-id.h:55
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
Definition type-id.h:57
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
Hold an unsigned integer type.
Definition uinteger.h:34
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.
base class for all MAC-level wifi objects.
Definition wifi-mac.h:90
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:1942
uint16_t GetMaxAmsduSize(AcIndex ac) const
Return the maximum A-MSDU size of the given Access Category.
Definition wifi-mac.cc:2587
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:1034
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:711
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition wifi-mac.cc:1878
virtual void SetMacQueueScheduler(Ptr< WifiMacQueueScheduler > scheduler)
Set the wifi MAC queue scheduler.
Definition wifi-mac.cc:698
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:1296
bool m_shortSlotTimeSupported
flag whether short slot time is supported
Definition wifi-mac.h:1274
void ConfigurePhyDependentParameters(uint8_t linkId)
Configure PHY dependent parameters such as CWmin and CWmax on the given link.
Definition wifi-mac.cc:958
Ptr< HeConfiguration > GetHeConfiguration() const
Definition wifi-mac.cc:2000
DroppedMpduTracedCallback m_droppedMpduCallback
This trace indicates that an MPDU was dropped for the given reason.
Definition wifi-mac.h:1369
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition wifi-mac.cc:491
uint32_t GetFrameRetryLimit() const
Definition wifi-mac.cc:2128
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:1272
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:1111
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:2280
Callback< void > m_linkDown
Callback when a link is down.
Definition wifi-mac.h:1035
bool GetQosSupported() const
Return whether the device supports QoS.
Definition wifi-mac.cc:1429
virtual void SetAddress(Mac48Address address)
Definition wifi-mac.cc:514
void SetFrameExchangeManagers(const std::vector< Ptr< FrameExchangeManager > > &feManagers)
Definition wifi-mac.cc:992
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:976
Ptr< Txop > m_txop
TXOP used for transmission of frames to non-QoS peers.
Definition wifi-mac.h:1031
void SetQosSupported(bool enable)
Enable or disable QoS support for the device.
Definition wifi-mac.cc:1421
Mac48Address m_address
MAC address of this station.
Definition wifi-mac.h:1283
std::set< uint8_t > m_linkIds
IDs of the links in use.
Definition wifi-mac.h:1281
Ptr< WifiMacQueueScheduler > GetMacQueueScheduler() const
Get the wifi MAC queue scheduler.
Definition wifi-mac.cc:705
uint16_t GetMpduBufferSize() const
Definition wifi-mac.cc:2115
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition wifi-mac.cc:1126
BlockAckType GetBaTypeAsRecipient(Mac48Address originator, uint8_t tid) const
Definition wifi-mac.cc:1970
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:1192
void Enqueue(Ptr< Packet > packet, Mac48Address to)
Definition wifi-mac.cc:1753
void UnblockUnicastTxOnLinks(WifiQueueBlockedReason reason, 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:1640
uint16_t m_voMaxAmsduSize
maximum A-MSDU size for AC_VO (in bytes)
Definition wifi-mac.h:1295
Ptr< MacRxMiddle > m_rxMiddle
RX middle (defragmentation etc.).
Definition wifi-mac.h:1029
Ptr< WifiMacQueueScheduler > m_scheduler
wifi MAC queue scheduler
Definition wifi-mac.h:1032
void DoInitialize() override
Initialize() implementation.
Definition wifi-mac.cc:418
TypeOfStation m_typeOfStation
the type of station
Definition wifi-mac.h:1277
uint16_t m_mpduBufferSize
BlockAck buffer size (in number of MPDUs).
Definition wifi-mac.h:1305
uint32_t m_beMaxAmpduSize
maximum A-MPDU size for AC_BE (in bytes)
Definition wifi-mac.h:1302
void SetChannelAccessManagers(const std::vector< Ptr< ChannelAccessManager > > &caManagers)
Definition wifi-mac.cc:1040
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:1339
std::variant< MgtBeaconHeader, MgtProbeResponseHeader, MgtAssocResponseHeader > MgtFrameType
type of the management frames
Definition wifi-mac.h:108
Ssid GetSsid() const
Definition wifi-mac.cc:534
void SetWifiRemoteStationManagers(const std::vector< Ptr< WifiRemoteStationManager > > &stationManagers)
Definition wifi-mac.cc:1075
void SetBeBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_BE.
Definition wifi-mac.cc:2154
bool GetErpSupported(uint8_t linkId) const
Return whether the device supports ERP on the given link.
Definition wifi-mac.cc:1435
void ResetWifiPhys()
Remove currently attached WifiPhy objects from this MAC.
Definition wifi-mac.cc:1403
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:1323
void SetErpSupported(bool enable, uint8_t linkId)
Enable or disable ERP support for the given link.
Definition wifi-mac.cc:1441
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:1703
uint32_t m_voMaxAmpduSize
maximum A-MPDU size for AC_VO (in bytes)
Definition wifi-mac.h:1300
void ConfigureDcf(Ptr< Txop > dcf, uint32_t cwmin, uint32_t cwmax, std::list< bool > isDsss, AcIndex ac)
Definition wifi-mac.cc:818
Ptr< WifiNetDevice > m_device
Pointer to the device.
Definition wifi-mac.h:1279
bool GetRobustAVStreamingSupported() const
Return whether the device supports Robust AV Streaming.
Definition wifi-mac.cc:2619
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:1823
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:1138
IcfDropTracedCallback m_icfDropCallback
traced callback for ICF drop events
Definition wifi-mac.h:1442
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:1374
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:1722
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition wifi-mac.cc:1397
void SetMpduBufferSize(uint16_t size)
Definition wifi-mac.cc:2106
void RecordCapabilities(const MgtFrameType &frame, const Mac48Address &addr, uint8_t linkId)
Update capabilities information from the given management frame.
Definition wifi-mac.cc:2627
MpduTracedCallback m_nackedMpduCallback
nack'ed MPDU callback
Definition wifi-mac.h:1375
bool GetEhtSupported() const
Return whether the device supports EHT.
Definition wifi-mac.cc:2033
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:2027
HtCapabilities GetHtCapabilities(uint8_t linkId) const
Return the HT capabilities of the device for the given link.
Definition wifi-mac.cc:2222
void SetBkBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_BK.
Definition wifi-mac.cc:2164
void SetVoBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_VO.
Definition wifi-mac.cc:2134
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:1158
std::optional< std::reference_wrapper< const RecipientBlockAckAgreement > > RecipientAgreementOptConstRef
optional const reference to RecipientBlockAckAgreement
Definition wifi-mac.h:716
void NotifyPromiscRx(Ptr< const Packet > packet)
Definition wifi-mac.cc:742
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:1311
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:681
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > stationManager)
Definition wifi-mac.cc:1068
UniformRandomBitGenerator m_shuffleLinkIdsGen
random number generator to shuffle link IDs
Definition wifi-mac.h:1027
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:1512
void CompleteConfig()
Complete the configuration of the MAC layer components.
Definition wifi-mac.cc:907
void SetBeBlockAckInactivityTimeout(uint16_t timeout)
Set BE block ack inactivity timeout.
Definition wifi-mac.cc:2194
virtual void NotifyChannelReleased(Ptr< Txop > txop, uint8_t linkId)
Notify that the given TXOP has released the channel on the given link.
Definition wifi-mac.cc:759
Ptr< EhtConfiguration > GetEhtConfiguration() const
Definition wifi-mac.cc:2006
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:1346
bool GetVhtSupported(uint8_t linkId) const
Return whether the device supports VHT on the given link.
Definition wifi-mac.cc:2019
void SetDsssSupported(bool enable, uint8_t linkId)
Enable or disable DSSS support for the given link.
Definition wifi-mac.cc:1452
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:1330
void BlockUnicastTxOnLinks(WifiQueueBlockedReason reason, 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:1594
Ptr< MacTxMiddle > m_txMiddle
TX middle (aggregation etc.).
Definition wifi-mac.h:1030
void NotifyTx(Ptr< const Packet > packet)
Definition wifi-mac.cc:724
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:1988
void SetFrameRetryLimit(uint32_t limit)
Set the frame retry limit.
Definition wifi-mac.cc:2121
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:1323
uint32_t GetMaxAmpduSize(AcIndex ac) const
Return the maximum A-MPDU size of the given Access Category.
Definition wifi-mac.cc:2562
BlockAckReqType GetBarTypeAsRecipient(Mac48Address originator, uint8_t tid) const
Definition wifi-mac.cc:1979
Ssid m_ssid
Service Set ID (SSID).
Definition wifi-mac.h:1284
std::map< uint8_t, std::unique_ptr< LinkEntity > > m_links
ID-indexed map of Link objects.
Definition wifi-mac.h:1280
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:1866
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:736
virtual Ptr< Txop > GetTxopFor(AcIndex ac) const
Get the (Qos)Txop associated with the given AC, if such (Qos)Txop is installed, or a null pointer,...
Definition wifi-mac.cc:671
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:1353
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:1289
BlockAckType GetBaTypeAsOriginator(const Mac48Address &recipient, uint8_t tid) const
Definition wifi-mac.cc:1952
MpduResponseTimeoutTracedCallback m_mpduResponseTimeoutCallback
MPDU response timeout traced callback.
Definition wifi-mac.h:1396
void SetForwardUpCallback(ForwardUpCallback upCallback)
Definition wifi-mac.cc:1491
PsduMapResponseTimeoutTracedCallback m_psduMapResponseTimeoutCallback
PSDU map response timeout traced callback.
Definition wifi-mac.h:1440
OriginatorAgreementOptConstRef GetBaAgreementEstablishedAsOriginator(Mac48Address recipient, uint8_t tid, std::optional< Mac48Address > gcrGroupAddr=std::nullopt) const
Definition wifi-mac.cc:1925
ExtendedCapabilities GetExtendedCapabilities() const
Return the extended capabilities of the device.
Definition wifi-mac.cc:2214
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:1338
uint16_t m_bkMaxAmsduSize
maximum A-MSDU size for AC_BK (in bytes)
Definition wifi-mac.h:1298
void SetBkBlockAckInactivityTimeout(uint16_t timeout)
Set BK block ack inactivity timeout.
Definition wifi-mac.cc:2204
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:1313
virtual bool SupportsSendFrom() const
Definition wifi-mac.cc:1485
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:2421
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:2091
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:1171
void SetViBlockAckThreshold(uint8_t threshold)
Set the block ack threshold for AC_VI.
Definition wifi-mac.cc:2144
void SetViBlockAckInactivityTimeout(uint16_t timeout)
Set VI block ack inactivity timeout.
Definition wifi-mac.cc:2184
bool GetShortSlotTimeSupported() const
Definition wifi-mac.cc:1479
BlockAckReqType GetBarTypeAsOriginator(const Mac48Address &recipient, uint8_t tid) const
Definition wifi-mac.cc:1961
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:775
void SetLinkDownCallback(Callback< void > linkDown)
Definition wifi-mac.cc:1505
bool m_robustAVStreamingSupported
flag whether robust AV streaming is supported
Definition wifi-mac.h:1308
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:1994
void NotifyRxDrop(Ptr< const Packet > packet)
Definition wifi-mac.cc:748
virtual void SetLinkUpCallback(Callback< void > linkUp)
Definition wifi-mac.cc:1498
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition wifi-mac.cc:1099
const std::set< uint8_t > & GetLinkIds() const
Definition wifi-mac.cc:1132
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:1465
Mac48Address GetLocalAddress(const Mac48Address &remoteAddr) const
Get the local MAC address used to communicate with a remote STA.
Definition wifi-mac.cc:1891
EdcaQueues m_edca
This is a map from Access Category index to the corresponding channel access function.
Definition wifi-mac.h:1293
uint32_t m_bkMaxAmpduSize
maximum A-MPDU size for AC_BK (in bytes)
Definition wifi-mac.h:1303
virtual void NotifyRequestAccess(Ptr< Txop > txop, uint8_t linkId)
Notify that the given TXOP is requesting channel access on the given link.
Definition wifi-mac.cc:754
bool GetHtSupported(uint8_t linkId) const
Return whether the device supports HT on the given link.
Definition wifi-mac.cc:2012
void ForwardUp(Ptr< const Packet > packet, Mac48Address from, Mac48Address to)
Forward the packet up to the device.
Definition wifi-mac.cc:1829
virtual void ConfigureContentionWindow(uint32_t cwMin, uint32_t cwMax)
Definition wifi-mac.cc:795
bool Is6GhzBand(uint8_t linkId) const
Indicate if a given link is on the 6 GHz band.
Definition wifi-mac.cc:1281
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:1836
std::optional< std::reference_wrapper< const OriginatorBlockAckAgreement > > OriginatorAgreementOptConstRef
optional const reference to OriginatorBlockAckAgreement
Definition wifi-mac.h:713
Mac48Address GetAddress() const
Definition wifi-mac.cc:521
ForwardUpCallback m_forwardUp
Callback to forward packet up the stack.
Definition wifi-mac.h:1315
EhtCapabilities GetEhtCapabilities(uint8_t linkId) const
Return the EHT capabilities of the device for the given link.
Definition wifi-mac.cc:2456
Callback< void > m_linkUp
Callback when a link is up.
Definition wifi-mac.h:1034
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition wifi-mac.cc:1117
void SetupDcfQueue()
This method is a private utility invoked to configure the channel access function for devices that do...
Definition wifi-mac.cc:764
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:2357
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:1375
Callback< void, Ptr< const Packet >, Mac48Address, Mac48Address > ForwardUpCallback
This type defines the callback of a higher layer that a WifiMac(-derived) object invokes to pass a pa...
Definition wifi-mac.h:480
PsduResponseTimeoutTracedCallback m_psduResponseTimeoutCallback
PSDU response timeout traced callback.
Definition wifi-mac.h:1417
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:730
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:2612
uint32_t m_frameRetryLimit
the frame retry limit
Definition wifi-mac.h:1306
bool GetDsssSupported(uint8_t linkId) const
Return whether the device supports DSSS on the given link.
Definition wifi-mac.cc:1459
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:1062
void SetVoBlockAckInactivityTimeout(uint16_t timeout)
Set VO block ack inactivity timeout.
Definition wifi-mac.cc:2174
virtual std::unique_ptr< LinkEntity > CreateLinkEntity() const
Create a LinkEntity object.
Definition wifi-mac.cc:1105
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:1472
bool m_ctsToSelfSupported
flag indicating whether CTS-To-Self is supported
Definition wifi-mac.h:1275
uint16_t m_beMaxAmsduSize
maximum A-MSDU size for AC_BE (in bytes)
Definition wifi-mac.h:1297
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:1919
uint32_t m_viMaxAmpduSize
maximum A-MPDU size for AC_VI (in bytes)
Definition wifi-mac.h:1301
#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 AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeObjectVectorChecker()
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
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:250
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:273
Ptr< const AttributeChecker > MakeSsidChecker()
Definition ssid.cc:102
Ptr< const AttributeAccessor > MakeSsidAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition ssid.h:85
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
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:690
#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:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#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:454
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1307
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1324
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:64
@ 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:74
@ AC_BE
Best Effort.
Definition qos-utils.h:66
@ AC_VO
Voice.
Definition qos-utils.h:72
@ AC_VI
Video.
Definition qos-utils.h:70
@ AC_BK
Background.
Definition qos-utils.h:68
@ AC_UNDEF
Total number of ACs.
Definition qos-utils.h:78
@ AC_BEACON
Beacon queue.
Definition qos-utils.h:76
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:463
double MHz_u
MHz weak type.
Definition wifi-units.h:31
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:605
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
@ WIFI_MAC_DATA
@ WIFI_MAC_QOSDATA
WifiDirection
Wifi direction.
Definition wifi-utils.h:40
std::tuple< WifiContainerQueueType, WifiRcvAddr, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
@ LOG_FUNCTION
Function tracing for non-trivial function calls.
Definition log.h:98
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:612
std::map< tid_t, std::set< linkId_t > > WifiTidLinkMapping
TID-indexed map of the link set to which the TID is mapped.
Definition wifi-utils.h:77
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
ns3::Time timeout
Struct containing all supported rates.
The different BlockAckRequest variants.
The different BlockAck variants.
uint8_t support320MhzIn6Ghz
Support For 320 MHz In 6 GHz.
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