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
27#include "mac-rx-middle.h"
28#include "mac-tx-middle.h"
29#include "mgt-headers.h"
30#include "msdu-aggregator.h"
31#include "qos-txop.h"
34#include "wifi-mac-queue.h"
35#include "wifi-net-device.h"
36#include "wifi-phy.h"
37
38#include "ns3/he-configuration.h"
39#include "ns3/ht-configuration.h"
40#include "ns3/log.h"
41#include "ns3/multi-link-element.h"
42#include "ns3/packet.h"
43#include "ns3/pointer.h"
44#include "ns3/random-variable-stream.h"
45#include "ns3/simulator.h"
46#include "ns3/string.h"
47
48namespace ns3
49{
50
51NS_LOG_COMPONENT_DEFINE("ApWifiMac");
52
54
55TypeId
57{
58 static TypeId tid =
59 TypeId("ns3::ApWifiMac")
61 .SetGroupName("Wifi")
62 .AddConstructor<ApWifiMac>()
63 .AddAttribute(
64 "BeaconInterval",
65 "Delay between two beacons",
66 TimeValue(MicroSeconds(102400)),
69 .AddAttribute("BeaconJitter",
70 "A uniform random variable to cause the initial beacon starting time "
71 "(after simulation time 0) "
72 "to be distributed between 0 and the BeaconInterval.",
73 StringValue("ns3::UniformRandomVariable"),
75 MakePointerChecker<UniformRandomVariable>())
76 .AddAttribute("EnableBeaconJitter",
77 "If beacons are enabled, whether to jitter the initial send event.",
78 BooleanValue(true),
81 .AddAttribute("BeaconGeneration",
82 "Whether or not beacons are generated.",
83 BooleanValue(true),
86 .AddAttribute("EnableNonErpProtection",
87 "Whether or not protection mechanism should be used when non-ERP STAs "
88 "are present within the BSS."
89 "This parameter is only used when ERP is supported by the AP.",
90 BooleanValue(true),
93 .AddAttribute("BsrLifetime",
94 "Lifetime of Buffer Status Reports received from stations.",
98 .AddTraceSource("AssociatedSta",
99 "A station associated with this access point.",
101 "ns3::ApWifiMac::AssociationCallback")
102 .AddTraceSource("DeAssociatedSta",
103 "A station lost association with this access point.",
105 "ns3::ApWifiMac::AssociationCallback");
106 return tid;
107}
108
110 : m_enableBeaconGeneration(false)
111{
112 NS_LOG_FUNCTION(this);
113 m_beaconTxop = CreateObject<Txop>(CreateObject<WifiMacQueue>(AC_BEACON));
115
116 // Let the lower layers know that we are acting as an AP.
118}
119
121{
122 NS_LOG_FUNCTION(this);
123}
124
125void
127{
128 NS_LOG_FUNCTION(this);
130 m_beaconTxop = nullptr;
133}
134
136{
139}
140
141std::unique_ptr<WifiMac::LinkEntity>
143{
144 return std::make_unique<ApLinkEntity>();
145}
146
148ApWifiMac::GetLink(uint8_t linkId) const
149{
150 return static_cast<ApLinkEntity&>(WifiMac::GetLink(linkId));
151}
152
153void
155{
156 NS_LOG_FUNCTION(this << standard);
159 m_beaconTxop->SetAifsns(std::vector<uint8_t>(GetNLinks(), 1));
160 m_beaconTxop->SetMinCws(std::vector<uint32_t>(GetNLinks(), 0));
161 m_beaconTxop->SetMaxCws(std::vector<uint32_t>(GetNLinks(), 0));
162 for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
163 {
165 }
166}
167
170{
171 if (ac == AC_BEACON)
172 {
174 }
175 return WifiMac::GetTxopQueue(ac);
176}
177
178void
180{
181 NS_LOG_FUNCTION(this << enable);
182 for (uint8_t linkId = 0; linkId < GetNLinks(); ++linkId)
183 {
184 if (!enable)
185 {
186 GetLink(linkId).beaconEvent.Cancel();
187 }
188 else if (!m_enableBeaconGeneration)
189 {
190 GetLink(linkId).beaconEvent =
192 }
193 }
195}
196
197Time
199{
200 NS_LOG_FUNCTION(this);
201 return m_beaconInterval;
202}
203
204void
206{
207 NS_LOG_FUNCTION(this << &linkUp);
209
210 // The approach taken here is that, from the point of view of an AP,
211 // the link is always up, so we immediately invoke the callback if
212 // one is set
213 linkUp();
214}
215
216void
218{
219 NS_LOG_FUNCTION(this << interval);
220 if ((interval.GetMicroSeconds() % 1024) != 0)
221 {
222 NS_FATAL_ERROR("beacon interval should be multiple of 1024us (802.11 time unit), see IEEE "
223 "Std. 802.11-2012");
224 }
225 if (interval.GetMicroSeconds() > (1024 * 65535))
226 {
228 "beacon interval should be smaller then or equal to 65535 * 1024us (802.11 time unit)");
229 }
230 m_beaconInterval = interval;
231}
232
233int64_t
235{
236 NS_LOG_FUNCTION(this << stream);
237 m_beaconJitter->SetStream(stream);
238 return 1;
239}
240
241void
243{
244 NS_LOG_FUNCTION(this << +linkId);
245 auto& link = GetLink(linkId);
246 if (GetErpSupported(linkId) && GetShortSlotTimeSupported() && (link.numNonErpStations == 0))
247 {
248 for (const auto& sta : link.staList)
249 {
251 {
252 link.shortSlotTimeEnabled = false;
253 return;
254 }
255 }
256 link.shortSlotTimeEnabled = true;
257 }
258 else
259 {
260 link.shortSlotTimeEnabled = false;
261 }
262}
263
264void
266{
267 NS_LOG_FUNCTION(this << +linkId);
268 auto& link = GetLink(linkId);
269 if (GetErpSupported(linkId) && GetWifiPhy(linkId)->GetShortPhyPreambleSupported())
270 {
271 for (const auto& sta : link.staList)
272 {
273 if (!GetWifiRemoteStationManager(linkId)->GetErpOfdmSupported(sta.second) ||
274 !GetWifiRemoteStationManager(linkId)->GetShortPreambleSupported(sta.second))
275 {
276 link.shortPreambleEnabled = false;
277 return;
278 }
279 }
280 link.shortPreambleEnabled = true;
281 }
282 else
283 {
284 link.shortPreambleEnabled = false;
285 }
286}
287
288void
290{
291 NS_LOG_FUNCTION(this << packet << from << to);
292 // If we are not a QoS AP then we definitely want to use AC_BE to
293 // transmit the packet. A TID of zero will map to AC_BE (through \c
294 // QosUtilsMapTidToAc()), so we use that as our default here.
295 uint8_t tid = 0;
296
297 // If we are a QoS AP then we attempt to get a TID for this packet
298 if (GetQosSupported())
299 {
300 tid = QosUtilsGetTidForPacket(packet);
301 // Any value greater than 7 is invalid and likely indicates that
302 // the packet had no QoS tag, so we revert to zero, which'll
303 // mean that AC_BE is used.
304 if (tid > 7)
305 {
306 tid = 0;
307 }
308 }
309
310 ForwardDown(packet, from, to, tid);
311}
312
313void
315{
316 NS_LOG_FUNCTION(this << packet << from << to << +tid);
317 WifiMacHeader hdr;
318
319 // For now, an AP that supports QoS does not support non-QoS
320 // associations, and vice versa. In future the AP model should
321 // support simultaneously associated QoS and non-QoS STAs, at which
322 // point there will need to be per-association QoS state maintained
323 // by the association state machine, and consulted here.
324 if (GetQosSupported())
325 {
328 hdr.SetQosNoEosp();
329 hdr.SetQosNoAmsdu();
330 // Transmission of multiple frames in the same Polled TXOP is not supported for now
331 hdr.SetQosTxopLimit(0);
332 // Fill in the QoS control field in the MAC header
333 hdr.SetQosTid(tid);
334 }
335 else
336 {
338 }
339
340 if (GetQosSupported())
341 {
342 hdr.SetNoOrder(); // explicitly set to 0 for the time being since HT control field is not
343 // yet implemented (set it to 1 when implemented)
344 }
345
346 std::list<Mac48Address> addr2Set;
347 if (to.IsGroup())
348 {
349 // broadcast frames are transmitted on all the links
350 for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
351 {
352 addr2Set.push_back(GetFrameExchangeManager(linkId)->GetAddress());
353 }
354 }
355 else
356 {
357 // the Transmitter Address (TA) is the MLD address only for non-broadcast data frames
358 // exchanged between two MLDs
359 addr2Set = {GetAddress()};
360 auto linkId = IsAssociated(to);
361 NS_ASSERT_MSG(linkId, "Station " << to << "is not associated, cannot send it a frame");
362 if (GetNLinks() == 1 || !GetWifiRemoteStationManager(*linkId)->GetMldAddress(to))
363 {
364 addr2Set = {GetFrameExchangeManager(*linkId)->GetAddress()};
365 }
366 }
367
368 for (const auto& addr2 : addr2Set)
369 {
370 hdr.SetAddr1(to);
371 hdr.SetAddr2(addr2);
372 hdr.SetAddr3(from);
373 hdr.SetDsFrom();
374 hdr.SetDsNotTo();
375
376 if (GetQosSupported())
377 {
378 // Sanity check that the TID is valid
379 NS_ASSERT(tid < 8);
380 GetQosTxop(tid)->Queue(packet, hdr);
381 }
382 else
383 {
384 GetTxop()->Queue(packet, hdr);
385 }
386 }
387}
388
389bool
391{
392 return (to.IsGroup() || IsAssociated(to));
393}
394
395void
397{
398 NS_LOG_FUNCTION(this << packet << to << from);
399 if (CanForwardPacketsTo(to))
400 {
401 ForwardDown(packet, from, to);
402 }
403 else
404 {
405 NotifyTxDrop(packet);
406 }
407}
408
409void
411{
412 NS_LOG_FUNCTION(this << packet << to);
413 // We're sending this packet with a from address that is our own. We
414 // get that address from the lower MAC and make use of the
415 // from-spoofing Enqueue() method to avoid duplicated code.
416 Enqueue(packet, to, GetAddress());
417}
418
419bool
421{
422 NS_LOG_FUNCTION(this);
423 return true;
424}
425
427ApWifiMac::GetSupportedRates(uint8_t linkId) const
428{
429 NS_LOG_FUNCTION(this << +linkId);
430 SupportedRates rates;
431 // Send the set of supported rates and make sure that we indicate
432 // the Basic Rate set in this set of supported rates.
433 for (const auto& mode : GetWifiPhy(linkId)->GetModeList())
434 {
435 uint64_t modeDataRate = mode.GetDataRate(GetWifiPhy(linkId)->GetChannelWidth());
436 NS_LOG_DEBUG("Adding supported rate of " << modeDataRate);
437 rates.AddSupportedRate(modeDataRate);
438 // Add rates that are part of the BSSBasicRateSet (manufacturer dependent!)
439 // here we choose to add the mandatory rates to the BSSBasicRateSet,
440 // except for 802.11b where we assume that only the non HR-DSSS rates are part of the
441 // BSSBasicRateSet
442 if (mode.IsMandatory() && (mode.GetModulationClass() != WIFI_MOD_CLASS_HR_DSSS))
443 {
444 NS_LOG_DEBUG("Adding basic mode " << mode.GetUniqueName());
446 }
447 }
448 // set the basic rates
449 for (uint8_t j = 0; j < GetWifiRemoteStationManager(linkId)->GetNBasicModes(); j++)
450 {
452 uint64_t modeDataRate = mode.GetDataRate(GetWifiPhy(linkId)->GetChannelWidth());
453 NS_LOG_DEBUG("Setting basic rate " << mode.GetUniqueName());
454 rates.SetBasicRate(modeDataRate);
455 }
456 // If it is a HT AP, then add the BSSMembershipSelectorSet
457 // The standard says that the BSSMembershipSelectorSet
458 // must have its MSB set to 1 (must be treated as a Basic Rate)
459 // Also the standard mentioned that at least 1 element should be included in the SupportedRates
460 // the rest can be in the ExtendedSupportedRates
461 if (GetHtSupported())
462 {
463 for (const auto& selector : GetWifiPhy(linkId)->GetBssMembershipSelectorList())
464 {
465 rates.AddBssMembershipSelectorRate(selector);
466 }
467 }
468 return rates;
469}
470
473{
474 NS_LOG_FUNCTION(this << +linkId);
476 DsssParameterSet dsssParameters;
477 dsssParameters.SetCurrentChannel(GetWifiPhy(linkId)->GetChannelNumber());
478 return dsssParameters;
479}
480
482ApWifiMac::GetCapabilities(uint8_t linkId) const
483{
484 NS_LOG_FUNCTION(this << +linkId);
485 CapabilityInformation capabilities;
486 capabilities.SetShortPreamble(GetLink(linkId).shortPreambleEnabled);
487 capabilities.SetShortSlotTime(GetLink(linkId).shortSlotTimeEnabled);
488 capabilities.SetEss();
489 return capabilities;
490}
491
493ApWifiMac::GetErpInformation(uint8_t linkId) const
494{
495 NS_LOG_FUNCTION(this << +linkId);
496 NS_ASSERT(GetErpSupported(linkId));
497 ErpInformation information;
498
499 information.SetNonErpPresent(GetLink(linkId).numNonErpStations > 0);
500 information.SetUseProtection(GetUseNonErpProtection(linkId));
501 if (GetLink(linkId).shortPreambleEnabled)
502 {
503 information.SetBarkerPreambleMode(0);
504 }
505 else
506 {
507 information.SetBarkerPreambleMode(1);
508 }
509
510 return information;
511}
512
515{
516 NS_LOG_FUNCTION(this << +linkId);
518 EdcaParameterSet edcaParameters;
519
520 Ptr<QosTxop> edca;
521 Time txopLimit;
522
523 edca = GetQosTxop(AC_BE);
524 txopLimit = edca->GetTxopLimit(linkId);
525 edcaParameters.SetBeAci(0);
526 edcaParameters.SetBeCWmin(edca->GetMinCw(linkId));
527 edcaParameters.SetBeCWmax(edca->GetMaxCw(linkId));
528 edcaParameters.SetBeAifsn(edca->GetAifsn(linkId));
529 edcaParameters.SetBeTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
530
531 edca = GetQosTxop(AC_BK);
532 txopLimit = edca->GetTxopLimit(linkId);
533 edcaParameters.SetBkAci(1);
534 edcaParameters.SetBkCWmin(edca->GetMinCw(linkId));
535 edcaParameters.SetBkCWmax(edca->GetMaxCw(linkId));
536 edcaParameters.SetBkAifsn(edca->GetAifsn(linkId));
537 edcaParameters.SetBkTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
538
539 edca = GetQosTxop(AC_VI);
540 txopLimit = edca->GetTxopLimit(linkId);
541 edcaParameters.SetViAci(2);
542 edcaParameters.SetViCWmin(edca->GetMinCw(linkId));
543 edcaParameters.SetViCWmax(edca->GetMaxCw(linkId));
544 edcaParameters.SetViAifsn(edca->GetAifsn(linkId));
545 edcaParameters.SetViTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
546
547 edca = GetQosTxop(AC_VO);
548 txopLimit = edca->GetTxopLimit(linkId);
549 edcaParameters.SetVoAci(3);
550 edcaParameters.SetVoCWmin(edca->GetMinCw(linkId));
551 edcaParameters.SetVoCWmax(edca->GetMaxCw(linkId));
552 edcaParameters.SetVoAifsn(edca->GetAifsn(linkId));
553 edcaParameters.SetVoTxopLimit(static_cast<uint16_t>(txopLimit.GetMicroSeconds() / 32));
554
555 edcaParameters.SetQosInfo(0);
556
557 return edcaParameters;
558}
559
560std::optional<MuEdcaParameterSet>
562{
563 NS_LOG_FUNCTION(this);
565
566 Ptr<HeConfiguration> heConfiguration = GetHeConfiguration();
567 NS_ASSERT(heConfiguration);
568
569 MuEdcaParameterSet muEdcaParameters;
570 muEdcaParameters.SetQosInfo(0);
571
572 UintegerValue uintegerValue;
573 TimeValue timeValue;
574
575 heConfiguration->GetAttribute("MuBeAifsn", uintegerValue);
576 muEdcaParameters.SetMuAifsn(AC_BE, uintegerValue.Get());
577 heConfiguration->GetAttribute("MuBeCwMin", uintegerValue);
578 muEdcaParameters.SetMuCwMin(AC_BE, uintegerValue.Get());
579 heConfiguration->GetAttribute("MuBeCwMax", uintegerValue);
580 muEdcaParameters.SetMuCwMax(AC_BE, uintegerValue.Get());
581 heConfiguration->GetAttribute("BeMuEdcaTimer", timeValue);
582 muEdcaParameters.SetMuEdcaTimer(AC_BE, timeValue.Get());
583
584 heConfiguration->GetAttribute("MuBkAifsn", uintegerValue);
585 muEdcaParameters.SetMuAifsn(AC_BK, uintegerValue.Get());
586 heConfiguration->GetAttribute("MuBkCwMin", uintegerValue);
587 muEdcaParameters.SetMuCwMin(AC_BK, uintegerValue.Get());
588 heConfiguration->GetAttribute("MuBkCwMax", uintegerValue);
589 muEdcaParameters.SetMuCwMax(AC_BK, uintegerValue.Get());
590 heConfiguration->GetAttribute("BkMuEdcaTimer", timeValue);
591 muEdcaParameters.SetMuEdcaTimer(AC_BK, timeValue.Get());
592
593 heConfiguration->GetAttribute("MuViAifsn", uintegerValue);
594 muEdcaParameters.SetMuAifsn(AC_VI, uintegerValue.Get());
595 heConfiguration->GetAttribute("MuViCwMin", uintegerValue);
596 muEdcaParameters.SetMuCwMin(AC_VI, uintegerValue.Get());
597 heConfiguration->GetAttribute("MuViCwMax", uintegerValue);
598 muEdcaParameters.SetMuCwMax(AC_VI, uintegerValue.Get());
599 heConfiguration->GetAttribute("ViMuEdcaTimer", timeValue);
600 muEdcaParameters.SetMuEdcaTimer(AC_VI, timeValue.Get());
601
602 heConfiguration->GetAttribute("MuVoAifsn", uintegerValue);
603 muEdcaParameters.SetMuAifsn(AC_VO, uintegerValue.Get());
604 heConfiguration->GetAttribute("MuVoCwMin", uintegerValue);
605 muEdcaParameters.SetMuCwMin(AC_VO, uintegerValue.Get());
606 heConfiguration->GetAttribute("MuVoCwMax", uintegerValue);
607 muEdcaParameters.SetMuCwMax(AC_VO, uintegerValue.Get());
608 heConfiguration->GetAttribute("VoMuEdcaTimer", timeValue);
609 muEdcaParameters.SetMuEdcaTimer(AC_VO, timeValue.Get());
610
611 // The timers of the MU EDCA Parameter Set must be either all zero or all
612 // non-zero. The information element is advertised if all timers are non-zero
613 auto timerNotNull = [&muEdcaParameters](uint8_t aci) {
614 return !muEdcaParameters.GetMuEdcaTimer(aci).IsZero();
615 };
616 auto aci = {0, 1, 2, 3};
617 if (std::all_of(aci.begin(), aci.end(), timerNotNull))
618 {
619 return muEdcaParameters;
620 }
621
622 NS_ABORT_MSG_UNLESS(std::none_of(aci.begin(), aci.end(), timerNotNull),
623 "MU EDCA Timers must be all zero if the IE is not advertised.");
624
625 return std::nullopt;
626}
627
628std::optional<ReducedNeighborReport>
630{
631 NS_LOG_FUNCTION(this << +linkId);
632
633 if (GetNLinks() <= 1)
634 {
635 return std::nullopt;
636 }
637
640
641 for (uint8_t index = 0; index < GetNLinks(); ++index)
642 {
643 if (index != linkId) // all links but the one used to send this Beacon frame
644 {
645 rnr.AddNbrApInfoField();
646 std::size_t nbrId = rnr.GetNNbrApInfoFields() - 1;
648 rnr.AddTbttInformationField(nbrId);
649 rnr.SetBssid(nbrId, 0, GetLink(index).feManager->GetAddress());
650 rnr.SetShortSsid(nbrId, 0, 0);
651 rnr.SetBssParameters(nbrId, 0, 0);
652 rnr.SetPsd20MHz(nbrId, 0, 0);
653 rnr.SetMldParameters(nbrId, 0, 0, index, 0);
654 }
655 }
656 return rnr;
657}
658
660ApWifiMac::GetMultiLinkElement(uint8_t linkId, WifiMacType frameType, const Mac48Address& to)
661{
662 NS_LOG_FUNCTION(this << +linkId << frameType << to);
663 NS_ABORT_IF(GetNLinks() == 1);
664
667 mle.SetLinkIdInfo(linkId);
669
670 // if the Multi-Link Element is being inserted in a (Re)Association Response frame
671 // and the remote station is affiliated with an MLD, try multi-link setup
672 if (auto staMldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(to);
673 (frameType == WIFI_MAC_MGT_ASSOCIATION_RESPONSE ||
675 staMldAddress.has_value())
676 {
677 for (uint8_t i = 0; i < GetNLinks(); i++)
678 {
679 auto remoteStationManager = GetWifiRemoteStationManager(i);
680 if (auto staAddress = remoteStationManager->GetAffiliatedStaAddress(*staMldAddress);
681 i != linkId && staAddress.has_value() &&
682 (remoteStationManager->IsWaitAssocTxOk(*staAddress) ||
683 remoteStationManager->IsAssocRefused(*staAddress)))
684 {
685 // For each requested link in addition to the link on which the
686 // (Re)Association Response frame is transmitted, the Link Info field
687 // of the Basic Multi-Link element carried in the (Re)Association
688 // Response frame shall contain the corresponding Per-STA Profile
689 // subelement(s) (Sec. 35.3.5.4 of 802.11be D2.0)
691 auto& perStaProfile = mle.GetPerStaProfile(mle.GetNPerStaProfileSubelements() - 1);
692 // The Link ID subfield of the STA Control field of the Per-STA Profile
693 // subelement for the AP corresponding to a link is set to the link ID
694 // of the AP affiliated with the AP MLD that is operating on that link.
695 perStaProfile.SetLinkId(i);
696 perStaProfile.SetCompleteProfile();
697 // For each Per-STA Profile subelement included in the Link Info field,
698 // the Complete Profile subfield of the STA Control field shall be set to 1
699 perStaProfile.SetStaMacAddress(GetFrameExchangeManager(i)->GetAddress());
700 perStaProfile.SetAssocResponse(GetAssocResp(*staAddress, i));
701 }
702 }
703 }
704
705 return mle;
706}
707
709ApWifiMac::GetHtOperation(uint8_t linkId) const
710{
711 NS_LOG_FUNCTION(this << +linkId);
713 HtOperation operation;
714 auto phy = GetWifiPhy(linkId);
715 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
716
717 operation.SetPrimaryChannel(phy->GetPrimaryChannelNumber(20));
718 operation.SetRifsMode(false);
719 operation.SetNonGfHtStasPresent(true);
720 if (phy->GetChannelWidth() > 20)
721 {
722 operation.SetSecondaryChannelOffset(1);
723 operation.SetStaChannelWidth(1);
724 }
725 if (GetLink(linkId).numNonHtStations == 0)
726 {
728 }
729 else
730 {
732 }
733 uint64_t maxSupportedRate = 0; // in bit/s
734 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HT))
735 {
736 uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
737 NS_ASSERT(nss > 0 && nss < 5);
738 uint64_t dataRate =
739 mcs.GetDataRate(phy->GetChannelWidth(),
740 GetHtConfiguration()->GetShortGuardIntervalSupported() ? 400 : 800,
741 nss);
742 if (dataRate > maxSupportedRate)
743 {
744 maxSupportedRate = dataRate;
745 NS_LOG_DEBUG("Updating maxSupportedRate to " << maxSupportedRate);
746 }
747 }
748 uint8_t maxSpatialStream = phy->GetMaxSupportedTxSpatialStreams();
749 auto mcsList = phy->GetMcsList(WIFI_MOD_CLASS_HT);
750 uint8_t nMcs = mcsList.size();
751 for (const auto& sta : GetLink(linkId).staList)
752 {
753 if (remoteStationManager->GetHtSupported(sta.second))
754 {
755 uint64_t maxSupportedRateByHtSta = 0; // in bit/s
756 auto itMcs = mcsList.begin();
757 for (uint8_t j = 0;
758 j < (std::min(nMcs, remoteStationManager->GetNMcsSupported(sta.second)));
759 j++)
760 {
761 WifiMode mcs = *itMcs++;
762 uint8_t nss = (mcs.GetMcsValue() / 8) + 1;
763 NS_ASSERT(nss > 0 && nss < 5);
764 uint64_t dataRate = mcs.GetDataRate(
765 remoteStationManager->GetChannelWidthSupported(sta.second),
766 remoteStationManager->GetShortGuardIntervalSupported(sta.second) ? 400 : 800,
767 nss);
768 if (dataRate > maxSupportedRateByHtSta)
769 {
770 maxSupportedRateByHtSta = dataRate;
771 }
772 }
773 if (maxSupportedRateByHtSta < maxSupportedRate)
774 {
775 maxSupportedRate = maxSupportedRateByHtSta;
776 }
777 if (remoteStationManager->GetNMcsSupported(sta.second) < nMcs)
778 {
779 nMcs = remoteStationManager->GetNMcsSupported(sta.second);
780 }
781 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
782 {
783 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
784 }
785 }
786 }
788 static_cast<uint16_t>(maxSupportedRate / 1e6)); // in Mbit/s
789 operation.SetTxMcsSetDefined(nMcs > 0);
790 operation.SetTxMaxNSpatialStreams(maxSpatialStream);
791 // To be filled in once supported
792 operation.SetObssNonHtStasPresent(0);
793 operation.SetDualBeacon(0);
794 operation.SetDualCtsProtection(0);
795 operation.SetStbcBeacon(0);
797 operation.SetPcoActive(0);
798 operation.SetPhase(0);
799 operation.SetRxMcsBitmask(0);
800 operation.SetTxRxMcsSetUnequal(0);
801 operation.SetTxUnequalModulation(0);
802
803 return operation;
804}
805
807ApWifiMac::GetVhtOperation(uint8_t linkId) const
808{
809 NS_LOG_FUNCTION(this << +linkId);
810 NS_ASSERT(GetVhtSupported(linkId));
811 VhtOperation operation;
812 auto phy = GetWifiPhy(linkId);
813 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
814
815 const uint16_t bssBandwidth = phy->GetChannelWidth();
816 // Set to 0 for 20 MHz or 40 MHz BSS bandwidth.
817 // Set to 1 for 80 MHz, 160 MHz or 80+80 MHz BSS bandwidth.
818 operation.SetChannelWidth((bssBandwidth > 40) ? 1 : 0);
819 // For 20, 40, or 80 MHz BSS bandwidth, indicates the channel center frequency
820 // index for the 20, 40, or 80 MHz channel on which the VHT BSS operates.
821 // For 160 MHz BSS bandwidth and the Channel Width subfield equal to 1,
822 // indicates the channel center frequency index of the 80 MHz channel
823 // segment that contains the primary channel.
825 (bssBandwidth == 160)
826 ? phy->GetOperatingChannel().GetPrimaryChannelNumber(80, phy->GetStandard())
827 : phy->GetChannelNumber());
828 // For a 20, 40, or 80 MHz BSS bandwidth, this subfield is set to 0.
829 // For a 160 MHz BSS bandwidth and the Channel Width subfield equal to 1,
830 // indicates the channel center frequency index of the 160 MHz channel on
831 // which the VHT BSS operates.
832 operation.SetChannelCenterFrequencySegment1((bssBandwidth == 160) ? phy->GetChannelNumber()
833 : 0);
834 uint8_t maxSpatialStream = phy->GetMaxSupportedRxSpatialStreams();
835 for (const auto& sta : GetLink(linkId).staList)
836 {
837 if (remoteStationManager->GetVhtSupported(sta.second))
838 {
839 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
840 {
841 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
842 }
843 }
844 }
845 for (uint8_t nss = 1; nss <= maxSpatialStream; nss++)
846 {
847 uint8_t maxMcs =
848 9; // TBD: hardcode to 9 for now since we assume all MCS values are supported
849 operation.SetMaxVhtMcsPerNss(nss, maxMcs);
850 }
851
852 return operation;
853}
854
856ApWifiMac::GetHeOperation(uint8_t linkId) const
857{
858 NS_LOG_FUNCTION(this << +linkId);
860 HeOperation operation;
861 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
862
863 uint8_t maxSpatialStream = GetWifiPhy(linkId)->GetMaxSupportedRxSpatialStreams();
864 for (const auto& sta : GetLink(linkId).staList)
865 {
866 if (remoteStationManager->GetHeSupported(sta.second))
867 {
868 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
869 {
870 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
871 }
872 }
873 }
874 for (uint8_t nss = 1; nss <= maxSpatialStream; nss++)
875 {
876 operation.SetMaxHeMcsPerNss(
877 nss,
878 11); // TBD: hardcode to 11 for now since we assume all MCS values are supported
879 }
880 operation.SetBssColor(GetHeConfiguration()->GetBssColor());
881
882 return operation;
883}
884
886ApWifiMac::GetEhtOperation(uint8_t linkId) const
887{
888 NS_LOG_FUNCTION(this << +linkId);
890 EhtOperation operation;
891 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
892
893 auto maxSpatialStream = GetWifiPhy(linkId)->GetMaxSupportedRxSpatialStreams();
894 for (const auto& sta : GetLink(linkId).staList)
895 {
896 if (remoteStationManager->GetEhtSupported(sta.second))
897 {
898 if (remoteStationManager->GetNumberOfSupportedStreams(sta.second) < maxSpatialStream)
899 {
900 maxSpatialStream = remoteStationManager->GetNumberOfSupportedStreams(sta.second);
901 }
902 }
903 }
904 operation.SetMaxRxNss(maxSpatialStream, 0, WIFI_EHT_MAX_MCS_INDEX);
905 operation.SetMaxTxNss(maxSpatialStream, 0, WIFI_EHT_MAX_MCS_INDEX);
906 return operation;
907}
908
909void
911{
912 NS_LOG_FUNCTION(this << to << +linkId);
913 WifiMacHeader hdr;
915 hdr.SetAddr1(to);
916 hdr.SetAddr2(GetLink(linkId).feManager->GetAddress());
917 hdr.SetAddr3(GetLink(linkId).feManager->GetAddress());
918 hdr.SetDsNotFrom();
919 hdr.SetDsNotTo();
920 Ptr<Packet> packet = Create<Packet>();
922 probe.SetSsid(GetSsid());
924 probe.SetBeaconIntervalUs(GetBeaconInterval().GetMicroSeconds());
925 probe.SetCapabilities(GetCapabilities(linkId));
927 GetLink(linkId).shortPreambleEnabled);
929 GetLink(linkId).shortSlotTimeEnabled);
930 if (GetDsssSupported(linkId))
931 {
933 }
934 if (GetErpSupported(linkId))
935 {
937 }
938 if (GetQosSupported())
939 {
941 }
942 if (GetHtSupported())
943 {
946 probe.SetHtOperation(GetHtOperation(linkId));
947 }
949 {
951 probe.SetVhtOperation(GetVhtOperation(linkId));
952 }
953 if (GetHeSupported())
954 {
956 probe.SetHeOperation(GetHeOperation(linkId));
957 if (auto muEdcaParameterSet = GetMuEdcaParameterSet(); muEdcaParameterSet.has_value())
958 {
959 probe.SetMuEdcaParameterSet(std::move(*muEdcaParameterSet));
960 }
961 }
962 if (GetEhtSupported())
963 {
965 probe.SetEhtOperation(GetEhtOperation(linkId));
966
967 if (GetNLinks() > 1)
968 {
969 /*
970 * If an AP is affiliated with an AP MLD and does not correspond to a nontransmitted
971 * BSSID, then the Beacon and Probe Response frames transmitted by the AP shall
972 * include a TBTT Information field in a Reduced Neighbor Report element with the
973 * TBTT Information Length field set to 16 or higher, for each of the other APs
974 * (if any) affiliated with the same AP MLD. (Sec. 35.3.4.1 of 802.11be D2.1.1)
975 */
976 if (auto rnr = GetReducedNeighborReport(linkId); rnr.has_value())
977 {
978 probe.SetReducedNeighborReport(std::move(*rnr));
979 }
980 /*
981 * If an AP affiliated with an AP MLD is not in a multiple BSSID set [..], the AP
982 * shall include, in a Beacon frame or a Probe Response frame, which is not a
983 * Multi-Link probe response, only the Common Info field of the Basic Multi-Link
984 * element for the AP MLD unless conditions in 35.3.11 (Multi-link procedures for
985 * channel switching, extended channel switching, and channel quieting) are
986 * satisfied. (Sec. 35.3.4.4 of 802.11be D2.1.1)
987 */
989 }
990 }
991 packet->AddHeader(probe);
992
993 if (!GetQosSupported())
994 {
995 GetTxop()->Queue(packet, hdr);
996 }
997 // "A QoS STA that transmits a Management frame determines access category used
998 // for medium access in transmission of the Management frame as follows
999 // (If dot11QMFActivated is false or not present)
1000 // — If the Management frame is individually addressed to a non-QoS STA, category
1001 // AC_BE should be selected.
1002 // — If category AC_BE was not selected by the previous step, category AC_VO
1003 // shall be selected." (Sec. 10.2.3.2 of 802.11-2020)
1004 else if (!GetWifiRemoteStationManager(linkId)->GetQosSupported(to))
1005 {
1006 GetBEQueue()->Queue(packet, hdr);
1007 }
1008 else
1009 {
1010 GetVOQueue()->Queue(packet, hdr);
1011 }
1012}
1013
1016{
1018 StatusCode code;
1019 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
1020 if (remoteStationManager->IsWaitAssocTxOk(to))
1021 {
1022 code.SetSuccess();
1023 }
1024 else
1025 {
1026 NS_ABORT_IF(!remoteStationManager->IsAssocRefused(to));
1027 // reset state
1028 remoteStationManager->RecordDisassociated(to);
1029 code.SetFailure();
1030 }
1031 assoc.SetSupportedRates(GetSupportedRates(linkId));
1032 assoc.SetStatusCode(code);
1033 assoc.SetCapabilities(GetCapabilities(linkId));
1034 if (GetErpSupported(linkId))
1035 {
1036 assoc.SetErpInformation(GetErpInformation(linkId));
1037 }
1038 if (GetQosSupported())
1039 {
1041 }
1042 if (GetHtSupported())
1043 {
1045 assoc.SetHtCapabilities(GetHtCapabilities(linkId));
1046 assoc.SetHtOperation(GetHtOperation(linkId));
1047 }
1048 if (GetVhtSupported(linkId))
1049 {
1051 assoc.SetVhtOperation(GetVhtOperation(linkId));
1052 }
1053 if (GetHeSupported())
1054 {
1055 assoc.SetHeCapabilities(GetHeCapabilities(linkId));
1056 assoc.SetHeOperation(GetHeOperation(linkId));
1057 if (auto muEdcaParameterSet = GetMuEdcaParameterSet(); muEdcaParameterSet.has_value())
1058 {
1059 assoc.SetMuEdcaParameterSet(std::move(*muEdcaParameterSet));
1060 }
1061 }
1062 if (GetEhtSupported())
1063 {
1065 assoc.SetEhtOperation(GetEhtOperation(linkId));
1066 }
1067 return assoc;
1068}
1069
1072 const Mac48Address& to,
1073 uint8_t linkId)
1074{
1075 // find all the links to setup (i.e., those for which status code is success)
1076 std::map<uint8_t /* link ID */, Mac48Address> linkIdStaAddrMap;
1077
1078 if (assoc.GetStatusCode().IsSuccess())
1079 {
1080 linkIdStaAddrMap[linkId] = to;
1081 }
1082
1083 if (const auto& mle = assoc.GetMultiLinkElement())
1084 {
1085 const auto staMldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(to);
1086 NS_ABORT_MSG_IF(!staMldAddress.has_value(),
1087 "Sending a Multi-Link Element to a single link device");
1088 for (std::size_t idx = 0; idx < mle->GetNPerStaProfileSubelements(); idx++)
1089 {
1090 auto& perStaProfile = mle->GetPerStaProfile(idx);
1091 if (perStaProfile.HasAssocResponse() &&
1092 perStaProfile.GetAssocResponse().GetStatusCode().IsSuccess())
1093 {
1094 uint8_t otherLinkId = perStaProfile.GetLinkId();
1095 auto staAddress = GetWifiRemoteStationManager(otherLinkId)
1096 ->GetAffiliatedStaAddress(*staMldAddress);
1097 NS_ABORT_MSG_IF(!staAddress.has_value(),
1098 "No STA to associate with on link " << +otherLinkId);
1099 const auto [it, inserted] = linkIdStaAddrMap.insert({otherLinkId, *staAddress});
1100 NS_ABORT_MSG_IF(!inserted,
1101 "More than one Association Response to MLD "
1102 << *staMldAddress << " on link ID " << +otherLinkId);
1103 }
1104 }
1105 }
1106
1107 return linkIdStaAddrMap;
1108}
1109
1110void
1112{
1113 if (linkIdStaAddrMap.empty())
1114 {
1115 // no link to setup, nothing to do
1116 return;
1117 }
1118
1119 // check if AIDs are already allocated to the STAs that are associating
1120 std::set<uint16_t> aids;
1121 std::map<uint8_t /* link ID */, uint16_t /* AID */> linkIdAidMap;
1122
1123 for (const auto& [id, staAddr] : linkIdStaAddrMap)
1124 {
1125 for (const auto& [aid, addr] : GetLink(id).staList)
1126 {
1127 if (addr == staAddr)
1128 {
1129 aids.insert(aid);
1130 linkIdAidMap[id] = aid;
1131 break;
1132 }
1133 }
1134 }
1135
1136 // check if an AID already assigned to an STA can be assigned to all other STAs
1137 // affiliated with the non-AP MLD we are associating with
1138 while (!aids.empty())
1139 {
1140 const uint16_t aid = *aids.begin();
1141 bool good = true;
1142
1143 for (const auto& [id, staAddr] : linkIdStaAddrMap)
1144 {
1145 if (auto it = GetLink(id).staList.find(aid);
1146 it != GetLink(id).staList.end() && it->second != staAddr)
1147 {
1148 // the AID is already assigned to an STA other than the one affiliated
1149 // with the non-AP MLD we are associating with
1150 aids.erase(aids.begin());
1151 good = false;
1152 break;
1153 }
1154 }
1155
1156 if (good)
1157 {
1158 break;
1159 }
1160 }
1161
1162 uint16_t aid = 0;
1163
1164 if (!aids.empty())
1165 {
1166 // one of the AIDs already assigned to an STA can be assigned to all the other
1167 // STAs affiliated with the non-AP MLD we are associating with
1168 aid = *aids.begin();
1169 }
1170 else
1171 {
1172 std::list<uint8_t> linkIds;
1173 std::transform(linkIdStaAddrMap.cbegin(),
1174 linkIdStaAddrMap.cend(),
1175 std::back_inserter(linkIds),
1176 [](auto&& linkIdStaAddrPair) { return linkIdStaAddrPair.first; });
1177 aid = GetNextAssociationId(linkIds);
1178 }
1179
1180 // store the MLD or link address in the AID-to-address map
1181 const auto& [linkId, staAddr] = *linkIdStaAddrMap.cbegin();
1183 GetWifiRemoteStationManager(linkId)->GetMldAddress(staAddr).value_or(staAddr);
1184
1185 for (const auto& [id, staAddr] : linkIdStaAddrMap)
1186 {
1187 auto remoteStationManager = GetWifiRemoteStationManager(id);
1188 auto& link = GetLink(id);
1189
1190 if (auto it = linkIdAidMap.find(id); it == linkIdAidMap.end() || it->second != aid)
1191 {
1192 // the STA on this link has no AID assigned or has a different AID assigned
1193 link.staList.insert(std::make_pair(aid, staAddr));
1194 m_assocLogger(aid, staAddr);
1195 remoteStationManager->SetAssociationId(staAddr, aid);
1196
1197 if (it == linkIdAidMap.end())
1198 {
1199 // the STA on this link had no AID assigned
1200 if (remoteStationManager->GetDsssSupported(staAddr) &&
1201 !remoteStationManager->GetErpOfdmSupported(staAddr))
1202 {
1203 link.numNonErpStations++;
1204 }
1205 if (!remoteStationManager->GetHtSupported(staAddr))
1206 {
1207 link.numNonHtStations++;
1208 }
1211 }
1212 else
1213 {
1214 // the STA on this link had a different AID assigned
1215 link.staList.erase(it->second); // free the previous AID
1216 }
1217 }
1218 }
1219
1220 // set the AID in all the Association Responses. NOTE that the Association
1221 // Responses included in the Per-STA Profile Subelements of the Multi-Link
1222 // Element must not contain the AID field. We set the AID field in such
1223 // Association Responses anyway, in order to ease future implementation of
1224 // the inheritance mechanism.
1225 if (assoc.GetStatusCode().IsSuccess())
1226 {
1227 assoc.SetAssociationId(aid);
1228 }
1229 if (const auto& mle = assoc.GetMultiLinkElement())
1230 {
1231 for (std::size_t idx = 0; idx < mle->GetNPerStaProfileSubelements(); idx++)
1232 {
1233 if (const auto& perStaProfile = mle->GetPerStaProfile(idx);
1234 perStaProfile.HasAssocResponse() &&
1235 perStaProfile.GetAssocResponse().GetStatusCode().IsSuccess())
1236 {
1237 perStaProfile.GetAssocResponse().SetAssociationId(aid);
1238 }
1239 }
1240 }
1241}
1242
1243void
1244ApWifiMac::SendAssocResp(Mac48Address to, bool isReassoc, uint8_t linkId)
1245{
1246 NS_LOG_FUNCTION(this << to << isReassoc << +linkId);
1247 WifiMacHeader hdr;
1250 hdr.SetAddr1(to);
1253 hdr.SetDsNotFrom();
1254 hdr.SetDsNotTo();
1255
1256 MgtAssocResponseHeader assoc = GetAssocResp(to, linkId);
1257
1258 // The AP that is affiliated with the AP MLD and that responds to an (Re)Association
1259 // Request frame that carries a Basic Multi-Link element shall include a Basic
1260 // Multi-Link element in the (Re)Association Response frame that it transmits
1261 // (Sec. 35.3.5.4 of 802.11be D2.0)
1262 // If the STA included a Multi-Link Element in the (Re)Association Request, we
1263 // stored its MLD address in the remote station manager
1264 if (GetNLinks() > 1 && GetWifiRemoteStationManager(linkId)->GetMldAddress(to).has_value())
1265 {
1266 assoc.SetMultiLinkElement(GetMultiLinkElement(linkId, hdr.GetType(), to));
1267 }
1268
1269 auto linkIdStaAddrMap = GetLinkIdStaAddrMap(assoc, to, linkId);
1270 SetAid(assoc, linkIdStaAddrMap);
1271
1272 if (GetNLinks() > 1)
1273 {
1274 ConfigQueueScheduler(linkIdStaAddrMap, to, linkId);
1275 }
1276
1277 Ptr<Packet> packet = Create<Packet>();
1278 packet->AddHeader(assoc);
1279
1280 if (!GetQosSupported())
1281 {
1282 GetTxop()->Queue(packet, hdr);
1283 }
1284 // "A QoS STA that transmits a Management frame determines access category used
1285 // for medium access in transmission of the Management frame as follows
1286 // (If dot11QMFActivated is false or not present)
1287 // — If the Management frame is individually addressed to a non-QoS STA, category
1288 // AC_BE should be selected.
1289 // — If category AC_BE was not selected by the previous step, category AC_VO
1290 // shall be selected." (Sec. 10.2.3.2 of 802.11-2020)
1291 else if (!GetWifiRemoteStationManager(linkId)->GetQosSupported(to))
1292 {
1293 GetBEQueue()->Queue(packet, hdr);
1294 }
1295 else
1296 {
1297 GetVOQueue()->Queue(packet, hdr);
1298 }
1299}
1300
1301void
1303 const Mac48Address& to,
1304 uint8_t linkId)
1305{
1306 NS_LOG_FUNCTION(this << to << +linkId);
1307
1308 // get a list of the IDs of the links to setup
1309 std::list<uint8_t> linkIds;
1310 std::transform(linkIdStaAddrMap.cbegin(),
1311 linkIdStaAddrMap.cend(),
1312 std::back_inserter(linkIds),
1313 [](auto&& linkIdStaAddrPair) { return linkIdStaAddrPair.first; });
1314
1315 // get the MLD address of the STA, if affiliated with a non-AP MLD, or the STA address
1316 auto staAddr = to;
1317 if (auto mldAddr = GetWifiRemoteStationManager(linkId)->GetMldAddress(to))
1318 {
1319 staAddr = *mldAddr;
1320 }
1321
1322 // configure the queue scheduler to only use the links that have been setup for
1323 // transmissions to this station
1324 for (const auto& [acIndex, wifiAc] : wifiAcList)
1325 {
1326 for (auto tid : {wifiAc.GetLowTid(), wifiAc.GetHighTid()})
1327 {
1328 WifiContainerQueueId queueId(WIFI_QOSDATA_UNICAST_QUEUE, staAddr, tid);
1329 m_scheduler->SetLinkIds(acIndex, queueId, linkIds);
1330 }
1331 }
1332}
1333
1334void
1336{
1337 NS_LOG_FUNCTION(this << +linkId);
1338 auto& link = GetLink(linkId);
1339 WifiMacHeader hdr;
1342 hdr.SetAddr2(link.feManager->GetAddress());
1343 hdr.SetAddr3(link.feManager->GetAddress());
1344 hdr.SetDsNotFrom();
1345 hdr.SetDsNotTo();
1346 Ptr<Packet> packet = Create<Packet>();
1347 MgtBeaconHeader beacon;
1348 beacon.SetSsid(GetSsid());
1349 beacon.SetSupportedRates(GetSupportedRates(linkId));
1350 beacon.SetBeaconIntervalUs(GetBeaconInterval().GetMicroSeconds());
1351 beacon.SetCapabilities(GetCapabilities(linkId));
1352 GetWifiRemoteStationManager(linkId)->SetShortPreambleEnabled(link.shortPreambleEnabled);
1353 GetWifiRemoteStationManager(linkId)->SetShortSlotTimeEnabled(link.shortSlotTimeEnabled);
1354 if (GetDsssSupported(linkId))
1355 {
1357 }
1358 if (GetErpSupported(linkId))
1359 {
1360 beacon.SetErpInformation(GetErpInformation(linkId));
1361 }
1362 if (GetQosSupported())
1363 {
1365 }
1366 if (GetHtSupported())
1367 {
1369 beacon.SetHtCapabilities(GetHtCapabilities(linkId));
1370 beacon.SetHtOperation(GetHtOperation(linkId));
1371 }
1372 if (GetVhtSupported(linkId))
1373 {
1374 beacon.SetVhtCapabilities(GetVhtCapabilities(linkId));
1375 beacon.SetVhtOperation(GetVhtOperation(linkId));
1376 }
1377 if (GetHeSupported())
1378 {
1379 beacon.SetHeCapabilities(GetHeCapabilities(linkId));
1380 beacon.SetHeOperation(GetHeOperation(linkId));
1381 if (auto muEdcaParameterSet = GetMuEdcaParameterSet(); muEdcaParameterSet.has_value())
1382 {
1383 beacon.SetMuEdcaParameterSet(std::move(*muEdcaParameterSet));
1384 }
1385 }
1386 if (GetEhtSupported())
1387 {
1388 beacon.SetEhtCapabilities(GetEhtCapabilities(linkId));
1389 beacon.SetEhtOperation(GetEhtOperation(linkId));
1390
1391 if (GetNLinks() > 1)
1392 {
1393 /*
1394 * If an AP is affiliated with an AP MLD and does not correspond to a nontransmitted
1395 * BSSID, then the Beacon and Probe Response frames transmitted by the AP shall
1396 * include a TBTT Information field in a Reduced Neighbor Report element with the
1397 * TBTT Information Length field set to 16 or higher, for each of the other APs
1398 * (if any) affiliated with the same AP MLD. (Sec. 35.3.4.1 of 802.11be D2.1.1)
1399 */
1400 if (auto rnr = GetReducedNeighborReport(linkId); rnr.has_value())
1401 {
1402 beacon.SetReducedNeighborReport(std::move(*rnr));
1403 }
1404 /*
1405 * If an AP affiliated with an AP MLD is not in a multiple BSSID set [..], the AP
1406 * shall include, in a Beacon frame or a Probe Response frame, which is not a
1407 * Multi-Link probe response, only the Common Info field of the Basic Multi-Link
1408 * element for the AP MLD unless conditions in 35.3.11 (Multi-link procedures for
1409 * channel switching, extended channel switching, and channel quieting) are
1410 * satisfied. (Sec. 35.3.4.4 of 802.11be D2.1.1)
1411 */
1413 }
1414 }
1415 packet->AddHeader(beacon);
1416
1417 // The beacon has it's own special queue, so we load it in there
1418 m_beaconTxop->Queue(packet, hdr);
1419 link.beaconEvent =
1421
1422 // If a STA that does not support Short Slot Time associates,
1423 // the AP shall use long slot time beginning at the first Beacon
1424 // subsequent to the association of the long slot time STA.
1425 if (GetErpSupported(linkId))
1426 {
1427 if (link.shortSlotTimeEnabled)
1428 {
1429 // Enable short slot time
1430 GetWifiPhy(linkId)->SetSlot(MicroSeconds(9));
1431 }
1432 else
1433 {
1434 // Disable short slot time
1435 GetWifiPhy(linkId)->SetSlot(MicroSeconds(20));
1436 }
1437 }
1438}
1439
1440void
1442{
1443 NS_LOG_FUNCTION(this << *mpdu);
1444 const WifiMacHeader& hdr = mpdu->GetHeader();
1445
1446 if (hdr.IsAssocResp() || hdr.IsReassocResp())
1447 {
1448 auto linkId = GetLinkIdByAddress(hdr.GetAddr2());
1449 NS_ABORT_MSG_IF(!linkId.has_value(), "No link ID matching the TA");
1450
1452 {
1453 NS_LOG_DEBUG("AP=" << hdr.GetAddr2() << " associated with STA=" << hdr.GetAddr1());
1455 }
1456
1457 if (auto staMldAddress =
1459 staMldAddress.has_value())
1460 {
1461 // the STA is affiliated with an MLD
1462 for (uint8_t i = 0; i < GetNLinks(); i++)
1463 {
1464 auto stationManager = GetWifiRemoteStationManager(i);
1465 if (auto staAddress = stationManager->GetAffiliatedStaAddress(*staMldAddress);
1466 staAddress.has_value() && i != *linkId &&
1467 stationManager->IsWaitAssocTxOk(*staAddress))
1468 {
1470 << " associated with STA=" << *staAddress);
1471 stationManager->RecordGotAssocTxOk(*staAddress);
1472 }
1473 }
1474 }
1475 }
1476}
1477
1478void
1480{
1481 NS_LOG_FUNCTION(this << +timeoutReason << *mpdu);
1482 const WifiMacHeader& hdr = mpdu->GetHeader();
1483
1484 if (hdr.IsAssocResp() || hdr.IsReassocResp())
1485 {
1486 auto linkId = GetLinkIdByAddress(hdr.GetAddr2());
1487 NS_ABORT_MSG_IF(!linkId.has_value(), "No link ID matching the TA");
1488
1490 {
1491 NS_LOG_DEBUG("AP=" << hdr.GetAddr2()
1492 << " association failed with STA=" << hdr.GetAddr1());
1494 }
1495
1496 if (auto staMldAddress =
1498 staMldAddress.has_value())
1499 {
1500 // the STA is affiliated with an MLD
1501 for (uint8_t i = 0; i < GetNLinks(); i++)
1502 {
1503 auto stationManager = GetWifiRemoteStationManager(i);
1504 if (auto staAddress = stationManager->GetAffiliatedStaAddress(*staMldAddress);
1505 staAddress.has_value() && i != *linkId &&
1506 stationManager->IsWaitAssocTxOk(*staAddress))
1507 {
1509 << " association failed with STA=" << *staAddress);
1510 stationManager->RecordGotAssocTxFailed(*staAddress);
1511 }
1512 }
1513 }
1514 }
1515}
1516
1517std::optional<uint8_t>
1519{
1520 for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++)
1521 {
1522 if (GetWifiRemoteStationManager(linkId)->IsAssociated(address))
1523 {
1524 return linkId;
1525 }
1526 }
1527 NS_LOG_DEBUG(address << " is not associated");
1528 return std::nullopt;
1529}
1530
1533{
1534 auto linkId = IsAssociated(remoteAddr);
1535 NS_ASSERT_MSG(linkId, remoteAddr << " is not associated");
1536 return GetFrameExchangeManager(*linkId)->GetAddress();
1537}
1538
1539std::optional<Mac48Address>
1541{
1542 if (const auto staIt = m_aidToMldOrLinkAddress.find(aid);
1543 staIt != m_aidToMldOrLinkAddress.cend())
1544 {
1545 return staIt->second;
1546 }
1547 return std::nullopt;
1548}
1549
1550void
1552{
1553 NS_LOG_FUNCTION(this << *mpdu << +linkId);
1554 // consider the MAC header of the original MPDU (makes a difference for data frames only)
1555 const WifiMacHeader* hdr = &mpdu->GetOriginal()->GetHeader();
1556 Ptr<const Packet> packet = mpdu->GetPacket();
1557 Mac48Address from = hdr->GetAddr2();
1558 if (hdr->IsData())
1559 {
1560 std::optional<uint8_t> apLinkId;
1561 if (!hdr->IsFromDs() && hdr->IsToDs() &&
1562 (apLinkId = IsAssociated(mpdu->GetHeader().GetAddr2())) &&
1563 mpdu->GetHeader().GetAddr1() == GetFrameExchangeManager(*apLinkId)->GetAddress())
1564 {
1565 Mac48Address to = hdr->GetAddr3();
1566 // Address3 can be our MLD address (e.g., this is an MPDU containing a single MSDU
1567 // addressed to us) or a BSSID (e.g., this is an MPDU containing an A-MSDU)
1568 if (to == GetAddress() ||
1569 (hdr->IsQosData() && hdr->IsQosAmsdu() && to == mpdu->GetHeader().GetAddr1()))
1570 {
1571 NS_LOG_DEBUG("frame for me from=" << from);
1572 if (hdr->IsQosData())
1573 {
1574 if (hdr->IsQosAmsdu())
1575 {
1576 NS_LOG_DEBUG("Received A-MSDU from=" << from
1577 << ", size=" << packet->GetSize());
1579 packet = nullptr;
1580 }
1581 else
1582 {
1583 ForwardUp(packet, from, GetAddress());
1584 }
1585 }
1586 else if (hdr->HasData())
1587 {
1588 ForwardUp(packet, from, GetAddress());
1589 }
1590 }
1591 else if (to.IsGroup() || IsAssociated(to))
1592 {
1593 NS_LOG_DEBUG("forwarding frame from=" << from << ", to=" << to);
1594 Ptr<Packet> copy = packet->Copy();
1595
1596 // If the frame we are forwarding is of type QoS Data,
1597 // then we need to preserve the UP in the QoS control
1598 // header...
1599 if (hdr->IsQosData())
1600 {
1601 ForwardDown(copy, from, to, hdr->GetQosTid());
1602 }
1603 else
1604 {
1605 ForwardDown(copy, from, to);
1606 }
1607 ForwardUp(packet, from, to);
1608 }
1609 else
1610 {
1611 ForwardUp(packet, from, to);
1612 }
1613 }
1614 else if (hdr->IsFromDs() && hdr->IsToDs())
1615 {
1616 // this is an AP-to-AP frame
1617 // we ignore for now.
1618 NotifyRxDrop(packet);
1619 }
1620 else
1621 {
1622 // we can ignore these frames since
1623 // they are not targeted at the AP
1624 NotifyRxDrop(packet);
1625 }
1626 return;
1627 }
1628 else if (hdr->IsMgt())
1629 {
1630 if (hdr->IsProbeReq() && (hdr->GetAddr1().IsGroup() ||
1631 hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress()))
1632 {
1633 // In the case where the Address 1 field contains a group address, the
1634 // Address 3 field also is validated to verify that the group addressed
1635 // frame originated from a STA in the BSS of which the receiving STA is
1636 // a member (Section 9.3.3.1 of 802.11-2020)
1637 if (hdr->GetAddr1().IsGroup() && !hdr->GetAddr3().IsBroadcast() &&
1638 hdr->GetAddr3() != GetFrameExchangeManager(linkId)->GetAddress())
1639 {
1640 // not addressed to us
1641 return;
1642 }
1643 MgtProbeRequestHeader probeRequestHeader;
1644 packet->PeekHeader(probeRequestHeader);
1645 const Ssid& ssid = probeRequestHeader.GetSsid();
1646 if (ssid == GetSsid() || ssid.IsBroadcast())
1647 {
1648 NS_LOG_DEBUG("Probe request received from " << from << ": send probe response");
1649 SendProbeResp(from, linkId);
1650 }
1651 return;
1652 }
1653 else if (hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress())
1654 {
1655 if (hdr->IsAssocReq() || hdr->IsReassocReq())
1656 {
1657 NS_LOG_DEBUG(((hdr->IsAssocReq()) ? "Association" : "Reassociation")
1658 << " request received from " << from
1659 << ((GetNLinks() > 1) ? " on link ID " + std::to_string(linkId) : ""));
1660
1661 MgtAssocRequestHeader assocReq;
1662 MgtReassocRequestHeader reassocReq;
1663 AssocReqRefVariant frame = assocReq;
1664 if (hdr->IsAssocReq())
1665 {
1666 packet->PeekHeader(assocReq);
1667 }
1668 else
1669 {
1670 packet->PeekHeader(reassocReq);
1671 frame = reassocReq;
1672 }
1673 ReceiveAssocRequest(frame, from, linkId);
1674 if (GetNLinks() > 1)
1675 {
1676 ParseReportedStaInfo(frame, from, linkId);
1677 }
1678 SendAssocResp(hdr->GetAddr2(), hdr->IsReassocReq(), linkId);
1679 return;
1680 }
1681 else if (hdr->IsDisassociation())
1682 {
1683 NS_LOG_DEBUG("Disassociation received from " << from);
1685 auto& staList = GetLink(linkId).staList;
1686 for (auto it = staList.begin(); it != staList.end(); ++it)
1687 {
1688 if (it->second == from)
1689 {
1690 staList.erase(it);
1691 m_deAssocLogger(it->first, it->second);
1692 if (GetWifiRemoteStationManager(linkId)->GetDsssSupported(from) &&
1693 !GetWifiRemoteStationManager(linkId)->GetErpOfdmSupported(from))
1694 {
1695 GetLink(linkId).numNonErpStations--;
1696 }
1697 if (!GetWifiRemoteStationManager(linkId)->GetHtSupported(from))
1698 {
1699 GetLink(linkId).numNonHtStations--;
1700 }
1703 break;
1704 }
1705 }
1706 return;
1707 }
1708 }
1709 }
1710
1711 // Invoke the receive handler of our parent class to deal with any
1712 // other frames. Specifically, this will handle Block Ack-related
1713 // Management Action frames.
1714 WifiMac::Receive(Create<WifiMpdu>(packet, *hdr), linkId);
1715}
1716
1717bool
1719 const Mac48Address& from,
1720 uint8_t linkId)
1721{
1722 NS_LOG_FUNCTION(this << from << +linkId);
1723
1724 auto remoteStationManager = GetWifiRemoteStationManager(linkId);
1725
1726 auto failure = [&](const std::string& msg) -> bool {
1727 NS_LOG_DEBUG("Association Request from " << from << " refused: " << msg);
1728 remoteStationManager->RecordAssocRefused(from);
1729 return false;
1730 };
1731
1732 // lambda to process received (Re)Association Request
1733 auto recvAssocRequest = [&](auto&& frameRefWrapper) -> bool {
1734 const auto& frame = frameRefWrapper.get();
1735
1736 // first, verify that the the station's supported
1737 // rate set is compatible with our Basic Rate set
1738 const CapabilityInformation& capabilities = frame.GetCapabilities();
1739 remoteStationManager->AddSupportedPhyPreamble(from, capabilities.IsShortPreamble());
1740 const SupportedRates& rates = frame.GetSupportedRates();
1741
1742 if (rates.GetNRates() == 0)
1743 {
1744 return failure("STA's supported rate set not compatible with our Basic Rate set");
1745 }
1746
1747 if (GetHtSupported())
1748 {
1749 // check whether the HT STA supports all MCSs in Basic MCS Set
1750 const auto& htCapabilities = frame.GetHtCapabilities();
1751 if (htCapabilities.has_value() && htCapabilities->IsSupportedMcs(0))
1752 {
1753 for (uint8_t i = 0; i < remoteStationManager->GetNBasicMcs(); i++)
1754 {
1755 WifiMode mcs = remoteStationManager->GetBasicMcs(i);
1756 if (!htCapabilities->IsSupportedMcs(mcs.GetMcsValue()))
1757 {
1758 return failure("HT STA does not support all MCSs in Basic MCS Set");
1759 }
1760 }
1761 }
1762 }
1763 if (GetVhtSupported(linkId))
1764 {
1765 // check whether the VHT STA supports all MCSs in Basic MCS Set
1766 const auto& vhtCapabilities = frame.GetVhtCapabilities();
1767 if (vhtCapabilities.has_value() && vhtCapabilities->GetVhtCapabilitiesInfo() != 0)
1768 {
1769 for (uint8_t i = 0; i < remoteStationManager->GetNBasicMcs(); i++)
1770 {
1771 WifiMode mcs = remoteStationManager->GetBasicMcs(i);
1772 if (!vhtCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
1773 {
1774 return failure("VHT STA does not support all MCSs in Basic MCS Set");
1775 }
1776 }
1777 }
1778 }
1779 if (GetHeSupported())
1780 {
1781 // check whether the HE STA supports all MCSs in Basic MCS Set
1782 const auto& heCapabilities = frame.GetHeCapabilities();
1783 if (heCapabilities.has_value() && heCapabilities->GetSupportedMcsAndNss() != 0)
1784 {
1785 for (uint8_t i = 0; i < remoteStationManager->GetNBasicMcs(); i++)
1786 {
1787 WifiMode mcs = remoteStationManager->GetBasicMcs(i);
1788 if (!heCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
1789 {
1790 return failure("HE STA does not support all MCSs in Basic MCS Set");
1791 }
1792 }
1793 }
1794 }
1795 if (GetEhtSupported())
1796 {
1797 // check whether the EHT STA supports all MCSs in Basic MCS Set
1798 // const auto& ehtCapabilities = frame.GetEhtCapabilities ();
1799 // TODO: to be completed
1800 }
1801
1802 // The association request from the station can be accepted.
1803 // Record all its supported modes in its associated WifiRemoteStation
1804 auto phy = GetWifiPhy(linkId);
1805
1806 for (const auto& mode : phy->GetModeList())
1807 {
1808 if (rates.IsSupportedRate(mode.GetDataRate(phy->GetChannelWidth())))
1809 {
1810 remoteStationManager->AddSupportedMode(from, mode);
1811 }
1812 }
1813 if (GetErpSupported(linkId) && remoteStationManager->GetErpOfdmSupported(from) &&
1814 capabilities.IsShortSlotTime())
1815 {
1816 remoteStationManager->AddSupportedErpSlotTime(from, true);
1817 }
1818 if (GetHtSupported())
1819 {
1820 const auto& htCapabilities = frame.GetHtCapabilities();
1821 if (htCapabilities.has_value() && htCapabilities->IsSupportedMcs(0))
1822 {
1823 remoteStationManager->AddStationHtCapabilities(from, *htCapabilities);
1824 }
1825 // const ExtendedCapabilities& extendedCapabilities = frame.GetExtendedCapabilities ();
1826 // TODO: to be completed
1827 }
1828 if (GetVhtSupported(linkId))
1829 {
1830 const auto& vhtCapabilities = frame.GetVhtCapabilities();
1831 // we will always fill in RxHighestSupportedLgiDataRate field at TX, so this can be used
1832 // to check whether it supports VHT
1833 if (vhtCapabilities.has_value() &&
1834 vhtCapabilities->GetRxHighestSupportedLgiDataRate() > 0)
1835 {
1836 remoteStationManager->AddStationVhtCapabilities(from, *vhtCapabilities);
1837 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_VHT))
1838 {
1839 if (vhtCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
1840 {
1841 remoteStationManager->AddSupportedMcs(from, mcs);
1842 // here should add a control to add basic MCS when it is implemented
1843 }
1844 }
1845 }
1846 }
1847 if (GetHeSupported())
1848 {
1849 const auto& heCapabilities = frame.GetHeCapabilities();
1850 if (heCapabilities.has_value() && heCapabilities->GetSupportedMcsAndNss() != 0)
1851 {
1852 remoteStationManager->AddStationHeCapabilities(from, *heCapabilities);
1853 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_HE))
1854 {
1855 if (heCapabilities->IsSupportedTxMcs(mcs.GetMcsValue()))
1856 {
1857 remoteStationManager->AddSupportedMcs(from, mcs);
1858 // here should add a control to add basic MCS when it is implemented
1859 }
1860 }
1861 }
1862 }
1863 if (GetEhtSupported())
1864 {
1865 if (const auto& ehtCapabilities = frame.GetEhtCapabilities())
1866 {
1867 remoteStationManager->AddStationEhtCapabilities(from, *ehtCapabilities);
1868 }
1869 for (const auto& mcs : phy->GetMcsList(WIFI_MOD_CLASS_EHT))
1870 {
1871 // TODO: Add check whether MCS is supported from the capabilities
1872 remoteStationManager->AddSupportedMcs(from, mcs);
1873 // here should add a control to add basic MCS when it is implemented
1874 }
1875 }
1876
1877 NS_LOG_DEBUG("Association Request from " << from << " accepted");
1878 remoteStationManager->RecordWaitAssocTxOk(from);
1879 return true;
1880 ;
1881 };
1882
1883 return std::visit(recvAssocRequest, assoc);
1884}
1885
1886void
1888{
1889 NS_LOG_FUNCTION(this << from << +linkId);
1890
1891 // lambda to process received Multi-Link Element
1892 auto recvMle = [&](auto&& frame) {
1893 const auto& mle = frame.get().GetMultiLinkElement();
1894
1895 if (!mle.has_value())
1896 {
1897 return;
1898 }
1899
1900 GetWifiRemoteStationManager(linkId)->SetMldAddress(from, mle->GetMldMacAddress());
1901
1902 for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++)
1903 {
1904 auto& perStaProfile = mle->GetPerStaProfile(i);
1905 if (!perStaProfile.HasStaMacAddress())
1906 {
1907 NS_LOG_DEBUG("[i=" << i
1908 << "] Cannot setup a link if the STA MAC address is missing");
1909 continue;
1910 }
1911 uint8_t newLinkId = perStaProfile.GetLinkId();
1912 if (newLinkId == linkId || newLinkId >= GetNLinks())
1913 {
1914 NS_LOG_DEBUG("[i=" << i << "] Link ID " << newLinkId << " not valid");
1915 continue;
1916 }
1917 if (!perStaProfile.HasAssocRequest() && !perStaProfile.HasReassocRequest())
1918 {
1919 NS_LOG_DEBUG("[i=" << i << "] No (Re)Association Request frame body present");
1920 continue;
1921 }
1922
1923 ReceiveAssocRequest(perStaProfile.GetAssocRequest(),
1924 perStaProfile.GetStaMacAddress(),
1925 newLinkId);
1926 GetWifiRemoteStationManager(newLinkId)->SetMldAddress(perStaProfile.GetStaMacAddress(),
1927 mle->GetMldMacAddress());
1928 }
1929 };
1930
1931 std::visit(recvMle, assoc);
1932}
1933
1934void
1936{
1937 NS_LOG_FUNCTION(this << *mpdu);
1938 for (auto& i : *PeekPointer(mpdu))
1939 {
1940 auto from = i.second.GetSourceAddr();
1941 auto to = i.second.GetDestinationAddr();
1942
1943 if (to.IsGroup() || IsAssociated(to))
1944 {
1945 NS_LOG_DEBUG("forwarding QoS frame from=" << from << ", to=" << to);
1946 ForwardDown(i.first->Copy(), from, to, mpdu->GetHeader().GetQosTid());
1947 }
1948
1949 ForwardUp(i.first, from, to);
1950 }
1951}
1952
1953void
1955{
1956 NS_LOG_FUNCTION(this);
1958
1959 for (uint8_t linkId = 0; linkId < GetNLinks(); ++linkId)
1960 {
1961 GetLink(linkId).beaconEvent.Cancel();
1963 {
1964 uint64_t jitterUs =
1966 ? static_cast<uint64_t>(m_beaconJitter->GetValue(0, 1) *
1968 : 0);
1969 NS_LOG_DEBUG("Scheduling initial beacon for access point "
1970 << GetAddress() << " at time " << jitterUs << "us");
1973 this,
1974 linkId);
1975 }
1978 }
1979
1984}
1985
1986bool
1988{
1989 bool useProtection = (GetLink(linkId).numNonErpStations > 0) && m_enableNonErpProtection;
1991 return useProtection;
1992}
1993
1994uint16_t
1995ApWifiMac::GetNextAssociationId(std::list<uint8_t> linkIds)
1996{
1997 // Return the first AID value between 1 and 2007 that is free for all the given links
1998 for (uint16_t nextAid = 1; nextAid <= 2007; nextAid++)
1999 {
2000 if (std::all_of(linkIds.begin(), linkIds.end(), [&](auto&& linkId) {
2001 auto& staList = GetLink(linkId).staList;
2002 return staList.find(nextAid) == staList.end();
2003 }))
2004 {
2005 return nextAid;
2006 }
2007 }
2008 NS_FATAL_ERROR("No free association ID available!");
2009 return 0;
2010}
2011
2012const std::map<uint16_t, Mac48Address>&
2013ApWifiMac::GetStaList(uint8_t linkId) const
2014{
2015 return GetLink(linkId).staList;
2016}
2017
2018uint16_t
2020{
2021 return GetWifiRemoteStationManager(linkId)->GetAssociationId(addr);
2022}
2023
2024uint8_t
2025ApWifiMac::GetBufferStatus(uint8_t tid, Mac48Address address) const
2026{
2027 auto it = m_bufferStatus.find(WifiAddressTidPair(address, tid));
2028 if (it == m_bufferStatus.end() || it->second.timestamp + m_bsrLifetime < Simulator::Now())
2029 {
2030 return 255;
2031 }
2032 return it->second.value;
2033}
2034
2035void
2036ApWifiMac::SetBufferStatus(uint8_t tid, Mac48Address address, uint8_t size)
2037{
2038 if (size == 255)
2039 {
2040 // no point in storing an unspecified size
2041 m_bufferStatus.erase(WifiAddressTidPair(address, tid));
2042 }
2043 else
2044 {
2045 m_bufferStatus[WifiAddressTidPair(address, tid)] = {size, Simulator::Now()};
2046 }
2047}
2048
2049uint8_t
2051{
2052 uint8_t maxSize = 0;
2053 bool found = false;
2054
2055 for (uint8_t tid = 0; tid < 8; tid++)
2056 {
2057 uint8_t size = GetBufferStatus(tid, address);
2058 if (size != 255)
2059 {
2060 maxSize = std::max(maxSize, size);
2061 found = true;
2062 }
2063 }
2064
2065 if (found)
2066 {
2067 return maxSize;
2068 }
2069 return 255;
2070}
2071
2072} // namespace ns3
Wi-Fi AP state machine.
Definition: ap-wifi-mac.h:64
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:142
Ptr< Txop > m_beaconTxop
Dedicated Txop for beacons.
Definition: ap-wifi-mac.h:495
void SetBeaconGeneration(bool enable)
Enable or disable beacon generation of the AP.
Definition: ap-wifi-mac.cc:179
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:242
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:126
void SetBeaconInterval(Time interval)
Definition: ap-wifi-mac.cc:217
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:305
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:482
Ptr< UniformRandomVariable > m_beaconJitter
UniformRandomVariable used to randomize the time of the first beacon.
Definition: ap-wifi-mac.h:499
SupportedRates 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:427
bool CanForwardPacketsTo(Mac48Address to) const override
Return true if packets can be forwarded to the given destination, false otherwise.
Definition: ap-wifi-mac.cc:390
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:501
EdcaParameterSet GetEdcaParameterSet(uint8_t linkId) const
Return the EDCA Parameter Set of the current AP for the given link.
Definition: ap-wifi-mac.cc:514
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:660
HtOperation GetHtOperation(uint8_t linkId) const
Return the HT operation of the current AP for the given link.
Definition: ap-wifi-mac.cc:709
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:265
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:204
TracedCallback< uint16_t, Mac48Address > m_deAssocLogger
deassociation logger
Definition: ap-wifi-mac.h:524
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:496
Time m_beaconInterval
Beacon interval.
Definition: ap-wifi-mac.h:497
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:500
std::unordered_map< WifiAddressTidPair, BsrType, WifiAddressTidHash > m_bufferStatus
Per (MAC address, TID) buffer status reports.
Definition: ap-wifi-mac.h:513
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:910
DsssParameterSet GetDsssParameterSet(uint8_t linkId) const
Return the DSSS Parameter Set that we support on the given link.
Definition: ap-wifi-mac.cc:472
TracedCallback< uint16_t, Mac48Address > m_assocLogger
association logger
Definition: ap-wifi-mac.h:523
Time GetBeaconInterval() const
Definition: ap-wifi-mac.cc:198
static TypeId GetTypeId()
Get the type ID.
Definition: ap-wifi-mac.cc:56
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:629
void Enqueue(Ptr< Packet > packet, Mac48Address to) override
Definition: ap-wifi-mac.cc:410
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:503
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:234
ApLinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: ap-wifi-mac.cc:148
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:886
void ConfigureStandard(WifiStandard standard) override
Definition: ap-wifi-mac.cc:154
ErpInformation GetErpInformation(uint8_t linkId) const
Return the ERP information of the current AP for the given link.
Definition: ap-wifi-mac.cc:493
void SetLinkUpCallback(Callback< void > linkUp) override
Definition: ap-wifi-mac.cc:205
VhtOperation GetVhtOperation(uint8_t linkId) const
Return the VHT operation of the current AP for the given link.
Definition: ap-wifi-mac.cc:807
~ApWifiMac() override
Definition: ap-wifi-mac.cc:120
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:856
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:561
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:420
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:289
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:169
void ConfigQueueScheduler(const LinkIdStaAddrMap &linkIdStaAddrMap, const Mac48Address &to, uint8_t linkId)
Configure the queue scheduler so that frames stored in the container queues associated with the stati...
bool GetUseNonErpProtection(uint8_t linkId) const
Return whether protection for non-ERP stations is used in the BSS corresponding to the given link.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Callback template class.
Definition: callback.h:443
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.
EHT Operation Information Element.
Definition: eht-operation.h:67
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 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:88
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.
Definition: ht-operation.cc:90
void SetSecondaryChannelOffset(uint8_t secondaryChannelOffset)
Set the secondary channel offset.
Definition: ht-operation.cc:78
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.
Definition: ht-operation.cc:96
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.
Definition: ht-operation.cc:84
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:72
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:55
Implement the header for management frames of type association and reassociation response.
Definition: mgt-headers.h:447
void SetHeCapabilities(const HeCapabilities &heCapabilities)
Set the HE capabilities.
const std::optional< MultiLinkElement > & GetMultiLinkElement() const
Return the Multi-Link Element information element, if present.
StatusCode GetStatusCode()
Return the status code.
void SetHtOperation(const HtOperation &htOperation)
Set the HT operation.
void SetMuEdcaParameterSet(const MuEdcaParameterSet &muEdcaParameterSet)
Set the MU EDCA Parameter Set.
void SetEdcaParameterSet(const EdcaParameterSet &edcaParameterSet)
Set the EDCA Parameter Set.
void SetEhtCapabilities(const EhtCapabilities &ehtCapabilities)
Set the EHT capabilities.
void SetStatusCode(StatusCode code)
Set the status code.
void SetVhtOperation(const VhtOperation &vhtOperation)
Set the VHT operation.
void SetHeOperation(const HeOperation &heOperation)
Set the HE operation.
void SetAssociationId(uint16_t aid)
Set the association ID.
void SetCapabilities(const CapabilityInformation &capabilities)
Set the Capability information.
void SetEhtOperation(const EhtOperation &ehtOperation)
Set the EHT operation.
void SetVhtCapabilities(const VhtCapabilities &vhtCapabilities)
Set the VHT capabilities.
void SetSupportedRates(const SupportedRates &rates)
Set the supported rates.
void SetExtendedCapabilities(const ExtendedCapabilities &extendedCapabilities)
Set the extended capabilities.
void SetHtCapabilities(const HtCapabilities &htCapabilities)
Set the HT capabilities.
void SetMultiLinkElement(const MultiLinkElement &multiLinkElement)
Set the Multi-Link Element information element.
void SetErpInformation(const ErpInformation &erpInformation)
Set the ERP information.
Implement the header for management frames of type beacon.
Definition: mgt-headers.h:1257
Implement the header for management frames of type probe request.
Definition: mgt-headers.h:754
const Ssid & GetSsid() const
Return the Service Set Identifier (SSID).
Definition: mgt-headers.cc:53
Implement the header for management frames of type probe response.
Definition: mgt-headers.h:903
void SetVhtOperation(const VhtOperation &vhtOperation)
Set the VHT operation.
Definition: mgt-headers.cc:421
void SetHtOperation(const HtOperation &htOperation)
Set the HT operation.
Definition: mgt-headers.cc:385
void SetDsssParameterSet(const DsssParameterSet &dsssParameterSet)
Set the DSSS Parameter Set.
Definition: mgt-headers.cc:541
void SetCapabilities(const CapabilityInformation &capabilities)
Set the Capability information.
Definition: mgt-headers.cc:331
void SetReducedNeighborReport(const ReducedNeighborReport &reducedNeighborReport)
Set the Reduced Neighbor Report information element.
Definition: mgt-headers.cc:601
void SetEhtCapabilities(const EhtCapabilities &ehtCapabilities)
Set the EHT capabilities.
Definition: mgt-headers.cc:475
void SetVhtCapabilities(const VhtCapabilities &vhtCapabilities)
Set the VHT capabilities.
Definition: mgt-headers.cc:403
void SetHtCapabilities(const HtCapabilities &htCapabilities)
Set the HT capabilities.
Definition: mgt-headers.cc:367
void SetSsid(const Ssid &ssid)
Set the Service Set Identifier (SSID).
Definition: mgt-headers.cc:511
void SetSupportedRates(const SupportedRates &rates)
Set the supported rates.
Definition: mgt-headers.cc:529
void SetHeOperation(const HeOperation &heOperation)
Set the HE operation.
Definition: mgt-headers.cc:457
void SetErpInformation(const ErpInformation &erpInformation)
Set the ERP information.
Definition: mgt-headers.cc:559
void SetExtendedCapabilities(const ExtendedCapabilities &extendedCapabilities)
Set the extended capabilities.
Definition: mgt-headers.cc:349
void SetBeaconIntervalUs(uint64_t us)
Set the beacon interval in microseconds unit.
Definition: mgt-headers.cc:523
void SetEdcaParameterSet(const EdcaParameterSet &edcaParameterSet)
Set the EDCA Parameter Set.
Definition: mgt-headers.cc:577
void SetHeCapabilities(const HeCapabilities &heCapabilities)
Set the HE capabilities.
Definition: mgt-headers.cc:439
void SetMuEdcaParameterSet(const MuEdcaParameterSet &muEdcaParameterSet)
Set the MU EDCA Parameter Set.
Definition: mgt-headers.cc:589
void SetMultiLinkElement(const MultiLinkElement &multiLinkElement)
Set the Multi-Link Element information element.
Definition: mgt-headers.cc:613
void SetEhtOperation(const EhtOperation &ehtOperation)
Set the EHT operation.
Definition: mgt-headers.cc:493
Implement the header for management frames of type reassociation request.
Definition: mgt-headers.h:248
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.
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.
uint8_t GetNRates() const
Return the number of supported rates.
void AddSupportedRate(uint64_t bs)
Add the given rate to the supported rates.
bool IsSupportedRate(uint64_t bs) const
Check if the given rate is supported.
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:220
virtual void SetWifiMac(const Ptr< WifiMac > mac)
Set the wifi MAC this Txop is associated to.
Definition: txop.cc:195
void SetMaxCws(std::vector< uint32_t > maxCws)
Set the maximum contention window size for each link.
Definition: txop.cc:262
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set MacTxMiddle this Txop is associated to.
Definition: txop.cc:188
void SetMinCws(std::vector< uint32_t > minCws)
Set the minimum contention window size for each link.
Definition: txop.cc:233
void SetAifsns(std::vector< uint8_t > aifsns)
Set the number of slots that make up an AIFS for each link.
Definition: txop.cc:359
virtual void Queue(Ptr< Packet > packet, const WifiMacHeader &hdr)
Definition: txop.cc:505
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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 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.
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.
bool IsDisassociation() const
Return true if the header is a Disassociation header.
void SetQosTxopLimit(uint8_t txop)
Set TXOP limit in the QoS control field.
WifiMacType GetType() const
Return the type (enum 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.
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:840
Ptr< QosTxop > GetBEQueue() const
Accessor for the AC_BE channel access function.
Definition: wifi-mac.cc:524
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition: wifi-mac.cc:1236
Ptr< HeConfiguration > GetHeConfiguration() const
Definition: wifi-mac.cc:1353
Ptr< Txop > GetTxop() const
Accessor for the Txop object.
Definition: wifi-mac.cc:484
VhtCapabilities GetVhtCapabilities(uint8_t linkId) const
Return the VHT capabilities of the device for the given link.
Definition: wifi-mac.cc:1590
bool GetQosSupported() const
Return whether the device supports QoS.
Definition: wifi-mac.cc:1006
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition: wifi-mac.cc:906
Ptr< WifiMacQueueScheduler > m_scheduler
wifi MAC queue scheduler
Definition: wifi-mac.h:754
void DoInitialize() override
Initialize() implementation.
Definition: wifi-mac.cc:353
virtual void ConfigureStandard(WifiStandard standard)
Definition: wifi-mac.cc:724
Ssid GetSsid() const
Definition: wifi-mac.cc:456
bool GetErpSupported(uint8_t linkId) const
Return whether the device supports ERP on the given link.
Definition: wifi-mac.cc:1012
bool GetHtSupported() const
Return whether the device supports HT.
Definition: wifi-mac.cc:1365
Ptr< QosTxop > GetVOQueue() const
Accessor for the AC_VO channel access function.
Definition: wifi-mac.cc:512
void SetTypeOfStation(TypeOfStation type)
This method is invoked by a subclass to specify what type of station it is implementing.
Definition: wifi-mac.cc:411
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:954
bool GetEhtSupported() const
Return whether the device supports EHT.
Definition: wifi-mac.cc:1384
bool GetHeSupported() const
Return whether the device supports HE.
Definition: wifi-mac.cc:1378
HtCapabilities GetHtCapabilities(uint8_t linkId) const
Return the HT capabilities of the device for the given link.
Definition: wifi-mac.cc:1533
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:912
bool GetVhtSupported(uint8_t linkId) const
Return whether the device supports VHT on the given link.
Definition: wifi-mac.cc:1371
Ptr< MacTxMiddle > m_txMiddle
TX middle (aggregation etc.)
Definition: wifi-mac.h:752
Ptr< HtConfiguration > GetHtConfiguration() const
Definition: wifi-mac.cc:1341
ExtendedCapabilities GetExtendedCapabilities() const
Return the extended capabilities of the device.
Definition: wifi-mac.cc:1522
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:536
bool GetShortSlotTimeSupported() const
Definition: wifi-mac.cc:1056
void NotifyRxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:595
virtual void SetLinkUpCallback(Callback< void > linkUp)
Definition: wifi-mac.cc:1075
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:886
void ForwardUp(Ptr< const Packet > packet, Mac48Address from, Mac48Address to)
Forward the packet up to the device.
Definition: wifi-mac.cc:1100
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:1107
Mac48Address GetAddress() const
Definition: wifi-mac.cc:443
EhtCapabilities GetEhtCapabilities(uint8_t linkId) const
Return the EHT capabilities of the device for the given link.
Definition: wifi-mac.cc:1727
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: wifi-mac.cc:898
HeCapabilities GetHeCapabilities(uint8_t linkId) const
Return the HE capabilities of the device for the given link.
Definition: wifi-mac.cc:1671
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:490
void NotifyTxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:577
void DoDispose() override
Destructor implementation.
Definition: wifi-mac.cc:369
bool GetDsssSupported(uint8_t linkId) const
Return whether the device supports DSSS on the given link.
Definition: wifi-mac.cc:1036
represent a single transmission mode
Definition: wifi-mode.h:50
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:1295
void SetSlot(Time slot)
Set the slot duration for this PHY.
Definition: wifi-phy.cc:780
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1008
void SetShortSlotTimeEnabled(bool enable)
Enable or disable short slot time.
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 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...
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.
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.
#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:231
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 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:160
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:72
@ 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
@ AP
Definition: wifi-mac.h:63
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:707
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:54
@ NO_PROTECTION
Definition: ht-operation.h:37
@ MIXED_MODE_PROTECTION
Definition: ht-operation.h:40
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
Definition: wifi-utils.h:140
constexpr uint8_t WIFI_EHT_MAX_MCS_INDEX
IEEE 802.11be D2.0 Figure 9-1002ai.
Definition: eht-operation.h:33
const std::map< AcIndex, WifiAc > wifiAcList
Map containing the four ACs in increasing order of priority (according to Table 10-1 "UP-to-AC Mappin...
Definition: qos-utils.cc:126
WifiMacType
Combination of valid MAC header type/subtype.
@ WIFI_MAC_MGT_BEACON
@ WIFI_MAC_MGT_ASSOCIATION_RESPONSE
@ WIFI_MAC_MGT_PROBE_RESPONSE
@ WIFI_MAC_DATA
@ WIFI_MAC_MGT_REASSOCIATION_RESPONSE
@ WIFI_MAC_QOSDATA
@ WIFI_QOSDATA_UNICAST_QUEUE
std::pair< Mac48Address, uint8_t > WifiAddressTidPair
(MAC address, TID) pair
Definition: qos-utils.h:35
std::tuple< WifiContainerQueueType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, Address, TID) identifying a container queue.