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-headers.h"
29#include "msdu-aggregator.h"
30#include "qos-txop.h"
33#include "wifi-mac-queue.h"
34#include "wifi-net-device.h"
35#include "wifi-phy.h"
36
37#include "ns3/eht-configuration.h"
38#include "ns3/eht-frame-exchange-manager.h"
39#include "ns3/he-configuration.h"
40#include "ns3/ht-configuration.h"
41#include "ns3/log.h"
42#include "ns3/multi-link-element.h"
43#include "ns3/packet.h"
44#include "ns3/pointer.h"
45#include "ns3/random-variable-stream.h"
46#include "ns3/simulator.h"
47#include "ns3/string.h"
48
49namespace ns3
50{
51
52NS_LOG_COMPONENT_DEFINE("ApWifiMac");
53
55
56TypeId
58{
59 static TypeId tid =
60 TypeId("ns3::ApWifiMac")
62 .SetGroupName("Wifi")
63 .AddConstructor<ApWifiMac>()
64 .AddAttribute(
65 "BeaconInterval",
66 "Delay between two beacons",
67 TimeValue(MicroSeconds(102400)),
70 .AddAttribute("BeaconJitter",
71 "A uniform random variable to cause the initial beacon starting time "
72 "(after simulation time 0) "
73 "to be distributed between 0 and the BeaconInterval.",
74 StringValue("ns3::UniformRandomVariable"),
76 MakePointerChecker<UniformRandomVariable>())
77 .AddAttribute("EnableBeaconJitter",
78 "If beacons are enabled, whether to jitter the initial send event.",
79 BooleanValue(true),
82 .AddAttribute("BeaconGeneration",
83 "Whether or not beacons are generated.",
84 BooleanValue(true),
87 .AddAttribute("EnableNonErpProtection",
88 "Whether or not protection mechanism should be used when non-ERP STAs "
89 "are present within the BSS."
90 "This parameter is only used when ERP is supported by the AP.",
91 BooleanValue(true),
94 .AddAttribute("BsrLifetime",
95 "Lifetime of Buffer Status Reports received from stations.",
99 .AddTraceSource("AssociatedSta",
100 "A station associated with this access point.",
102 "ns3::ApWifiMac::AssociationCallback")
103 .AddTraceSource("DeAssociatedSta",
104 "A station lost association with this access point.",
106 "ns3::ApWifiMac::AssociationCallback");
107 return tid;
108}
109
111 : m_enableBeaconGeneration(false)
112{
113 NS_LOG_FUNCTION(this);
114 m_beaconTxop = CreateObject<Txop>(CreateObject<WifiMacQueue>(AC_BEACON));
116
117 // Let the lower layers know that we are acting as an AP.
119}
120
122{
123 NS_LOG_FUNCTION(this);
124}
125
126void
128{
129 NS_LOG_FUNCTION(this);
131 m_beaconTxop = nullptr;
134}
135
137{
140}
141
142std::unique_ptr<WifiMac::LinkEntity>
144{
145 return std::make_unique<ApLinkEntity>();
146}
147
149ApWifiMac::GetLink(uint8_t linkId) const
150{
151 return static_cast<ApLinkEntity&>(WifiMac::GetLink(linkId));
152}
153
154void
156{
157 NS_LOG_FUNCTION(this << standard);
160 m_beaconTxop->SetAifsns(std::vector<uint8_t>(GetNLinks(), 1));
161 m_beaconTxop->SetMinCws(std::vector<uint32_t>(GetNLinks(), 0));
162 m_beaconTxop->SetMaxCws(std::vector<uint32_t>(GetNLinks(), 0));
163 for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
164 {
166 }
167}
168
171{
172 if (ac == AC_BEACON)
173 {
175 }
176 return WifiMac::GetTxopQueue(ac);
177}
178
179void
181{
182 NS_LOG_FUNCTION(this << enable);
183 for (uint8_t linkId = 0; linkId < GetNLinks(); ++linkId)
184 {
185 if (!enable)
186 {
187 GetLink(linkId).beaconEvent.Cancel();
188 }
189 else if (!m_enableBeaconGeneration)
190 {
191 GetLink(linkId).beaconEvent =
193 }
194 }
196}
197
198Time
200{
201 NS_LOG_FUNCTION(this);
202 return m_beaconInterval;
203}
204
205void
207{
208 NS_LOG_FUNCTION(this << &linkUp);
210
211 // The approach taken here is that, from the point of view of an AP,
212 // the link is always up, so we immediately invoke the callback if
213 // one is set
214 linkUp();
215}
216
217void
219{
220 NS_LOG_FUNCTION(this << interval);
221 if ((interval.GetMicroSeconds() % 1024) != 0)
222 {
223 NS_FATAL_ERROR("beacon interval should be multiple of 1024us (802.11 time unit), see IEEE "
224 "Std. 802.11-2012");
225 }
226 if (interval.GetMicroSeconds() > (1024 * 65535))
227 {
229 "beacon interval should be smaller then or equal to 65535 * 1024us (802.11 time unit)");
230 }
231 m_beaconInterval = interval;
232}
233
234int64_t
236{
237 NS_LOG_FUNCTION(this << stream);
238 m_beaconJitter->SetStream(stream);
239 return 1;
240}
241
242void
244{
245 NS_LOG_FUNCTION(this << +linkId);
246 auto& link = GetLink(linkId);
247 if (GetErpSupported(linkId) && GetShortSlotTimeSupported() && (link.numNonErpStations == 0))
248 {
249 for (const auto& sta : link.staList)
250 {
252 {
253 link.shortSlotTimeEnabled = false;
254 return;
255 }
256 }
257 link.shortSlotTimeEnabled = true;
258 }
259 else
260 {
261 link.shortSlotTimeEnabled = false;
262 }
263}
264
265void
267{
268 NS_LOG_FUNCTION(this << +linkId);
269 auto& link = GetLink(linkId);
270 if (GetErpSupported(linkId) && GetWifiPhy(linkId)->GetShortPhyPreambleSupported())
271 {
272 for (const auto& sta : link.staList)
273 {
274 if (!GetWifiRemoteStationManager(linkId)->GetErpOfdmSupported(sta.second) ||
275 !GetWifiRemoteStationManager(linkId)->GetShortPreambleSupported(sta.second))
276 {
277 link.shortPreambleEnabled = false;
278 return;
279 }
280 }
281 link.shortPreambleEnabled = true;
282 }
283 else
284 {
285 link.shortPreambleEnabled = false;
286 }
287}
288
289void
291{
292 NS_LOG_FUNCTION(this << packet << from << to);
293 // If we are not a QoS AP then we definitely want to use AC_BE to
294 // transmit the packet. A TID of zero will map to AC_BE (through \c
295 // QosUtilsMapTidToAc()), so we use that as our default here.
296 uint8_t tid = 0;
297
298 // If we are a QoS AP then we attempt to get a TID for this packet
299 if (GetQosSupported())
300 {
301 tid = QosUtilsGetTidForPacket(packet);
302 // Any value greater than 7 is invalid and likely indicates that
303 // the packet had no QoS tag, so we revert to zero, which'll
304 // mean that AC_BE is used.
305 if (tid > 7)
306 {
307 tid = 0;
308 }
309 }
310
311 ForwardDown(packet, from, to, tid);
312}
313
314void
316{
317 NS_LOG_FUNCTION(this << packet << from << to << +tid);
318 WifiMacHeader hdr;
319
320 // For now, an AP that supports QoS does not support non-QoS
321 // associations, and vice versa. In future the AP model should
322 // support simultaneously associated QoS and non-QoS STAs, at which
323 // point there will need to be per-association QoS state maintained
324 // by the association state machine, and consulted here.
325 if (GetQosSupported())
326 {
329 hdr.SetQosNoEosp();
330 hdr.SetQosNoAmsdu();
331 // Transmission of multiple frames in the same Polled TXOP is not supported for now
332 hdr.SetQosTxopLimit(0);
333 // Fill in the QoS control field in the MAC header
334 hdr.SetQosTid(tid);
335 }
336 else
337 {
339 }
340
341 if (GetQosSupported())
342 {
343 hdr.SetNoOrder(); // explicitly set to 0 for the time being since HT control field is not
344 // yet implemented (set it to 1 when implemented)
345 }
346
347 std::list<Mac48Address> addr2Set;
348 if (to.IsGroup())
349 {
350 // broadcast frames are transmitted on all the links
351 for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
352 {
353 addr2Set.push_back(GetFrameExchangeManager(linkId)->GetAddress());
354 }
355 }
356 else
357 {
358 // the Transmitter Address (TA) is the MLD address only for non-broadcast data frames
359 // exchanged between two MLDs
360 addr2Set = {GetAddress()};
361 auto linkId = IsAssociated(to);
362 NS_ASSERT_MSG(linkId, "Station " << to << "is not associated, cannot send it a frame");
363 if (GetNLinks() == 1 || !GetWifiRemoteStationManager(*linkId)->GetMldAddress(to))
364 {
365 addr2Set = {GetFrameExchangeManager(*linkId)->GetAddress()};
366 }
367 }
368
369 for (const auto& addr2 : addr2Set)
370 {
371 hdr.SetAddr1(to);
372 hdr.SetAddr2(addr2);
373 hdr.SetAddr3(from);
374 hdr.SetDsFrom();
375 hdr.SetDsNotTo();
376
377 if (GetQosSupported())
378 {
379 // Sanity check that the TID is valid
380 NS_ASSERT(tid < 8);
381 GetQosTxop(tid)->Queue(packet, hdr);
382 }
383 else
384 {
385 GetTxop()->Queue(packet, hdr);
386 }
387 }
388}
389
390bool
392{
393 return (to.IsGroup() || IsAssociated(to));
394}
395
396void
398{
399 NS_LOG_FUNCTION(this << packet << to << from);
400 if (CanForwardPacketsTo(to))
401 {
402 ForwardDown(packet, from, to);
403 }
404 else
405 {
406 NotifyTxDrop(packet);
407 }
408}
409
410void
412{
413 NS_LOG_FUNCTION(this << packet << to);
414 // We're sending this packet with a from address that is our own. We
415 // get that address from the lower MAC and make use of the
416 // from-spoofing Enqueue() method to avoid duplicated code.
417 Enqueue(packet, to, GetAddress());
418}
419
420bool
422{
423 NS_LOG_FUNCTION(this);
424 return true;
425}
426
428ApWifiMac::GetSupportedRates(uint8_t linkId) const
429{
430 NS_LOG_FUNCTION(this << +linkId);
431 AllSupportedRates rates;
432 // Send the set of supported rates and make sure that we indicate
433 // the Basic Rate set in this set of supported rates.
434 for (const auto& mode : GetWifiPhy(linkId)->GetModeList())
435 {
436 uint64_t modeDataRate = mode.GetDataRate(GetWifiPhy(linkId)->GetChannelWidth());
437 NS_LOG_DEBUG("Adding supported rate of " << modeDataRate);
438 rates.AddSupportedRate(modeDataRate);
439 // Add rates that are part of the BSSBasicRateSet (manufacturer dependent!)
440 // here we choose to add the mandatory rates to the BSSBasicRateSet,
441 // except for 802.11b where we assume that only the non HR-DSSS rates are part of the
442 // BSSBasicRateSet
443 if (mode.IsMandatory() && (mode.GetModulationClass() != WIFI_MOD_CLASS_HR_DSSS))
444 {
445 NS_LOG_DEBUG("Adding basic mode " << mode.GetUniqueName());
447 }
448 }
449 // set the basic rates
450 for (uint8_t j = 0; j < GetWifiRemoteStationManager(linkId)->GetNBasicModes(); j++)
451 {
453 uint64_t modeDataRate = mode.GetDataRate(GetWifiPhy(linkId)->GetChannelWidth());
454 NS_LOG_DEBUG("Setting basic rate " << mode.GetUniqueName());
455 rates.SetBasicRate(modeDataRate);
456 }
457 // If it is a HT AP, then add the BSSMembershipSelectorSet
458 // The standard says that the BSSMembershipSelectorSet
459 // must have its MSB set to 1 (must be treated as a Basic Rate)
460 // Also the standard mentioned that at least 1 element should be included in the SupportedRates
461 // the rest can be in the ExtendedSupportedRates
462 if (GetHtSupported())
463 {
464 for (const auto& selector : GetWifiPhy(linkId)->GetBssMembershipSelectorList())
465 {
466 rates.AddBssMembershipSelectorRate(selector);
467 }
468 }
469 return rates;
470}
471
474{
475 NS_LOG_FUNCTION(this << +linkId);
477 DsssParameterSet dsssParameters;
478 dsssParameters.SetCurrentChannel(GetWifiPhy(linkId)->GetChannelNumber());
479 return dsssParameters;
480}
481
483ApWifiMac::GetCapabilities(uint8_t linkId) const
484{
485 NS_LOG_FUNCTION(this << +linkId);
486 CapabilityInformation capabilities;
487 capabilities.SetShortPreamble(GetLink(linkId).shortPreambleEnabled);
488 capabilities.SetShortSlotTime(GetLink(linkId).shortSlotTimeEnabled);
489 capabilities.SetEss();
490 return capabilities;
491}
492
494ApWifiMac::GetErpInformation(uint8_t linkId) const
495{
496 NS_LOG_FUNCTION(this << +linkId);
497 NS_ASSERT(GetErpSupported(linkId));
498 ErpInformation information;
499
500 information.SetNonErpPresent(GetLink(linkId).numNonErpStations > 0);
501 information.SetUseProtection(GetUseNonErpProtection(linkId));
502 if (GetLink(linkId).shortPreambleEnabled)
503 {
504 information.SetBarkerPreambleMode(0);
505 }
506 else
507 {
508 information.SetBarkerPreambleMode(1);
509 }
510
511 return information;
512}
513
516{
517 NS_LOG_FUNCTION(this << +linkId);
519 EdcaParameterSet edcaParameters;
520
521 Ptr<QosTxop> edca;
522 Time txopLimit;
523
524 edca = GetQosTxop(AC_BE);
525 txopLimit = edca->GetTxopLimit(linkId);
526 edcaParameters.SetBeAci(0);
527 edcaParameters.SetBeCWmin(edca->GetMinCw(linkId));
528 edcaParameters.SetBeCWmax(edca->GetMaxCw(linkId));
529 edcaParameters.SetBeAifsn(edca->GetAifsn(linkId));
530 edcaParameters.SetBeTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
531
532 edca = GetQosTxop(AC_BK);
533 txopLimit = edca->GetTxopLimit(linkId);
534 edcaParameters.SetBkAci(1);
535 edcaParameters.SetBkCWmin(edca->GetMinCw(linkId));
536 edcaParameters.SetBkCWmax(edca->GetMaxCw(linkId));
537 edcaParameters.SetBkAifsn(edca->GetAifsn(linkId));
538 edcaParameters.SetBkTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
539
540 edca = GetQosTxop(AC_VI);
541 txopLimit = edca->GetTxopLimit(linkId);
542 edcaParameters.SetViAci(2);
543 edcaParameters.SetViCWmin(edca->GetMinCw(linkId));
544 edcaParameters.SetViCWmax(edca->GetMaxCw(linkId));
545 edcaParameters.SetViAifsn(edca->GetAifsn(linkId));
546 edcaParameters.SetViTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
547
548 edca = GetQosTxop(AC_VO);
549 txopLimit = edca->GetTxopLimit(linkId);
550 edcaParameters.SetVoAci(3);
551 edcaParameters.SetVoCWmin(edca->GetMinCw(linkId));
552 edcaParameters.SetVoCWmax(edca->GetMaxCw(linkId));
553 edcaParameters.SetVoAifsn(edca->GetAifsn(linkId));
554 edcaParameters.SetVoTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
555
556 edcaParameters.SetQosInfo(0);
557
558 return edcaParameters;
559}
560
561std::optional<MuEdcaParameterSet>
563{
564 NS_LOG_FUNCTION(this);
566
567 Ptr<HeConfiguration> heConfiguration = GetHeConfiguration();
568 NS_ASSERT(heConfiguration);
569
570 MuEdcaParameterSet muEdcaParameters;
571 muEdcaParameters.SetQosInfo(0);
572
573 UintegerValue uintegerValue;
574 TimeValue timeValue;
575
576 heConfiguration->GetAttribute("MuBeAifsn", uintegerValue);
577 muEdcaParameters.SetMuAifsn(AC_BE, uintegerValue.Get());
578 heConfiguration->GetAttribute("MuBeCwMin", uintegerValue);
579 muEdcaParameters.SetMuCwMin(AC_BE, uintegerValue.Get());
580 heConfiguration->GetAttribute("MuBeCwMax", uintegerValue);
581 muEdcaParameters.SetMuCwMax(AC_BE, uintegerValue.Get());
582 heConfiguration->GetAttribute("BeMuEdcaTimer", timeValue);
583 muEdcaParameters.SetMuEdcaTimer(AC_BE, timeValue.Get());
584
585 heConfiguration->GetAttribute("MuBkAifsn", uintegerValue);
586 muEdcaParameters.SetMuAifsn(AC_BK, uintegerValue.Get());
587 heConfiguration->GetAttribute("MuBkCwMin", uintegerValue);
588 muEdcaParameters.SetMuCwMin(AC_BK, uintegerValue.Get());
589 heConfiguration->GetAttribute("MuBkCwMax", uintegerValue);
590 muEdcaParameters.SetMuCwMax(AC_BK, uintegerValue.Get());
591 heConfiguration->GetAttribute("BkMuEdcaTimer", timeValue);
592 muEdcaParameters.SetMuEdcaTimer(AC_BK, timeValue.Get());
593
594 heConfiguration->GetAttribute("MuViAifsn", uintegerValue);
595 muEdcaParameters.SetMuAifsn(AC_VI, uintegerValue.Get());
596 heConfiguration->GetAttribute("MuViCwMin", uintegerValue);
597 muEdcaParameters.SetMuCwMin(AC_VI, uintegerValue.Get());
598 heConfiguration->GetAttribute("MuViCwMax", uintegerValue);
599 muEdcaParameters.SetMuCwMax(AC_VI, uintegerValue.Get());
600 heConfiguration->GetAttribute("ViMuEdcaTimer", timeValue);
601 muEdcaParameters.SetMuEdcaTimer(AC_VI, timeValue.Get());
602
603 heConfiguration->GetAttribute("MuVoAifsn", uintegerValue);
604 muEdcaParameters.SetMuAifsn(AC_VO, uintegerValue.Get());
605 heConfiguration->GetAttribute("MuVoCwMin", uintegerValue);
606 muEdcaParameters.SetMuCwMin(AC_VO, uintegerValue.Get());
607 heConfiguration->GetAttribute("MuVoCwMax", uintegerValue);
608 muEdcaParameters.SetMuCwMax(AC_VO, uintegerValue.Get());
609 heConfiguration->GetAttribute("VoMuEdcaTimer", timeValue);
610 muEdcaParameters.SetMuEdcaTimer(AC_VO, timeValue.Get());
611
612 // The timers of the MU EDCA Parameter Set must be either all zero or all
613 // non-zero. The information element is advertised if all timers are non-zero
614 auto timerNotNull = [&muEdcaParameters](uint8_t aci) {
615 return !muEdcaParameters.GetMuEdcaTimer(aci).IsZero();
616 };
617 auto aci = {0, 1, 2, 3};
618 if (std::all_of(aci.begin(), aci.end(), timerNotNull))
619 {
620 return muEdcaParameters;
621 }
622
623 NS_ABORT_MSG_UNLESS(std::none_of(aci.begin(), aci.end(), timerNotNull),
624 "MU EDCA Timers must be all zero if the IE is not advertised.");
625
626 return std::nullopt;
627}
628
629std::optional<ReducedNeighborReport>
631{
632 NS_LOG_FUNCTION(this << +linkId);
633
634 if (GetNLinks() <= 1)
635 {
636 return std::nullopt;
637 }
638
641
642 for (uint8_t index = 0; index < GetNLinks(); ++index)
643 {
644 if (index != linkId) // all links but the one used to send this Beacon frame
645 {
646 rnr.AddNbrApInfoField();
647 std::size_t nbrId = rnr.GetNNbrApInfoFields() - 1;
649 rnr.AddTbttInformationField(nbrId);
650 rnr.SetBssid(nbrId, 0, GetLink(index).feManager->GetAddress());
651 rnr.SetShortSsid(nbrId, 0, 0);
652 rnr.SetBssParameters(nbrId, 0, 0);
653 rnr.SetPsd20MHz(nbrId, 0, 0);
654 rnr.SetMldParameters(nbrId, 0, 0, index, 0);
655 }
656 }
657 return rnr;
658}
659
661ApWifiMac::GetMultiLinkElement(uint8_t linkId, WifiMacType frameType, const Mac48Address& to)
662{
663 NS_LOG_FUNCTION(this << +linkId << frameType << to);
664 NS_ABORT_IF(GetNLinks() == 1);
665
668 mle.SetLinkIdInfo(linkId);
670
671 auto ehtConfiguration = GetEhtConfiguration();
672 NS_ASSERT(ehtConfiguration);
673
674 if (BooleanValue emlsrActivated;
675 ehtConfiguration->GetAttributeFailSafe("EmlsrActivated", emlsrActivated) &&
676 emlsrActivated.Get())
677 {
678 mle.SetEmlsrSupported(true);
679 // When the EMLSR Padding Delay subfield is included in a frame sent by an AP affiliated
680 // with an AP MLD, the EMLSR Padding Delay subfield is reserved.
681 // When the EMLSR Transition Delay subfield is included in a frame sent by an AP affiliated
682 // with an AP MLD, the EMLSR Transition Delay subfield is reserved. (Sec. 9.4.2.312.2.3
683 // of 802.11be D2.3)
684 TimeValue time;
685 ehtConfiguration->GetAttribute("TransitionTimeout", time);
686 mle.SetTransitionTimeout(time.Get());
687 }
688
689 // if the Multi-Link Element is being inserted in a (Re)Association Response frame
690 // and the remote station is affiliated with an MLD, try multi-link setup
691 if (auto staMldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(to);
692 (frameType == WIFI_MAC_MGT_ASSOCIATION_RESPONSE ||
694 staMldAddress.has_value())
695 {
696 for (uint8_t i = 0; i < GetNLinks(); i++)
697 {
698 auto remoteStationManager = GetWifiRemoteStationManager(i);
699 if (auto staAddress = remoteStationManager->GetAffiliatedStaAddress(*staMldAddress);
700 i != linkId && staAddress.has_value() &&
701 (remoteStationManager->IsWaitAssocTxOk(*staAddress) ||
702 remoteStationManager->IsAssocRefused(*staAddress)))
703 {
704 // For each requested link in addition to the link on which the
705 // (Re)Association Response frame is transmitted, the Link Info field
706 // of the Basic Multi-Link element carried in the (Re)Association
707 // Response frame shall contain the corresponding Per-STA Profile
708 // subelement(s) (Sec. 35.3.5.4 of 802.11be D2.0)
710 auto& perStaProfile = mle.GetPerStaProfile(mle.GetNPerStaProfileSubelements() - 1);
711 // The Link ID subfield of the STA Control field of the Per-STA Profile
712 // subelement for the AP corresponding to a link is set to the link ID
713 // of the AP affiliated with the AP MLD that is operating on that link.
714 perStaProfile.SetLinkId(i);
715 perStaProfile.SetCompleteProfile();
716 // For each Per-STA Profile subelement included in the Link Info field,
717 // the Complete Profile subfield of the STA Control field shall be set to 1
718 perStaProfile.SetStaMacAddress(GetFrameExchangeManager(i)->GetAddress());
719 perStaProfile.SetAssocResponse(GetAssocResp(*staAddress, i));
720 }
721 }
722 }
723
724 return mle;
725}
726
728ApWifiMac::GetHtOperation(uint8_t linkId) const
729{
730 NS_LOG_FUNCTION(this << +linkId);
732 HtOperation operation;
733 auto phy = GetWifiPhy(linkId);
734 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
735
736 operation.SetPrimaryChannel(phy->GetPrimaryChannelNumber(20));
737 operation.SetRifsMode(false);
738 operation.SetNonGfHtStasPresent(true);
739 if (phy->GetChannelWidth() > 20)
740 {
741 operation.SetSecondaryChannelOffset(1);
742 operation.SetStaChannelWidth(1);
743 }
744 if (GetLink(linkId).numNonHtStations == 0)
745 {
747 }
748 else
749 {
751 }
752 uint64_t maxSupportedRate = 0; // in bit/s
753 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HT))
754 {
755 uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
756 NS_ASSERT(nss > 0 && nss < 5);
757 uint64_t dataRate =
758 mcs.GetDataRate(phy->GetChannelWidth(),
759 GetHtConfiguration()->GetShortGuardIntervalSupported() ? 400 : 800,
760 nss);
761 if (dataRate > maxSupportedRate)
762 {
763 maxSupportedRate = dataRate;
764 NS_LOG_DEBUG("Updating maxSupportedRate to " << maxSupportedRate);
765 }
766 }
767 uint8_t maxSpatialStream = phy->GetMaxSupportedTxSpatialStreams();
768 auto mcsList = phy->GetMcsList(WIFI_MOD_CLASS_HT);
769 uint8_t nMcs = mcsList.size();
770 for (const auto& sta : GetLink(linkId).staList)
771 {
772 if (remoteStationManager->GetHtSupported(sta.second))
773 {
774 uint64_t maxSupportedRateByHtSta = 0; // in bit/s
775 auto itMcs = mcsList.begin();
776 for (uint8_t j = 0;
777 j < (std::min(nMcs, remoteStationManager->GetNMcsSupported(sta.second)));
778 j++)
779 {
780 WifiMode mcs = *itMcs++;
781 uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
782 NS_ASSERT(nss > 0 && nss < 5);
783 uint64_t dataRate = mcs.GetDataRate(
784 remoteStationManager->GetChannelWidthSupported(sta.second),
785 remoteStationManager->GetShortGuardIntervalSupported(sta.second) ? 400 : 800,
786 nss);
787 if (dataRate > maxSupportedRateByHtSta)
788 {
789 maxSupportedRateByHtSta = dataRate;
790 }
791 }
792 if (maxSupportedRateByHtSta < maxSupportedRate)
793 {
794 maxSupportedRate = maxSupportedRateByHtSta;
795 }
796 if (remoteStationManager->GetNMcsSupported(sta.second) < nMcs)
797 {
798 nMcs = remoteStationManager->GetNMcsSupported(sta.second);
799 }
800 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
801 {
802 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
803 }
804 }
805 }
807 static_cast<uint16_t>(maxSupportedRate / 1e6)); // in Mbit/s
808 operation.SetTxMcsSetDefined(nMcs > 0);
809 operation.SetTxMaxNSpatialStreams(maxSpatialStream);
810 // To be filled in once supported
811 operation.SetObssNonHtStasPresent(0);
812 operation.SetDualBeacon(0);
813 operation.SetDualCtsProtection(0);
814 operation.SetStbcBeacon(0);
816 operation.SetPcoActive(0);
817 operation.SetPhase(0);
818 operation.SetRxMcsBitmask(0);
819 operation.SetTxRxMcsSetUnequal(0);
820 operation.SetTxUnequalModulation(0);
821
822 return operation;
823}
824
826ApWifiMac::GetVhtOperation(uint8_t linkId) const
827{
828 NS_LOG_FUNCTION(this << +linkId);
829 NS_ASSERT(GetVhtSupported(linkId));
830 VhtOperation operation;
831 auto phy = GetWifiPhy(linkId);
832 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
833
834 const uint16_t bssBandwidth = phy->GetChannelWidth();
835 // Set to 0 for 20 MHz or 40 MHz BSS bandwidth.
836 // Set to 1 for 80 MHz, 160 MHz or 80+80 MHz BSS bandwidth.
837 operation.SetChannelWidth((bssBandwidth > 40) ? 1 : 0);
838 // For 20, 40, or 80 MHz BSS bandwidth, indicates the channel center frequency
839 // index for the 20, 40, or 80 MHz channel on which the VHT BSS operates.
840 // For 160 MHz BSS bandwidth and the Channel Width subfield equal to 1,
841 // indicates the channel center frequency index of the 80 MHz channel
842 // segment that contains the primary channel.
844 (bssBandwidth == 160)
845 ? phy->GetOperatingChannel().GetPrimaryChannelNumber(80, phy->GetStandard())
846 : phy->GetChannelNumber());
847 // For a 20, 40, or 80 MHz BSS bandwidth, this subfield is set to 0.
848 // For a 160 MHz BSS bandwidth and the Channel Width subfield equal to 1,
849 // indicates the channel center frequency index of the 160 MHz channel on
850 // which the VHT BSS operates.
851 operation.SetChannelCenterFrequencySegment1((bssBandwidth == 160) ? phy->GetChannelNumber()
852 : 0);
853 uint8_t maxSpatialStream = phy->GetMaxSupportedRxSpatialStreams();
854 for (const auto& sta : GetLink(linkId).staList)
855 {
856 if (remoteStationManager->GetVhtSupported(sta.second))
857 {
858 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
859 {
860 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
861 }
862 }
863 }
864 for (uint8_t nss = 1; nss <= maxSpatialStream; nss++)
865 {
866 uint8_t maxMcs =
867 9; // TBD: hardcode to 9 for now since we assume all MCS values are supported
868 operation.SetMaxVhtMcsPerNss(nss, maxMcs);
869 }
870
871 return operation;
872}
873
875ApWifiMac::GetHeOperation(uint8_t linkId) const
876{
877 NS_LOG_FUNCTION(this << +linkId);
879 HeOperation operation;
880 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
881
882 uint8_t maxSpatialStream = GetWifiPhy(linkId)->GetMaxSupportedRxSpatialStreams();
883 for (const auto& sta : GetLink(linkId).staList)
884 {
885 if (remoteStationManager->GetHeSupported(sta.second))
886 {
887 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
888 {
889 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
890 }
891 }
892 }
893 for (uint8_t nss = 1; nss <= maxSpatialStream; nss++)
894 {
895 operation.SetMaxHeMcsPerNss(
896 nss,
897 11); // TBD: hardcode to 11 for now since we assume all MCS values are supported
898 }
899 operation.SetBssColor(GetHeConfiguration()->GetBssColor());
900
901 return operation;
902}
903
905ApWifiMac::GetEhtOperation(uint8_t linkId) const
906{
907 NS_LOG_FUNCTION(this << +linkId);
909 EhtOperation operation;
910 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
911
912 auto maxSpatialStream = GetWifiPhy(linkId)->GetMaxSupportedRxSpatialStreams();
913 for (const auto& sta : GetLink(linkId).staList)
914 {
915 if (remoteStationManager->GetEhtSupported(sta.second))
916 {
917 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
918 {
919 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
920 }
921 }
922 }
923 operation.SetMaxRxNss(maxSpatialStream, 0, WIFI_EHT_MAX_MCS_INDEX);
924 operation.SetMaxTxNss(maxSpatialStream, 0, WIFI_EHT_MAX_MCS_INDEX);
925 return operation;
926}
927
928void
930{
931 NS_LOG_FUNCTION(this << to << +linkId);
932 WifiMacHeader hdr;
934 hdr.SetAddr1(to);
935 hdr.SetAddr2(GetLink(linkId).feManager->GetAddress());
936 hdr.SetAddr3(GetLink(linkId).feManager->GetAddress());
937 hdr.SetDsNotFrom();
938 hdr.SetDsNotTo();
939 Ptr<Packet> packet = Create<Packet>();
941 probe.Get<Ssid>() = GetSsid();
942 auto supportedRates = GetSupportedRates(linkId);
943 probe.Get<SupportedRates>() = supportedRates.rates;
944 probe.Get<ExtendedSupportedRatesIE>() = supportedRates.extendedRates;
946 probe.Capabilities() = GetCapabilities(linkId);
948 GetLink(linkId).shortPreambleEnabled);
950 GetLink(linkId).shortSlotTimeEnabled);
951 if (GetDsssSupported(linkId))
952 {
953 probe.Get<DsssParameterSet>() = GetDsssParameterSet(linkId);
954 }
955 if (GetErpSupported(linkId))
956 {
957 probe.Get<ErpInformation>() = GetErpInformation(linkId);
958 }
959 if (GetQosSupported())
960 {
961 probe.Get<EdcaParameterSet>() = GetEdcaParameterSet(linkId);
962 }
963 if (GetHtSupported())
964 {
966 probe.Get<HtCapabilities>() = GetHtCapabilities(linkId);
967 probe.Get<HtOperation>() = GetHtOperation(linkId);
968 }
969 if (GetVhtSupported(linkId))
970 {
971 probe.Get<VhtCapabilities>() = GetVhtCapabilities(linkId);
972 probe.Get<VhtOperation>() = GetVhtOperation(linkId);
973 }
974 if (GetHeSupported())
975 {
976 probe.Get<HeCapabilities>() = GetHeCapabilities(linkId);
977 probe.Get<HeOperation>() = GetHeOperation(linkId);
978 if (auto muEdcaParameterSet = GetMuEdcaParameterSet(); muEdcaParameterSet.has_value())
979 {
980 probe.Get<MuEdcaParameterSet>() = std::move(*muEdcaParameterSet);
981 }
982 }
983 if (GetEhtSupported())
984 {
985 probe.Get<EhtCapabilities>() = GetEhtCapabilities(linkId);
986 probe.Get<EhtOperation>() = GetEhtOperation(linkId);
987
988 if (GetNLinks() > 1)
989 {
990 /*
991 * If an AP is affiliated with an AP MLD and does not correspond to a nontransmitted
992 * BSSID, then the Beacon and Probe Response frames transmitted by the AP shall
993 * include a TBTT Information field in a Reduced Neighbor Report element with the
994 * TBTT Information Length field set to 16 or higher, for each of the other APs
995 * (if any) affiliated with the same AP MLD. (Sec. 35.3.4.1 of 802.11be D2.1.1)
996 */
997 if (auto rnr = GetReducedNeighborReport(linkId); rnr.has_value())
998 {
999 probe.Get<ReducedNeighborReport>() = std::move(*rnr);
1000 }
1001 /*
1002 * If an AP affiliated with an AP MLD is not in a multiple BSSID set [..], the AP
1003 * shall include, in a Beacon frame or a Probe Response frame, which is not a
1004 * Multi-Link probe response, only the Common Info field of the Basic Multi-Link
1005 * element for the AP MLD unless conditions in 35.3.11 (Multi-link procedures for
1006 * channel switching, extended channel switching, and channel quieting) are
1007 * satisfied. (Sec. 35.3.4.4 of 802.11be D2.1.1)
1008 */
1009 probe.Get<MultiLinkElement>() =
1011 }
1012 }
1013 packet->AddHeader(probe);
1014
1015 if (!GetQosSupported())
1016 {
1017 GetTxop()->Queue(packet, hdr);
1018 }
1019 // "A QoS STA that transmits a Management frame determines access category used
1020 // for medium access in transmission of the Management frame as follows
1021 // (If dot11QMFActivated is false or not present)
1022 // — If the Management frame is individually addressed to a non-QoS STA, category
1023 // AC_BE should be selected.
1024 // — If category AC_BE was not selected by the previous step, category AC_VO
1025 // shall be selected." (Sec. 10.2.3.2 of 802.11-2020)
1026 else if (!GetWifiRemoteStationManager(linkId)->GetQosSupported(to))
1027 {
1028 GetBEQueue()->Queue(packet, hdr);
1029 }
1030 else
1031 {
1032 GetVOQueue()->Queue(packet, hdr);
1033 }
1034}
1035
1038{
1040 StatusCode code;
1041 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
1042 if (remoteStationManager->IsWaitAssocTxOk(to))
1043 {
1044 code.SetSuccess();
1045 }
1046 else
1047 {
1048 NS_ABORT_IF(!remoteStationManager->IsAssocRefused(to));
1049 // reset state
1050 remoteStationManager->RecordDisassociated(to);
1051 code.SetFailure();
1052 }
1053 auto supportedRates = GetSupportedRates(linkId);
1054 assoc.Get<SupportedRates>() = supportedRates.rates;
1055 assoc.Get<ExtendedSupportedRatesIE>() = supportedRates.extendedRates;
1056 assoc.SetStatusCode(code);
1057 assoc.Capabilities() = GetCapabilities(linkId);
1058 if (GetQosSupported())
1059 {
1060 assoc.Get<EdcaParameterSet>() = GetEdcaParameterSet(linkId);
1061 }
1062 if (GetHtSupported())
1063 {
1065 assoc.Get<HtCapabilities>() = GetHtCapabilities(linkId);
1066 assoc.Get<HtOperation>() = GetHtOperation(linkId);
1067 }
1068 if (GetVhtSupported(linkId))
1069 {
1070 assoc.Get<VhtCapabilities>() = GetVhtCapabilities(linkId);
1071 assoc.Get<VhtOperation>() = GetVhtOperation(linkId);
1072 }
1073 if (GetHeSupported())
1074 {
1075 assoc.Get<HeCapabilities>() = GetHeCapabilities(linkId);
1076 assoc.Get<HeOperation>() = GetHeOperation(linkId);
1077 if (auto muEdcaParameterSet = GetMuEdcaParameterSet(); muEdcaParameterSet.has_value())
1078 {
1079 assoc.Get<MuEdcaParameterSet>() = std::move(*muEdcaParameterSet);
1080 }
1081 }
1082 if (GetEhtSupported())
1083 {
1084 assoc.Get<EhtCapabilities>() = GetEhtCapabilities(linkId);
1085 assoc.Get<EhtOperation>() = GetEhtOperation(linkId);
1086 }
1087 return assoc;
1088}
1089
1092 const Mac48Address& to,
1093 uint8_t linkId)
1094{
1095 // find all the links to setup (i.e., those for which status code is success)
1096 std::map<uint8_t /* link ID */, Mac48Address> linkIdStaAddrMap;
1097
1098 if (assoc.GetStatusCode().IsSuccess())
1099 {
1100 linkIdStaAddrMap[linkId] = to;
1101 }
1102
1103 if (const auto& mle = assoc.Get<MultiLinkElement>())
1104 {
1105 const auto staMldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(to);
1106 NS_ABORT_MSG_IF(!staMldAddress.has_value(),
1107 "Sending a Multi-Link Element to a single link device");
1108 for (std::size_t idx = 0; idx < mle->GetNPerStaProfileSubelements(); idx++)
1109 {
1110 auto& perStaProfile = mle->GetPerStaProfile(idx);
1111 if (perStaProfile.HasAssocResponse() &&
1112 perStaProfile.GetAssocResponse().GetStatusCode().IsSuccess())
1113 {
1114 uint8_t otherLinkId = perStaProfile.GetLinkId();
1115 auto staAddress = GetWifiRemoteStationManager(otherLinkId)
1116 ->GetAffiliatedStaAddress(*staMldAddress);
1117 NS_ABORT_MSG_IF(!staAddress.has_value(),
1118 "No STA to associate with on link " << +otherLinkId);
1119 const auto [it, inserted] = linkIdStaAddrMap.insert({otherLinkId, *staAddress});
1120 NS_ABORT_MSG_IF(!inserted,
1121 "More than one Association Response to MLD "
1122 << *staMldAddress << " on link ID " << +otherLinkId);
1123 }
1124 }
1125 }
1126
1127 return linkIdStaAddrMap;
1128}
1129
1130void
1132{
1133 if (linkIdStaAddrMap.empty())
1134 {
1135 // no link to setup, nothing to do
1136 return;
1137 }
1138
1139 // check if AIDs are already allocated to the STAs that are associating
1140 std::set<uint16_t> aids;
1141 std::map<uint8_t /* link ID */, uint16_t /* AID */> linkIdAidMap;
1142
1143 for (const auto& [id, staAddr] : linkIdStaAddrMap)
1144 {
1145 for (const auto& [aid, addr] : GetLink(id).staList)
1146 {
1147 if (addr == staAddr)
1148 {
1149 aids.insert(aid);
1150 linkIdAidMap[id] = aid;
1151 break;
1152 }
1153 }
1154 }
1155
1156 // check if an AID already assigned to an STA can be assigned to all other STAs
1157 // affiliated with the non-AP MLD we are associating with
1158 while (!aids.empty())
1159 {
1160 const uint16_t aid = *aids.begin();
1161 bool good = true;
1162
1163 for (const auto& [id, staAddr] : linkIdStaAddrMap)
1164 {
1165 if (auto it = GetLink(id).staList.find(aid);
1166 it != GetLink(id).staList.end() && it->second != staAddr)
1167 {
1168 // the AID is already assigned to an STA other than the one affiliated
1169 // with the non-AP MLD we are associating with
1170 aids.erase(aids.begin());
1171 good = false;
1172 break;
1173 }
1174 }
1175
1176 if (good)
1177 {
1178 break;
1179 }
1180 }
1181
1182 uint16_t aid = 0;
1183
1184 if (!aids.empty())
1185 {
1186 // one of the AIDs already assigned to an STA can be assigned to all the other
1187 // STAs affiliated with the non-AP MLD we are associating with
1188 aid = *aids.begin();
1189 }
1190 else
1191 {
1192 std::list<uint8_t> linkIds;
1193 std::transform(linkIdStaAddrMap.cbegin(),
1194 linkIdStaAddrMap.cend(),
1195 std::back_inserter(linkIds),
1196 [](auto&& linkIdStaAddrPair) { return linkIdStaAddrPair.first; });
1197 aid = GetNextAssociationId(linkIds);
1198 }
1199
1200 // store the MLD or link address in the AID-to-address map
1201 const auto& [linkId, staAddr] = *linkIdStaAddrMap.cbegin();
1203 GetWifiRemoteStationManager(linkId)->GetMldAddress(staAddr).value_or(staAddr);
1204
1205 for (const auto& [id, staAddr] : linkIdStaAddrMap)
1206 {
1207 auto remoteStationManager = GetWifiRemoteStationManager(id);
1208 auto& link = GetLink(id);
1209
1210 if (auto it = linkIdAidMap.find(id); it == linkIdAidMap.end() || it->second != aid)
1211 {
1212 // the STA on this link has no AID assigned or has a different AID assigned
1213 link.staList.insert(std::make_pair(aid, staAddr));
1214 m_assocLogger(aid, staAddr);
1215 remoteStationManager->SetAssociationId(staAddr, aid);
1216
1217 if (it == linkIdAidMap.end())
1218 {
1219 // the STA on this link had no AID assigned
1220 if (remoteStationManager->GetDsssSupported(staAddr) &&
1221 !remoteStationManager->GetErpOfdmSupported(staAddr))
1222 {
1223 link.numNonErpStations++;
1224 }
1225 if (!remoteStationManager->GetHtSupported(staAddr))
1226 {
1227 link.numNonHtStations++;
1228 }
1231 }
1232 else
1233 {
1234 // the STA on this link had a different AID assigned
1235 link.staList.erase(it->second); // free the previous AID
1236 }
1237 }
1238 }
1239
1240 // set the AID in all the Association Responses. NOTE that the Association
1241 // Responses included in the Per-STA Profile Subelements of the Multi-Link
1242 // Element must not contain the AID field. We set the AID field in such
1243 // Association Responses anyway, in order to ease future implementation of
1244 // the inheritance mechanism.
1245 if (assoc.GetStatusCode().IsSuccess())
1246 {
1247 assoc.SetAssociationId(aid);
1248 }
1249 if (const auto& mle = assoc.Get<MultiLinkElement>())
1250 {
1251 for (std::size_t idx = 0; idx < mle->GetNPerStaProfileSubelements(); idx++)
1252 {
1253 if (const auto& perStaProfile = mle->GetPerStaProfile(idx);
1254 perStaProfile.HasAssocResponse() &&
1255 perStaProfile.GetAssocResponse().GetStatusCode().IsSuccess())
1256 {
1257 perStaProfile.GetAssocResponse().SetAssociationId(aid);
1258 }
1259 }
1260 }
1261}
1262
1263void
1264ApWifiMac::SendAssocResp(Mac48Address to, bool isReassoc, uint8_t linkId)
1265{
1266 NS_LOG_FUNCTION(this << to << isReassoc << +linkId);
1267 WifiMacHeader hdr;
1270 hdr.SetAddr1(to);
1273 hdr.SetDsNotFrom();
1274 hdr.SetDsNotTo();
1275
1276 MgtAssocResponseHeader assoc = GetAssocResp(to, linkId);
1277
1278 // The AP that is affiliated with the AP MLD and that responds to an (Re)Association
1279 // Request frame that carries a Basic Multi-Link element shall include a Basic
1280 // Multi-Link element in the (Re)Association Response frame that it transmits
1281 // (Sec. 35.3.5.4 of 802.11be D2.0)
1282 // If the STA included a Multi-Link Element in the (Re)Association Request, we
1283 // stored its MLD address in the remote station manager
1284 if (GetNLinks() > 1 && GetWifiRemoteStationManager(linkId)->GetMldAddress(to).has_value())
1285 {
1286 assoc.Get<MultiLinkElement>() = GetMultiLinkElement(linkId, hdr.GetType(), to);
1287 }
1288
1289 auto linkIdStaAddrMap = GetLinkIdStaAddrMap(assoc, to, linkId);
1290 SetAid(assoc, linkIdStaAddrMap);
1291
1292 Ptr<Packet> packet = Create<Packet>();
1293 packet->AddHeader(assoc);
1294
1295 if (!GetQosSupported())
1296 {
1297 GetTxop()->Queue(packet, hdr);
1298 }
1299 // "A QoS STA that transmits a Management frame determines access category used
1300 // for medium access in transmission of the Management frame as follows
1301 // (If dot11QMFActivated is false or not present)
1302 // — If the Management frame is individually addressed to a non-QoS STA, category
1303 // AC_BE should be selected.
1304 // — If category AC_BE was not selected by the previous step, category AC_VO
1305 // shall be selected." (Sec. 10.2.3.2 of 802.11-2020)
1306 else if (!GetWifiRemoteStationManager(linkId)->GetQosSupported(to))
1307 {
1308 GetBEQueue()->Queue(packet, hdr);
1309 }
1310 else
1311 {
1312 GetVOQueue()->Queue(packet, hdr);
1313 }
1314}
1315
1316void
1318{
1319 NS_LOG_FUNCTION(this << +linkId);
1320 auto& link = GetLink(linkId);
1321 WifiMacHeader hdr;
1324 hdr.SetAddr2(link.feManager->GetAddress());
1325 hdr.SetAddr3(link.feManager->GetAddress());
1326 hdr.SetDsNotFrom();
1327 hdr.SetDsNotTo();
1328 Ptr<Packet> packet = Create<Packet>();
1329 MgtBeaconHeader beacon;
1330 beacon.Get<Ssid>() = GetSsid();
1331 auto supportedRates = GetSupportedRates(linkId);
1332 beacon.Get<SupportedRates>() = supportedRates.rates;
1333 beacon.Get<ExtendedSupportedRatesIE>() = supportedRates.extendedRates;
1335 beacon.Capabilities() = GetCapabilities(linkId);
1336 GetWifiRemoteStationManager(linkId)->SetShortPreambleEnabled(link.shortPreambleEnabled);
1337 GetWifiRemoteStationManager(linkId)->SetShortSlotTimeEnabled(link.shortSlotTimeEnabled);
1338 if (GetDsssSupported(linkId))
1339 {
1340 beacon.Get<DsssParameterSet>() = GetDsssParameterSet(linkId);
1341 }
1342 if (GetErpSupported(linkId))
1343 {
1344 beacon.Get<ErpInformation>() = GetErpInformation(linkId);
1345 }
1346 if (GetQosSupported())
1347 {
1348 beacon.Get<EdcaParameterSet>() = GetEdcaParameterSet(linkId);
1349 }
1350 if (GetHtSupported())
1351 {
1353 beacon.Get<HtCapabilities>() = GetHtCapabilities(linkId);
1354 beacon.Get<HtOperation>() = GetHtOperation(linkId);
1355 }
1356 if (GetVhtSupported(linkId))
1357 {
1358 beacon.Get<VhtCapabilities>() = GetVhtCapabilities(linkId);
1359 beacon.Get<VhtOperation>() = GetVhtOperation(linkId);
1360 }
1361 if (GetHeSupported())
1362 {
1363 beacon.Get<HeCapabilities>() = GetHeCapabilities(linkId);
1364 beacon.Get<HeOperation>() = GetHeOperation(linkId);
1365 if (auto muEdcaParameterSet = GetMuEdcaParameterSet(); muEdcaParameterSet.has_value())
1366 {
1367 beacon.Get<MuEdcaParameterSet>() = std::move(*muEdcaParameterSet);
1368 }
1369 }
1370 if (GetEhtSupported())
1371 {
1372 beacon.Get<EhtCapabilities>() = GetEhtCapabilities(linkId);
1373 beacon.Get<EhtOperation>() = GetEhtOperation(linkId);
1374
1375 if (GetNLinks() > 1)
1376 {
1377 /*
1378 * If an AP is affiliated with an AP MLD and does not correspond to a nontransmitted
1379 * BSSID, then the Beacon and Probe Response frames transmitted by the AP shall
1380 * include a TBTT Information field in a Reduced Neighbor Report element with the
1381 * TBTT Information Length field set to 16 or higher, for each of the other APs
1382 * (if any) affiliated with the same AP MLD. (Sec. 35.3.4.1 of 802.11be D2.1.1)
1383 */
1384 if (auto rnr = GetReducedNeighborReport(linkId); rnr.has_value())
1385 {
1386 beacon.Get<ReducedNeighborReport>() = std::move(*rnr);
1387 }
1388 /*
1389 * If an AP affiliated with an AP MLD is not in a multiple BSSID set [..], the AP
1390 * shall include, in a Beacon frame or a Probe Response frame, which is not a
1391 * Multi-Link probe response, only the Common Info field of the Basic Multi-Link
1392 * element for the AP MLD unless conditions in 35.3.11 (Multi-link procedures for
1393 * channel switching, extended channel switching, and channel quieting) are
1394 * satisfied. (Sec. 35.3.4.4 of 802.11be D2.1.1)
1395 */
1397 }
1398 }
1399 packet->AddHeader(beacon);
1400
1401 // The beacon has it's own special queue, so we load it in there
1402 m_beaconTxop->Queue(packet, hdr);
1403 link.beaconEvent =
1405
1406 // If a STA that does not support Short Slot Time associates,
1407 // the AP shall use long slot time beginning at the first Beacon
1408 // subsequent to the association of the long slot time STA.
1409 if (GetErpSupported(linkId))
1410 {
1411 if (link.shortSlotTimeEnabled)
1412 {
1413 // Enable short slot time
1414 GetWifiPhy(linkId)->SetSlot(MicroSeconds(9));
1415 }
1416 else
1417 {
1418 // Disable short slot time
1419 GetWifiPhy(linkId)->SetSlot(MicroSeconds(20));
1420 }
1421 }
1422}
1423
1424void
1426{
1427 NS_LOG_FUNCTION(this << *mpdu);
1428 const WifiMacHeader& hdr = mpdu->GetHeader();
1429
1430 if (hdr.IsAssocResp() || hdr.IsReassocResp())
1431 {
1432 auto linkId = GetLinkIdByAddress(hdr.GetAddr2());
1433 NS_ABORT_MSG_IF(!linkId.has_value(), "No link ID matching the TA");
1434
1436 {
1437 NS_LOG_DEBUG("AP=" << hdr.GetAddr2() << " associated with STA=" << hdr.GetAddr1());
1439 }
1440
1441 if (auto staMldAddress =
1443 staMldAddress.has_value())
1444 {
1456 for (uint8_t i = 0; i < GetNLinks(); i++)
1457 {
1458 auto stationManager = GetWifiRemoteStationManager(i);
1459 if (auto staAddress = stationManager->GetAffiliatedStaAddress(*staMldAddress);
1460 staAddress.has_value() && i != *linkId &&
1461 stationManager->IsWaitAssocTxOk(*staAddress))
1462 {
1464 << " associated with STA=" << *staAddress);
1465 stationManager->RecordGotAssocTxOk(*staAddress);
1466 StaSwitchingToPsMode(*staAddress, i);
1467 }
1468 }
1469 }
1470 }
1471 else if (hdr.IsAction())
1472 {
1473 if (auto [category, action] = WifiActionHeader::Peek(mpdu->GetPacket());
1474 category == WifiActionHeader::PROTECTED_EHT &&
1475 action.protectedEhtAction ==
1477 {
1478 // the EMLSR client acknowledged the EML Operating Mode Notification frame;
1479 // we can stop the timer and enforce the configuration deriving from the
1480 // EML Notification frame sent by the EMLSR client
1481 if (auto eventIt = m_transitionTimeoutEvents.find(hdr.GetAddr1());
1482 eventIt != m_transitionTimeoutEvents.cend() && eventIt->second.IsRunning())
1483 {
1484 // no need to wait until the expiration of the transition timeout
1485 eventIt->second.PeekEventImpl()->Invoke();
1486 eventIt->second.Cancel();
1487 }
1488 }
1489 }
1490}
1491
1492void
1494{
1495 NS_LOG_FUNCTION(this << +timeoutReason << *mpdu);
1496 const WifiMacHeader& hdr = mpdu->GetHeader();
1497
1498 if (hdr.IsAssocResp() || hdr.IsReassocResp())
1499 {
1500 auto linkId = GetLinkIdByAddress(hdr.GetAddr2());
1501 NS_ABORT_MSG_IF(!linkId.has_value(), "No link ID matching the TA");
1502
1504 {
1505 NS_LOG_DEBUG("AP=" << hdr.GetAddr2()
1506 << " association failed with STA=" << hdr.GetAddr1());
1508 }
1509
1510 if (auto staMldAddress =
1512 staMldAddress.has_value())
1513 {
1514 // the STA is affiliated with an MLD
1515 for (uint8_t i = 0; i < GetNLinks(); i++)
1516 {
1517 auto stationManager = GetWifiRemoteStationManager(i);
1518 if (auto staAddress = stationManager->GetAffiliatedStaAddress(*staMldAddress);
1519 staAddress.has_value() && i != *linkId &&
1520 stationManager->IsWaitAssocTxOk(*staAddress))
1521 {
1523 << " association failed with STA=" << *staAddress);
1524 stationManager->RecordGotAssocTxFailed(*staAddress);
1525 }
1526 }
1527 }
1528 }
1529}
1530
1531void
1533{
1534 NS_LOG_FUNCTION(this << *mpdu << linkId);
1535
1536 Mac48Address staAddr = mpdu->GetHeader().GetAddr2();
1537 bool staInPsMode = GetWifiRemoteStationManager(linkId)->IsInPsMode(staAddr);
1538
1539 if (!staInPsMode && mpdu->GetHeader().IsPowerManagement())
1540 {
1541 // the sending STA is switching to Power Save mode
1542 StaSwitchingToPsMode(staAddr, linkId);
1543 }
1544 else if (staInPsMode && !mpdu->GetHeader().IsPowerManagement())
1545 {
1546 // the sending STA is switching back to Active mode
1548 }
1549}
1550
1551void
1552ApWifiMac::StaSwitchingToPsMode(const Mac48Address& staAddr, uint8_t linkId)
1553{
1554 NS_LOG_FUNCTION(this << staAddr << linkId);
1555
1556 GetWifiRemoteStationManager(linkId)->SetPsMode(staAddr, true);
1557
1558 // Block frames addressed to the STA in PS mode
1559 NS_LOG_DEBUG("Block destination " << staAddr << " on link " << +linkId);
1560 auto staMldAddr = GetWifiRemoteStationManager(linkId)->GetMldAddress(staAddr).value_or(staAddr);
1562}
1563
1564void
1566{
1567 NS_LOG_FUNCTION(this << staAddr << linkId);
1568
1569 GetWifiRemoteStationManager(linkId)->SetPsMode(staAddr, false);
1570
1571 if (GetWifiRemoteStationManager(linkId)->IsAssociated(staAddr))
1572 {
1573 // the station is still associated, unblock its frames
1574 NS_LOG_DEBUG("Unblock destination " << staAddr << " on link " << +linkId);
1575 auto staMldAddr =
1576 GetWifiRemoteStationManager(linkId)->GetMldAddress(staAddr).value_or(staAddr);
1578 }
1579}
1580
1581std::optional<uint8_t>
1583{
1584 for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
1585 {
1586 if (GetWifiRemoteStationManager(linkId)->IsAssociated(address))
1587 {
1588 return linkId;
1589 }
1590 }
1591 NS_LOG_DEBUG(address << " is not associated");
1592 return std::nullopt;
1593}
1594
1597{
1598 auto linkId = IsAssociated(remoteAddr);
1599 NS_ASSERT_MSG(linkId, remoteAddr << " is not associated");
1600 return GetFrameExchangeManager(*linkId)->GetAddress();
1601}
1602
1603std::optional<Mac48Address>
1605{
1606 if (const auto staIt = m_aidToMldOrLinkAddress.find(aid);
1607 staIt != m_aidToMldOrLinkAddress.cend())
1608 {
1609 return staIt->second;
1610 }
1611 return std::nullopt;
1612}
1613
1614void
1616{
1617 NS_LOG_FUNCTION(this << *mpdu << +linkId);
1618 // consider the MAC header of the original MPDU (makes a difference for data frames only)
1619 const WifiMacHeader* hdr = &mpdu->GetOriginal()->GetHeader();
1620 Ptr<const Packet> packet = mpdu->GetPacket();
1621 Mac48Address from = hdr->GetAddr2();
1622 if (hdr->IsData())
1623 {
1624 std::optional<uint8_t> apLinkId;
1625 if (!hdr->IsFromDs() && hdr->IsToDs() &&
1626 (apLinkId = IsAssociated(mpdu->GetHeader().GetAddr2())) &&
1627 mpdu->GetHeader().GetAddr1() == GetFrameExchangeManager(*apLinkId)->GetAddress())
1628 {
1629 // this MPDU is being acknowledged by the AP, so we can process
1630 // the Power Management flag
1631 ProcessPowerManagementFlag(mpdu, *apLinkId);
1632
1633 Mac48Address to = hdr->GetAddr3();
1634 // Address3 can be our MLD address (e.g., this is an MPDU containing a single MSDU
1635 // addressed to us) or a BSSID (e.g., this is an MPDU containing an A-MSDU)
1636 if (to == GetAddress() ||
1637 (hdr->IsQosData() && hdr->IsQosAmsdu() && to == mpdu->GetHeader().GetAddr1()))
1638 {
1639 NS_LOG_DEBUG("frame for me from=" << from);
1640 if (hdr->IsQosData())
1641 {
1642 if (hdr->IsQosAmsdu())
1643 {
1644 NS_LOG_DEBUG("Received A-MSDU from=" << from
1645 << ", size=" << packet->GetSize());
1647 packet = nullptr;
1648 }
1649 else if (hdr->HasData())
1650 {
1651 ForwardUp(packet, from, GetAddress());
1652 }
1653 }
1654 else if (hdr->HasData())
1655 {
1656 ForwardUp(packet, from, GetAddress());
1657 }
1658 }
1659 else if (to.IsGroup() || IsAssociated(to))
1660 {
1661 NS_LOG_DEBUG("forwarding frame from=" << from << ", to=" << to);
1662 Ptr<Packet> copy = packet->Copy();
1663
1664 // If the frame we are forwarding is of type QoS Data,
1665 // then we need to preserve the UP in the QoS control
1666 // header...
1667 if (hdr->IsQosData())
1668 {
1669 ForwardDown(copy, from, to, hdr->GetQosTid());
1670 }
1671 else
1672 {
1673 ForwardDown(copy, from, to);
1674 }
1675 ForwardUp(packet, from, to);
1676 }
1677 else if (hdr->HasData())
1678 {
1679 ForwardUp(packet, from, to);
1680 }
1681 }
1682 else if (hdr->IsFromDs() && hdr->IsToDs())
1683 {
1684 // this is an AP-to-AP frame
1685 // we ignore for now.
1686 NotifyRxDrop(packet);
1687 }
1688 else
1689 {
1690 // we can ignore these frames since
1691 // they are not targeted at the AP
1692 NotifyRxDrop(packet);
1693 }
1694 return;
1695 }
1696 else if (hdr->IsMgt())
1697 {
1698 if (hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress() &&
1700 {
1701 // this MPDU is being acknowledged by the AP, so we can process
1702 // the Power Management flag
1703 ProcessPowerManagementFlag(mpdu, linkId);
1704 }
1705 if (hdr->IsProbeReq() && (hdr->GetAddr1().IsGroup() ||
1706 hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress()))
1707 {
1708 // In the case where the Address 1 field contains a group address, the
1709 // Address 3 field also is validated to verify that the group addressed
1710 // frame originated from a STA in the BSS of which the receiving STA is
1711 // a member (Section 9.3.3.1 of 802.11-2020)
1712 if (hdr->GetAddr1().IsGroup() && !hdr->GetAddr3().IsBroadcast() &&
1713 hdr->GetAddr3() != GetFrameExchangeManager(linkId)->GetAddress())
1714 {
1715 // not addressed to us
1716 return;
1717 }
1718 MgtProbeRequestHeader probeRequestHeader;
1719 packet->PeekHeader(probeRequestHeader);
1720 const auto& ssid = probeRequestHeader.Get<Ssid>();
1721 if (ssid == GetSsid() || ssid->IsBroadcast())
1722 {
1723 NS_LOG_DEBUG("Probe request received from " << from << ": send probe response");
1724 SendProbeResp(from, linkId);
1725 }
1726 return;
1727 }
1728 else if (hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress())
1729 {
1730 switch (hdr->GetType())
1731 {
1734 NS_LOG_DEBUG(((hdr->IsAssocReq()) ? "Association" : "Reassociation")
1735 << " request received from " << from
1736 << ((GetNLinks() > 1) ? " on link ID " + std::to_string(linkId) : ""));
1737
1738 MgtAssocRequestHeader assocReq;
1739 MgtReassocRequestHeader reassocReq;
1740 AssocReqRefVariant frame = assocReq;
1741 if (hdr->IsAssocReq())
1742 {
1743 packet->PeekHeader(assocReq);
1744 }
1745 else
1746 {
1747 packet->PeekHeader(reassocReq);
1748 frame = reassocReq;
1749 }
1750 ReceiveAssocRequest(frame, from, linkId);
1751 if (GetNLinks() > 1)
1752 {
1753 ParseReportedStaInfo(frame, from, linkId);
1754 }
1755 SendAssocResp(hdr->GetAddr2(), hdr->IsReassocReq(), linkId);
1756 return;
1757 }
1759 NS_LOG_DEBUG("Disassociation received from " << from);
1761 auto& staList = GetLink(linkId).staList;
1762 for (auto it = staList.begin(); it != staList.end(); ++it)
1763 {
1764 if (it->second == from)
1765 {
1766 staList.erase(it);
1767 m_deAssocLogger(it->first, it->second);
1768 if (GetWifiRemoteStationManager(linkId)->GetDsssSupported(from) &&
1769 !GetWifiRemoteStationManager(linkId)->GetErpOfdmSupported(from))
1770 {
1771 GetLink(linkId).numNonErpStations--;
1772 }
1773 if (!GetWifiRemoteStationManager(linkId)->GetHtSupported(from))
1774 {
1775 GetLink(linkId).numNonHtStations--;
1776 }
1780 break;
1781 }
1782 }
1783 return;
1784 }
1785 case WIFI_MAC_MGT_ACTION: {
1786 auto pkt = mpdu->GetPacket()->Copy();
1787 auto [category, action] = WifiActionHeader::Remove(pkt);
1788 if (category == WifiActionHeader::PROTECTED_EHT &&
1789 action.protectedEhtAction ==
1791 IsAssociated(hdr->GetAddr2()))
1792 {
1793 // received an EML Operating Mode Notification frame from an associated station
1795 pkt->RemoveHeader(frame);
1796 ReceiveEmlNotification(frame, hdr->GetAddr2(), linkId);
1797 return;
1798 }
1799 break;
1800 }
1801 default:;
1802 // do nothing
1803 }
1804 }
1805 }
1806
1807 // Invoke the receive handler of our parent class to deal with any
1808 // other frames. Specifically, this will handle Block Ack-related
1809 // Management Action frames.
1810 WifiMac::Receive(Create<WifiMpdu>(packet, *hdr), linkId);
1811}
1812
1813bool
1815 const Mac48Address& from,
1816 uint8_t linkId)
1817{
1818 NS_LOG_FUNCTION(this << from << +linkId);
1819
1820 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
1821
1822 auto failure = [&](const std::string& msg) -> bool {
1823 NS_LOG_DEBUG("Association Request from " << from << " refused: " << msg);
1824 remoteStationManager->RecordAssocRefused(from);
1825 return false;
1826 };
1827
1828 // lambda to process received (Re)Association Request
1829 auto recvAssocRequest = [&](auto&& frameRefWrapper) -> bool {
1830 const auto& frame = frameRefWrapper.get();
1831
1832 // first, verify that the the station's supported
1833 // rate set is compatible with our Basic Rate set
1834 const CapabilityInformation& capabilities = frame.Capabilities();
1835 remoteStationManager->AddSupportedPhyPreamble(from, capabilities.IsShortPreamble());
1836 NS_ASSERT(frame.template Get<SupportedRates>());
1837 const auto rates = AllSupportedRates{*frame.template Get<SupportedRates>(),
1838 frame.template Get<ExtendedSupportedRatesIE>()};
1839
1840 if (rates.GetNRates() == 0)
1841 {
1842 return failure("STA's supported rate set not compatible with our Basic Rate set");
1843 }
1844
1845 if (GetHtSupported())
1846 {
1847 // check whether the HT STA supports all MCSs in Basic MCS Set
1848 const auto& htCapabilities = frame.template Get<HtCapabilities>();
1849 if (htCapabilities.has_value() && htCapabilities->IsSupportedMcs(0))
1850 {
1851 for (uint8_t i = 0; i < remoteStationManager->GetNBasicMcs(); i++)
1852 {
1853 WifiMode mcs = remoteStationManager->GetBasicMcs(i);
1854 if (!htCapabilities->IsSupportedMcs(mcs.GetMcsValue()))
1855 {
1856 return failure("HT STA does not support all MCSs in Basic MCS Set");
1857 }
1858 }
1859 }
1860 }
1861 if (GetVhtSupported(linkId))
1862 {
1863 // check whether the VHT STA supports all MCSs in Basic MCS Set
1864 const auto& vhtCapabilities = frame.template Get<VhtCapabilities>();
1865 if (vhtCapabilities.has_value() && vhtCapabilities->GetVhtCapabilitiesInfo() != 0)
1866 {
1867 for (uint8_t i = 0; i < remoteStationManager->GetNBasicMcs(); i++)
1868 {
1869 WifiMode mcs = remoteStationManager->GetBasicMcs(i);
1870 if (!vhtCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
1871 {
1872 return failure("VHT STA does not support all MCSs in Basic MCS Set");
1873 }
1874 }
1875 }
1876 }
1877 if (GetHeSupported())
1878 {
1879 // check whether the HE STA supports all MCSs in Basic MCS Set
1880 const auto& heCapabilities = frame.template Get<HeCapabilities>();
1881 if (heCapabilities.has_value() && heCapabilities->GetSupportedMcsAndNss() != 0)
1882 {
1883 for (uint8_t i = 0; i < remoteStationManager->GetNBasicMcs(); i++)
1884 {
1885 WifiMode mcs = remoteStationManager->GetBasicMcs(i);
1886 if (!heCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
1887 {
1888 return failure("HE STA does not support all MCSs in Basic MCS Set");
1889 }
1890 }
1891 }
1892 }
1893 if (GetEhtSupported())
1894 {
1895 // check whether the EHT STA supports all MCSs in Basic MCS Set
1896 // const auto& ehtCapabilities = frame.GetEhtCapabilities ();
1897 // TODO: to be completed
1898 }
1899
1900 // The association request from the station can be accepted.
1901 // Record all its supported modes in its associated WifiRemoteStation
1902 auto phy = GetWifiPhy(linkId);
1903
1904 for (const auto& mode : phy->GetModeList())
1905 {
1906 if (rates.IsSupportedRate(mode.GetDataRate(phy->GetChannelWidth())))
1907 {
1908 remoteStationManager->AddSupportedMode(from, mode);
1909 }
1910 }
1911 if (GetErpSupported(linkId) && remoteStationManager->GetErpOfdmSupported(from) &&
1912 capabilities.IsShortSlotTime())
1913 {
1914 remoteStationManager->AddSupportedErpSlotTime(from, true);
1915 }
1916 if (GetHtSupported())
1917 {
1918 const auto& htCapabilities = frame.template Get<HtCapabilities>();
1919 if (htCapabilities.has_value() && htCapabilities->IsSupportedMcs(0))
1920 {
1921 remoteStationManager->AddStationHtCapabilities(from, *htCapabilities);
1922 }
1923 // const ExtendedCapabilities& extendedCapabilities = frame.GetExtendedCapabilities();
1924 // TODO: to be completed
1925 }
1926 if (GetVhtSupported(linkId))
1927 {
1928 const auto& vhtCapabilities = frame.template Get<VhtCapabilities>();
1929 // we will always fill in RxHighestSupportedLgiDataRate field at TX, so this can be used
1930 // to check whether it supports VHT
1931 if (vhtCapabilities.has_value() &&
1932 vhtCapabilities->GetRxHighestSupportedLgiDataRate() > 0)
1933 {
1934 remoteStationManager->AddStationVhtCapabilities(from, *vhtCapabilities);
1935 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
1936 {
1937 if (vhtCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
1938 {
1939 remoteStationManager->AddSupportedMcs(from, mcs);
1940 // here should add a control to add basic MCS when it is implemented
1941 }
1942 }
1943 }
1944 }
1945 if (GetHeSupported())
1946 {
1947 const auto& heCapabilities = frame.template Get<HeCapabilities>();
1948 if (heCapabilities.has_value() && heCapabilities->GetSupportedMcsAndNss() != 0)
1949 {
1950 remoteStationManager->AddStationHeCapabilities(from, *heCapabilities);
1951 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HE))
1952 {
1953 if (heCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
1954 {
1955 remoteStationManager->AddSupportedMcs(from, mcs);
1956 // here should add a control to add basic MCS when it is implemented
1957 }
1958 }
1959 }
1960 }
1961 if (GetEhtSupported())
1962 {
1963 if (const auto& ehtCapabilities = frame.template Get<EhtCapabilities>())
1964 {
1965 remoteStationManager->AddStationEhtCapabilities(from, *ehtCapabilities);
1966 }
1967 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_EHT))
1968 {
1969 // TODO: Add check whether MCS is supported from the capabilities
1970 remoteStationManager->AddSupportedMcs(from, mcs);
1971 // here should add a control to add basic MCS when it is implemented
1972 }
1973 }
1974
1975 NS_LOG_DEBUG("Association Request from " << from << " accepted");
1976 remoteStationManager->RecordWaitAssocTxOk(from);
1977 return true;
1978 ;
1979 };
1980
1981 return std::visit(recvAssocRequest, assoc);
1982}
1983
1984void
1986{
1987 NS_LOG_FUNCTION(this << from << +linkId);
1988
1989 // lambda to process received Multi-Link Element
1990 auto recvMle = [&](auto&& frame) {
1991 const auto& mle = frame.get().template Get<MultiLinkElement>();
1992
1993 if (!mle.has_value())
1994 {
1995 return;
1996 }
1997
1998 auto emlCapabilities = std::make_shared<CommonInfoBasicMle::EmlCapabilities>();
1999 if (mle->HasEmlCapabilities())
2000 {
2001 emlCapabilities->emlsrSupport = mle->IsEmlsrSupported() ? 1 : 0;
2002 emlCapabilities->emlsrPaddingDelay =
2003 CommonInfoBasicMle::EncodeEmlsrPaddingDelay(mle->GetEmlsrPaddingDelay());
2004 emlCapabilities->emlsrTransitionDelay =
2005 CommonInfoBasicMle::EncodeEmlsrTransitionDelay(mle->GetEmlsrTransitionDelay());
2006 }
2007
2008 GetWifiRemoteStationManager(linkId)->SetMldAddress(from, mle->GetMldMacAddress());
2009 GetWifiRemoteStationManager(linkId)->AddStationEmlCapabilities(from, emlCapabilities);
2010
2011 for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
2012 {
2013 auto& perStaProfile = mle->GetPerStaProfile(i);
2014 if (!perStaProfile.HasStaMacAddress())
2015 {
2016 NS_LOG_DEBUG("[i=" << i
2017 << "] Cannot setup a link if the STA MAC address is missing");
2018 continue;
2019 }
2020 uint8_t newLinkId = perStaProfile.GetLinkId();
2021 if (newLinkId == linkId || newLinkId >= GetNLinks())
2022 {
2023 NS_LOG_DEBUG("[i=" << i << "] Link ID " << newLinkId << " not valid");
2024 continue;
2025 }
2026 if (!perStaProfile.HasAssocRequest() && !perStaProfile.HasReassocRequest())
2027 {
2028 NS_LOG_DEBUG("[i=" << i << "] No (Re)Association Request frame body present");
2029 continue;
2030 }
2031
2032 ReceiveAssocRequest(perStaProfile.GetAssocRequest(),
2033 perStaProfile.GetStaMacAddress(),
2034 newLinkId);
2035 GetWifiRemoteStationManager(newLinkId)->SetMldAddress(perStaProfile.GetStaMacAddress(),
2036 mle->GetMldMacAddress());
2038 perStaProfile.GetStaMacAddress(),
2039 emlCapabilities);
2040 }
2041 };
2042
2043 std::visit(recvMle, assoc);
2044}
2045
2046void
2048 const Mac48Address& sender,
2049 uint8_t linkId)
2050{
2051 NS_LOG_FUNCTION(this << frame << sender << linkId);
2052
2053 auto ehtConfiguration = GetEhtConfiguration();
2054
2055 if (BooleanValue emlsrActivated;
2056 !ehtConfiguration ||
2057 !ehtConfiguration->GetAttributeFailSafe("EmlsrActivated", emlsrActivated) ||
2058 !emlsrActivated.Get())
2059 {
2061 "Received an EML Operating Mode Notification frame but EMLSR is not activated");
2062 return;
2063 }
2064
2066 {
2068 auto emlCapabilities =
2070 NS_ASSERT_MSG(emlCapabilities, "EML Capabilities not stored for STA " << sender);
2071
2072 // update values stored in remote station manager
2073 emlCapabilities->emlsrPaddingDelay = frame.m_emlsrParamUpdate->paddingDelay;
2074 emlCapabilities->emlsrTransitionDelay = frame.m_emlsrParamUpdate->transitionDelay;
2075 }
2076
2077 auto mldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(sender);
2078 NS_ASSERT_MSG(mldAddress, "No MLD address stored for STA " << sender);
2079 auto emlsrLinks =
2080 frame.m_emlControl.emlsrMode == 1 ? frame.GetLinkBitmap() : std::list<uint8_t>{};
2081
2082 // The AP MLD has to consider the changes carried by the received EML Notification frame
2083 // as effective at the same time as the non-AP MLD. Therefore, we need to start a time
2084 // when the transmission of the Ack following the received EML Notification frame is
2085 // completed. For this purpose, we connect a callback to the PHY TX begin trace to catch
2086 // the Ack transmitted after the EML Notification frame.
2088 [=](WifiConstPsduMap psduMap, WifiTxVector txVector, double /* txPowerW */) {
2089 NS_ASSERT_MSG(psduMap.size() == 1 && psduMap.begin()->second->GetNMpdus() == 1 &&
2090 psduMap.begin()->second->GetHeader(0).IsAck(),
2091 "Expected a Normal Ack after EML Notification frame");
2092
2093 auto ackDuration =
2094 WifiPhy::CalculateTxDuration(psduMap, txVector, GetLink(linkId).phy->GetPhyBand());
2095
2096 TimeValue transitionTimeout;
2097 ehtConfiguration->GetAttribute("TransitionTimeout", transitionTimeout);
2098
2100 Simulator::Schedule(ackDuration + transitionTimeout.Get(), [=]() {
2101 for (uint8_t id = 0; id < GetNLinks(); id++)
2102 {
2103 auto linkAddress =
2104 GetWifiRemoteStationManager(id)->GetAffiliatedStaAddress(*mldAddress);
2105 if (!linkAddress)
2106 {
2107 // this link has not been setup by the non-AP MLD
2108 continue;
2109 }
2110
2111 if (!emlsrLinks.empty())
2112 {
2113 // the non-AP MLD is enabling EMLSR mode
2125 auto enabled = std::find(emlsrLinks.cbegin(), emlsrLinks.cend(), id) !=
2126 emlsrLinks.cend();
2127 if (enabled)
2128 {
2129 StaSwitchingToActiveModeOrDeassociated(*linkAddress, id);
2130 }
2131 GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, enabled);
2132 }
2133 else
2134 {
2135 // the non-AP MLD is disabling EMLSR mode
2148 if (id != linkId &&
2149 GetWifiRemoteStationManager(id)->GetEmlsrEnabled(*linkAddress))
2150 {
2151 StaSwitchingToPsMode(*linkAddress, id);
2152 }
2153 GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, false);
2154 }
2155 }
2156 });
2157 });
2158
2159 // connect the callback to the PHY TX begin trace to catch the Ack and disconnect
2160 // after its transmission begins
2161 auto phy = GetLink(linkId).phy;
2162 phy->TraceConnectWithoutContext("PhyTxPsduBegin", cb);
2163 Simulator::Schedule(phy->GetSifs() + NanoSeconds(1),
2164 [=]() { phy->TraceDisconnectWithoutContext("PhyTxPsduBegin", cb); });
2165
2166 // An AP MLD with dot11EHTEMLSROptionActivated equal to true sets the EMLSR Mode subfield
2167 // to the value obtained from the EMLSR Mode subfield of the received EML Operating Mode
2168 // Notification frame. (Sec. 9.6.35.8 of 802.11be D3.0)
2169
2170 // When included in a frame sent by an AP affiliated with an AP MLD, the EMLSR Parameter
2171 // Update Control subfield is set to 0. (Sec. 9.6.35.8 of 802.11be D3.0)
2172 frame.m_emlControl.emlsrParamUpdateCtrl = 0;
2173
2174 // An AP MLD with dot11EHTEMLSROptionImplemented equal to true sets the EMLSR Link Bitmap
2175 // subfield to the value obtained from the EMLSR Link Bitmap subfield of the received
2176 // EML Operating Mode Notification frame. (Sec. 9.6.35.8 of 802.11be D3.0)
2177
2178 // The EMLSR Parameter Update field [..] is present if [..] the Action frame is sent by
2179 // a non-AP STA affiliated with a non-AP MLD (Sec. 9.6.35.8 of 802.11be D3.0)
2180 frame.m_emlsrParamUpdate.reset();
2181
2182 auto ehtFem = StaticCast<EhtFrameExchangeManager>(GetFrameExchangeManager(linkId));
2183 ehtFem->SendEmlOperatingModeNotification(sender, frame);
2184}
2185
2186void
2188{
2189 NS_LOG_FUNCTION(this << *mpdu);
2190 for (auto& i : *PeekPointer(mpdu))
2191 {
2192 auto from = i.second.GetSourceAddr();
2193 auto to = i.second.GetDestinationAddr();
2194
2195 if (to.IsGroup() || IsAssociated(to))
2196 {
2197 NS_LOG_DEBUG("forwarding QoS frame from=" << from << ", to=" << to);
2198 ForwardDown(i.first->Copy(), from, to, mpdu->GetHeader().GetQosTid());
2199 }
2200
2201 ForwardUp(i.first, from, to);
2202 }
2203}
2204
2205void
2207{
2208 NS_LOG_FUNCTION(this);
2210
2211 for (uint8_t linkId = 0; linkId < GetNLinks(); ++linkId)
2212 {
2213 GetLink(linkId).beaconEvent.Cancel();
2215 {
2216 uint64_t jitterUs =
2218 ? static_cast<uint64_t>(m_beaconJitter->GetValue(0, 1) *
2220 : 0);
2221 NS_LOG_DEBUG("Scheduling initial beacon for access point "
2222 << GetAddress() << " at time " << jitterUs << "us");
2225 this,
2226 linkId);
2227 }
2230 }
2231
2236}
2237
2238bool
2240{
2241 bool useProtection = (GetLink(linkId).numNonErpStations > 0) && m_enableNonErpProtection;
2243 return useProtection;
2244}
2245
2246uint16_t
2247ApWifiMac::GetNextAssociationId(std::list<uint8_t> linkIds)
2248{
2249 // Return the first AID value between 1 and 2007 that is free for all the given links
2250 for (uint16_t nextAid = 1; nextAid <= 2007; nextAid++)
2251 {
2252 if (std::all_of(linkIds.begin(), linkIds.end(), [&](auto&& linkId) {
2253 auto& staList = GetLink(linkId).staList;
2254 return staList.find(nextAid) == staList.end();
2255 }))
2256 {
2257 return nextAid;
2258 }
2259 }
2260 NS_FATAL_ERROR("No free association ID available!");
2261 return 0;
2262}
2263
2264const std::map<uint16_t, Mac48Address>&
2265ApWifiMac::GetStaList(uint8_t linkId) const
2266{
2267 return GetLink(linkId).staList;
2268}
2269
2270uint16_t
2272{
2273 return GetWifiRemoteStationManager(linkId)->GetAssociationId(addr);
2274}
2275
2276uint8_t
2277ApWifiMac::GetBufferStatus(uint8_t tid, Mac48Address address) const
2278{
2279 auto it = m_bufferStatus.find(WifiAddressTidPair(address, tid));
2280 if (it == m_bufferStatus.end() || it->second.timestamp + m_bsrLifetime < Simulator::Now())
2281 {
2282 return 255;
2283 }
2284 return it->second.value;
2285}
2286
2287void
2288ApWifiMac::SetBufferStatus(uint8_t tid, Mac48Address address, uint8_t size)
2289{
2290 if (size == 255)
2291 {
2292 // no point in storing an unspecified size
2293 m_bufferStatus.erase(WifiAddressTidPair(address, tid));
2294 }
2295 else
2296 {
2297 m_bufferStatus[WifiAddressTidPair(address, tid)] = {size, Simulator::Now()};
2298 }
2299}
2300
2301uint8_t
2303{
2304 uint8_t maxSize = 0;
2305 bool found = false;
2306
2307 for (uint8_t tid = 0; tid < 8; tid++)
2308 {
2309 uint8_t size = GetBufferStatus(tid, address);
2310 if (size != 255)
2311 {
2312 maxSize = std::max(maxSize, size);
2313 found = true;
2314 }
2315 }
2316
2317 if (found)
2318 {
2319 return maxSize;
2320 }
2321 return 255;
2322}
2323
2324} // namespace ns3
Wi-Fi AP state machine.
Definition: ap-wifi-mac.h:65
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:143
Ptr< Txop > m_beaconTxop
Dedicated Txop for beacons.
Definition: ap-wifi-mac.h:521
void SetBeaconGeneration(bool enable)
Enable or disable beacon generation of the AP.
Definition: ap-wifi-mac.cc:180
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:243
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:127
void SetBeaconInterval(Time interval)
Definition: ap-wifi-mac.cc:218
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:318
std::map< Mac48Address, EventId > m_transitionTimeoutEvents
transition timeout events running for EMLSR clients
Definition: ap-wifi-mac.h:531
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:483
Ptr< UniformRandomVariable > m_beaconJitter
UniformRandomVariable used to randomize the time of the first beacon.
Definition: ap-wifi-mac.h:525
bool CanForwardPacketsTo(Mac48Address to) const override
Return true if packets can be forwarded to the given destination, false otherwise.
Definition: ap-wifi-mac.cc:391
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:527
EdcaParameterSet GetEdcaParameterSet(uint8_t linkId) const
Return the EDCA Parameter Set of the current AP for the given link.
Definition: ap-wifi-mac.cc:515
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:661
HtOperation GetHtOperation(uint8_t linkId) const
Return the HT operation of the current AP for the given link.
Definition: ap-wifi-mac.cc:728
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:266
void TxOk(Ptr< const WifiMpdu > mpdu)
The packet we sent was successfully received by the receiver (i.e.
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:205
TracedCallback< uint16_t, Mac48Address > m_deAssocLogger
deassociation logger
Definition: ap-wifi-mac.h:552
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.
bool m_enableBeaconGeneration
Flag whether beacons are being generated.
Definition: ap-wifi-mac.h:522
Time m_beaconInterval
Beacon interval.
Definition: ap-wifi-mac.h:523
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:526
std::unordered_map< WifiAddressTidPair, BsrType, WifiAddressTidHash > m_bufferStatus
Per (MAC address, TID) buffer status reports.
Definition: ap-wifi-mac.h:541
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 ...
Definition: ap-wifi-mac.cc:929
DsssParameterSet GetDsssParameterSet(uint8_t linkId) const
Return the DSSS Parameter Set that we support on the given link.
Definition: ap-wifi-mac.cc:473
TracedCallback< uint16_t, Mac48Address > m_assocLogger
association logger
Definition: ap-wifi-mac.h:551
Time GetBeaconInterval() const
Definition: ap-wifi-mac.cc:199
static TypeId GetTypeId()
Get the type ID.
Definition: ap-wifi-mac.cc:57
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:630
void ReceiveEmlNotification(MgtEmlOperatingModeNotification &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:411
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:529
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: ap-wifi-mac.cc:235
ApLinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: ap-wifi-mac.cc:149
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.
Definition: ap-wifi-mac.cc:905
void ConfigureStandard(WifiStandard standard) override
Definition: ap-wifi-mac.cc:155
ErpInformation GetErpInformation(uint8_t linkId) const
Return the ERP information of the current AP for the given link.
Definition: ap-wifi-mac.cc:494
void SetLinkUpCallback(Callback< void > linkUp) override
Definition: ap-wifi-mac.cc:206
VhtOperation GetVhtOperation(uint8_t linkId) const
Return the VHT operation of the current AP for the given link.
Definition: ap-wifi-mac.cc:826
~ApWifiMac() override
Definition: ap-wifi-mac.cc:121
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.
Definition: ap-wifi-mac.cc:875
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...
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:562
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:421
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:290
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:170
bool GetUseNonErpProtection(uint8_t linkId) const
Return whether protection for non-ERP stations is used in the BSS corresponding to the given link.
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:428
AttributeValue implementation for Boolean.
Definition: boolean.h:37
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.
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.
The IEEE 802.11ax HE Capabilities.
The HE Operation Information Element.
Definition: he-operation.h:36
void SetBssColor(uint8_t bssColor)
Set the BSS color.
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 tuple (n...
Definition: he-operation.cc:94
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.
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:161
Implement the header for management frames of type association and reassociation response.
Definition: mgt-headers.h:338
CapabilityInformation & Capabilities()
Definition: mgt-headers.cc:475
StatusCode GetStatusCode()
Return the status code.
Definition: mgt-headers.cc:457
void SetStatusCode(StatusCode code)
Set the status code.
Definition: mgt-headers.cc:463
void SetAssociationId(uint16_t aid)
Set the association ID.
Definition: mgt-headers.cc:481
Implement the header for management frames of type beacon.
Definition: mgt-headers.h:516
Implement the header for Action frames of type EML Operating Mode Notification.
Definition: mgt-headers.h:1113
EmlControl m_emlControl
EML Control field.
Definition: mgt-headers.h:1163
std::list< uint8_t > GetLinkBitmap() const
std::optional< EmlsrParamUpdate > m_emlsrParamUpdate
EMLSR Parameter Update field.
Definition: mgt-headers.h:1164
Implement the header for management frames of type probe request.
Definition: mgt-headers.h:436
Implement the header for management frames of type probe response.
Definition: mgt-headers.h:455
void SetBeaconIntervalUs(uint64_t us)
Set the beacon interval in microseconds unit.
Definition: mgt-headers.cc:82
CapabilityInformation & Capabilities()
Definition: mgt-headers.cc:94
Implement the header for management frames of type reassociation request.
Definition: mgt-headers.h:245
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:311
void Initialize()
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:186
void Dispose()
Dispose of this Object.
Definition: object.cc:219
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
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:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:606
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:314
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:412
AttributeValue implementation for Time.
Definition: nstime.h:1423
Time Get() const
Definition: time.cc:532
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:216
virtual void SetWifiMac(const Ptr< WifiMac > mac)
Set the wifi MAC this Txop is associated to.
Definition: txop.cc:191
void SetMaxCws(std::vector< uint32_t > maxCws)
Set the maximum contention window size for each link.
Definition: txop.cc:258
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set MacTxMiddle this Txop is associated to.
Definition: txop.cc:184
void SetMinCws(std::vector< uint32_t > minCws)
Set the minimum contention window size for each link.
Definition: txop.cc:229
void SetAifsns(std::vector< uint8_t > aifsns)
Set the number of slots that make up an AIFS for each link.
Definition: txop.cc:355
virtual void Queue(Ptr< Packet > packet, const WifiMacHeader &hdr)
Definition: txop.cc:501
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
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.
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.
@ PROTECTED_EHT_EML_OPERATING_MODE_NOTIFICATION
Definition: mgt-headers.h:714
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.
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.
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:94
Ptr< FrameExchangeManager > GetFrameExchangeManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Frame Exchange Manager associated with the given link.
Definition: wifi-mac.cc:864
Ptr< QosTxop > GetBEQueue() const
Accessor for the AC_BE channel access function.
Definition: wifi-mac.cc:531
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition: wifi-mac.cc:1358
Ptr< HeConfiguration > GetHeConfiguration() const
Definition: wifi-mac.cc:1475
Ptr< Txop > GetTxop() const
Accessor for the Txop object.
Definition: wifi-mac.cc:491
VhtCapabilities GetVhtCapabilities(uint8_t linkId) const
Return the VHT capabilities of the device for the given link.
Definition: wifi-mac.cc:1712
bool GetQosSupported() const
Return whether the device supports QoS.
Definition: wifi-mac.cc:1030
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition: wifi-mac.cc:930
void DoInitialize() override
Initialize() implementation.
Definition: wifi-mac.cc:352
virtual void ConfigureStandard(WifiStandard standard)
Definition: wifi-mac.cc:748
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:1154
Ssid GetSsid() const
Definition: wifi-mac.cc:463
bool GetErpSupported(uint8_t linkId) const
Return whether the device supports ERP on the given link.
Definition: wifi-mac.cc:1036
bool GetHtSupported() const
Return whether the device supports HT.
Definition: wifi-mac.cc:1487
Ptr< QosTxop > GetVOQueue() const
Accessor for the AC_VO channel access function.
Definition: wifi-mac.cc:519
void SetTypeOfStation(TypeOfStation type)
This method is invoked by a subclass to specify what type of station it is implementing.
Definition: wifi-mac.cc:418
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:978
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:1113
bool GetEhtSupported() const
Return whether the device supports EHT.
Definition: wifi-mac.cc:1506
bool GetHeSupported() const
Return whether the device supports HE.
Definition: wifi-mac.cc:1500
HtCapabilities GetHtCapabilities(uint8_t linkId) const
Return the HT capabilities of the device for the given link.
Definition: wifi-mac.cc:1655
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:936
Ptr< EhtConfiguration > GetEhtConfiguration() const
Definition: wifi-mac.cc:1481
bool GetVhtSupported(uint8_t linkId) const
Return whether the device supports VHT on the given link.
Definition: wifi-mac.cc:1493
Ptr< MacTxMiddle > m_txMiddle
TX middle (aggregation etc.)
Definition: wifi-mac.h:785
Ptr< HtConfiguration > GetHtConfiguration() const
Definition: wifi-mac.cc:1463
ExtendedCapabilities GetExtendedCapabilities() const
Return the extended capabilities of the device.
Definition: wifi-mac.cc:1644
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:543
bool GetShortSlotTimeSupported() const
Definition: wifi-mac.cc:1080
void NotifyRxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:619
virtual void SetLinkUpCallback(Callback< void > linkUp)
Definition: wifi-mac.cc:1099
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:910
void ForwardUp(Ptr< const Packet > packet, Mac48Address from, Mac48Address to)
Forward the packet up to the device.
Definition: wifi-mac.cc:1216
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:1223
Mac48Address GetAddress() const
Definition: wifi-mac.cc:450
EhtCapabilities GetEhtCapabilities(uint8_t linkId) const
Return the EHT capabilities of the device for the given link.
Definition: wifi-mac.cc:1849
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: wifi-mac.cc:922
HeCapabilities GetHeCapabilities(uint8_t linkId) const
Return the HE capabilities of the device for the given link.
Definition: wifi-mac.cc:1793
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:497
void NotifyTxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:601
void DoDispose() override
Destructor implementation.
Definition: wifi-mac.cc:376
bool GetDsssSupported(uint8_t linkId) const
Return whether the device supports DSSS on the given link.
Definition: wifi-mac.cc:1060
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:1311
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1496
void SetSlot(Time slot)
Set the slot duration for this PHY.
Definition: wifi-phy.cc:789
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1017
void SetShortSlotTimeEnabled(bool enable)
Enable or disable short slot time.
void SetPsMode(const Mac48Address &address, bool isInPsMode)
Register whether the STA is in Power Save mode or not.
void AddBasicMode(WifiMode mode)
Invoked in a STA upon association to store the set of rates which belong to the BSSBasicRateSet of th...
uint16_t GetAssociationId(Mac48Address remoteAddress) const
Get the AID of a remote station.
uint8_t GetNBasicModes() const
Return the number of basic modes we support.
void AddStationEmlCapabilities(Mac48Address from, const std::shared_ptr< CommonInfoBasicMle::EmlCapabilities > &emlCapabilities)
Records EML capabilities of the remote station.
void SetUseNonErpProtection(bool enable)
Enable or disable protection for non-ERP stations.
std::optional< Mac48Address > GetAffiliatedStaAddress(const Mac48Address &mldAddress) const
Get the address of the remote station operating on this link and affiliated with the MLD having the g...
std::shared_ptr< CommonInfoBasicMle::EmlCapabilities > GetStationEmlCapabilities(const Mac48Address &from)
void SetShortPreambleEnabled(bool enable)
Enable or disable short PHY preambles.
bool IsAssociated(Mac48Address address) const
Return whether the station associated.
void SetMldAddress(const Mac48Address &address, const Mac48Address &mldAddress)
Set the address of the MLD the given station is affiliated with.
void RecordGotAssocTxOk(Mac48Address address)
Records that we got an ACK for the association response we sent.
bool IsInPsMode(const Mac48Address &address) const
Return whether the STA is currently in Power Save mode.
WifiMode GetBasicMode(uint8_t i) const
Return a basic mode from the set of basic modes.
void RecordDisassociated(Mac48Address address)
Records that the STA was disassociated.
void RecordGotAssocTxFailed(Mac48Address address)
Records that we missed an ACK for the association response we sent.
std::optional< Mac48Address > GetMldAddress(const Mac48Address &address) const
Get the address of the MLD the given station is affiliated with, if any.
bool IsWaitAssocTxOk(Mac48Address address) const
Return whether we are waiting for an ACK for the association response we sent.
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< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1444
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1424
#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_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:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiMacDropReason
The reason why an MPDU was dropped.
Definition: wifi-mac.h:75
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:72
@ AP
Definition: wifi-mac.h:64
@ 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:74
@ AC_VO
Voice.
Definition: qos-utils.h:80
@ AC_VI
Video.
Definition: qos-utils.h:78
@ AC_BK
Background.
Definition: qos-utils.h:76
@ AC_BEACON
Beacon queue.
Definition: qos-utils.h:84
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:488
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
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:702
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:55
@ NO_PROTECTION
Definition: ht-operation.h:37
@ MIXED_MODE_PROTECTION
Definition: ht-operation.h:40
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
std::pair< Mac48Address, uint8_t > WifiAddressTidPair
(MAC address, TID) pair
Definition: qos-utils.h:35
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.
static uint8_t EncodeEmlsrTransitionDelay(Time delay)
static uint8_t EncodeEmlsrPaddingDelay(Time delay)
uint8_t emlsrParamUpdateCtrl
EMLSR Parameter Update Control.
Definition: mgt-headers.h:1135