A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ap-wifi-mac.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006, 2009 INRIA
3 * Copyright (c) 2009 MIRKO BANCHI
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 * Mirko Banchi <mk.banchi@gmail.com>
20 */
21
22#include "ap-wifi-mac.h"
23
26#include "mac-rx-middle.h"
27#include "mac-tx-middle.h"
28#include "mgt-action-headers.h"
29#include "mgt-headers.h"
30#include "msdu-aggregator.h"
31#include "qos-txop.h"
34#include "wifi-mac-queue.h"
35#include "wifi-net-device.h"
36#include "wifi-phy.h"
37
38#include "ns3/eht-configuration.h"
39#include "ns3/eht-frame-exchange-manager.h"
40#include "ns3/he-configuration.h"
41#include "ns3/ht-configuration.h"
42#include "ns3/log.h"
43#include "ns3/multi-link-element.h"
44#include "ns3/packet.h"
45#include "ns3/pointer.h"
46#include "ns3/random-variable-stream.h"
47#include "ns3/simulator.h"
48#include "ns3/string.h"
49
50namespace ns3
51{
52
53NS_LOG_COMPONENT_DEFINE("ApWifiMac");
54
56
57TypeId
59{
60 static TypeId tid =
61 TypeId("ns3::ApWifiMac")
63 .SetGroupName("Wifi")
64 .AddConstructor<ApWifiMac>()
65 .AddAttribute(
66 "BeaconInterval",
67 "Delay between two beacons",
68 TimeValue(MicroSeconds(102400)),
71 .AddAttribute("BeaconJitter",
72 "A uniform random variable to cause the initial beacon starting time "
73 "(after simulation time 0) "
74 "to be distributed between 0 and the BeaconInterval.",
75 StringValue("ns3::UniformRandomVariable"),
77 MakePointerChecker<UniformRandomVariable>())
78 .AddAttribute("EnableBeaconJitter",
79 "If beacons are enabled, whether to jitter the initial send event.",
80 BooleanValue(true),
83 .AddAttribute("BeaconGeneration",
84 "Whether or not beacons are generated.",
85 BooleanValue(true),
88 .AddAttribute("FdBeaconInterval6GHz",
89 "Time between a Beacon frame and a FILS Discovery (FD) frame or between "
90 "two FD frames to be sent on a 6GHz link. A value of zero disables the "
91 "transmission of FD frames.",
92 TimeValue(Time{0}),
95 .AddAttribute("FdBeaconIntervalNon6GHz",
96 "Time between a Beacon frame and a FILS Discovery (FD) frame or between "
97 "two FD frames to be sent on a non-6GHz link. A value of zero disables "
98 "the transmission of FD frames.",
99 TimeValue(Time{0}),
102 .AddAttribute("SendUnsolProbeResp",
103 "Send unsolicited broadcast Probe Response instead of FILS Discovery",
104 BooleanValue(false),
107 .AddAttribute("EnableNonErpProtection",
108 "Whether or not protection mechanism should be used when non-ERP STAs "
109 "are present within the BSS."
110 "This parameter is only used when ERP is supported by the AP.",
111 BooleanValue(true),
114 .AddAttribute("BsrLifetime",
115 "Lifetime of Buffer Status Reports received from stations.",
119 .AddAttribute(
120 "CwMinsForSta",
121 "The CW min values that the AP advertises in EDCA Parameter Set elements and the "
122 "associated stations will use. The value of this attribute is an AC-indexed map "
123 "containing the CW min values for given ACs for all the links (sorted in "
124 "increasing order of link ID). If no values are provided for an AC, the same "
125 "values used by the AP are advertised. In case a string is used to set this "
126 "attribute, the string shall contain the pairs separated by a semicolon (;); "
127 "in every pair, the AC index and the list of values are separated by a blank "
128 "space, and the values of a list are separated by a comma (,) without spaces. "
129 "E.g. \"BE 31,31,31; VI 15,15,15\" defines the CW min values for AC BE and AC VI "
130 "for an AP MLD having three links.",
131 StringValue(""),
132 MakeAttributeContainerAccessor<UintAccessParamsPairValue, ';'>(
134 GetUintAccessParamsChecker<uint32_t>())
135 .AddAttribute(
136 "CwMaxsForSta",
137 "The CW max values that the AP advertises in EDCA Parameter Set elements and the "
138 "associated stations will use. The value of this attribute is an AC-indexed map "
139 "containing the CW max values for given ACs for all the links (sorted in "
140 "increasing order of link ID). If no values are provided for an AC, the same "
141 "values used by the AP are advertised. In case a string is used to set this "
142 "attribute, the string shall contain the pairs separated by a semicolon (;); "
143 "in every pair, the AC index and the list of values are separated by a blank "
144 "space, and the values of a list are separated by a comma (,) without spaces. "
145 "E.g. \"BE 31,31,31; VI 15,15,15\" defines the CW max values for AC BE and AC VI "
146 "for an AP MLD having three links.",
147 StringValue(""),
148 MakeAttributeContainerAccessor<UintAccessParamsPairValue, ';'>(
150 GetUintAccessParamsChecker<uint32_t>())
151 .AddAttribute(
152 "AifsnsForSta",
153 "The AIFSN values that the AP advertises in EDCA Parameter Set elements and the "
154 "associated stations will use. The value of this attribute is an AC-indexed map "
155 "containing the AIFSN values for given ACs for all the links (sorted in "
156 "increasing order of link ID). If no values are provided for an AC, the same "
157 "values used by the AP are advertised. In case a string is used to set this "
158 "attribute, the string shall contain the pairs separated by a semicolon (;); "
159 "in every pair, the AC index and the list of values are separated by a blank "
160 "space, and the values of a list are separated by a comma (,) without spaces. "
161 "E.g. \"BE 3,3,3; VI 2,2,2\" defines the AIFSN values for AC BE and AC VI "
162 "for an AP MLD having three links.",
163 StringValue(""),
164 MakeAttributeContainerAccessor<UintAccessParamsPairValue, ';'>(
166 GetUintAccessParamsChecker<uint8_t>())
167 .AddAttribute(
168 "TxopLimitsForSta",
169 "The TXOP limit values that the AP advertises in EDCA Parameter Set elements and "
170 "the associated stations will use. The value of this attribute is an AC-indexed "
171 "map containing the TXOP limit values for given ACs for all the links (sorted in "
172 "increasing order of link ID). If no values are provided for an AC, the same "
173 "values used by the AP are advertised. In case a string is used to set this "
174 "attribute, the string shall contain the pairs separated by a semicolon (;); "
175 "in every pair, the AC index and the list of values are separated by a blank "
176 "space, and the values of a list are separated by a comma (,) without spaces. "
177 "E.g. \"BE 3200us,3200us,3200us; VI 2400us,2400us,2400us\" defines the TXOP limit "
178 "values for AC BE and AC VI for an AP MLD having three links.",
179 StringValue(""),
180 MakeAttributeContainerAccessor<TimeAccessParamsPairValue, ';'>(
183 .AddTraceSource("AssociatedSta",
184 "A station associated with this access point.",
186 "ns3::ApWifiMac::AssociationCallback")
187 .AddTraceSource("DeAssociatedSta",
188 "A station lost association with this access point.",
190 "ns3::ApWifiMac::AssociationCallback");
191 return tid;
192}
193
194template <class T>
197{
198 return MakeAttributeContainerChecker<UintAccessParamsPairValue, ';'>(
200 AttributeContainerValue<UintegerValue, ',', std::vector>>(
201 MakeEnumChecker(AC_BE, "BE", AC_BK, "BK", AC_VI, "VI", AC_VO, "VO"),
203 MakeUintegerChecker<T>())));
204}
205
208{
209 return MakeAttributeContainerChecker<TimeAccessParamsPairValue, ';'>(
211 MakeEnumChecker(AC_BE, "BE", AC_BK, "BK", AC_VI, "VI", AC_VO, "VO"),
213}
214
216 : m_enableBeaconGeneration(false)
217{
218 NS_LOG_FUNCTION(this);
219 m_beaconTxop = CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BEACON"));
221
222 // Let the lower layers know that we are acting as an AP.
224}
225
227{
228 NS_LOG_FUNCTION(this);
229}
230
231void
233{
234 NS_LOG_FUNCTION(this);
236 m_beaconTxop = nullptr;
239}
240
242{
245}
246
247std::unique_ptr<WifiMac::LinkEntity>
249{
250 return std::make_unique<ApLinkEntity>();
251}
252
254ApWifiMac::GetLink(uint8_t linkId) const
255{
256 return static_cast<ApLinkEntity&>(WifiMac::GetLink(linkId));
257}
258
259void
261{
262 NS_LOG_FUNCTION(this);
264 // DCF behavior may be edited here; the default is PIFS access with zero backoff
265 m_beaconTxop->SetAifsns(std::vector<uint8_t>(GetNLinks(), 1));
266 m_beaconTxop->SetMinCws(std::vector<uint32_t>(GetNLinks(), 0));
267 m_beaconTxop->SetMaxCws(std::vector<uint32_t>(GetNLinks(), 0));
268 for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
269 {
271 }
272}
273
276{
277 if (ac == AC_BEACON)
278 {
280 }
281 return WifiMac::GetTxopQueue(ac);
282}
283
284void
286{
287 NS_LOG_FUNCTION(this << enable);
288 for (uint8_t linkId = 0; linkId < GetNLinks(); ++linkId)
289 {
290 if (!enable)
291 {
292 GetLink(linkId).beaconEvent.Cancel();
293 }
294 else if (!m_enableBeaconGeneration)
295 {
296 GetLink(linkId).beaconEvent =
298 }
299 }
301}
302
303Time
305{
306 NS_LOG_FUNCTION(this);
307 return m_beaconInterval;
308}
309
310void
312{
313 NS_LOG_FUNCTION(this << &linkUp);
315
316 // The approach taken here is that, from the point of view of an AP,
317 // the link is always up, so we immediately invoke the callback if
318 // one is set
319 linkUp();
320}
321
322void
324{
325 NS_LOG_FUNCTION(this << interval);
326 if ((interval.GetMicroSeconds() % 1024) != 0)
327 {
328 NS_FATAL_ERROR("beacon interval should be multiple of 1024us (802.11 time unit), see IEEE "
329 "Std. 802.11-2012");
330 }
331 if (interval.GetMicroSeconds() > (1024 * 65535))
332 {
334 "beacon interval should be smaller then or equal to 65535 * 1024us (802.11 time unit)");
335 }
336 m_beaconInterval = interval;
337}
338
339int64_t
341{
342 NS_LOG_FUNCTION(this << stream);
343 m_beaconJitter->SetStream(stream);
344 auto currentStream = stream + 1;
345 currentStream += m_beaconTxop->AssignStreams(currentStream);
346 currentStream += WifiMac::AssignStreams(currentStream);
347 return (currentStream - stream);
348}
349
350void
352{
353 NS_LOG_FUNCTION(this << +linkId);
354 auto& link = GetLink(linkId);
355 if (GetErpSupported(linkId) && GetShortSlotTimeSupported() && (link.numNonErpStations == 0))
356 {
357 for (const auto& sta : link.staList)
358 {
360 {
361 link.shortSlotTimeEnabled = false;
362 return;
363 }
364 }
365 link.shortSlotTimeEnabled = true;
366 }
367 else
368 {
369 link.shortSlotTimeEnabled = false;
370 }
371}
372
373void
375{
376 NS_LOG_FUNCTION(this << +linkId);
377 auto& link = GetLink(linkId);
378 if (GetErpSupported(linkId) && GetWifiPhy(linkId)->GetShortPhyPreambleSupported())
379 {
380 for (const auto& sta : link.staList)
381 {
382 if (!GetWifiRemoteStationManager(linkId)->GetErpOfdmSupported(sta.second) ||
383 !GetWifiRemoteStationManager(linkId)->GetShortPreambleSupported(sta.second))
384 {
385 link.shortPreambleEnabled = false;
386 return;
387 }
388 }
389 link.shortPreambleEnabled = true;
390 }
391 else
392 {
393 link.shortPreambleEnabled = false;
394 }
395}
396
397void
399{
400 NS_LOG_FUNCTION(this << packet << from << to);
401 // If we are not a QoS AP then we definitely want to use AC_BE to
402 // transmit the packet. A TID of zero will map to AC_BE (through \c
403 // QosUtilsMapTidToAc()), so we use that as our default here.
404 uint8_t tid = 0;
405
406 // If we are a QoS AP then we attempt to get a TID for this packet
407 if (GetQosSupported())
408 {
409 tid = QosUtilsGetTidForPacket(packet);
410 // Any value greater than 7 is invalid and likely indicates that
411 // the packet had no QoS tag, so we revert to zero, which'll
412 // mean that AC_BE is used.
413 if (tid > 7)
414 {
415 tid = 0;
416 }
417 }
418
419 ForwardDown(packet, from, to, tid);
420}
421
422void
424{
425 NS_LOG_FUNCTION(this << packet << from << to << +tid);
426 WifiMacHeader hdr;
427
428 // For now, an AP that supports QoS does not support non-QoS
429 // associations, and vice versa. In future the AP model should
430 // support simultaneously associated QoS and non-QoS STAs, at which
431 // point there will need to be per-association QoS state maintained
432 // by the association state machine, and consulted here.
433 if (GetQosSupported())
434 {
437 hdr.SetQosNoEosp();
438 hdr.SetQosNoAmsdu();
439 // Transmission of multiple frames in the same Polled TXOP is not supported for now
440 hdr.SetQosTxopLimit(0);
441 // Fill in the QoS control field in the MAC header
442 hdr.SetQosTid(tid);
443 }
444 else
445 {
447 }
448
449 if (GetQosSupported())
450 {
451 hdr.SetNoOrder(); // explicitly set to 0 for the time being since HT control field is not
452 // yet implemented (set it to 1 when implemented)
453 }
454
455 std::list<Mac48Address> addr2Set;
456 if (to.IsGroup())
457 {
458 // broadcast frames are transmitted on all the links
459 for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
460 {
461 addr2Set.push_back(GetFrameExchangeManager(linkId)->GetAddress());
462 }
463 }
464 else
465 {
466 // the Transmitter Address (TA) is the MLD address only for non-broadcast data frames
467 // exchanged between two MLDs
468 addr2Set = {GetAddress()};
469 auto linkId = IsAssociated(to);
470 NS_ASSERT_MSG(linkId, "Station " << to << "is not associated, cannot send it a frame");
471 if (GetNLinks() == 1 || !GetWifiRemoteStationManager(*linkId)->GetMldAddress(to))
472 {
473 addr2Set = {GetFrameExchangeManager(*linkId)->GetAddress()};
474 }
475 }
476
477 for (const auto& addr2 : addr2Set)
478 {
479 hdr.SetAddr1(to);
480 hdr.SetAddr2(addr2);
481 hdr.SetAddr3(from);
482 hdr.SetDsFrom();
483 hdr.SetDsNotTo();
484
485 if (GetQosSupported())
486 {
487 // Sanity check that the TID is valid
488 NS_ASSERT(tid < 8);
489 GetQosTxop(tid)->Queue(packet, hdr);
490 }
491 else
492 {
493 GetTxop()->Queue(packet, hdr);
494 }
495 }
496}
497
498bool
500{
501 return (to.IsGroup() || IsAssociated(to));
502}
503
504void
506{
507 NS_LOG_FUNCTION(this << packet << to << from);
508 if (CanForwardPacketsTo(to))
509 {
510 ForwardDown(packet, from, to);
511 }
512 else
513 {
514 NotifyTxDrop(packet);
515 }
516}
517
518void
520{
521 NS_LOG_FUNCTION(this << packet << to);
522 // We're sending this packet with a from address that is our own. We
523 // get that address from the lower MAC and make use of the
524 // from-spoofing Enqueue() method to avoid duplicated code.
525 Enqueue(packet, to, GetAddress());
526}
527
528bool
530{
531 NS_LOG_FUNCTION(this);
532 return true;
533}
534
536ApWifiMac::GetSupportedRates(uint8_t linkId) const
537{
538 NS_LOG_FUNCTION(this << +linkId);
539 AllSupportedRates rates;
540 // Send the set of supported rates and make sure that we indicate
541 // the Basic Rate set in this set of supported rates.
542 for (const auto& mode : GetWifiPhy(linkId)->GetModeList())
543 {
544 uint64_t modeDataRate = mode.GetDataRate(GetWifiPhy(linkId)->GetChannelWidth());
545 NS_LOG_DEBUG("Adding supported rate of " << modeDataRate);
546 rates.AddSupportedRate(modeDataRate);
547 // Add rates that are part of the BSSBasicRateSet (manufacturer dependent!)
548 // here we choose to add the mandatory rates to the BSSBasicRateSet,
549 // except for 802.11b where we assume that only the non HR-DSSS rates are part of the
550 // BSSBasicRateSet
551 if (mode.IsMandatory() && (mode.GetModulationClass() != WIFI_MOD_CLASS_HR_DSSS))
552 {
553 NS_LOG_DEBUG("Adding basic mode " << mode.GetUniqueName());
554 GetWifiRemoteStationManager(linkId)->AddBasicMode(mode);
555 }
556 }
557 // set the basic rates
558 for (uint8_t j = 0; j < GetWifiRemoteStationManager(linkId)->GetNBasicModes(); j++)
559 {
560 WifiMode mode = GetWifiRemoteStationManager(linkId)->GetBasicMode(j);
561 uint64_t modeDataRate = mode.GetDataRate(GetWifiPhy(linkId)->GetChannelWidth());
562 NS_LOG_DEBUG("Setting basic rate " << mode.GetUniqueName());
563 rates.SetBasicRate(modeDataRate);
564 }
565 // If it is a HT AP, then add the BSSMembershipSelectorSet
566 // The standard says that the BSSMembershipSelectorSet
567 // must have its MSB set to 1 (must be treated as a Basic Rate)
568 // Also the standard mentioned that at least 1 element should be included in the SupportedRates
569 // the rest can be in the ExtendedSupportedRates
570 if (GetHtSupported(linkId))
571 {
572 for (const auto& selector : GetWifiPhy(linkId)->GetBssMembershipSelectorList())
573 {
574 rates.AddBssMembershipSelectorRate(selector);
575 }
576 }
577 return rates;
578}
579
582{
583 NS_LOG_FUNCTION(this << +linkId);
585 DsssParameterSet dsssParameters;
586 dsssParameters.SetCurrentChannel(GetWifiPhy(linkId)->GetChannelNumber());
587 return dsssParameters;
588}
589
591ApWifiMac::GetCapabilities(uint8_t linkId) const
592{
593 NS_LOG_FUNCTION(this << +linkId);
594 CapabilityInformation capabilities;
595 capabilities.SetShortPreamble(GetLink(linkId).shortPreambleEnabled);
596 capabilities.SetShortSlotTime(GetLink(linkId).shortSlotTimeEnabled);
597 capabilities.SetEss();
598 return capabilities;
599}
600
602ApWifiMac::GetErpInformation(uint8_t linkId) const
603{
604 NS_LOG_FUNCTION(this << +linkId);
605 NS_ASSERT(GetErpSupported(linkId));
606 ErpInformation information;
607
608 information.SetNonErpPresent(GetLink(linkId).numNonErpStations > 0);
609 information.SetUseProtection(GetUseNonErpProtection(linkId));
610 if (GetLink(linkId).shortPreambleEnabled)
611 {
612 information.SetBarkerPreambleMode(0);
613 }
614 else
615 {
616 information.SetBarkerPreambleMode(1);
617 }
618
619 return information;
620}
621
624{
625 NS_LOG_FUNCTION(this << +linkId);
627 EdcaParameterSet edcaParameters;
628
629 Ptr<QosTxop> edca;
630 Time txopLimit;
631
632 edca = GetQosTxop(AC_BE);
633 edcaParameters.SetBeAci(0);
634 edcaParameters.SetBeCWmin(m_cwMinsForSta.contains(AC_BE) ? m_cwMinsForSta.at(AC_BE).at(linkId)
635 : edca->GetMinCw(linkId));
636 edcaParameters.SetBeCWmax(m_cwMaxsForSta.contains(AC_BE) ? m_cwMaxsForSta.at(AC_BE).at(linkId)
637 : edca->GetMaxCw(linkId));
638 edcaParameters.SetBeAifsn(m_aifsnsForSta.contains(AC_BE) ? m_aifsnsForSta.at(AC_BE).at(linkId)
639 : edca->GetAifsn(linkId));
640 txopLimit = m_txopLimitsForSta.contains(AC_BE) ? m_txopLimitsForSta.at(AC_BE).at(linkId)
641 : edca->GetTxopLimit(linkId);
642 edcaParameters.SetBeTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
643
644 edca = GetQosTxop(AC_BK);
645 edcaParameters.SetBkAci(1);
646 edcaParameters.SetBkCWmin(m_cwMinsForSta.contains(AC_BK) ? m_cwMinsForSta.at(AC_BK).at(linkId)
647 : edca->GetMinCw(linkId));
648 edcaParameters.SetBkCWmax(m_cwMaxsForSta.contains(AC_BK) ? m_cwMaxsForSta.at(AC_BK).at(linkId)
649 : edca->GetMaxCw(linkId));
650 edcaParameters.SetBkAifsn(m_aifsnsForSta.contains(AC_BK) ? m_aifsnsForSta.at(AC_BK).at(linkId)
651 : edca->GetAifsn(linkId));
652 txopLimit = m_txopLimitsForSta.contains(AC_BK) ? m_txopLimitsForSta.at(AC_BK).at(linkId)
653 : edca->GetTxopLimit(linkId);
654 edcaParameters.SetBkTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
655
656 edca = GetQosTxop(AC_VI);
657 edcaParameters.SetViAci(2);
658 edcaParameters.SetViCWmin(m_cwMinsForSta.contains(AC_VI) ? m_cwMinsForSta.at(AC_VI).at(linkId)
659 : edca->GetMinCw(linkId));
660 edcaParameters.SetViCWmax(m_cwMaxsForSta.contains(AC_VI) ? m_cwMaxsForSta.at(AC_VI).at(linkId)
661 : edca->GetMaxCw(linkId));
662 edcaParameters.SetViAifsn(m_aifsnsForSta.contains(AC_VI) ? m_aifsnsForSta.at(AC_VI).at(linkId)
663 : edca->GetAifsn(linkId));
664 txopLimit = m_txopLimitsForSta.contains(AC_VI) ? m_txopLimitsForSta.at(AC_VI).at(linkId)
665 : edca->GetTxopLimit(linkId);
666 edcaParameters.SetViTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
667
668 edca = GetQosTxop(AC_VO);
669 edcaParameters.SetVoAci(3);
670 edcaParameters.SetVoCWmin(m_cwMinsForSta.contains(AC_VO) ? m_cwMinsForSta.at(AC_VO).at(linkId)
671 : edca->GetMinCw(linkId));
672 edcaParameters.SetVoCWmax(m_cwMaxsForSta.contains(AC_VO) ? m_cwMaxsForSta.at(AC_VO).at(linkId)
673 : edca->GetMaxCw(linkId));
674 edcaParameters.SetVoAifsn(m_aifsnsForSta.contains(AC_VO) ? m_aifsnsForSta.at(AC_VO).at(linkId)
675 : edca->GetAifsn(linkId));
676 txopLimit = m_txopLimitsForSta.contains(AC_VO) ? m_txopLimitsForSta.at(AC_VO).at(linkId)
677 : edca->GetTxopLimit(linkId);
678 edcaParameters.SetVoTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
679
680 edcaParameters.SetQosInfo(0);
681
682 return edcaParameters;
683}
684
685std::optional<MuEdcaParameterSet>
687{
688 NS_LOG_FUNCTION(this);
690
691 Ptr<HeConfiguration> heConfiguration = GetHeConfiguration();
692 NS_ASSERT(heConfiguration);
693
694 MuEdcaParameterSet muEdcaParameters;
695 muEdcaParameters.SetQosInfo(0);
696
697 UintegerValue uintegerValue;
698 TimeValue timeValue;
699
700 heConfiguration->GetAttribute("MuBeAifsn", uintegerValue);
701 muEdcaParameters.SetMuAifsn(AC_BE, uintegerValue.Get());
702 heConfiguration->GetAttribute("MuBeCwMin", uintegerValue);
703 muEdcaParameters.SetMuCwMin(AC_BE, uintegerValue.Get());
704 heConfiguration->GetAttribute("MuBeCwMax", uintegerValue);
705 muEdcaParameters.SetMuCwMax(AC_BE, uintegerValue.Get());
706 heConfiguration->GetAttribute("BeMuEdcaTimer", timeValue);
707 muEdcaParameters.SetMuEdcaTimer(AC_BE, timeValue.Get());
708
709 heConfiguration->GetAttribute("MuBkAifsn", uintegerValue);
710 muEdcaParameters.SetMuAifsn(AC_BK, uintegerValue.Get());
711 heConfiguration->GetAttribute("MuBkCwMin", uintegerValue);
712 muEdcaParameters.SetMuCwMin(AC_BK, uintegerValue.Get());
713 heConfiguration->GetAttribute("MuBkCwMax", uintegerValue);
714 muEdcaParameters.SetMuCwMax(AC_BK, uintegerValue.Get());
715 heConfiguration->GetAttribute("BkMuEdcaTimer", timeValue);
716 muEdcaParameters.SetMuEdcaTimer(AC_BK, timeValue.Get());
717
718 heConfiguration->GetAttribute("MuViAifsn", uintegerValue);
719 muEdcaParameters.SetMuAifsn(AC_VI, uintegerValue.Get());
720 heConfiguration->GetAttribute("MuViCwMin", uintegerValue);
721 muEdcaParameters.SetMuCwMin(AC_VI, uintegerValue.Get());
722 heConfiguration->GetAttribute("MuViCwMax", uintegerValue);
723 muEdcaParameters.SetMuCwMax(AC_VI, uintegerValue.Get());
724 heConfiguration->GetAttribute("ViMuEdcaTimer", timeValue);
725 muEdcaParameters.SetMuEdcaTimer(AC_VI, timeValue.Get());
726
727 heConfiguration->GetAttribute("MuVoAifsn", uintegerValue);
728 muEdcaParameters.SetMuAifsn(AC_VO, uintegerValue.Get());
729 heConfiguration->GetAttribute("MuVoCwMin", uintegerValue);
730 muEdcaParameters.SetMuCwMin(AC_VO, uintegerValue.Get());
731 heConfiguration->GetAttribute("MuVoCwMax", uintegerValue);
732 muEdcaParameters.SetMuCwMax(AC_VO, uintegerValue.Get());
733 heConfiguration->GetAttribute("VoMuEdcaTimer", timeValue);
734 muEdcaParameters.SetMuEdcaTimer(AC_VO, timeValue.Get());
735
736 // The timers of the MU EDCA Parameter Set must be either all zero or all
737 // non-zero. The information element is advertised if all timers are non-zero
738 auto timerNotNull = [&muEdcaParameters](uint8_t aci) {
739 return !muEdcaParameters.GetMuEdcaTimer(aci).IsZero();
740 };
741 auto aci = {0, 1, 2, 3};
742 if (std::all_of(aci.begin(), aci.end(), timerNotNull))
743 {
744 return muEdcaParameters;
745 }
746
747 NS_ABORT_MSG_UNLESS(std::none_of(aci.begin(), aci.end(), timerNotNull),
748 "MU EDCA Timers must be all zero if the IE is not advertised.");
749
750 return std::nullopt;
751}
752
753std::optional<ReducedNeighborReport>
755{
756 NS_LOG_FUNCTION(this << +linkId);
757
758 if (GetNLinks() <= 1)
759 {
760 return std::nullopt;
761 }
762
765
766 for (uint8_t index = 0; index < GetNLinks(); ++index)
767 {
768 if (index != linkId) // all links but the one used to send this Beacon frame
769 {
770 rnr.AddNbrApInfoField();
771 std::size_t nbrId = rnr.GetNNbrApInfoFields() - 1;
773 rnr.AddTbttInformationField(nbrId);
774 rnr.SetBssid(nbrId, 0, GetLink(index).feManager->GetAddress());
775 rnr.SetShortSsid(nbrId, 0, 0);
776 rnr.SetBssParameters(nbrId, 0, 0);
777 rnr.SetPsd20MHz(nbrId, 0, 0);
778 rnr.SetMldParameters(nbrId, 0, 0, index, 0);
779 }
780 }
781 return rnr;
782}
783
785ApWifiMac::GetMultiLinkElement(uint8_t linkId, WifiMacType frameType, const Mac48Address& to)
786{
787 NS_LOG_FUNCTION(this << +linkId << frameType << to);
788 NS_ABORT_IF(GetNLinks() == 1);
789
792 mle.SetLinkIdInfo(linkId);
794
795 auto ehtConfiguration = GetEhtConfiguration();
796 NS_ASSERT(ehtConfiguration);
797
798 if (BooleanValue emlsrActivated;
799 ehtConfiguration->GetAttributeFailSafe("EmlsrActivated", emlsrActivated) &&
800 emlsrActivated.Get())
801 {
802 mle.SetEmlsrSupported(true);
803 // When the EMLSR Padding Delay subfield is included in a frame sent by an AP affiliated
804 // with an AP MLD, the EMLSR Padding Delay subfield is reserved.
805 // When the EMLSR Transition Delay subfield is included in a frame sent by an AP affiliated
806 // with an AP MLD, the EMLSR Transition Delay subfield is reserved. (Sec. 9.4.2.312.2.3
807 // of 802.11be D2.3)
808 TimeValue time;
809 ehtConfiguration->GetAttribute("TransitionTimeout", time);
810 mle.SetTransitionTimeout(time.Get());
811
812 // An AP affiliated with an AP MLD may include the Medium Synchronization Delay Information
813 // subfield in the Common Info field of the Basic Multi-Link element carried in transmitted
814 // (Re)Association Response or Multi-Link Probe Response frames to provide medium
815 // synchronization information used by the AP MLD. (Section 35.3.16.8.2 of 802.11be D3.1)
816 if (frameType == WIFI_MAC_MGT_ASSOCIATION_RESPONSE)
817 {
818 auto& commonInfo = mle.GetCommonInfoBasic();
819
820 ehtConfiguration->GetAttribute("MediumSyncDuration", time);
821 commonInfo.SetMediumSyncDelayTimer(time.Get());
822
823 IntegerValue ofdmEdThres;
824 ehtConfiguration->GetAttribute("MsdOfdmEdThreshold", ofdmEdThres);
825 commonInfo.SetMediumSyncOfdmEdThreshold(ofdmEdThres.Get());
826
827 UintegerValue maxNTxops;
828 ehtConfiguration->GetAttribute("MsdMaxNTxops", maxNTxops);
829 commonInfo.SetMediumSyncMaxNTxops(maxNTxops.Get());
830 }
831 }
832
833 // The MLD Capabilities And Operations subfield is present in the Common Info field of the
834 // Basic Multi-Link element carried in Beacon, Probe Response, (Re)Association Request, and
835 // (Re)Association Response frames. (Sec. 9.4.2.312.2.3 of 802.11be D3.1)
836 if (frameType == WIFI_MAC_MGT_BEACON || frameType == WIFI_MAC_MGT_PROBE_RESPONSE ||
840 {
841 auto& mldCapabilities = mle.GetCommonInfoBasic().m_mldCapabilities;
842 mldCapabilities.emplace();
843 mldCapabilities->maxNSimultaneousLinks = GetNLinks() - 1; // assuming STR for now
844 mldCapabilities->srsSupport = 0;
846 ehtConfiguration->GetAttributeFailSafe("TidToLinkMappingNegSupport", negSupport);
847 mldCapabilities->tidToLinkMappingSupport = static_cast<uint8_t>(negSupport.Get());
848 mldCapabilities->freqSepForStrApMld = 0; // not supported yet
849 mldCapabilities->aarSupport = 0; // not supported yet
850 }
851
852 // if the Multi-Link Element is being inserted in a (Re)Association Response frame
853 // and the remote station is affiliated with an MLD, try multi-link setup
854 if (auto staMldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(to);
855 (frameType == WIFI_MAC_MGT_ASSOCIATION_RESPONSE ||
857 staMldAddress.has_value())
858 {
859 for (uint8_t i = 0; i < GetNLinks(); i++)
860 {
861 auto remoteStationManager = GetWifiRemoteStationManager(i);
862 if (auto staAddress = remoteStationManager->GetAffiliatedStaAddress(*staMldAddress);
863 i != linkId && staAddress.has_value() &&
864 (remoteStationManager->IsWaitAssocTxOk(*staAddress) ||
865 remoteStationManager->IsAssocRefused(*staAddress)))
866 {
867 // For each requested link in addition to the link on which the
868 // (Re)Association Response frame is transmitted, the Link Info field
869 // of the Basic Multi-Link element carried in the (Re)Association
870 // Response frame shall contain the corresponding Per-STA Profile
871 // subelement(s) (Sec. 35.3.5.4 of 802.11be D2.0)
873 auto& perStaProfile = mle.GetPerStaProfile(mle.GetNPerStaProfileSubelements() - 1);
874 // The Link ID subfield of the STA Control field of the Per-STA Profile
875 // subelement for the AP corresponding to a link is set to the link ID
876 // of the AP affiliated with the AP MLD that is operating on that link.
877 perStaProfile.SetLinkId(i);
878 perStaProfile.SetCompleteProfile();
879 // For each Per-STA Profile subelement included in the Link Info field,
880 // the Complete Profile subfield of the STA Control field shall be set to 1
881 perStaProfile.SetStaMacAddress(GetFrameExchangeManager(i)->GetAddress());
882 perStaProfile.SetAssocResponse(GetAssocResp(*staAddress, i));
883 }
884 }
885 }
886
887 return mle;
888}
889
891ApWifiMac::GetHtOperation(uint8_t linkId) const
892{
893 NS_LOG_FUNCTION(this << +linkId);
894 NS_ASSERT(GetHtSupported(linkId));
895 HtOperation operation;
896 auto phy = GetWifiPhy(linkId);
897 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
898
899 operation.SetPrimaryChannel(phy->GetPrimaryChannelNumber(20));
900 operation.SetRifsMode(false);
901 operation.SetNonGfHtStasPresent(true);
902 if (phy->GetChannelWidth() > 20)
903 {
904 operation.SetSecondaryChannelOffset(1);
905 operation.SetStaChannelWidth(1);
906 }
907 if (GetLink(linkId).numNonHtStations == 0)
908 {
910 }
911 else
912 {
914 }
915 uint64_t maxSupportedRate = 0; // in bit/s
916 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HT))
917 {
918 uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
919 NS_ASSERT(nss > 0 && nss < 5);
920 uint64_t dataRate =
921 mcs.GetDataRate(phy->GetChannelWidth(),
922 GetHtConfiguration()->GetShortGuardIntervalSupported() ? 400 : 800,
923 nss);
924 if (dataRate > maxSupportedRate)
925 {
926 maxSupportedRate = dataRate;
927 NS_LOG_DEBUG("Updating maxSupportedRate to " << maxSupportedRate);
928 }
929 }
930 uint8_t maxSpatialStream = phy->GetMaxSupportedTxSpatialStreams();
931 auto mcsList = phy->GetMcsList(WIFI_MOD_CLASS_HT);
932 uint8_t nMcs = mcsList.size();
933 for (const auto& sta : GetLink(linkId).staList)
934 {
935 if (remoteStationManager->GetHtSupported(sta.second) ||
936 remoteStationManager->GetStationHe6GhzCapabilities(sta.second))
937 {
938 uint64_t maxSupportedRateByHtSta = 0; // in bit/s
939 auto itMcs = mcsList.begin();
940 for (uint8_t j = 0;
941 j < (std::min(nMcs, remoteStationManager->GetNMcsSupported(sta.second)));
942 j++)
943 {
944 WifiMode mcs = *itMcs++;
945 uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
946 NS_ASSERT(nss > 0 && nss < 5);
947 uint64_t dataRate = mcs.GetDataRate(
948 remoteStationManager->GetChannelWidthSupported(sta.second),
949 remoteStationManager->GetShortGuardIntervalSupported(sta.second) ? 400 : 800,
950 nss);
951 if (dataRate > maxSupportedRateByHtSta)
952 {
953 maxSupportedRateByHtSta = dataRate;
954 }
955 }
956 if (maxSupportedRateByHtSta < maxSupportedRate)
957 {
958 maxSupportedRate = maxSupportedRateByHtSta;
959 }
960 if (remoteStationManager->GetNMcsSupported(sta.second) < nMcs)
961 {
962 nMcs = remoteStationManager->GetNMcsSupported(sta.second);
963 }
964 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
965 {
966 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
967 }
968 }
969 }
971 static_cast<uint16_t>(maxSupportedRate / 1e6)); // in Mbit/s
972 operation.SetTxMcsSetDefined(nMcs > 0);
973 operation.SetTxMaxNSpatialStreams(maxSpatialStream);
974 // To be filled in once supported
975 operation.SetObssNonHtStasPresent(0);
976 operation.SetDualBeacon(0);
977 operation.SetDualCtsProtection(0);
978 operation.SetStbcBeacon(0);
980 operation.SetPcoActive(0);
981 operation.SetPhase(0);
982 operation.SetRxMcsBitmask(0);
983 operation.SetTxRxMcsSetUnequal(0);
984 operation.SetTxUnequalModulation(0);
985
986 return operation;
987}
988
990ApWifiMac::GetVhtOperation(uint8_t linkId) const
991{
992 NS_LOG_FUNCTION(this << +linkId);
993 NS_ASSERT(GetVhtSupported(linkId));
994 VhtOperation operation;
995 auto phy = GetWifiPhy(linkId);
996 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
997
998 const uint16_t bssBandwidth = phy->GetChannelWidth();
999 // Set to 0 for 20 MHz or 40 MHz BSS bandwidth.
1000 // Set to 1 for 80 MHz, 160 MHz or 80+80 MHz BSS bandwidth.
1001 operation.SetChannelWidth((bssBandwidth > 40) ? 1 : 0);
1002 // For 20, 40, or 80 MHz BSS bandwidth, indicates the channel center frequency
1003 // index for the 20, 40, or 80 MHz channel on which the VHT BSS operates.
1004 // For 160 MHz BSS bandwidth and the Channel Width subfield equal to 1,
1005 // indicates the channel center frequency index of the 80 MHz channel
1006 // segment that contains the primary channel.
1008 (bssBandwidth == 160)
1009 ? phy->GetOperatingChannel().GetPrimaryChannelNumber(80, phy->GetStandard())
1010 : phy->GetChannelNumber());
1011 // For a 20, 40, or 80 MHz BSS bandwidth, this subfield is set to 0.
1012 // For a 160 MHz BSS bandwidth and the Channel Width subfield equal to 1,
1013 // indicates the channel center frequency index of the 160 MHz channel on
1014 // which the VHT BSS operates.
1015 operation.SetChannelCenterFrequencySegment1((bssBandwidth == 160) ? phy->GetChannelNumber()
1016 : 0);
1017 uint8_t maxSpatialStream = phy->GetMaxSupportedRxSpatialStreams();
1018 for (const auto& sta : GetLink(linkId).staList)
1019 {
1020 if (remoteStationManager->GetVhtSupported(sta.second))
1021 {
1022 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
1023 {
1024 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
1025 }
1026 }
1027 }
1028 for (uint8_t nss = 1; nss <= maxSpatialStream; nss++)
1029 {
1030 uint8_t maxMcs =
1031 9; // TBD: hardcode to 9 for now since we assume all MCS values are supported
1032 operation.SetMaxVhtMcsPerNss(nss, maxMcs);
1033 }
1034
1035 return operation;
1036}
1037
1039ApWifiMac::GetHeOperation(uint8_t linkId) const
1040{
1041 NS_LOG_FUNCTION(this << +linkId);
1043 HeOperation operation;
1044 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
1045
1046 uint8_t maxSpatialStream = GetWifiPhy(linkId)->GetMaxSupportedRxSpatialStreams();
1047 for (const auto& sta : GetLink(linkId).staList)
1048 {
1049 if (remoteStationManager->GetHeSupported(sta.second))
1050 {
1051 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
1052 {
1053 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
1054 }
1055 }
1056 }
1057 for (uint8_t nss = 1; nss <= maxSpatialStream; nss++)
1058 {
1059 operation.SetMaxHeMcsPerNss(
1060 nss,
1061 11); // TBD: hardcode to 11 for now since we assume all MCS values are supported
1062 }
1063 operation.m_bssColorInfo.m_bssColor = GetHeConfiguration()->GetBssColor();
1064
1065 if (auto phy = GetWifiPhy(linkId); phy && phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ)
1066 {
1068 const auto bw = phy->GetChannelWidth();
1069 const auto ch = phy->GetOperatingChannel();
1070 op6Ghz.m_chWid = (bw == 20) ? 0 : (bw == 40) ? 1 : (bw == 80) ? 2 : 3;
1071 op6Ghz.m_primCh = ch.GetPrimaryChannelNumber(20, WIFI_STANDARD_80211ax);
1072 op6Ghz.m_chCntrFreqSeg0 =
1073 (bw == 160) ? ch.GetPrimaryChannelNumber(80, WIFI_STANDARD_80211ax) : ch.GetNumber();
1074 // TODO: for 80+80 MHz channels, set this field to the secondary 80 MHz segment number
1075 op6Ghz.m_chCntrFreqSeg1 = (bw == 160) ? ch.GetNumber() : 0;
1076
1077 operation.m_6GHzOpInfo = op6Ghz;
1078 }
1079
1080 return operation;
1081}
1082
1084ApWifiMac::GetEhtOperation(uint8_t linkId) const
1085{
1086 NS_LOG_FUNCTION(this << +linkId);
1088 EhtOperation operation;
1089 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
1090
1091 auto maxSpatialStream = GetWifiPhy(linkId)->GetMaxSupportedRxSpatialStreams();
1092 for (const auto& sta : GetLink(linkId).staList)
1093 {
1094 if (remoteStationManager->GetEhtSupported(sta.second))
1095 {
1096 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
1097 {
1098 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
1099 }
1100 }
1101 }
1102 operation.SetMaxRxNss(maxSpatialStream, 0, WIFI_EHT_MAX_MCS_INDEX);
1103 operation.SetMaxTxNss(maxSpatialStream, 0, WIFI_EHT_MAX_MCS_INDEX);
1104 return operation;
1105}
1106
1107void
1109{
1110 NS_LOG_FUNCTION(this << to << +linkId);
1111 WifiMacHeader hdr;
1113 hdr.SetAddr1(to);
1114 hdr.SetAddr2(GetLink(linkId).feManager->GetAddress());
1115 hdr.SetAddr3(GetLink(linkId).feManager->GetAddress());
1116 hdr.SetDsNotFrom();
1117 hdr.SetDsNotTo();
1118 Ptr<Packet> packet = Create<Packet>();
1120 probe.Get<Ssid>() = GetSsid();
1121 auto supportedRates = GetSupportedRates(linkId);
1122 probe.Get<SupportedRates>() = supportedRates.rates;
1123 probe.Get<ExtendedSupportedRatesIE>() = supportedRates.extendedRates;
1125 probe.Capabilities() = GetCapabilities(linkId);
1126 GetWifiRemoteStationManager(linkId)->SetShortPreambleEnabled(
1127 GetLink(linkId).shortPreambleEnabled);
1128 GetWifiRemoteStationManager(linkId)->SetShortSlotTimeEnabled(
1129 GetLink(linkId).shortSlotTimeEnabled);
1130 if (GetDsssSupported(linkId))
1131 {
1132 probe.Get<DsssParameterSet>() = GetDsssParameterSet(linkId);
1133 }
1134 if (GetErpSupported(linkId))
1135 {
1136 probe.Get<ErpInformation>() = GetErpInformation(linkId);
1137 }
1138 if (GetQosSupported())
1139 {
1140 probe.Get<EdcaParameterSet>() = GetEdcaParameterSet(linkId);
1141 }
1142 if (GetHtSupported(linkId))
1143 {
1145 probe.Get<HtCapabilities>() = GetHtCapabilities(linkId);
1146 probe.Get<HtOperation>() = GetHtOperation(linkId);
1147 }
1148 if (GetVhtSupported(linkId))
1149 {
1150 probe.Get<VhtCapabilities>() = GetVhtCapabilities(linkId);
1151 probe.Get<VhtOperation>() = GetVhtOperation(linkId);
1152 }
1153 if (GetHeSupported())
1154 {
1155 probe.Get<HeCapabilities>() = GetHeCapabilities(linkId);
1156 probe.Get<HeOperation>() = GetHeOperation(linkId);
1157 if (auto muEdcaParameterSet = GetMuEdcaParameterSet())
1158 {
1159 probe.Get<MuEdcaParameterSet>() = std::move(*muEdcaParameterSet);
1160 }
1161 if (Is6GhzBand(linkId))
1162 {
1164 }
1165 }
1166 if (GetEhtSupported())
1167 {
1168 probe.Get<EhtCapabilities>() = GetEhtCapabilities(linkId);
1169 probe.Get<EhtOperation>() = GetEhtOperation(linkId);
1170
1171 if (GetNLinks() > 1)
1172 {
1173 /*
1174 * If an AP is affiliated with an AP MLD and does not correspond to a nontransmitted
1175 * BSSID, then the Beacon and Probe Response frames transmitted by the AP shall
1176 * include a TBTT Information field in a Reduced Neighbor Report element with the
1177 * TBTT Information Length field set to 16 or higher, for each of the other APs
1178 * (if any) affiliated with the same AP MLD. (Sec. 35.3.4.1 of 802.11be D2.1.1)
1179 */
1180 if (auto rnr = GetReducedNeighborReport(linkId); rnr.has_value())
1181 {
1182 probe.Get<ReducedNeighborReport>() = std::move(*rnr);
1183 }
1184 /*
1185 * If an AP affiliated with an AP MLD is not in a multiple BSSID set [..], the AP
1186 * shall include, in a Beacon frame or a Probe Response frame, which is not a
1187 * Multi-Link probe response, only the Common Info field of the Basic Multi-Link
1188 * element for the AP MLD unless conditions in 35.3.11 (Multi-link procedures for
1189 * channel switching, extended channel switching, and channel quieting) are
1190 * satisfied. (Sec. 35.3.4.4 of 802.11be D2.1.1)
1191 */
1192 probe.Get<MultiLinkElement>() =
1194 }
1195 }
1196 packet->AddHeader(probe);
1197
1198 if (!GetQosSupported())
1199 {
1200 GetTxop()->Queue(packet, hdr);
1201 }
1202 // "A QoS STA that transmits a Management frame determines access category used
1203 // for medium access in transmission of the Management frame as follows
1204 // (If dot11QMFActivated is false or not present)
1205 // — If the Management frame is individually addressed to a non-QoS STA, category
1206 // AC_BE should be selected.
1207 // — If category AC_BE was not selected by the previous step, category AC_VO
1208 // shall be selected." (Sec. 10.2.3.2 of 802.11-2020)
1209 else if (!GetWifiRemoteStationManager(linkId)->GetQosSupported(to))
1210 {
1211 GetBEQueue()->Queue(packet, hdr);
1212 }
1213 else
1214 {
1215 GetVOQueue()->Queue(packet, hdr);
1216 }
1217}
1218
1221{
1223 StatusCode code;
1224 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
1225 if (remoteStationManager->IsWaitAssocTxOk(to))
1226 {
1227 code.SetSuccess();
1228 }
1229 else
1230 {
1231 NS_ABORT_IF(!remoteStationManager->IsAssocRefused(to));
1232 // reset state
1233 remoteStationManager->RecordDisassociated(to);
1234 code.SetFailure();
1235 }
1236 auto supportedRates = GetSupportedRates(linkId);
1237 assoc.Get<SupportedRates>() = supportedRates.rates;
1238 assoc.Get<ExtendedSupportedRatesIE>() = supportedRates.extendedRates;
1239 assoc.SetStatusCode(code);
1240 assoc.Capabilities() = GetCapabilities(linkId);
1241 if (GetQosSupported())
1242 {
1243 assoc.Get<EdcaParameterSet>() = GetEdcaParameterSet(linkId);
1244 }
1245 if (GetHtSupported(linkId))
1246 {
1248 assoc.Get<HtCapabilities>() = GetHtCapabilities(linkId);
1249 assoc.Get<HtOperation>() = GetHtOperation(linkId);
1250 }
1251 if (GetVhtSupported(linkId))
1252 {
1253 assoc.Get<VhtCapabilities>() = GetVhtCapabilities(linkId);
1254 assoc.Get<VhtOperation>() = GetVhtOperation(linkId);
1255 }
1256 if (GetHeSupported())
1257 {
1258 assoc.Get<HeCapabilities>() = GetHeCapabilities(linkId);
1259 assoc.Get<HeOperation>() = GetHeOperation(linkId);
1260 if (auto muEdcaParameterSet = GetMuEdcaParameterSet(); muEdcaParameterSet.has_value())
1261 {
1262 assoc.Get<MuEdcaParameterSet>() = std::move(*muEdcaParameterSet);
1263 }
1264 if (Is6GhzBand(linkId))
1265 {
1267 }
1268 }
1269 if (GetEhtSupported())
1270 {
1271 assoc.Get<EhtCapabilities>() = GetEhtCapabilities(linkId);
1272 assoc.Get<EhtOperation>() = GetEhtOperation(linkId);
1273 // The AP MLD that accepts the requested TID-to-link mapping shall not include in the
1274 // (Re)Association Response frame the TID-to-link Mapping element.
1275 // (Sec. 35.3.7.1.8 of 802.11be D3.1).
1276 // For now, we assume that AP MLDs always accept requested TID-to-link mappings.
1277 }
1278 return assoc;
1279}
1280
1283 const Mac48Address& to,
1284 uint8_t linkId)
1285{
1286 // find all the links to setup (i.e., those for which status code is success)
1287 std::map<uint8_t /* link ID */, Mac48Address> linkIdStaAddrMap;
1288
1289 if (assoc.GetStatusCode().IsSuccess())
1290 {
1291 linkIdStaAddrMap[linkId] = to;
1292 }
1293
1294 if (const auto& mle = assoc.Get<MultiLinkElement>())
1295 {
1296 const auto staMldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(to);
1297 NS_ABORT_MSG_IF(!staMldAddress.has_value(),
1298 "Sending a Multi-Link Element to a single link device");
1299 for (std::size_t idx = 0; idx < mle->GetNPerStaProfileSubelements(); idx++)
1300 {
1301 auto& perStaProfile = mle->GetPerStaProfile(idx);
1302 if (perStaProfile.HasAssocResponse() &&
1303 perStaProfile.GetAssocResponse().GetStatusCode().IsSuccess())
1304 {
1305 uint8_t otherLinkId = perStaProfile.GetLinkId();
1306 auto staAddress = GetWifiRemoteStationManager(otherLinkId)
1307 ->GetAffiliatedStaAddress(*staMldAddress);
1308 NS_ABORT_MSG_IF(!staAddress.has_value(),
1309 "No STA to associate with on link " << +otherLinkId);
1310 const auto [it, inserted] = linkIdStaAddrMap.insert({otherLinkId, *staAddress});
1311 NS_ABORT_MSG_IF(!inserted,
1312 "More than one Association Response to MLD "
1313 << *staMldAddress << " on link ID " << +otherLinkId);
1314 }
1315 }
1316 }
1317
1318 return linkIdStaAddrMap;
1319}
1320
1321void
1323{
1324 if (linkIdStaAddrMap.empty())
1325 {
1326 // no link to setup, nothing to do
1327 return;
1328 }
1329
1330 // check if AIDs are already allocated to the STAs that are associating
1331 std::set<uint16_t> aids;
1332 std::map<uint8_t /* link ID */, uint16_t /* AID */> linkIdAidMap;
1333
1334 for (const auto& [id, staAddr] : linkIdStaAddrMap)
1335 {
1336 for (const auto& [aid, addr] : GetLink(id).staList)
1337 {
1338 if (addr == staAddr)
1339 {
1340 aids.insert(aid);
1341 linkIdAidMap[id] = aid;
1342 break;
1343 }
1344 }
1345 }
1346
1347 // check if an AID already assigned to an STA can be assigned to all other STAs
1348 // affiliated with the non-AP MLD we are associating with
1349 while (!aids.empty())
1350 {
1351 const uint16_t aid = *aids.begin();
1352 bool good = true;
1353
1354 for (const auto& [id, staAddr] : linkIdStaAddrMap)
1355 {
1356 if (auto it = GetLink(id).staList.find(aid);
1357 it != GetLink(id).staList.end() && it->second != staAddr)
1358 {
1359 // the AID is already assigned to an STA other than the one affiliated
1360 // with the non-AP MLD we are associating with
1361 aids.erase(aids.begin());
1362 good = false;
1363 break;
1364 }
1365 }
1366
1367 if (good)
1368 {
1369 break;
1370 }
1371 }
1372
1373 uint16_t aid = 0;
1374
1375 if (!aids.empty())
1376 {
1377 // one of the AIDs already assigned to an STA can be assigned to all the other
1378 // STAs affiliated with the non-AP MLD we are associating with
1379 aid = *aids.begin();
1380 }
1381 else
1382 {
1383 std::list<uint8_t> linkIds;
1384 std::transform(linkIdStaAddrMap.cbegin(),
1385 linkIdStaAddrMap.cend(),
1386 std::back_inserter(linkIds),
1387 [](auto&& linkIdStaAddrPair) { return linkIdStaAddrPair.first; });
1388 aid = GetNextAssociationId(linkIds);
1389 }
1390
1391 // store the MLD or link address in the AID-to-address map
1392 const auto& [linkId, staAddr] = *linkIdStaAddrMap.cbegin();
1394 GetWifiRemoteStationManager(linkId)->GetMldAddress(staAddr).value_or(staAddr);
1395
1396 for (const auto& [id, staAddr] : linkIdStaAddrMap)
1397 {
1398 auto remoteStationManager = GetWifiRemoteStationManager(id);
1399 auto& link = GetLink(id);
1400
1401 if (auto it = linkIdAidMap.find(id); it == linkIdAidMap.end() || it->second != aid)
1402 {
1403 // the STA on this link has no AID assigned or has a different AID assigned
1404 link.staList.insert(std::make_pair(aid, staAddr));
1405 m_assocLogger(aid, staAddr);
1406 remoteStationManager->SetAssociationId(staAddr, aid);
1407
1408 if (it == linkIdAidMap.end())
1409 {
1410 // the STA on this link had no AID assigned
1411 if (remoteStationManager->GetDsssSupported(staAddr) &&
1412 !remoteStationManager->GetErpOfdmSupported(staAddr))
1413 {
1414 link.numNonErpStations++;
1415 }
1416 if (!remoteStationManager->GetHtSupported(staAddr) &&
1417 !remoteStationManager->GetStationHe6GhzCapabilities(staAddr))
1418 {
1419 link.numNonHtStations++;
1420 }
1423 }
1424 else
1425 {
1426 // the STA on this link had a different AID assigned
1427 link.staList.erase(it->second); // free the previous AID
1428 }
1429 }
1430 }
1431
1432 // set the AID in all the Association Responses. NOTE that the Association
1433 // Responses included in the Per-STA Profile Subelements of the Multi-Link
1434 // Element must not contain the AID field. We set the AID field in such
1435 // Association Responses anyway, in order to ease future implementation of
1436 // the inheritance mechanism.
1437 if (assoc.GetStatusCode().IsSuccess())
1438 {
1439 assoc.SetAssociationId(aid);
1440 }
1441 if (const auto& mle = assoc.Get<MultiLinkElement>())
1442 {
1443 for (std::size_t idx = 0; idx < mle->GetNPerStaProfileSubelements(); idx++)
1444 {
1445 if (const auto& perStaProfile = mle->GetPerStaProfile(idx);
1446 perStaProfile.HasAssocResponse() &&
1447 perStaProfile.GetAssocResponse().GetStatusCode().IsSuccess())
1448 {
1449 perStaProfile.GetAssocResponse().SetAssociationId(aid);
1450 }
1451 }
1452 }
1453}
1454
1455void
1456ApWifiMac::SendAssocResp(Mac48Address to, bool isReassoc, uint8_t linkId)
1457{
1458 NS_LOG_FUNCTION(this << to << isReassoc << +linkId);
1459 WifiMacHeader hdr;
1462 hdr.SetAddr1(to);
1465 hdr.SetDsNotFrom();
1466 hdr.SetDsNotTo();
1467
1468 MgtAssocResponseHeader assoc = GetAssocResp(to, linkId);
1469
1470 // The AP that is affiliated with the AP MLD and that responds to an (Re)Association
1471 // Request frame that carries a Basic Multi-Link element shall include a Basic
1472 // Multi-Link element in the (Re)Association Response frame that it transmits
1473 // (Sec. 35.3.5.4 of 802.11be D2.0)
1474 // If the STA included a Multi-Link Element in the (Re)Association Request, we
1475 // stored its MLD address in the remote station manager
1476 if (GetNLinks() > 1 && GetWifiRemoteStationManager(linkId)->GetMldAddress(to).has_value())
1477 {
1478 assoc.Get<MultiLinkElement>() = GetMultiLinkElement(linkId, hdr.GetType(), to);
1479 }
1480
1481 auto linkIdStaAddrMap = GetLinkIdStaAddrMap(assoc, to, linkId);
1482 SetAid(assoc, linkIdStaAddrMap);
1483
1484 Ptr<Packet> packet = Create<Packet>();
1485 packet->AddHeader(assoc);
1486
1487 if (!GetQosSupported())
1488 {
1489 GetTxop()->Queue(packet, hdr);
1490 }
1491 // "A QoS STA that transmits a Management frame determines access category used
1492 // for medium access in transmission of the Management frame as follows
1493 // (If dot11QMFActivated is false or not present)
1494 // — If the Management frame is individually addressed to a non-QoS STA, category
1495 // AC_BE should be selected.
1496 // — If category AC_BE was not selected by the previous step, category AC_VO
1497 // shall be selected." (Sec. 10.2.3.2 of 802.11-2020)
1498 else if (!GetWifiRemoteStationManager(linkId)->GetQosSupported(to))
1499 {
1500 GetBEQueue()->Queue(packet, hdr);
1501 }
1502 else
1503 {
1504 GetVOQueue()->Queue(packet, hdr);
1505 }
1506}
1507
1508void
1510{
1511 NS_LOG_FUNCTION(this << +linkId);
1512 auto& link = GetLink(linkId);
1513 WifiMacHeader hdr;
1516 hdr.SetAddr2(link.feManager->GetAddress());
1517 hdr.SetAddr3(link.feManager->GetAddress());
1518 hdr.SetDsNotFrom();
1519 hdr.SetDsNotTo();
1520 Ptr<Packet> packet = Create<Packet>();
1521 MgtBeaconHeader beacon;
1522 beacon.Get<Ssid>() = GetSsid();
1523 auto supportedRates = GetSupportedRates(linkId);
1524 beacon.Get<SupportedRates>() = supportedRates.rates;
1525 beacon.Get<ExtendedSupportedRatesIE>() = supportedRates.extendedRates;
1527 beacon.Capabilities() = GetCapabilities(linkId);
1528 GetWifiRemoteStationManager(linkId)->SetShortPreambleEnabled(link.shortPreambleEnabled);
1529 GetWifiRemoteStationManager(linkId)->SetShortSlotTimeEnabled(link.shortSlotTimeEnabled);
1530 if (GetDsssSupported(linkId))
1531 {
1532 beacon.Get<DsssParameterSet>() = GetDsssParameterSet(linkId);
1533 }
1534 if (GetErpSupported(linkId))
1535 {
1536 beacon.Get<ErpInformation>() = GetErpInformation(linkId);
1537 }
1538 if (GetQosSupported())
1539 {
1540 beacon.Get<EdcaParameterSet>() = GetEdcaParameterSet(linkId);
1541 }
1542 if (GetHtSupported(linkId))
1543 {
1545 beacon.Get<HtCapabilities>() = GetHtCapabilities(linkId);
1546 beacon.Get<HtOperation>() = GetHtOperation(linkId);
1547 }
1548 if (GetVhtSupported(linkId))
1549 {
1550 beacon.Get<VhtCapabilities>() = GetVhtCapabilities(linkId);
1551 beacon.Get<VhtOperation>() = GetVhtOperation(linkId);
1552 }
1553 if (GetHeSupported())
1554 {
1555 beacon.Get<HeCapabilities>() = GetHeCapabilities(linkId);
1556 beacon.Get<HeOperation>() = GetHeOperation(linkId);
1557 if (auto muEdcaParameterSet = GetMuEdcaParameterSet(); muEdcaParameterSet.has_value())
1558 {
1559 beacon.Get<MuEdcaParameterSet>() = std::move(*muEdcaParameterSet);
1560 }
1561 if (Is6GhzBand(linkId))
1562 {
1563 beacon.Get<He6GhzBandCapabilities>() = GetHe6GhzBandCapabilities(linkId);
1564 }
1565 }
1566 if (GetEhtSupported())
1567 {
1568 beacon.Get<EhtCapabilities>() = GetEhtCapabilities(linkId);
1569 beacon.Get<EhtOperation>() = GetEhtOperation(linkId);
1570
1571 if (GetNLinks() > 1)
1572 {
1573 /*
1574 * If an AP is affiliated with an AP MLD and does not correspond to a nontransmitted
1575 * BSSID, then the Beacon and Probe Response frames transmitted by the AP shall
1576 * include a TBTT Information field in a Reduced Neighbor Report element with the
1577 * TBTT Information Length field set to 16 or higher, for each of the other APs
1578 * (if any) affiliated with the same AP MLD. (Sec. 35.3.4.1 of 802.11be D2.1.1)
1579 */
1580 if (auto rnr = GetReducedNeighborReport(linkId); rnr.has_value())
1581 {
1582 beacon.Get<ReducedNeighborReport>() = std::move(*rnr);
1583 }
1584 /*
1585 * If an AP affiliated with an AP MLD is not in a multiple BSSID set [..], the AP
1586 * shall include, in a Beacon frame or a Probe Response frame, which is not a
1587 * Multi-Link probe response, only the Common Info field of the Basic Multi-Link
1588 * element for the AP MLD unless conditions in 35.3.11 (Multi-link procedures for
1589 * channel switching, extended channel switching, and channel quieting) are
1590 * satisfied. (Sec. 35.3.4.4 of 802.11be D2.1.1)
1591 */
1593 }
1594 }
1595 packet->AddHeader(beacon);
1596
1597 NS_LOG_INFO("Generating beacon from " << link.feManager->GetAddress() << " linkID " << +linkId);
1598 // The beacon has it's own special queue, so we load it in there
1599 m_beaconTxop->Queue(packet, hdr);
1600 link.beaconEvent =
1602
1604
1605 // If a STA that does not support Short Slot Time associates,
1606 // the AP shall use long slot time beginning at the first Beacon
1607 // subsequent to the association of the long slot time STA.
1608 if (GetErpSupported(linkId))
1609 {
1610 if (link.shortSlotTimeEnabled)
1611 {
1612 // Enable short slot time
1613 GetWifiPhy(linkId)->SetSlot(MicroSeconds(9));
1614 }
1615 else
1616 {
1617 // Disable short slot time
1618 GetWifiPhy(linkId)->SetSlot(MicroSeconds(20));
1619 }
1620 }
1621}
1622
1624ApWifiMac::GetFilsDiscovery(uint8_t linkId) const
1625{
1628 auto& link = GetLink(linkId);
1629 hdr.SetAddr2(link.feManager->GetAddress());
1630 hdr.SetAddr3(link.feManager->GetAddress());
1631 hdr.SetDsNotFrom();
1632 hdr.SetDsNotTo();
1633
1634 WifiActionHeader actionHdr;
1636 action.publicAction = WifiActionHeader::FILS_DISCOVERY;
1637 actionHdr.SetAction(WifiActionHeader::PUBLIC, action);
1638
1639 FilsDiscHeader fils;
1640 fils.SetSsid(GetSsid().PeekString());
1641 fils.m_beaconInt = (m_beaconInterval / WIFI_TU).GetHigh();
1642
1644 fils.m_fdCap->SetOpChannelWidth(link.phy->GetChannelWidth());
1645 fils.m_fdCap->SetMaxNss(std::min(link.phy->GetMaxSupportedTxSpatialStreams(),
1646 link.phy->GetMaxSupportedRxSpatialStreams()));
1647 fils.m_fdCap->SetStandard(link.phy->GetStandard());
1648
1649 fils.SetLengthSubfield();
1650 fils.m_rnr = GetReducedNeighborReport(linkId);
1651
1652 auto packet = Create<Packet>();
1653 packet->AddHeader(fils);
1654 packet->AddHeader(actionHdr);
1655
1656 return Create<WifiMpdu>(packet, hdr);
1657}
1658
1659void
1661{
1662 NS_LOG_FUNCTION(this << linkId);
1663 auto phy = GetLink(linkId).phy;
1664
1665 auto fdBeaconInterval = (phy->GetPhyBand() == WIFI_PHY_BAND_6GHZ) ? m_fdBeaconInterval6GHz
1667
1668 if (!fdBeaconInterval.IsStrictlyPositive())
1669 {
1670 NS_LOG_DEBUG("Sending FILS Discovery/unsolicited Probe Response disabled");
1671 return;
1672 }
1673
1674 // Schedule FD or unsolicited Probe Response frames (IEEE Std 802.11ax-2021 26.17.2.3.2)
1675 for (uint8_t count = 1; count < (m_beaconInterval / fdBeaconInterval).GetHigh(); ++count)
1676 {
1678 {
1679 Simulator::Schedule(fdBeaconInterval * count,
1681 this,
1683 linkId);
1684 }
1685 else
1686 {
1687 Simulator::Schedule(fdBeaconInterval * count,
1688 [=, this]() { m_beaconTxop->Queue(GetFilsDiscovery(linkId)); });
1689 }
1690 }
1691}
1692
1693void
1695{
1696 NS_LOG_FUNCTION(this << *mpdu);
1697 const WifiMacHeader& hdr = mpdu->GetHeader();
1698
1699 if (hdr.IsAssocResp() || hdr.IsReassocResp())
1700 {
1701 auto linkId = GetLinkIdByAddress(hdr.GetAddr2());
1702 NS_ABORT_MSG_IF(!linkId.has_value(), "No link ID matching the TA");
1703
1704 if (GetWifiRemoteStationManager(*linkId)->IsWaitAssocTxOk(hdr.GetAddr1()))
1705 {
1706 NS_LOG_DEBUG("AP=" << hdr.GetAddr2() << " associated with STA=" << hdr.GetAddr1());
1707 GetWifiRemoteStationManager(*linkId)->RecordGotAssocTxOk(hdr.GetAddr1());
1708 }
1709
1710 if (auto staMldAddress =
1711 GetWifiRemoteStationManager(*linkId)->GetMldAddress(hdr.GetAddr1());
1712 staMldAddress.has_value())
1713 {
1714 /**
1715 * The STA is affiliated with an MLD. From Sec. 35.3.7.1.4 of 802.11be D3.0:
1716 * When a link becomes enabled for a non-AP STA that is affiliated with a non-AP MLD
1717 * after successful association with an AP MLD with (Re)Association Request/Response
1718 * frames transmitted on another link [...], the power management mode of the non-AP
1719 * STA, immediately after the acknowledgement of the (Re)Association Response frame
1720 * [...], is power save mode, and its power state is doze.
1721 *
1722 * Thus, STAs operating on all the links but the link used to establish association
1723 * transition to power save mode.
1724 */
1725 for (uint8_t i = 0; i < GetNLinks(); i++)
1726 {
1727 auto stationManager = GetWifiRemoteStationManager(i);
1728 if (auto staAddress = stationManager->GetAffiliatedStaAddress(*staMldAddress);
1729 staAddress.has_value() && i != *linkId &&
1730 stationManager->IsWaitAssocTxOk(*staAddress))
1731 {
1733 << " associated with STA=" << *staAddress);
1734 stationManager->RecordGotAssocTxOk(*staAddress);
1735 StaSwitchingToPsMode(*staAddress, i);
1736 }
1737 }
1738
1739 // Apply the negotiated TID-to-Link Mapping (if any) for DL direction
1741 }
1742 }
1743 else if (hdr.IsAction())
1744 {
1745 if (auto [category, action] = WifiActionHeader::Peek(mpdu->GetPacket());
1746 category == WifiActionHeader::PROTECTED_EHT &&
1747 action.protectedEhtAction ==
1749 {
1750 // the EMLSR client acknowledged the EML Operating Mode Notification frame;
1751 // we can stop the timer and enforce the configuration deriving from the
1752 // EML Notification frame sent by the EMLSR client
1753 if (auto eventIt = m_transitionTimeoutEvents.find(hdr.GetAddr1());
1754 eventIt != m_transitionTimeoutEvents.cend() && eventIt->second.IsPending())
1755 {
1756 // no need to wait until the expiration of the transition timeout
1757 eventIt->second.PeekEventImpl()->Invoke();
1758 eventIt->second.Cancel();
1759 }
1760 }
1761 }
1762}
1763
1764void
1766{
1767 NS_LOG_FUNCTION(this << +timeoutReason << *mpdu);
1768 const WifiMacHeader& hdr = mpdu->GetHeader();
1769
1770 if (hdr.IsAssocResp() || hdr.IsReassocResp())
1771 {
1772 auto linkId = GetLinkIdByAddress(hdr.GetAddr2());
1773 NS_ABORT_MSG_IF(!linkId.has_value(), "No link ID matching the TA");
1774
1775 if (GetWifiRemoteStationManager(*linkId)->IsWaitAssocTxOk(hdr.GetAddr1()))
1776 {
1777 NS_LOG_DEBUG("AP=" << hdr.GetAddr2()
1778 << " association failed with STA=" << hdr.GetAddr1());
1779 GetWifiRemoteStationManager(*linkId)->RecordGotAssocTxFailed(hdr.GetAddr1());
1780 }
1781
1782 if (auto staMldAddress =
1783 GetWifiRemoteStationManager(*linkId)->GetMldAddress(hdr.GetAddr1());
1784 staMldAddress.has_value())
1785 {
1786 // the STA is affiliated with an MLD
1787 for (uint8_t i = 0; i < GetNLinks(); i++)
1788 {
1789 auto stationManager = GetWifiRemoteStationManager(i);
1790 if (auto staAddress = stationManager->GetAffiliatedStaAddress(*staMldAddress);
1791 staAddress.has_value() && i != *linkId &&
1792 stationManager->IsWaitAssocTxOk(*staAddress))
1793 {
1795 << " association failed with STA=" << *staAddress);
1796 stationManager->RecordGotAssocTxFailed(*staAddress);
1797 }
1798 }
1799 }
1800 }
1801}
1802
1803void
1805{
1806 NS_LOG_FUNCTION(this << *mpdu << linkId);
1807
1808 Mac48Address staAddr = mpdu->GetHeader().GetAddr2();
1809 bool staInPsMode = GetWifiRemoteStationManager(linkId)->IsInPsMode(staAddr);
1810
1811 if (!staInPsMode && mpdu->GetHeader().IsPowerManagement())
1812 {
1813 // the sending STA is switching to Power Save mode
1814 StaSwitchingToPsMode(staAddr, linkId);
1815 }
1816 else if (staInPsMode && !mpdu->GetHeader().IsPowerManagement())
1817 {
1818 // the sending STA is switching back to Active mode
1820 }
1821}
1822
1823void
1824ApWifiMac::StaSwitchingToPsMode(const Mac48Address& staAddr, uint8_t linkId)
1825{
1826 NS_LOG_FUNCTION(this << staAddr << linkId);
1827
1828 GetWifiRemoteStationManager(linkId)->SetPsMode(staAddr, true);
1829
1830 // Block frames addressed to the STA in PS mode
1831 NS_LOG_DEBUG("Block destination " << staAddr << " on link " << +linkId);
1832 auto staMldAddr = GetWifiRemoteStationManager(linkId)->GetMldAddress(staAddr).value_or(staAddr);
1834}
1835
1836void
1838{
1839 NS_LOG_FUNCTION(this << staAddr << linkId);
1840
1841 GetWifiRemoteStationManager(linkId)->SetPsMode(staAddr, false);
1842
1843 if (GetWifiRemoteStationManager(linkId)->IsAssociated(staAddr))
1844 {
1845 // the station is still associated, unblock its frames
1846 NS_LOG_DEBUG("Unblock destination " << staAddr << " on link " << +linkId);
1847 auto staMldAddr =
1848 GetWifiRemoteStationManager(linkId)->GetMldAddress(staAddr).value_or(staAddr);
1850 }
1851}
1852
1853std::optional<uint8_t>
1855{
1856 for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
1857 {
1858 if (GetWifiRemoteStationManager(linkId)->IsAssociated(address))
1859 {
1860 return linkId;
1861 }
1862 }
1863 NS_LOG_DEBUG(address << " is not associated");
1864 return std::nullopt;
1865}
1866
1869{
1870 auto linkId = IsAssociated(remoteAddr);
1871 NS_ASSERT_MSG(linkId, remoteAddr << " is not associated");
1872 return GetFrameExchangeManager(*linkId)->GetAddress();
1873}
1874
1875std::optional<Mac48Address>
1877{
1878 if (const auto staIt = m_aidToMldOrLinkAddress.find(aid);
1879 staIt != m_aidToMldOrLinkAddress.cend())
1880 {
1881 return staIt->second;
1882 }
1883 return std::nullopt;
1884}
1885
1886void
1888{
1889 NS_LOG_FUNCTION(this << *mpdu << +linkId);
1890 // consider the MAC header of the original MPDU (makes a difference for data frames only)
1891 const WifiMacHeader* hdr = &mpdu->GetOriginal()->GetHeader();
1892 Ptr<const Packet> packet = mpdu->GetPacket();
1893 Mac48Address from = hdr->GetAddr2();
1894 if (hdr->IsData())
1895 {
1896 std::optional<uint8_t> apLinkId;
1897 if (!hdr->IsFromDs() && hdr->IsToDs() &&
1898 (apLinkId = IsAssociated(mpdu->GetHeader().GetAddr2())) &&
1899 mpdu->GetHeader().GetAddr1() == GetFrameExchangeManager(*apLinkId)->GetAddress())
1900 {
1901 // this MPDU is being acknowledged by the AP, so we can process
1902 // the Power Management flag
1903 ProcessPowerManagementFlag(mpdu, *apLinkId);
1904
1905 Mac48Address to = hdr->GetAddr3();
1906 // Address3 can be our MLD address (e.g., this is an MPDU containing a single MSDU
1907 // addressed to us) or a BSSID (e.g., this is an MPDU containing an A-MSDU)
1908 if (to == GetAddress() ||
1909 (hdr->IsQosData() && hdr->IsQosAmsdu() && to == mpdu->GetHeader().GetAddr1()))
1910 {
1911 NS_LOG_DEBUG("frame for me from=" << from);
1912 if (hdr->IsQosData())
1913 {
1914 if (hdr->IsQosAmsdu())
1915 {
1916 NS_LOG_DEBUG("Received A-MSDU from=" << from
1917 << ", size=" << packet->GetSize());
1919 packet = nullptr;
1920 }
1921 else if (hdr->HasData())
1922 {
1923 ForwardUp(packet, from, GetAddress());
1924 }
1925 }
1926 else if (hdr->HasData())
1927 {
1928 ForwardUp(packet, from, GetAddress());
1929 }
1930 }
1931 else if (to.IsGroup() || IsAssociated(to))
1932 {
1933 NS_LOG_DEBUG("forwarding frame from=" << from << ", to=" << to);
1934 Ptr<Packet> copy = packet->Copy();
1935
1936 // If the frame we are forwarding is of type QoS Data,
1937 // then we need to preserve the UP in the QoS control
1938 // header...
1939 if (hdr->IsQosData())
1940 {
1941 ForwardDown(copy, from, to, hdr->GetQosTid());
1942 }
1943 else
1944 {
1945 ForwardDown(copy, from, to);
1946 }
1947 ForwardUp(packet, from, to);
1948 }
1949 else if (hdr->HasData())
1950 {
1951 ForwardUp(packet, from, to);
1952 }
1953 }
1954 // NOLINTBEGIN(bugprone-branch-clone)
1955 else if (hdr->IsFromDs() && hdr->IsToDs())
1956 {
1957 // this is an AP-to-AP frame
1958 // we ignore for now.
1959 NotifyRxDrop(packet);
1960 }
1961 // NOLINTEND(bugprone-branch-clone)
1962 else
1963 {
1964 // we can ignore these frames since
1965 // they are not targeted at the AP
1966 NotifyRxDrop(packet);
1967 }
1968 return;
1969 }
1970 else if (hdr->IsMgt())
1971 {
1972 if (hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress() &&
1974 {
1975 // this MPDU is being acknowledged by the AP, so we can process
1976 // the Power Management flag
1977 ProcessPowerManagementFlag(mpdu, linkId);
1978 }
1979 if (hdr->IsProbeReq() && (hdr->GetAddr1().IsGroup() ||
1980 hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress()))
1981 {
1982 // In the case where the Address 1 field contains a group address, the
1983 // Address 3 field also is validated to verify that the group addressed
1984 // frame originated from a STA in the BSS of which the receiving STA is
1985 // a member (Section 9.3.3.1 of 802.11-2020)
1986 if (hdr->GetAddr1().IsGroup() && !hdr->GetAddr3().IsBroadcast() &&
1987 hdr->GetAddr3() != GetFrameExchangeManager(linkId)->GetAddress())
1988 {
1989 // not addressed to us
1990 return;
1991 }
1992 MgtProbeRequestHeader probeRequestHeader;
1993 packet->PeekHeader(probeRequestHeader);
1994 const auto& ssid = probeRequestHeader.Get<Ssid>();
1995 if (ssid == GetSsid() || ssid->IsBroadcast())
1996 {
1997 NS_LOG_DEBUG("Probe request received from " << from << ": send probe response");
1998 SendProbeResp(from, linkId);
1999 }
2000 return;
2001 }
2002 else if (hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress())
2003 {
2004 switch (hdr->GetType())
2005 {
2008 NS_LOG_DEBUG(((hdr->IsAssocReq()) ? "Association" : "Reassociation")
2009 << " request received from " << from
2010 << ((GetNLinks() > 1) ? " on link ID " + std::to_string(linkId) : ""));
2011
2012 MgtAssocRequestHeader assocReq;
2013 MgtReassocRequestHeader reassocReq;
2014 AssocReqRefVariant frame = assocReq;
2015 if (hdr->IsAssocReq())
2016 {
2017 packet->PeekHeader(assocReq);
2018 }
2019 else
2020 {
2021 packet->PeekHeader(reassocReq);
2022 frame = reassocReq;
2023 }
2024 if (ReceiveAssocRequest(frame, from, linkId) && GetNLinks() > 1)
2025 {
2026 ParseReportedStaInfo(frame, from, linkId);
2027 }
2028 SendAssocResp(hdr->GetAddr2(), hdr->IsReassocReq(), linkId);
2029 return;
2030 }
2032 NS_LOG_DEBUG("Disassociation received from " << from);
2033 GetWifiRemoteStationManager(linkId)->RecordDisassociated(from);
2034 auto& staList = GetLink(linkId).staList;
2035 for (auto it = staList.begin(); it != staList.end(); ++it)
2036 {
2037 if (it->second == from)
2038 {
2039 staList.erase(it);
2040 m_deAssocLogger(it->first, it->second);
2041 if (GetWifiRemoteStationManager(linkId)->GetDsssSupported(from) &&
2042 !GetWifiRemoteStationManager(linkId)->GetErpOfdmSupported(from))
2043 {
2044 GetLink(linkId).numNonErpStations--;
2045 }
2046 if (!GetWifiRemoteStationManager(linkId)->GetHtSupported(from) &&
2047 !GetWifiRemoteStationManager(linkId)->GetStationHe6GhzCapabilities(
2048 from))
2049 {
2050 GetLink(linkId).numNonHtStations--;
2051 }
2055 break;
2056 }
2057 }
2058 return;
2059 }
2060 case WIFI_MAC_MGT_ACTION: {
2061 auto pkt = mpdu->GetPacket()->Copy();
2062 auto [category, action] = WifiActionHeader::Remove(pkt);
2063 if (category == WifiActionHeader::PROTECTED_EHT &&
2064 action.protectedEhtAction ==
2066 IsAssociated(hdr->GetAddr2()))
2067 {
2068 // received an EML Operating Mode Notification frame from an associated station
2069 MgtEmlOmn frame;
2070 pkt->RemoveHeader(frame);
2071 ReceiveEmlOmn(frame, hdr->GetAddr2(), linkId);
2072 return;
2073 }
2074 break;
2075 }
2076 default:;
2077 // do nothing
2078 }
2079 }
2080 }
2081
2082 // Invoke the receive handler of our parent class to deal with any
2083 // other frames. Specifically, this will handle Block Ack-related
2084 // Management Action frames.
2085 WifiMac::Receive(Create<WifiMpdu>(packet, *hdr), linkId);
2086}
2087
2088bool
2090 const Mac48Address& from,
2091 uint8_t linkId)
2092{
2093 NS_LOG_FUNCTION(this << from << +linkId);
2094
2095 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
2096
2097 auto failure = [&](const std::string& msg) -> bool {
2098 NS_LOG_DEBUG("Association Request from " << from << " refused: " << msg);
2099 remoteStationManager->RecordAssocRefused(from);
2100 return false;
2101 };
2102
2103 // lambda to process received (Re)Association Request
2104 auto recvAssocRequest = [&](auto&& frameRefWrapper) -> bool {
2105 const auto& frame = frameRefWrapper.get();
2106
2107 // first, verify that the the station's supported
2108 // rate set is compatible with our Basic Rate set
2109 const CapabilityInformation& capabilities = frame.Capabilities();
2110 remoteStationManager->AddSupportedPhyPreamble(from, capabilities.IsShortPreamble());
2111 NS_ASSERT(frame.template Get<SupportedRates>());
2112 const auto rates = AllSupportedRates{*frame.template Get<SupportedRates>(),
2113 frame.template Get<ExtendedSupportedRatesIE>()};
2114
2115 if (rates.GetNRates() == 0)
2116 {
2117 return failure("STA's supported rate set not compatible with our Basic Rate set");
2118 }
2119
2120 if (GetHtSupported(linkId))
2121 {
2122 // check whether the HT STA supports all MCSs in Basic MCS Set
2123 const auto& htCapabilities = frame.template Get<HtCapabilities>();
2124 if (htCapabilities.has_value() && htCapabilities->IsSupportedMcs(0))
2125 {
2126 for (uint8_t i = 0; i < remoteStationManager->GetNBasicMcs(); i++)
2127 {
2128 WifiMode mcs = remoteStationManager->GetBasicMcs(i);
2129 if (!htCapabilities->IsSupportedMcs(mcs.GetMcsValue()))
2130 {
2131 return failure("HT STA does not support all MCSs in Basic MCS Set");
2132 }
2133 }
2134 }
2135 }
2136 if (GetVhtSupported(linkId))
2137 {
2138 // check whether the VHT STA supports all MCSs in Basic MCS Set
2139 const auto& vhtCapabilities = frame.template Get<VhtCapabilities>();
2140 if (vhtCapabilities.has_value() && vhtCapabilities->GetVhtCapabilitiesInfo() != 0)
2141 {
2142 for (uint8_t i = 0; i < remoteStationManager->GetNBasicMcs(); i++)
2143 {
2144 WifiMode mcs = remoteStationManager->GetBasicMcs(i);
2145 if (!vhtCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
2146 {
2147 return failure("VHT STA does not support all MCSs in Basic MCS Set");
2148 }
2149 }
2150 }
2151 }
2152 if (GetHeSupported())
2153 {
2154 // check whether the HE STA supports all MCSs in Basic MCS Set
2155 const auto& heCapabilities = frame.template Get<HeCapabilities>();
2156 if (heCapabilities.has_value() && heCapabilities->GetSupportedMcsAndNss() != 0)
2157 {
2158 for (uint8_t i = 0; i < remoteStationManager->GetNBasicMcs(); i++)
2159 {
2160 WifiMode mcs = remoteStationManager->GetBasicMcs(i);
2161 if (!heCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
2162 {
2163 return failure("HE STA does not support all MCSs in Basic MCS Set");
2164 }
2165 }
2166 }
2167 if (Is6GhzBand(linkId))
2168 {
2169 if (const auto& he6GhzCapabilities = frame.template Get<He6GhzBandCapabilities>())
2170 {
2171 remoteStationManager->AddStationHe6GhzCapabilities(from, *he6GhzCapabilities);
2172 }
2173 }
2174 }
2175 if (GetEhtSupported())
2176 {
2177 // TODO check whether the EHT STA supports all MCSs in Basic MCS Set
2178 auto ehtConfig = GetEhtConfiguration();
2179 NS_ASSERT(ehtConfig);
2180
2181 if (const auto& tidLinkMapping = frame.template Get<TidToLinkMapping>();
2182 !tidLinkMapping.empty())
2183 {
2184 // non-AP MLD included TID-to-Link Mapping IE(s) in the Association Request.
2185 // We refuse association if we do not support TID-to-Link mapping negotiation
2186 // or the non-AP MLD included more than two TID-to-Link Mapping IEs
2187 // or we support negotiation type 1 but TIDs are mapped onto distinct link sets
2188 // or there is some TID that is not mapped to any link
2189 // or the direction(s) is/are not set properly
2190 if (tidLinkMapping.size() > 2)
2191 {
2192 return failure("More than two TID-to-Link Mapping IEs");
2193 }
2194
2195 // if only one Tid-to-Link Mapping element is present, it must be valid for
2196 // both directions
2197 bool bothDirIfOneTlm =
2198 tidLinkMapping.size() != 1 ||
2199 tidLinkMapping[0].m_control.direction == WifiDirection::BOTH_DIRECTIONS;
2200 // An MLD that includes two TID-To-Link Mapping elements in a (Re)Association
2201 // Request frame or a (Re)Association Response frame shall set the Direction
2202 // subfield in one of the TID-To-Link Mapping elements to 0 and the Direction
2203 // subfield in the other TID-To- Link Mapping element to 1.
2204 // (Sec. 35.3.7.1.8 of 802.11be D3.1)
2205 bool distinctDirsIfTwoTlms =
2206 tidLinkMapping.size() != 2 ||
2207 (tidLinkMapping[0].m_control.direction != WifiDirection::BOTH_DIRECTIONS &&
2208 tidLinkMapping[1].m_control.direction != WifiDirection::BOTH_DIRECTIONS &&
2209 tidLinkMapping[0].m_control.direction !=
2210 tidLinkMapping[1].m_control.direction);
2211
2212 if (!bothDirIfOneTlm || !distinctDirsIfTwoTlms)
2213 {
2214 return failure("Incorrect directions in TID-to-Link Mapping IEs");
2215 }
2216
2218 ehtConfig->GetAttributeFailSafe("TidToLinkMappingNegSupport", negSupport);
2219
2221 {
2222 return failure("TID-to-Link Mapping negotiation not supported");
2223 }
2224
2225 auto getMapping = [](const TidToLinkMapping& tlmIe, WifiTidLinkMapping& mapping) {
2226 if (tlmIe.m_control.defaultMapping)
2227 {
2228 return;
2229 }
2230 for (uint8_t tid = 0; tid < 8; tid++)
2231 {
2232 if (auto linkSet = tlmIe.GetLinkMappingOfTid(tid); !linkSet.empty())
2233 {
2234 mapping.emplace(tid, std::move(linkSet));
2235 }
2236 }
2237 };
2238
2239 WifiTidLinkMapping dlMapping;
2240 WifiTidLinkMapping ulMapping;
2241
2242 switch (tidLinkMapping[0].m_control.direction)
2243 {
2245 getMapping(tidLinkMapping.at(0), dlMapping);
2246 ulMapping = dlMapping;
2247 break;
2249 getMapping(tidLinkMapping.at(0), dlMapping);
2250 getMapping(tidLinkMapping.at(1), ulMapping);
2251 break;
2253 getMapping(tidLinkMapping.at(0), ulMapping);
2254 getMapping(tidLinkMapping.at(1), dlMapping);
2255 break;
2256 }
2257
2259 !TidToLinkMappingValidForNegType1(dlMapping, ulMapping))
2260 {
2261 return failure("Mapping TIDs to distinct link sets is incompatible with "
2262 "negotiation support of 1");
2263 }
2264
2265 // otherwise, we accept the TID-to-link Mapping and store it
2266 const auto& mle = frame.template Get<MultiLinkElement>();
2267 NS_ASSERT_MSG(mle,
2268 "Multi-Link Element not present in an Association Request including "
2269 "TID-to-Link Mapping element(s)");
2270 auto mldAddr = mle->GetMldMacAddress();
2271
2272 // The requested link mappings are valid and can be accepted; store them.
2274 UpdateTidToLinkMapping(mldAddr, WifiDirection::UPLINK, ulMapping);
2275 }
2276 }
2277
2278 // The association request from the station can be accepted.
2279 // Record all its supported modes in its associated WifiRemoteStation
2280 auto phy = GetWifiPhy(linkId);
2281
2282 for (const auto& mode : phy->GetModeList())
2283 {
2284 if (rates.IsSupportedRate(mode.GetDataRate(phy->GetChannelWidth())))
2285 {
2286 remoteStationManager->AddSupportedMode(from, mode);
2287 }
2288 }
2289 if (GetErpSupported(linkId) && remoteStationManager->GetErpOfdmSupported(from) &&
2290 capabilities.IsShortSlotTime())
2291 {
2292 remoteStationManager->AddSupportedErpSlotTime(from, true);
2293 }
2294 if (GetHtSupported(linkId))
2295 {
2296 const auto& htCapabilities = frame.template Get<HtCapabilities>();
2297 if (htCapabilities.has_value() && htCapabilities->IsSupportedMcs(0))
2298 {
2299 remoteStationManager->AddStationHtCapabilities(from, *htCapabilities);
2300 }
2301 // const ExtendedCapabilities& extendedCapabilities = frame.GetExtendedCapabilities();
2302 // TODO: to be completed
2303 }
2304 if (GetVhtSupported(linkId))
2305 {
2306 const auto& vhtCapabilities = frame.template Get<VhtCapabilities>();
2307 // we will always fill in RxHighestSupportedLgiDataRate field at TX, so this can be used
2308 // to check whether it supports VHT
2309 if (vhtCapabilities.has_value() &&
2310 vhtCapabilities->GetRxHighestSupportedLgiDataRate() > 0)
2311 {
2312 remoteStationManager->AddStationVhtCapabilities(from, *vhtCapabilities);
2313 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
2314 {
2315 if (vhtCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
2316 {
2317 remoteStationManager->AddSupportedMcs(from, mcs);
2318 // here should add a control to add basic MCS when it is implemented
2319 }
2320 }
2321 }
2322 }
2323 if (GetHeSupported())
2324 {
2325 const auto& heCapabilities = frame.template Get<HeCapabilities>();
2326 if (heCapabilities.has_value() && heCapabilities->GetSupportedMcsAndNss() != 0)
2327 {
2328 remoteStationManager->AddStationHeCapabilities(from, *heCapabilities);
2329 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HE))
2330 {
2331 if (heCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
2332 {
2333 remoteStationManager->AddSupportedMcs(from, mcs);
2334 // here should add a control to add basic MCS when it is implemented
2335 }
2336 }
2337 }
2338 }
2339 if (GetEhtSupported())
2340 {
2341 if (const auto& ehtCapabilities = frame.template Get<EhtCapabilities>())
2342 {
2343 remoteStationManager->AddStationEhtCapabilities(from, *ehtCapabilities);
2344 }
2345 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_EHT))
2346 {
2347 // TODO: Add check whether MCS is supported from the capabilities
2348 remoteStationManager->AddSupportedMcs(from, mcs);
2349 // here should add a control to add basic MCS when it is implemented
2350 }
2351 }
2352
2353 NS_LOG_DEBUG("Association Request from " << from << " accepted");
2354 remoteStationManager->RecordWaitAssocTxOk(from);
2355 return true;
2356 };
2357
2358 return std::visit(recvAssocRequest, assoc);
2359}
2360
2361void
2363{
2364 NS_LOG_FUNCTION(this << from << +linkId);
2365
2366 // lambda to process received Multi-Link Element
2367 auto recvMle = [&](auto&& frame) {
2368 const auto& mle = frame.get().template Get<MultiLinkElement>();
2369
2370 if (!mle.has_value())
2371 {
2372 return;
2373 }
2374
2375 auto mleCommonInfo = std::make_shared<CommonInfoBasicMle>(mle->GetCommonInfoBasic());
2376 GetWifiRemoteStationManager(linkId)->AddStationMleCommonInfo(from, mleCommonInfo);
2377
2378 for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
2379 {
2380 auto& perStaProfile = mle->GetPerStaProfile(i);
2381 if (!perStaProfile.HasStaMacAddress())
2382 {
2383 NS_LOG_DEBUG("[i=" << i
2384 << "] Cannot setup a link if the STA MAC address is missing");
2385 continue;
2386 }
2387 uint8_t newLinkId = perStaProfile.GetLinkId();
2388 if (newLinkId == linkId || newLinkId >= GetNLinks())
2389 {
2390 NS_LOG_DEBUG("[i=" << i << "] Link ID " << newLinkId << " not valid");
2391 continue;
2392 }
2393 if (!perStaProfile.HasAssocRequest() && !perStaProfile.HasReassocRequest())
2394 {
2395 NS_LOG_DEBUG("[i=" << i << "] No (Re)Association Request frame body present");
2396 continue;
2397 }
2398
2399 ReceiveAssocRequest(perStaProfile.GetAssocRequest(),
2400 perStaProfile.GetStaMacAddress(),
2401 newLinkId);
2402 GetWifiRemoteStationManager(newLinkId)->AddStationMleCommonInfo(
2403 perStaProfile.GetStaMacAddress(),
2404 mleCommonInfo);
2405 }
2406 };
2407
2408 std::visit(recvMle, assoc);
2409}
2410
2411void
2412ApWifiMac::ReceiveEmlOmn(MgtEmlOmn& frame, const Mac48Address& sender, uint8_t linkId)
2413{
2414 NS_LOG_FUNCTION(this << frame << sender << linkId);
2415
2416 auto ehtConfiguration = GetEhtConfiguration();
2417
2418 if (BooleanValue emlsrActivated;
2419 !ehtConfiguration ||
2420 !ehtConfiguration->GetAttributeFailSafe("EmlsrActivated", emlsrActivated) ||
2421 !emlsrActivated.Get())
2422 {
2424 "Received an EML Operating Mode Notification frame but EMLSR is not activated");
2425 return;
2426 }
2427
2429 {
2431 auto emlCapabilities =
2432 GetWifiRemoteStationManager(linkId)->GetStationEmlCapabilities(sender);
2433 NS_ASSERT_MSG(emlCapabilities, "EML Capabilities not stored for STA " << sender);
2434
2435 // update values stored in remote station manager
2436 emlCapabilities->get().emlsrPaddingDelay = frame.m_emlsrParamUpdate->paddingDelay;
2437 emlCapabilities->get().emlsrTransitionDelay = frame.m_emlsrParamUpdate->transitionDelay;
2438 }
2439
2440 auto mldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(sender);
2441 NS_ASSERT_MSG(mldAddress, "No MLD address stored for STA " << sender);
2442 auto emlsrLinks =
2443 frame.m_emlControl.emlsrMode == 1 ? frame.GetLinkBitmap() : std::list<uint8_t>{};
2444
2445 // The AP MLD has to consider the changes carried by the received EML Notification frame
2446 // as effective at the same time as the non-AP MLD. Therefore, we need to start a time
2447 // when the transmission of the Ack following the received EML Notification frame is
2448 // completed. For this purpose, we connect a callback to the PHY TX begin trace to catch
2449 // the Ack transmitted after the EML Notification frame.
2451 [=, this](WifiConstPsduMap psduMap, WifiTxVector txVector, double /* txPowerW */) {
2452 NS_ASSERT_MSG(psduMap.size() == 1 && psduMap.begin()->second->GetNMpdus() == 1 &&
2453 psduMap.begin()->second->GetHeader(0).IsAck(),
2454 "Expected a Normal Ack after EML Notification frame");
2455
2456 auto ackDuration =
2457 WifiPhy::CalculateTxDuration(psduMap, txVector, GetLink(linkId).phy->GetPhyBand());
2458
2459 TimeValue transitionTimeout;
2460 ehtConfiguration->GetAttribute("TransitionTimeout", transitionTimeout);
2461
2463 Simulator::Schedule(ackDuration + transitionTimeout.Get(), [=, this]() {
2464 for (uint8_t id = 0; id < GetNLinks(); id++)
2465 {
2466 auto linkAddress =
2467 GetWifiRemoteStationManager(id)->GetAffiliatedStaAddress(*mldAddress);
2468 if (!linkAddress)
2469 {
2470 // this link has not been setup by the non-AP MLD
2471 continue;
2472 }
2473
2474 if (!emlsrLinks.empty())
2475 {
2476 // the non-AP MLD is enabling EMLSR mode
2477 /**
2478 * After the successful transmission of the EML Operating Mode
2479 * Notification frame by the non-AP STA affiliated with the non-AP MLD,
2480 * the non-AP MLD shall operate in the EMLSR mode and the other non-AP
2481 * STAs operating on the corresponding EMLSR links shall transition to
2482 * active mode after the transition delay indicated in the Transition
2483 * Timeout subfield in the EML Capabilities subfield of the Basic
2484 * Multi-Link element or immediately after receiving an EML Operating
2485 * Mode Notification frame from one of the APs operating on the EMLSR
2486 * links and affiliated with the AP MLD (Sec. 35.3.17 of 802.11be D3.0)
2487 */
2488 auto enabled = std::find(emlsrLinks.cbegin(), emlsrLinks.cend(), id) !=
2489 emlsrLinks.cend();
2490 if (enabled)
2491 {
2492 StaSwitchingToActiveModeOrDeassociated(*linkAddress, id);
2493 }
2494 GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, enabled);
2495 }
2496 else
2497 {
2498 // the non-AP MLD is disabling EMLSR mode
2499 /**
2500 * After the successful transmission of the EML Operating Mode
2501 * Notification frame by the non-AP STA affiliated with the non-AP MLD,
2502 * the non-AP MLD shall disable the EMLSR mode and the other non-AP
2503 * STAs operating on the corresponding EMLSR links shall transition to
2504 * power save mode after the transition delay indicated in the
2505 * Transition Timeout subfield in the EML Capabilities subfield of the
2506 * Basic Multi-Link element or immediately after receiving an EML
2507 * Operating Mode Notification frame from one of the APs operating on
2508 * the EMLSR links and affiliated with the AP MLD. (Sec. 35.3.17 of
2509 * 802.11be D3.0)
2510 */
2511 if (id != linkId &&
2512 GetWifiRemoteStationManager(id)->GetEmlsrEnabled(*linkAddress))
2513 {
2514 StaSwitchingToPsMode(*linkAddress, id);
2515 }
2516 GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, false);
2517 }
2518 }
2519 });
2520 });
2521
2522 // connect the callback to the PHY TX begin trace to catch the Ack and disconnect
2523 // after its transmission begins
2524 auto phy = GetLink(linkId).phy;
2525 phy->TraceConnectWithoutContext("PhyTxPsduBegin", cb);
2526 Simulator::Schedule(phy->GetSifs() + NanoSeconds(1),
2527 [=]() { phy->TraceDisconnectWithoutContext("PhyTxPsduBegin", cb); });
2528
2529 // An AP MLD with dot11EHTEMLSROptionActivated equal to true sets the EMLSR Mode subfield
2530 // to the value obtained from the EMLSR Mode subfield of the received EML Operating Mode
2531 // Notification frame. (Sec. 9.6.35.8 of 802.11be D3.0)
2532
2533 // When included in a frame sent by an AP affiliated with an AP MLD, the EMLSR Parameter
2534 // Update Control subfield is set to 0. (Sec. 9.6.35.8 of 802.11be D3.0)
2535 frame.m_emlControl.emlsrParamUpdateCtrl = 0;
2536
2537 // An AP MLD with dot11EHTEMLSROptionImplemented equal to true sets the EMLSR Link Bitmap
2538 // subfield to the value obtained from the EMLSR Link Bitmap subfield of the received
2539 // EML Operating Mode Notification frame. (Sec. 9.6.35.8 of 802.11be D3.0)
2540
2541 // The EMLSR Parameter Update field [..] is present if [..] the Action frame is sent by
2542 // a non-AP STA affiliated with a non-AP MLD (Sec. 9.6.35.8 of 802.11be D3.0)
2543 frame.m_emlsrParamUpdate.reset();
2544
2545 auto ehtFem = StaticCast<EhtFrameExchangeManager>(GetFrameExchangeManager(linkId));
2546 ehtFem->SendEmlOmn(sender, frame);
2547}
2548
2549void
2551{
2552 NS_LOG_FUNCTION(this << *mpdu);
2553 for (auto& i : *PeekPointer(mpdu))
2554 {
2555 auto from = i.second.GetSourceAddr();
2556 auto to = i.second.GetDestinationAddr();
2557
2558 if (to.IsGroup() || IsAssociated(to))
2559 {
2560 NS_LOG_DEBUG("forwarding QoS frame from=" << from << ", to=" << to);
2561 ForwardDown(i.first->Copy(), from, to, mpdu->GetHeader().GetQosTid());
2562 }
2563
2564 ForwardUp(i.first, from, to);
2565 }
2566}
2567
2568void
2570{
2571 NS_LOG_FUNCTION(this);
2573
2574 for (uint8_t linkId = 0; linkId < GetNLinks(); ++linkId)
2575 {
2576 GetLink(linkId).beaconEvent.Cancel();
2578 {
2579 uint64_t jitterUs =
2581 ? static_cast<uint64_t>(m_beaconJitter->GetValue(0, 1) *
2583 : 0);
2584 NS_LOG_DEBUG("Scheduling initial beacon for access point "
2585 << GetAddress() << " at time " << jitterUs << "us");
2588 this,
2589 linkId);
2590 }
2593 }
2594
2599}
2600
2601bool
2603{
2604 bool useProtection = (GetLink(linkId).numNonErpStations > 0) && m_enableNonErpProtection;
2605 GetWifiRemoteStationManager(linkId)->SetUseNonErpProtection(useProtection);
2606 return useProtection;
2607}
2608
2609uint16_t
2610ApWifiMac::GetNextAssociationId(std::list<uint8_t> linkIds)
2611{
2612 // Return the first AID value between 1 and 2007 that is free for all the given links
2613 for (uint16_t nextAid = 1; nextAid <= 2007; nextAid++)
2614 {
2615 if (std::all_of(linkIds.begin(), linkIds.end(), [&](auto&& linkId) {
2616 auto& staList = GetLink(linkId).staList;
2617 return !staList.contains(nextAid);
2618 }))
2619 {
2620 return nextAid;
2621 }
2622 }
2623 NS_FATAL_ERROR("No free association ID available!");
2624 return 0;
2625}
2626
2627const std::map<uint16_t, Mac48Address>&
2628ApWifiMac::GetStaList(uint8_t linkId) const
2629{
2630 return GetLink(linkId).staList;
2631}
2632
2633uint16_t
2635{
2636 return GetWifiRemoteStationManager(linkId)->GetAssociationId(addr);
2637}
2638
2639uint8_t
2640ApWifiMac::GetBufferStatus(uint8_t tid, Mac48Address address) const
2641{
2642 auto it = m_bufferStatus.find(WifiAddressTidPair(address, tid));
2643 if (it == m_bufferStatus.end() || it->second.timestamp + m_bsrLifetime < Simulator::Now())
2644 {
2645 return 255;
2646 }
2647 return it->second.value;
2648}
2649
2650void
2651ApWifiMac::SetBufferStatus(uint8_t tid, Mac48Address address, uint8_t size)
2652{
2653 if (size == 255)
2654 {
2655 // no point in storing an unspecified size
2656 m_bufferStatus.erase(WifiAddressTidPair(address, tid));
2657 }
2658 else
2659 {
2660 m_bufferStatus[WifiAddressTidPair(address, tid)] = {size, Simulator::Now()};
2661 }
2662}
2663
2664uint8_t
2666{
2667 uint8_t maxSize = 0;
2668 bool found = false;
2669
2670 for (uint8_t tid = 0; tid < 8; tid++)
2671 {
2672 uint8_t size = GetBufferStatus(tid, address);
2673 if (size != 255)
2674 {
2675 maxSize = std::max(maxSize, size);
2676 found = true;
2677 }
2678 }
2679
2680 if (found)
2681 {
2682 return maxSize;
2683 }
2684 return 255;
2685}
2686
2687} // namespace ns3
Wi-Fi AP state machine.
Definition: ap-wifi-mac.h:73
void SendAssocResp(Mac48Address to, bool isReassoc, uint8_t linkId)
Forward an association or a reassociation response packet to the DCF/EDCA.
uint16_t GetAssociationId(Mac48Address addr, uint8_t linkId) const
std::unique_ptr< LinkEntity > CreateLinkEntity() const override
Create a LinkEntity object.
Definition: ap-wifi-mac.cc:248
Ptr< Txop > m_beaconTxop
Dedicated Txop for beacons.
Definition: ap-wifi-mac.h:592
void SetBeaconGeneration(bool enable)
Enable or disable beacon generation of the AP.
Definition: ap-wifi-mac.cc:285
void ParseReportedStaInfo(const AssocReqRefVariant &assoc, Mac48Address from, uint8_t linkId)
Given a (Re)Association Request frame body containing a Multi-Link Element, check if a link can be se...
void UpdateShortSlotTimeEnabled(uint8_t linkId)
Update whether short slot time should be enabled or not in the BSS corresponding to the given link.
Definition: ap-wifi-mac.cc:351
void DoCompleteConfig() override
Allow subclasses to complete the configuration of the MAC layer components.
Definition: ap-wifi-mac.cc:260
const std::map< uint16_t, Mac48Address > & GetStaList(uint8_t linkId) const
Get a const reference to the map of associated stations on the given link.
void DoDispose() override
Destructor implementation.
Definition: ap-wifi-mac.cc:232
void SetBeaconInterval(Time interval)
Definition: ap-wifi-mac.cc:323
bool ReceiveAssocRequest(const AssocReqRefVariant &assoc, const Mac48Address &from, uint8_t linkId)
Check whether the supported rate set included in the received (Re)Association Request frame is compat...
std::map< uint8_t, Mac48Address > LinkIdStaAddrMap
Map of (link ID, remote STA address) of the links to setup.
Definition: ap-wifi-mac.h:373
std::map< Mac48Address, EventId > m_transitionTimeoutEvents
transition timeout events running for EMLSR clients
Definition: ap-wifi-mac.h:602
UintAccessParamsMap m_cwMaxsForSta
Per-AC CW max values to advertise to stations.
Definition: ap-wifi-mac.h:605
void ScheduleFilsDiscOrUnsolProbeRespFrames(uint8_t linkId)
Schedule the transmission of FILS Discovery frames or unsolicited Probe Response frames on the given ...
Mac48Address DoGetLocalAddress(const Mac48Address &remoteAddr) const override
This method is called if this device is an MLD to determine the MAC address of the affiliated STA use...
CapabilityInformation GetCapabilities(uint8_t linkId) const
Return the Capability information of the current AP for the given link.
Definition: ap-wifi-mac.cc:591
Ptr< UniformRandomVariable > m_beaconJitter
UniformRandomVariable used to randomize the time of the first beacon.
Definition: ap-wifi-mac.h:596
bool CanForwardPacketsTo(Mac48Address to) const override
Return true if packets can be forwarded to the given destination, false otherwise.
Definition: ap-wifi-mac.cc:499
bool m_enableNonErpProtection
Flag whether protection mechanism is used or not when non-ERP STAs are present within the BSS.
Definition: ap-wifi-mac.h:598
EdcaParameterSet GetEdcaParameterSet(uint8_t linkId) const
Return the EDCA Parameter Set of the current AP for the given link.
Definition: ap-wifi-mac.cc:623
void StaSwitchingToActiveModeOrDeassociated(const Mac48Address &staAddr, uint8_t linkId)
Perform the necessary actions when a given station deassociates or switches from powersave mode to ac...
MultiLinkElement GetMultiLinkElement(uint8_t linkId, WifiMacType frameType, const Mac48Address &to=Mac48Address::GetBroadcast())
Return the Multi-Link Element that the current AP includes in the management frames of the given type...
Definition: ap-wifi-mac.cc:785
HtOperation GetHtOperation(uint8_t linkId) const
Return the HT operation of the current AP for the given link.
Definition: ap-wifi-mac.cc:891
std::optional< Mac48Address > GetMldOrLinkAddressByAid(uint16_t aid) const
void UpdateShortPreambleEnabled(uint8_t linkId)
Update whether short preamble should be enabled or not in the BSS corresponding to the given link.
Definition: ap-wifi-mac.cc:374
void TxOk(Ptr< const WifiMpdu > mpdu)
The packet we sent was successfully received by the receiver (i.e.
Time m_fdBeaconIntervalNon6GHz
Time elapsing between a beacon and FILS Discovery (FD) frame or between two FD frames on 2....
Definition: ap-wifi-mac.h:611
std::map< uint16_t, Mac48Address > m_aidToMldOrLinkAddress
Maps AIDs to MLD addresses (for MLDs) or link addresses (in case of single link devices)
Definition: ap-wifi-mac.h:261
TracedCallback< uint16_t, Mac48Address > m_deAssocLogger
deassociation logger
Definition: ap-wifi-mac.h:634
LinkIdStaAddrMap GetLinkIdStaAddrMap(MgtAssocResponseHeader &assoc, const Mac48Address &to, uint8_t linkId)
Get a map of (link ID, remote STA address) of the links to setup.
void SetAid(MgtAssocResponseHeader &assoc, const LinkIdStaAddrMap &linkIdStaAddrMap)
Set the AID field of the given Association Response frame.
static Ptr< const AttributeChecker > GetTimeAccessParamsChecker()
Get a checker for the TxopLimitsForSta attribute, which can be used to deserialize an ACI-indexed map...
Definition: ap-wifi-mac.cc:207
bool m_enableBeaconGeneration
Flag whether beacons are being generated.
Definition: ap-wifi-mac.h:593
Time m_beaconInterval
Beacon interval.
Definition: ap-wifi-mac.h:594
uint16_t GetNextAssociationId(std::list< uint8_t > linkIds)
bool m_enableBeaconJitter
Flag whether the first beacon should be generated at random time.
Definition: ap-wifi-mac.h:597
std::unordered_map< WifiAddressTidPair, BsrType, WifiAddressTidHash > m_bufferStatus
Per (MAC address, TID) buffer status reports.
Definition: ap-wifi-mac.h:623
void SendProbeResp(Mac48Address to, uint8_t linkId)
Send a Probe Response in response to a Probe Request received from the STA with the given address on ...
DsssParameterSet GetDsssParameterSet(uint8_t linkId) const
Return the DSSS Parameter Set that we support on the given link.
Definition: ap-wifi-mac.cc:581
TracedCallback< uint16_t, Mac48Address > m_assocLogger
association logger
Definition: ap-wifi-mac.h:633
Time GetBeaconInterval() const
Definition: ap-wifi-mac.cc:304
static TypeId GetTypeId()
Get the type ID.
Definition: ap-wifi-mac.cc:58
std::optional< ReducedNeighborReport > GetReducedNeighborReport(uint8_t linkId) const
Return the Reduced Neighbor Report (RNR) element that the current AP sends on the given link,...
Definition: ap-wifi-mac.cc:754
void ReceiveEmlOmn(MgtEmlOmn &frame, const Mac48Address &sender, uint8_t linkId)
Take necessary actions upon receiving the given EML Operating Mode Notification frame from the given ...
void Enqueue(Ptr< Packet > packet, Mac48Address to) override
Definition: ap-wifi-mac.cc:519
Time m_fdBeaconInterval6GHz
Time elapsing between a beacon and FILS Discovery (FD) frame or between two FD frames on 6GHz links.
Definition: ap-wifi-mac.h:609
uint8_t GetMaxBufferStatus(Mac48Address address) const
Return the maximum among the values of the Queue Size subfield of the last QoS Data or QoS Null frame...
Time m_bsrLifetime
Lifetime of Buffer Status Reports.
Definition: ap-wifi-mac.h:600
ApLinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: ap-wifi-mac.cc:254
void Receive(Ptr< const WifiMpdu > mpdu, uint8_t linkId) override
This method acts as the MacRxMiddle receive callback and is invoked to notify us that a frame has bee...
uint8_t GetBufferStatus(uint8_t tid, Mac48Address address) const
Return the value of the Queue Size subfield of the last QoS Data or QoS Null frame received from the ...
EhtOperation GetEhtOperation(uint8_t linkId) const
Return the EHT operation of the current AP for the given link.
bool m_sendUnsolProbeResp
send unsolicited Probe Response instead of FILS Discovery
Definition: ap-wifi-mac.h:613
ErpInformation GetErpInformation(uint8_t linkId) const
Return the ERP information of the current AP for the given link.
Definition: ap-wifi-mac.cc:602
void SetLinkUpCallback(Callback< void > linkUp) override
Definition: ap-wifi-mac.cc:311
VhtOperation GetVhtOperation(uint8_t linkId) const
Return the VHT operation of the current AP for the given link.
Definition: ap-wifi-mac.cc:990
~ApWifiMac() override
Definition: ap-wifi-mac.cc:226
void TxFailed(WifiMacDropReason timeoutReason, Ptr< const WifiMpdu > mpdu)
The packet we sent was successfully received by the receiver (i.e.
HeOperation GetHeOperation(uint8_t linkId) const
Return the HE operation of the current AP for the given link.
void SetBufferStatus(uint8_t tid, Mac48Address address, uint8_t size)
Store the value of the Queue Size subfield of the last QoS Data or QoS Null frame received from the s...
TimeAccessParamsMap m_txopLimitsForSta
Per-AC TXOP limits values to advertise to stations.
Definition: ap-wifi-mac.h:607
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
Definition: ap-wifi-mac.cc:340
std::optional< MuEdcaParameterSet > GetMuEdcaParameterSet() const
Return the MU EDCA Parameter Set of the current AP, if one needs to be advertised.
Definition: ap-wifi-mac.cc:686
void ProcessPowerManagementFlag(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
Process the Power Management bit in the Frame Control field of an MPDU successfully received on the g...
void DeaggregateAmsduAndForward(Ptr< const WifiMpdu > mpdu) override
This method is called to de-aggregate an A-MSDU and forward the constituent packets up the stack.
bool SupportsSendFrom() const override
Definition: ap-wifi-mac.cc:529
MgtAssocResponseHeader GetAssocResp(Mac48Address to, uint8_t linkId)
Get the Association Response frame to send on a given link.
void ForwardDown(Ptr< Packet > packet, Mac48Address from, Mac48Address to)
Forward the packet down to DCF/EDCAF (enqueue the packet).
Definition: ap-wifi-mac.cc:398
Ptr< WifiMpdu > GetFilsDiscovery(uint8_t linkId) const
Get the FILS Discovery frame to send on the given link.
static Ptr< const AttributeChecker > GetUintAccessParamsChecker()
Get a checker for the CwMinsForSta, CwMaxsForSta and AifsnsForSta attributes, which can be used to de...
Definition: ap-wifi-mac.cc:196
void DoInitialize() override
Initialize() implementation.
std::optional< uint8_t > IsAssociated(const Mac48Address &address) const
Get the ID of a link (if any) that has been setup with the station having the given MAC address.
void SendOneBeacon(uint8_t linkId)
Forward a beacon packet to the beacon special DCF for transmission on the given link.
Ptr< WifiMacQueue > GetTxopQueue(AcIndex ac) const override
Get the wifi MAC queue of the (Qos)Txop associated with the given AC, if such (Qos)Txop is installed,...
Definition: ap-wifi-mac.cc:275
bool GetUseNonErpProtection(uint8_t linkId) const
Return whether protection for non-ERP stations is used in the BSS corresponding to the given link.
UintAccessParamsMap m_cwMinsForSta
Per-AC CW min values to advertise to stations.
Definition: ap-wifi-mac.h:604
UintAccessParamsMap m_aifsnsForSta
Per-AC AIFS values to advertise to stations.
Definition: ap-wifi-mac.h:606
void StaSwitchingToPsMode(const Mac48Address &staAddr, uint8_t linkId)
Perform the necessary actions when a given station switches from active mode to powersave mode.
AllSupportedRates GetSupportedRates(uint8_t linkId) const
Return an instance of SupportedRates that contains all rates that we support for the given link (incl...
Definition: ap-wifi-mac.cc:536
A container for one type of attribute.
bool Get() const
Definition: boolean.cc:55
Base class for Callback class.
Definition: callback.h:360
Callback template class.
Definition: callback.h:438
void SetEss()
Set the Extended Service Set (ESS) bit in the capability information field.
bool IsShortSlotTime() const
Check if the short slot time in the capability information field is set to 1.
void SetShortSlotTime(bool shortSlotTime)
Set the short slot time bit in the capability information field.
void SetShortPreamble(bool shortPreamble)
Set the short preamble bit in the capability information field.
bool IsShortPreamble() const
Check if the short preamble bit in the capability information field is set to 1.
The DSSS Parameter Set.
void SetCurrentChannel(uint8_t currentChannel)
Set the Current Channel field in the DsssParameterSet information element.
The EDCA Parameter Set.
void SetViTxopLimit(uint16_t txop)
Set the AC_VI TXOP Limit field in the EdcaParameterSet information element.
void SetViAifsn(uint8_t aifsn)
Set the AC_VI AIFSN field in the EdcaParameterSet information element.
void SetVoAci(uint8_t aci)
Set the AC_VO ACI field in the EdcaParameterSet information element.
void SetVoCWmax(uint32_t cwMax)
Set the AC_VO CWmax field in the EdcaParameterSet information element.
void SetViCWmin(uint32_t cwMin)
Set the AC_VI CWmin field in the EdcaParameterSet information element.
void SetVoTxopLimit(uint16_t txop)
Set the AC_VO TXOP Limit field in the EdcaParameterSet information element.
void SetVoAifsn(uint8_t aifsn)
Set the AC_VO AIFSN field in the EdcaParameterSet information element.
void SetQosInfo(uint8_t qosInfo)
Set the QoS Info field in the EdcaParameterSet information element.
void SetBkCWmin(uint32_t cwMin)
Set the AC_BK CWmin field in the EdcaParameterSet information element.
void SetViAci(uint8_t aci)
Set the AC_VI ACI field in the EdcaParameterSet information element.
void SetViCWmax(uint32_t cwMax)
Set the AC_VI CWmax field in the EdcaParameterSet information element.
void SetVoCWmin(uint32_t cwMin)
Set the AC_VO CWmin field in the EdcaParameterSet information element.
void SetBeTxopLimit(uint16_t txop)
Set the AC_BE TXOP Limit field in the EdcaParameterSet information element.
void SetBeCWmax(uint32_t cwMax)
Set the AC_BE CWmax field in the EdcaParameterSet information element.
void SetBeAci(uint8_t aci)
Set the AC_BE ACI field in the EdcaParameterSet information element.
void SetBkCWmax(uint32_t cwMax)
Set the AC_BK CWmax field in the EdcaParameterSet information element.
void SetBkTxopLimit(uint16_t txop)
Set the AC_BK TXOP Limit field in the EdcaParameterSet information element.
void SetBkAifsn(uint8_t aifsn)
Set the AC_BK AIFSN field in the EdcaParameterSet information element.
void SetBeCWmin(uint32_t cwMin)
Set the AC_BE CWmin field in the EdcaParameterSet information element.
void SetBkAci(uint8_t aci)
Set the AC_BK ACI field in the EdcaParameterSet information element.
void SetBeAifsn(uint8_t aifsn)
Set the AC_BE AIFSN field in the EdcaParameterSet information element.
The IEEE 802.11be EHT Capabilities.
EHT Operation Information Element.
Definition: eht-operation.h:66
void SetMaxTxNss(uint8_t maxNss, uint8_t mcsStart, uint8_t mcsEnd)
Set the max Tx NSS for input MCS index range.
void SetMaxRxNss(uint8_t maxNss, uint8_t mcsStart, uint8_t mcsEnd)
Set the max Rx NSS for input MCS index range.
Hold variables of type enum.
Definition: enum.h:62
T Get() const
Definition: enum.h:97
The ErpInformation Information Element.
void SetBarkerPreambleMode(uint8_t barkerPreambleMode)
Set the Barker_Preamble_Mode field in the ErpInformation information element.
void SetUseProtection(uint8_t useProtection)
Set the Use_Protection field in the ErpInformation information element.
void SetNonErpPresent(uint8_t nonErpPresent)
Set the Non_Erp_Present field in the ErpInformation information element.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
The Extended Capabilities Information Element.
The Extended Supported Rates Information Element.
Implement the FILS (Fast Initial Link Setup) action frame.
uint16_t m_beaconInt
Beacon Interval in TU (1024 us)
std::optional< ReducedNeighborReport > m_rnr
Reduced Neighbor Report.
void SetSsid(const std::string &ssid)
Set the SSID field.
OptFieldWithPresenceInd< FdCapability > m_fdCap
FD Capability.
void SetLengthSubfield()
sets value of Length subfield
The HE 6 GHz Band Capabilities (IEEE 802.11ax-2021 9.4.2.263)
The IEEE 802.11ax HE Capabilities.
The HE Operation Information Element.
Definition: he-operation.h:38
OptFieldWithPresenceInd< OpInfo6GHz > m_6GHzOpInfo
6 GHz Operation Information field
Definition: he-operation.h:175
void SetMaxHeMcsPerNss(uint8_t nss, uint8_t maxHeMcs)
Set the Basic HE-MCS and NSS field in the HE Operation information element by specifying the pair (ns...
BssColorInfo m_bssColorInfo
BSS Color Information field.
Definition: he-operation.h:173
The HT Capabilities Information Element.
The HT Operation Information Element.
Definition: ht-operation.h:51
void SetObssNonHtStasPresent(uint8_t obssNonHtStasPresent)
Set the OBSS non HT STAs present.
void SetRifsMode(uint8_t rifsMode)
Set the RIFS mode.
void SetSecondaryChannelOffset(uint8_t secondaryChannelOffset)
Set the secondary channel offset.
Definition: ht-operation.cc:95
void SetPcoActive(uint8_t pcoActive)
Set the PCO active.
void SetTxUnequalModulation(uint8_t txUnequalModulation)
Set the transmit unequal modulation.
void SetHtProtection(uint8_t htProtection)
Set the HT protection.
void SetTxMaxNSpatialStreams(uint8_t maxTxSpatialStreams)
Set the transmit maximum number spatial streams.
void SetTxRxMcsSetUnequal(uint8_t txRxMcsSetUnequal)
Set the transmit / receive MCS set unequal.
void SetDualBeacon(uint8_t dualBeacon)
Set the dual beacon.
void SetNonGfHtStasPresent(uint8_t nonGfHtStasPresent)
Set the non GF HT STAs present.
void SetTxMcsSetDefined(uint8_t txMcsSetDefined)
Set the transmit MCS set defined.
void SetLSigTxopProtectionFullSupport(uint8_t lSigTxopProtectionFullSupport)
Set the LSIG TXOP protection full support.
void SetStaChannelWidth(uint8_t staChannelWidth)
Set the STA channel width.
void SetRxHighestSupportedDataRate(uint16_t maxSupportedRate)
Set the receive highest supported data rate.
void SetRxMcsBitmask(uint8_t index)
Set the receive MCS bitmask.
void SetPrimaryChannel(uint8_t ctrl)
Set the Primary Channel field in the HT Operation information element.
Definition: ht-operation.cc:89
void SetDualCtsProtection(uint8_t dualCtsProtection)
Set the dual CTS protection.
void SetPhase(uint8_t pcoPhase)
Set the PCO phase.
void SetStbcBeacon(uint8_t stbcBeacon)
Set the STBC beacon.
Hold a signed integer type.
Definition: integer.h:45
int64_t Get() const
Definition: integer.cc:37
an EUI-48 address
Definition: mac48-address.h:46
bool IsGroup() const
static Mac48Address GetBroadcast()
bool IsBroadcast() const
Implement the header for management frames of type association request.
Definition: mgt-headers.h:162
Implement the header for management frames of type association and reassociation response.
Definition: mgt-headers.h:339
CapabilityInformation & Capabilities()
Definition: mgt-headers.cc:474
StatusCode GetStatusCode()
Return the status code.
Definition: mgt-headers.cc:456
void SetStatusCode(StatusCode code)
Set the status code.
Definition: mgt-headers.cc:462
void SetAssociationId(uint16_t aid)
Set the association ID.
Definition: mgt-headers.cc:480
Implement the header for management frames of type beacon.
Definition: mgt-headers.h:517
Implement the header for Action frames of type EML Operating Mode Notification.
EmlControl m_emlControl
EML Control field.
std::optional< EmlsrParamUpdate > m_emlsrParamUpdate
EMLSR Parameter Update field.
std::list< uint8_t > GetLinkBitmap() const
Implement the header for management frames of type probe request.
Definition: mgt-headers.h:437
Implement the header for management frames of type probe response.
Definition: mgt-headers.h:456
void SetBeaconIntervalUs(uint64_t us)
Set the beacon interval in microseconds unit.
Definition: mgt-headers.cc:81
CapabilityInformation & Capabilities()
Definition: mgt-headers.cc:93
Implement the header for management frames of type reassociation request.
Definition: mgt-headers.h:246
The MU EDCA Parameter Set.
void SetMuCwMin(uint8_t aci, uint16_t cwMin)
Set the ECWmin subfield of the ECWmin/ECWmax field in the MU AC Parameter Record field corresponding ...
void SetMuEdcaTimer(uint8_t aci, Time timer)
Set the MU EDCA Timer field in the MU AC Parameter Record field corresponding to the given AC Index (...
void SetMuAifsn(uint8_t aci, uint8_t aifsn)
Set the AIFSN subfield of the ACI/AIFSN field in the MU AC Parameter Record field corresponding to th...
void SetQosInfo(uint8_t qosInfo)
Set the QoS Info field in the MuEdcaParameterSet information element.
Time GetMuEdcaTimer(uint8_t aci) const
Get the MU EDCA Timer value encoded in the MU AC Parameter Record field corresponding to the given AC...
void SetMuCwMax(uint8_t aci, uint16_t cwMax)
Set the ECWmax subfield of the ECWmin/ECWmax field in the MU AC Parameter Record field corresponding ...
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:322
void Initialize()
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:214
void Dispose()
Dispose of this Object.
Definition: object.cc:258
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
The Reduced Neighbor Report element.
std::size_t GetNNbrApInfoFields() const
Get the number of Neighbor AP Information fields.
void SetMldParameters(std::size_t nbrApInfoId, std::size_t index, uint8_t mldId, uint8_t linkId, uint8_t changeSequence)
Set the MLD Parameters subfield of the i-th TBTT Information field of the given Neighbor AP Informati...
void SetShortSsid(std::size_t nbrApInfoId, std::size_t index, uint32_t shortSsid)
Set the Short SSID field of the i-th TBTT Information field of the given Neighbor AP Information fiel...
void SetBssid(std::size_t nbrApInfoId, std::size_t index, Mac48Address bssid)
Set the BSSID field of the i-th TBTT Information field of the given Neighbor AP Information field.
void SetPsd20MHz(std::size_t nbrApInfoId, std::size_t index, uint8_t psd20MHz)
Set the 20 MHz PSD field of the i-th TBTT Information field of the given Neighbor AP Information fiel...
void AddNbrApInfoField()
Add a Neighbor AP Information field.
void SetBssParameters(std::size_t nbrApInfoId, std::size_t index, uint8_t bssParameters)
Set the BSS Parameters field of the i-th TBTT Information field of the given Neighbor AP Information ...
void AddTbttInformationField(std::size_t nbrApInfoId)
Add a TBTT Information fields to the TBTT Information Set field of the given Neighbor AP Information ...
void SetOperatingChannel(std::size_t nbrApInfoId, const WifiPhyOperatingChannel &channel)
Set the Operating Class and the Channel Number fields of the given Neighbor AP Information field base...
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
Status code for association response.
Definition: status-code.h:32
bool IsSuccess() const
Return whether the status code is success.
Definition: status-code.cc:42
void SetFailure()
Set success bit to 1 (failure).
Definition: status-code.cc:36
void SetSuccess()
Set success bit to 0 (success).
Definition: status-code.cc:30
Hold variables of type string.
Definition: string.h:56
The Supported Rates Information Element.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
bool IsZero() const
Exactly equivalent to t == 0.
Definition: nstime.h:315
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:413
Time Get() const
Definition: time.cc:530
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: txop.cc:695
void SetMaxCws(const std::vector< uint32_t > &maxCws)
Set the maximum contention window size for each link.
Definition: txop.cc:330
void SetAifsns(const std::vector< uint8_t > &aifsns)
Set the number of slots that make up an AIFS for each link.
Definition: txop.cc:441
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:275
virtual void SetWifiMac(const Ptr< WifiMac > mac)
Set the wifi MAC this Txop is associated to.
Definition: txop.cc:253
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set MacTxMiddle this Txop is associated to.
Definition: txop.cc:246
void SetMinCws(const std::vector< uint32_t > &minCws)
Set the minimum contention window size for each link.
Definition: txop.cc:287
virtual void Queue(Ptr< Packet > packet, const WifiMacHeader &hdr)
Definition: txop.cc:623
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Hold an unsigned integer type.
Definition: uinteger.h:45
uint64_t Get() const
Definition: uinteger.cc:37
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
The IEEE 802.11ac VHT Capabilities.
The VHT Operation Information Element.
Definition: vht-operation.h:36
void SetMaxVhtMcsPerNss(uint8_t nss, uint8_t maxVhtMcs)
Set the Basic VHT-MCS and NSS field in the VHT Operation information element by specifying the tuple ...
void SetChannelWidth(uint8_t channelWidth)
Set the Channel Width field in the VHT Operation information element.
void SetChannelCenterFrequencySegment1(uint8_t channelCenterFrequencySegment1)
Set the Channel Center Frequency Segment 1 field in the VHT Operation information element.
void SetChannelCenterFrequencySegment0(uint8_t channelCenterFrequencySegment0)
Set the Channel Center Frequency Segment 0 field in the VHT Operation information element.
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
static std::pair< CategoryValue, ActionValue > Peek(Ptr< const Packet > pkt)
Peek an Action header from the given packet.
static std::pair< CategoryValue, ActionValue > Remove(Ptr< Packet > pkt)
Remove an Action header from the given packet.
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
bool IsAssocReq() const
Return true if the header is an Association Request header.
void SetQosAckPolicy(QosAckPolicy policy)
Set the QoS Ack policy in the QoS control field.
bool IsProbeReq() const
Return true if the header is a Probe Request header.
bool IsQosAmsdu() const
Check if the A-MSDU present bit is set in the QoS control field.
Mac48Address GetAddr3() const
Return the address in the Address 3 field.
bool IsAssocResp() const
Return true if the header is an Association Response header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
void SetQosTxopLimit(uint8_t txop)
Set TXOP limit in the QoS control field.
virtual WifiMacType GetType() const
Return the type (WifiMacType)
bool IsMgt() const
Return true if the Type is Management.
void SetNoOrder()
Unset order bit in the frame control field.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
bool IsAction() const
Return true if the header is an Action header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
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.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
bool HasData() const
Return true if the header type is DATA and is not DATA_NULL.
bool IsReassocReq() const
Return true if the header is a Reassociation Request header.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
bool IsData() const
Return true if the Type is DATA.
void SetQosNoEosp()
Un-set the end of service period (EOSP) bit in the QoS control field.
bool IsReassocResp() const
Return true if the header is a Reassociation Response header.
void SetDsFrom()
Set the From DS bit in the Frame Control field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
base class for all MAC-level wifi objects.
Definition: wifi-mac.h:99
Ptr< FrameExchangeManager > GetFrameExchangeManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Frame Exchange Manager associated with the given link.
Definition: wifi-mac.cc:981
Ptr< QosTxop > GetBEQueue() const
Accessor for the AC_BE channel access function.
Definition: wifi-mac.cc:627
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition: wifi-mac.cc:1774
Ptr< HeConfiguration > GetHeConfiguration() const
Definition: wifi-mac.cc:1891
Ptr< Txop > GetTxop() const
Accessor for the Txop object.
Definition: wifi-mac.cc:547
VhtCapabilities GetVhtCapabilities(uint8_t linkId) const
Return the VHT capabilities of the device for the given link.
Definition: wifi-mac.cc:2162
bool GetQosSupported() const
Return whether the device supports QoS.
Definition: wifi-mac.cc:1347
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition: wifi-mac.cc:1072
void DoInitialize() override
Initialize() implementation.
Definition: wifi-mac.cc:393
void UnblockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Unblock the transmission on the given links of all unicast frames addressed to the station with the g...
Definition: wifi-mac.cc:1558
Ssid GetSsid() const
Definition: wifi-mac.cc:509
bool GetErpSupported(uint8_t linkId) const
Return whether the device supports ERP on the given link.
Definition: wifi-mac.cc:1353
Ptr< QosTxop > GetVOQueue() const
Accessor for the AC_VO channel access function.
Definition: wifi-mac.cc:615
void SetTypeOfStation(TypeOfStation type)
This method is invoked by a subclass to specify what type of station it is implementing.
Definition: wifi-mac.cc:459
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:1315
void BlockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Block the transmission on the given links of all unicast frames addressed to the station with the giv...
Definition: wifi-mac.cc:1512
bool GetEhtSupported() const
Return whether the device supports EHT.
Definition: wifi-mac.cc:1924
bool GetHeSupported() const
Return whether the device supports HE.
Definition: wifi-mac.cc:1918
HtCapabilities GetHtCapabilities(uint8_t linkId) const
Return the HT capabilities of the device for the given link.
Definition: wifi-mac.cc:2103
virtual std::optional< uint8_t > GetLinkIdByAddress(const Mac48Address &address) const
Get the ID of the link having the given MAC address, if any.
Definition: wifi-mac.cc:1100
void ApplyTidLinkMapping(const Mac48Address &mldAddr, WifiDirection dir)
Apply the TID-to-Link Mapping negotiated with the given MLD for the given direction by properly confi...
Definition: wifi-mac.cc:1430
Ptr< EhtConfiguration > GetEhtConfiguration() const
Definition: wifi-mac.cc:1897
bool GetVhtSupported(uint8_t linkId) const
Return whether the device supports VHT on the given link.
Definition: wifi-mac.cc:1910
Ptr< MacTxMiddle > m_txMiddle
TX middle (aggregation etc.)
Definition: wifi-mac.h:915
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: wifi-mac.cc:364
Ptr< HtConfiguration > GetHtConfiguration() const
Definition: wifi-mac.cc:1879
void UpdateTidToLinkMapping(const Mac48Address &mldAddr, WifiDirection dir, const WifiTidLinkMapping &mapping)
Update the TID-to-Link Mappings for the given MLD in the given direction based on the given negotiate...
Definition: wifi-mac.cc:1213
ExtendedCapabilities GetExtendedCapabilities() const
Return the extended capabilities of the device.
Definition: wifi-mac.cc:2092
He6GhzBandCapabilities GetHe6GhzBandCapabilities(uint8_t linkId) const
Return the HE 6GHz band capabilities of the device for the given 6 GHz link.
Definition: wifi-mac.cc:2302
virtual Ptr< WifiMacQueue > GetTxopQueue(AcIndex ac) const
Get the wifi MAC queue of the (Qos)Txop associated with the given AC, if such (Qos)Txop is installed,...
Definition: wifi-mac.cc:639
bool GetShortSlotTimeSupported() const
Definition: wifi-mac.cc:1397
void NotifyRxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:713
virtual void SetLinkUpCallback(Callback< void > linkUp)
Definition: wifi-mac.cc:1416
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:1045
bool GetHtSupported(uint8_t linkId) const
Return whether the device supports HT on the given link.
Definition: wifi-mac.cc:1903
void ForwardUp(Ptr< const Packet > packet, Mac48Address from, Mac48Address to)
Forward the packet up to the device.
Definition: wifi-mac.cc:1632
bool Is6GhzBand(uint8_t linkId) const
Indicate if a given link is on the 6 GHz band.
Definition: wifi-mac.cc:1205
virtual void Receive(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
This method acts as the MacRxMiddle receive callback and is invoked to notify us that a frame has bee...
Definition: wifi-mac.cc:1639
Mac48Address GetAddress() const
Definition: wifi-mac.cc:496
EhtCapabilities GetEhtCapabilities(uint8_t linkId) const
Return the EHT capabilities of the device for the given link.
Definition: wifi-mac.cc:2337
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: wifi-mac.cc:1063
HeCapabilities GetHeCapabilities(uint8_t linkId) const
Return the HE capabilities of the device for the given link.
Definition: wifi-mac.cc:2244
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:593
void NotifyTxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:695
void DoDispose() override
Destructor implementation.
Definition: wifi-mac.cc:417
bool GetDsssSupported(uint8_t linkId) const
Return whether the device supports DSSS on the given link.
Definition: wifi-mac.cc:1377
represent a single transmission mode
Definition: wifi-mode.h:51
std::string GetUniqueName() const
Definition: wifi-mode.cc:148
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:122
uint8_t GetMcsValue() const
Definition: wifi-mode.cc:163
uint8_t GetMaxSupportedRxSpatialStreams() const
Definition: wifi-phy.cc:1351
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1539
void SetSlot(Time slot)
Set the slot duration for this PHY.
Definition: wifi-phy.cc:819
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1065
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Ptr< AttributeChecker > MakeAttributeContainerChecker()
Make uninitialized AttributeContainerChecker using explicit types.
Ptr< AttributeChecker > MakePairChecker()
Make a PairChecker without abscissa and ordinate AttributeCheckers.
Definition: pair.h:298
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:259
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition: abort.h:144
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:76
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1343
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1355
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1331
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiMacDropReason
The reason why an MPDU was dropped.
Definition: wifi-mac.h:80
uint8_t QosUtilsGetTidForPacket(Ptr< const Packet > packet)
If a QoS tag is attached to the packet, returns a value < 8.
Definition: qos-utils.cc:156
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:73
@ AP
Definition: wifi-mac.h:69
@ WIFI_STANDARD_80211ax
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
Definition: wifi-phy-band.h:39
@ WIFI_MOD_CLASS_HR_DSSS
HR/DSSS (Clause 16)
@ 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
Best Effort.
Definition: qos-utils.h:75
@ AC_VO
Voice.
Definition: qos-utils.h:81
@ AC_VI
Video.
Definition: qos-utils.h:79
@ AC_BK
Background.
Definition: qos-utils.h:77
@ AC_BEACON
Beacon queue.
Definition: qos-utils.h:85
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:454
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
const Time WIFI_TU
Wi-Fi Time Unit (see IEEE 802.11-2020 sec. 3.1)
Definition: wifi-utils.cc:33
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1407
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:700
std::variant< std::reference_wrapper< MgtAssocRequestHeader >, std::reference_wrapper< MgtReassocRequestHeader > > AssocReqRefVariant
variant holding a reference to a (Re)Association Request
Definition: ap-wifi-mac.h:59
@ NO_PROTECTION
Definition: ht-operation.h:37
@ MIXED_MODE_PROTECTION
Definition: ht-operation.h:40
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:189
constexpr uint8_t WIFI_EHT_MAX_MCS_INDEX
IEEE 802.11be D2.0 Figure 9-1002ai.
Definition: eht-operation.h:32
WifiMacType
Combination of valid MAC header type/subtype.
@ WIFI_MAC_MGT_BEACON
@ WIFI_MAC_MGT_ACTION
@ WIFI_MAC_MGT_ASSOCIATION_RESPONSE
@ WIFI_MAC_MGT_DISASSOCIATION
@ WIFI_MAC_MGT_ASSOCIATION_REQUEST
@ WIFI_MAC_MGT_REASSOCIATION_REQUEST
@ WIFI_MAC_MGT_PROBE_RESPONSE
@ WIFI_MAC_DATA
@ WIFI_MAC_MGT_REASSOCIATION_RESPONSE
@ WIFI_MAC_QOSDATA
bool TidToLinkMappingValidForNegType1(const WifiTidLinkMapping &dlLinkMapping, const WifiTidLinkMapping &ulLinkMapping)
Check if the given TID-to-Link Mappings are valid for a negotiation type of 1.
Definition: wifi-utils.cc:150
std::pair< Mac48Address, uint8_t > WifiAddressTidPair
(MAC address, TID) pair
Definition: qos-utils.h:36
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:81
std::map< uint8_t, std::set< uint8_t > > WifiTidLinkMapping
TID-indexed map of the link set to which the TID is mapped.
Definition: wifi-utils.h:75
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1427
Struct containing all supported rates.
void SetBasicRate(uint64_t bs)
Set the given rate to basic rates.
void AddBssMembershipSelectorRate(uint64_t bs)
Add a special value to the supported rate set, corresponding to a BSS membership selector.
void AddSupportedRate(uint64_t bs)
Add the given rate to the supported rates.
std::optional< MldCapabilities > m_mldCapabilities
MLD Capabilities.
void SetMediumSyncDelayTimer(Time delay)
Set the Medium Synchronization Duration subfield of the Medium Synchronization Delay Information in t...
FD Capability subfield of FILS Discovery Information field.
uint8_t m_bssColor
BSS Color.
Definition: he-operation.h:90
6 GHz Operation Information field
Definition: he-operation.h:124
uint8_t m_chCntrFreqSeg0
Channel center frequency segment 0.
Definition: he-operation.h:130
uint8_t m_chWid
Channel Width.
Definition: he-operation.h:126
uint8_t m_chCntrFreqSeg1
Channel center frequency segment 1.
Definition: he-operation.h:131
uint8_t m_primCh
Primary Channel.
Definition: he-operation.h:125
uint8_t emlsrParamUpdateCtrl
EMLSR Parameter Update Control.
typedef for union of different ActionValues