A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
sta-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 "sta-wifi-mac.h"
23
26#include "mgt-headers.h"
27#include "qos-txop.h"
28#include "snr-tag.h"
29#include "wifi-assoc-manager.h"
30#include "wifi-mac-queue.h"
31#include "wifi-net-device.h"
32#include "wifi-phy.h"
33
34#include "ns3/attribute-container.h"
35#include "ns3/eht-configuration.h"
36#include "ns3/emlsr-manager.h"
37#include "ns3/he-configuration.h"
38#include "ns3/ht-configuration.h"
39#include "ns3/log.h"
40#include "ns3/packet.h"
41#include "ns3/pair.h"
42#include "ns3/pointer.h"
43#include "ns3/random-variable-stream.h"
44#include "ns3/simulator.h"
45#include "ns3/string.h"
46
47#include <numeric>
48
49namespace ns3
50{
51
52NS_LOG_COMPONENT_DEFINE("StaWifiMac");
53
55
56TypeId
58{
59 static TypeId tid =
60 TypeId("ns3::StaWifiMac")
62 .SetGroupName("Wifi")
63 .AddConstructor<StaWifiMac>()
64 .AddAttribute("ProbeRequestTimeout",
65 "The duration to actively probe the channel.",
66 TimeValue(Seconds(0.05)),
69 .AddAttribute("WaitBeaconTimeout",
70 "The duration to dwell on a channel while passively scanning for beacon",
74 .AddAttribute("AssocRequestTimeout",
75 "The interval between two consecutive association request attempts.",
76 TimeValue(Seconds(0.5)),
79 .AddAttribute("MaxMissedBeacons",
80 "Number of beacons which much be consecutively missed before "
81 "we attempt to restart association.",
82 UintegerValue(10),
84 MakeUintegerChecker<uint32_t>())
85 .AddAttribute(
86 "ActiveProbing",
87 "If true, we send probe requests. If false, we don't."
88 "NOTE: if more than one STA in your simulation is using active probing, "
89 "you should enable it at a different simulation time for each STA, "
90 "otherwise all the STAs will start sending probes at the same time resulting in "
91 "collisions. "
92 "See bug 1060 for more info.",
93 BooleanValue(false),
96 .AddAttribute("ProbeDelay",
97 "Delay (in microseconds) to be used prior to transmitting a "
98 "Probe frame during active scanning.",
99 StringValue("ns3::UniformRandomVariable[Min=50.0|Max=250.0]"),
101 MakePointerChecker<RandomVariableStream>())
102 .AddAttribute(
103 "PowerSaveMode",
104 "Enable/disable power save mode on the given link. The power management mode is "
105 "actually changed when the AP acknowledges a frame sent with the Power Management "
106 "field set to the value corresponding to the requested mode",
107 TypeId::ATTR_GET | TypeId::ATTR_SET, // do not set at construction time
109 MakePairAccessor<BooleanValue, UintegerValue>(&StaWifiMac::SetPowerSaveMode),
110 MakePairChecker<BooleanValue, UintegerValue>(MakeBooleanChecker(),
111 MakeUintegerChecker<uint8_t>()))
112 .AddAttribute("PmModeSwitchTimeout",
113 "If switching to a new Power Management mode is not completed within "
114 "this amount of time, make another attempt at switching Power "
115 "Management mode.",
116 TimeValue(Seconds(0.1)),
119 .AddTraceSource("Assoc",
120 "Associated with an access point. If this is an MLD that associated "
121 "with an AP MLD, the AP MLD address is provided.",
123 "ns3::Mac48Address::TracedCallback")
124 .AddTraceSource("LinkSetupCompleted",
125 "A link was setup in the context of ML setup with an AP MLD. "
126 "Provides ID of the setup link and AP MAC address",
128 "ns3::StaWifiMac::LinkSetupCallback")
129 .AddTraceSource("DeAssoc",
130 "Association with an access point lost. If this is an MLD "
131 "that disassociated with an AP MLD, the AP MLD address is provided.",
133 "ns3::Mac48Address::TracedCallback")
134 .AddTraceSource("LinkSetupCanceled",
135 "A link setup in the context of ML setup with an AP MLD was torn down. "
136 "Provides ID of the setup link and AP MAC address",
138 "ns3::StaWifiMac::LinkSetupCallback")
139 .AddTraceSource("BeaconArrival",
140 "Time of beacons arrival from associated AP",
142 "ns3::Time::TracedCallback")
143 .AddTraceSource("ReceivedBeaconInfo",
144 "Information about every received Beacon frame",
146 "ns3::ApInfo::TracedCallback");
147 return tid;
148}
149
151 : m_state(UNASSOCIATED),
152 m_aid(0),
153 m_assocRequestEvent()
154{
155 NS_LOG_FUNCTION(this);
156
157 // Let the lower layers know that we are acting as a non-AP STA in
158 // an infrastructure BSS.
160}
161
162void
164{
165 NS_LOG_FUNCTION(this);
166 // an EMLSR client must perform ML setup by using its main PHY
168 {
169 auto mainPhyId = m_emlsrManager->GetMainPhyId();
170 auto linkId = GetLinkForPhy(mainPhyId);
171 NS_ASSERT(linkId);
172 m_assocManager->SetAttribute(
173 "AllowedLinks",
174 AttributeContainerValue<UintegerValue>(std::list<uint8_t>{*linkId}));
175 }
176 if (m_emlsrManager)
177 {
178 m_emlsrManager->Initialize();
179 }
183}
184
185void
187{
188 NS_LOG_FUNCTION(this);
189 if (m_assocManager)
190 {
191 m_assocManager->Dispose();
192 }
193 m_assocManager = nullptr;
194 if (m_emlsrManager)
195 {
196 m_emlsrManager->Dispose();
197 }
198 m_emlsrManager = nullptr;
200}
201
203{
204 NS_LOG_FUNCTION(this);
205}
206
208{
210}
211
212std::unique_ptr<WifiMac::LinkEntity>
214{
215 return std::make_unique<StaLinkEntity>();
216}
217
219StaWifiMac::GetLink(uint8_t linkId) const
220{
221 return static_cast<StaLinkEntity&>(WifiMac::GetLink(linkId));
222}
223
225StaWifiMac::GetStaLink(const std::unique_ptr<WifiMac::LinkEntity>& link) const
226{
227 return static_cast<StaLinkEntity&>(*link);
228}
229
230int64_t
232{
233 NS_LOG_FUNCTION(this << stream);
234 m_probeDelay->SetStream(stream);
235 return 1;
236}
237
238void
240{
241 NS_LOG_FUNCTION(this << assocManager);
242 m_assocManager = assocManager;
243 m_assocManager->SetStaWifiMac(this);
244}
245
246void
248{
249 NS_LOG_FUNCTION(this << emlsrManager);
250 m_emlsrManager = emlsrManager;
251 m_emlsrManager->SetWifiMac(this);
252}
253
256{
257 return m_emlsrManager;
258}
259
260uint16_t
262{
263 NS_ASSERT_MSG(IsAssociated(), "This station is not associated to any AP");
264 return m_aid;
265}
266
267void
269{
270 NS_LOG_FUNCTION(this << enable);
271 m_activeProbing = enable;
272 if (m_state == SCANNING)
273 {
274 NS_LOG_DEBUG("STA is still scanning, reset scanning process");
276 }
277}
278
279bool
281{
282 return m_activeProbing;
283}
284
285void
286StaWifiMac::SetWifiPhys(const std::vector<Ptr<WifiPhy>>& phys)
287{
288 NS_LOG_FUNCTION(this);
290 for (auto& phy : phys)
291 {
292 phy->SetCapabilitiesChangedCallback(
294 }
295}
296
298StaWifiMac::GetCurrentChannel(uint8_t linkId) const
299{
300 auto phy = GetWifiPhy(linkId);
301 uint16_t width = phy->GetOperatingChannel().IsOfdm() ? 20 : phy->GetChannelWidth();
302 uint8_t ch = phy->GetOperatingChannel().GetPrimaryChannelNumber(width, phy->GetStandard());
303 return {ch, phy->GetPhyBand()};
304}
305
306void
307StaWifiMac::NotifyEmlsrModeChanged(const std::set<uint8_t>& linkIds)
308{
309 NS_LOG_FUNCTION(this << linkIds.size());
310
311 for (const auto& [linkId, lnk] : GetLinks())
312 {
313 auto& link = GetStaLink(lnk);
314
315 if (linkIds.count(linkId) > 0)
316 {
317 // EMLSR mode enabled
318 link.emlsrEnabled = true;
319 link.pmMode = WIFI_PM_ACTIVE;
320 }
321 else
322 {
323 // EMLSR mode disabled
324 if (link.emlsrEnabled)
325 {
326 link.pmMode = WIFI_PM_POWERSAVE;
327 }
328 link.emlsrEnabled = false;
329 }
330 }
331}
332
333bool
334StaWifiMac::IsEmlsrLink(uint8_t linkId) const
335{
336 return GetLink(linkId).emlsrEnabled;
337}
338
339void
341{
342 NS_LOG_FUNCTION(this << linkId);
343 WifiMacHeader hdr;
348 hdr.SetDsNotFrom();
349 hdr.SetDsNotTo();
350 Ptr<Packet> packet = Create<Packet>();
352 probe.Get<Ssid>() = GetSsid();
353 auto supportedRates = GetSupportedRates(linkId);
354 probe.Get<SupportedRates>() = supportedRates.rates;
355 probe.Get<ExtendedSupportedRatesIE>() = supportedRates.extendedRates;
356 if (GetHtSupported())
357 {
359 probe.Get<HtCapabilities>() = GetHtCapabilities(linkId);
360 }
361 if (GetVhtSupported(linkId))
362 {
363 probe.Get<VhtCapabilities>() = GetVhtCapabilities(linkId);
364 }
365 if (GetHeSupported())
366 {
367 probe.Get<HeCapabilities>() = GetHeCapabilities(linkId);
368 }
369 if (GetEhtSupported())
370 {
371 probe.Get<EhtCapabilities>() = GetEhtCapabilities(linkId);
372 }
373 packet->AddHeader(probe);
374
375 if (!GetQosSupported())
376 {
377 GetTxop()->Queue(packet, hdr);
378 }
379 // "A QoS STA that transmits a Management frame determines access category used
380 // for medium access in transmission of the Management frame as follows
381 // (If dot11QMFActivated is false or not present)
382 // — If the Management frame is individually addressed to a non-QoS STA, category
383 // AC_BE should be selected.
384 // — If category AC_BE was not selected by the previous step, category AC_VO
385 // shall be selected." (Sec. 10.2.3.2 of 802.11-2020)
386 else
387 {
388 GetVOQueue()->Queue(packet, hdr);
389 }
390}
391
392std::variant<MgtAssocRequestHeader, MgtReassocRequestHeader>
393StaWifiMac::GetAssociationRequest(bool isReassoc, uint8_t linkId) const
394{
395 NS_LOG_FUNCTION(this << isReassoc << +linkId);
396
397 std::variant<MgtAssocRequestHeader, MgtReassocRequestHeader> mgtFrame;
398
399 if (isReassoc)
400 {
402 reassoc.SetCurrentApAddress(GetBssid(linkId));
403 mgtFrame = std::move(reassoc);
404 }
405 else
406 {
407 mgtFrame = MgtAssocRequestHeader();
408 }
409
410 // lambda to set the fields of the (Re)Association Request
411 auto fill = [&](auto&& frame) {
412 frame.template Get<Ssid>() = GetSsid();
413 auto supportedRates = GetSupportedRates(linkId);
414 frame.template Get<SupportedRates>() = supportedRates.rates;
415 frame.template Get<ExtendedSupportedRatesIE>() = supportedRates.extendedRates;
416 frame.Capabilities() = GetCapabilities(linkId);
417 frame.SetListenInterval(0);
418 if (GetHtSupported())
419 {
420 frame.template Get<ExtendedCapabilities>() = GetExtendedCapabilities();
421 frame.template Get<HtCapabilities>() = GetHtCapabilities(linkId);
422 }
423 if (GetVhtSupported(linkId))
424 {
425 frame.template Get<VhtCapabilities>() = GetVhtCapabilities(linkId);
426 }
427 if (GetHeSupported())
428 {
429 frame.template Get<HeCapabilities>() = GetHeCapabilities(linkId);
430 }
431 if (GetEhtSupported())
432 {
433 frame.template Get<EhtCapabilities>() = GetEhtCapabilities(linkId);
434 }
435 };
436
437 std::visit(fill, mgtFrame);
438 return mgtFrame;
439}
440
442StaWifiMac::GetMultiLinkElement(bool isReassoc, uint8_t linkId) const
443{
444 NS_LOG_FUNCTION(this << isReassoc << +linkId);
445
447 // The Common info field of the Basic Multi-Link element carried in the (Re)Association
448 // Request frame shall include the MLD MAC address, the MLD Capabilities and Operations,
449 // and the EML Capabilities subfields, and shall not include the Link ID Info, the BSS
450 // Parameters Change Count, and the Medium Synchronization Delay Information subfields
451 // (Sec. 35.3.5.4 of 802.11be D2.0)
452 // TODO Add the MLD Capabilities and Operations subfield
453 multiLinkElement.SetMldMacAddress(GetAddress());
454
455 if (m_emlsrManager) // EMLSR Manager is only installed if EMLSR is activated
456 {
457 multiLinkElement.SetEmlsrSupported(true);
458 TimeValue time;
459 m_emlsrManager->GetAttribute("EmlsrPaddingDelay", time);
460 multiLinkElement.SetEmlsrPaddingDelay(time.Get());
461 m_emlsrManager->GetAttribute("EmlsrTransitionDelay", time);
462 multiLinkElement.SetEmlsrTransitionDelay(time.Get());
463 // When the Transition Timeout subfield is included in a frame sent by a non-AP STA
464 // affiliated with a non-AP MLD, the Transition Timeout subfield is reserved
465 // (Section 9.4.2.312.2.3 of 802.11be D2.3)
466 }
467
468 // The MLD Capabilities And Operations subfield is present in the Common Info field of the
469 // Basic Multi-Link element carried in Beacon, Probe Response, (Re)Association Request, and
470 // (Re)Association Response frames. (Sec. 9.4.2.312.2.3 of 802.11be D3.1)
471 auto& mldCapabilities = multiLinkElement.GetCommonInfoBasic().m_mldCapabilities;
472 mldCapabilities.emplace();
473 mldCapabilities->maxNSimultaneousLinks = GetNLinks() - 1; // assuming STR for now
474 mldCapabilities->srsSupport = 0;
475
476 auto ehtConfiguration = GetEhtConfiguration();
477 NS_ASSERT(ehtConfiguration);
478 EnumValue negSupport;
479 ehtConfiguration->GetAttributeFailSafe("TidToLinkMappingNegSupport", negSupport);
480
481 mldCapabilities->tidToLinkMappingSupport = negSupport.Get();
482 mldCapabilities->freqSepForStrApMld = 0; // not supported yet
483 mldCapabilities->aarSupport = 0; // not supported yet
484
485 // For each requested link in addition to the link on which the (Re)Association Request
486 // frame is transmitted, the Link Info field of the Basic Multi-Link element carried
487 // in the (Re)Association Request frame shall contain the corresponding Per-STA Profile
488 // subelement(s).
489 for (const auto& [index, link] : GetLinks())
490 {
491 const auto& staLink = GetStaLink(link);
492
493 if (index != linkId && staLink.bssid.has_value())
494 {
495 multiLinkElement.AddPerStaProfileSubelement();
496 auto& perStaProfile = multiLinkElement.GetPerStaProfile(
497 multiLinkElement.GetNPerStaProfileSubelements() - 1);
498 // The Link ID subfield of the STA Control field of the Per-STA Profile subelement
499 // for the corresponding non-AP STA that requests a link for multi-link (re)setup
500 // with the AP MLD is set to the link ID of the AP affiliated with the AP MLD that
501 // is operating on that link. The link ID is obtained during multi-link discovery
502 perStaProfile.SetLinkId(index);
503 // For each Per-STA Profile subelement included in the Link Info field, the
504 // Complete Profile subfield of the STA Control field shall be set to 1
505 perStaProfile.SetCompleteProfile();
506 // The MAC Address Present subfield indicates the presence of the STA MAC Address
507 // subfield in the STA Info field and is set to 1 if the STA MAC Address subfield
508 // is present in the STA Info field; otherwise set to 0. An STA sets this subfield
509 // to 1 when the element carries complete profile.
510 perStaProfile.SetStaMacAddress(staLink.feManager->GetAddress());
511 perStaProfile.SetAssocRequest(GetAssociationRequest(isReassoc, index));
512 }
513 }
514
515 return multiLinkElement;
516}
517
518std::vector<TidToLinkMapping>
520{
521 NS_LOG_FUNCTION(this << apNegSupport);
522
523 auto ehtConfig = GetEhtConfiguration();
524 NS_ASSERT(ehtConfig);
525
526 EnumValue negSupport;
527 ehtConfig->GetAttributeFailSafe("TidToLinkMappingNegSupport", negSupport);
528
529 NS_ABORT_MSG_IF(negSupport.Get() == 0,
530 "Cannot request TID-to-Link Mapping if negotiation is not supported");
531
532 // store the mappings, so that we can enforce them when the AP MLD accepts them
533 m_dlTidLinkMappingInAssocReq = ehtConfig->GetTidLinkMapping(WifiDirection::DOWNLINK);
534 m_ulTidLinkMappingInAssocReq = ehtConfig->GetTidLinkMapping(WifiDirection::UPLINK);
535
539 negSupport.Get() == 1 && !mappingValidForNegType1,
540 "Mapping TIDs to distinct link sets is incompatible with negotiation support of 1");
541
542 if (apNegSupport == 1 && !mappingValidForNegType1)
543 {
544 // If the TID-to-link Mapping Negotiation Support subfield value received from a peer
545 // MLD is equal to 1, the MLD that initiates a TID-to-link mapping negotiation with the
546 // peer MLD shall send only the TID-to-link Mapping element where all TIDs are mapped to
547 // the same link set (Sec. 35.3.7.1.3 of 802.11be D3.1). We use default mapping to meet
548 // this requirement.
549 NS_LOG_DEBUG("Using default mapping because AP MLD advertised negotiation support of 1");
552 }
553
554 std::vector<TidToLinkMapping> ret(1);
555
556 ret.back().m_control.direction = WifiDirection::DOWNLINK;
557
558 // lambda to fill the last TID-to-Link Mapping IE in the vector to return
559 auto fillIe = [&ret](const auto& mapping) {
560 ret.back().m_control.defaultMapping = mapping.empty();
561
562 for (const auto& [tid, linkSet] : mapping)
563 {
564 // At any point in time, a TID shall always be mapped to at least one setup link both
565 // in DL and UL, which means that a TID-to-link mapping change is only valid and
566 // successful if it will not result in having any TID for which the link set for DL
567 // or UL is made of zero setup links (Sec. 35.3.7.1.1 of 802.11be D3.1)
568 NS_ABORT_MSG_IF(linkSet.empty(), "Cannot map a TID to an empty link set");
569 ret.back().SetLinkMappingOfTid(tid, linkSet);
570 }
571 };
572
574
576 {
577 ret.back().m_control.direction = WifiDirection::BOTH_DIRECTIONS;
578 return ret;
579 }
580
581 ret.emplace_back();
582 ret.back().m_control.direction = WifiDirection::UPLINK;
584
585 return ret;
586}
587
588void
590{
591 // find the link where the (Re)Association Request has to be sent
592 auto it = GetLinks().cbegin();
593 while (it != GetLinks().cend())
594 {
595 if (GetStaLink(it->second).sendAssocReq)
596 {
597 break;
598 }
599 it++;
600 }
601 NS_ABORT_MSG_IF(it == GetLinks().cend(),
602 "No link selected to send the (Re)Association Request");
603 uint8_t linkId = it->first;
604 auto& link = GetLink(linkId);
605 NS_ABORT_MSG_IF(!link.bssid.has_value(),
606 "No BSSID set for the link on which the (Re)Association Request is to be sent");
607
608 NS_LOG_FUNCTION(this << *link.bssid << isReassoc);
609 WifiMacHeader hdr;
611 hdr.SetAddr1(*link.bssid);
612 hdr.SetAddr2(link.feManager->GetAddress());
613 hdr.SetAddr3(*link.bssid);
614 hdr.SetDsNotFrom();
615 hdr.SetDsNotTo();
616 Ptr<Packet> packet = Create<Packet>();
617
618 auto frame = GetAssociationRequest(isReassoc, linkId);
619
620 // include a Multi-Link Element if this device has multiple links (independently
621 // of how many links will be setup) and the AP is a multi-link device;
622 // if the AP MLD has indicated a support of TID-to-link mapping negotiation, also
623 // include the TID-to-link Mapping element(s)
624 if (GetNLinks() > 1 &&
625 GetWifiRemoteStationManager(linkId)->GetMldAddress(*link.bssid).has_value())
626 {
627 auto addMle = [&](auto&& frame) {
628 frame.template Get<MultiLinkElement>() = GetMultiLinkElement(isReassoc, linkId);
629 };
630 std::visit(addMle, frame);
631
632 uint8_t negSupport;
633 if (const auto& mldCapabilities =
634 GetWifiRemoteStationManager(linkId)->GetStationMldCapabilities(*link.bssid);
635 mldCapabilities && (negSupport = mldCapabilities->get().tidToLinkMappingSupport) > 0)
636 {
637 auto addTlm = [&](auto&& frame) {
638 frame.template Get<TidToLinkMapping>() = GetTidToLinkMappingElements(negSupport);
639 };
640 std::visit(addTlm, frame);
641 }
642 }
643
644 if (!isReassoc)
645 {
646 packet->AddHeader(std::get<MgtAssocRequestHeader>(frame));
647 }
648 else
649 {
650 packet->AddHeader(std::get<MgtReassocRequestHeader>(frame));
651 }
652
653 if (!GetQosSupported())
654 {
655 GetTxop()->Queue(packet, hdr);
656 }
657 // "A QoS STA that transmits a Management frame determines access category used
658 // for medium access in transmission of the Management frame as follows
659 // (If dot11QMFActivated is false or not present)
660 // — If the Management frame is individually addressed to a non-QoS STA, category
661 // AC_BE should be selected.
662 // — If category AC_BE was not selected by the previous step, category AC_VO
663 // shall be selected." (Sec. 10.2.3.2 of 802.11-2020)
664 else if (!GetWifiRemoteStationManager(linkId)->GetQosSupported(*link.bssid))
665 {
666 GetBEQueue()->Queue(packet, hdr);
667 }
668 else
669 {
670 GetVOQueue()->Queue(packet, hdr);
671 }
672
674 {
676 }
679}
680
681void
683{
684 NS_LOG_FUNCTION(this);
685 switch (m_state)
686 {
687 case ASSOCIATED:
688 return;
689 case SCANNING:
690 /* we have initiated active or passive scanning, continue to wait
691 and gather beacons or probe responses until the scanning timeout
692 */
693 break;
694 case UNASSOCIATED:
695 /* we were associated but we missed a bunch of beacons
696 * so we should assume we are not associated anymore.
697 * We try to initiate a scan now.
698 */
699 m_linkDown();
701 break;
702 case WAIT_ASSOC_RESP:
703 /* we have sent an association request so we do not need to
704 re-send an association request right now. We just need to
705 wait until either assoc-request-timeout or until
706 we get an association response.
707 */
708 break;
709 case REFUSED:
710 /* we have sent an association request and received a negative
711 association response. We wait until someone restarts an
712 association with a given SSID.
713 */
714 break;
715 }
716}
717
718void
720{
721 NS_LOG_FUNCTION(this);
724
725 WifiScanParams scanParams;
726 scanParams.ssid = GetSsid();
727 for (const auto& [id, link] : GetLinks())
728 {
730 (link->phy->HasFixedPhyBand()) ? WifiScanParams::Channel{0, link->phy->GetPhyBand()}
732
733 scanParams.channelList.push_back(channel);
734 }
735 if (m_activeProbing)
736 {
737 scanParams.type = WifiScanType::ACTIVE;
739 scanParams.minChannelTime = scanParams.maxChannelTime = m_probeRequestTimeout;
740 }
741 else
742 {
743 scanParams.type = WifiScanType::PASSIVE;
745 }
746
747 m_assocManager->StartScanning(std::move(scanParams));
748}
749
750void
751StaWifiMac::ScanningTimeout(const std::optional<ApInfo>& bestAp)
752{
753 NS_LOG_FUNCTION(this);
754
755 if (!bestAp.has_value())
756 {
757 NS_LOG_DEBUG("Exhausted list of candidate AP; restart scanning");
759 return;
760 }
761
762 NS_LOG_DEBUG("Attempting to associate with AP: " << *bestAp);
763 UpdateApInfo(bestAp->m_frame, bestAp->m_apAddr, bestAp->m_bssid, bestAp->m_linkId);
764 // reset info on links to setup
765 for (auto& [id, link] : GetLinks())
766 {
767 auto& staLink = GetStaLink(link);
768 staLink.sendAssocReq = false;
769 staLink.bssid = std::nullopt;
770 }
771 // send Association Request on the link where the Beacon/Probe Response was received
772 GetLink(bestAp->m_linkId).sendAssocReq = true;
773 GetLink(bestAp->m_linkId).bssid = bestAp->m_bssid;
774 std::shared_ptr<CommonInfoBasicMle> mleCommonInfo;
775 // update info on links to setup (11be MLDs only)
776 const auto& mle =
777 std::visit([](auto&& frame) { return frame.template Get<MultiLinkElement>(); },
778 bestAp->m_frame);
779 std::map<uint8_t, uint8_t> swapInfo;
780 for (const auto& [localLinkId, apLinkId, bssid] : bestAp->m_setupLinks)
781 {
782 NS_ASSERT_MSG(mle, "We get here only for ML setup");
783 NS_LOG_DEBUG("Setting up link (local ID=" << +localLinkId << ", AP ID=" << +apLinkId
784 << ")");
785 GetLink(localLinkId).bssid = bssid;
786 if (!mleCommonInfo)
787 {
788 mleCommonInfo = std::make_shared<CommonInfoBasicMle>(mle->GetCommonInfoBasic());
789 }
790 GetWifiRemoteStationManager(localLinkId)->AddStationMleCommonInfo(bssid, mleCommonInfo);
791 swapInfo.emplace(localLinkId, apLinkId);
792 }
793
794 SwapLinks(swapInfo);
795
796 // lambda to get beacon interval from Beacon or Probe Response
797 auto getBeaconInterval = [](auto&& frame) {
798 using T = std::decay_t<decltype(frame)>;
799 if constexpr (std::is_same_v<T, MgtBeaconHeader> ||
800 std::is_same_v<T, MgtProbeResponseHeader>)
801 {
802 return MicroSeconds(frame.GetBeaconIntervalUs());
803 }
804 else
805 {
806 NS_ABORT_MSG("Unexpected frame type");
807 return Seconds(0);
808 }
809 };
810 Time beaconInterval = std::visit(getBeaconInterval, bestAp->m_frame);
811 Time delay = beaconInterval * m_maxMissedBeacons;
812 // restart beacon watchdog for all links to setup
813 for (const auto& [id, link] : GetLinks())
814 {
815 if (GetStaLink(link).bssid.has_value() || GetNLinks() == 1)
816 {
817 RestartBeaconWatchdog(delay, id);
818 }
819 }
822}
823
824void
826{
827 NS_LOG_FUNCTION(this);
830}
831
832void
834{
835 NS_LOG_FUNCTION(this << +linkId);
836 auto& link = GetLink(linkId);
837 if (link.beaconWatchdogEnd > Simulator::Now())
838 {
839 if (link.beaconWatchdog.IsRunning())
840 {
841 link.beaconWatchdog.Cancel();
842 }
843 link.beaconWatchdog = Simulator::Schedule(link.beaconWatchdogEnd - Simulator::Now(),
845 this,
846 linkId);
847 return;
848 }
849 NS_LOG_DEBUG("beacon missed");
850 // We need to switch to the UNASSOCIATED state. However, if we are receiving
851 // a frame, wait until the RX is completed (otherwise, crashes may occur if
852 // we are receiving a MU frame because its reception requires the STA-ID)
853 Time delay = Seconds(0);
854 if (GetWifiPhy(linkId)->IsStateRx())
855 {
856 delay = GetWifiPhy(linkId)->GetDelayUntilIdle();
857 }
858 Simulator::Schedule(delay, &StaWifiMac::Disassociated, this, linkId);
859}
860
861void
863{
864 NS_LOG_FUNCTION(this << +linkId);
865
866 auto& link = GetLink(linkId);
867 if (link.bssid.has_value())
868 {
869 // this is a link setup in an ML setup
870 m_setupCanceled(linkId, GetBssid(linkId));
871 }
872
873 // disable the given link
874 link.bssid = std::nullopt;
875 link.phy->SetOffMode();
876
877 for (const auto& [id, lnk] : GetLinks())
878 {
879 if (GetStaLink(lnk).bssid.has_value())
880 {
881 // found an enabled link
882 return;
883 }
884 }
885
886 NS_LOG_DEBUG("Set state to UNASSOCIATED and start scanning");
888 // cancel the association request timer (see issue #862)
890 auto mldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(GetBssid(linkId));
891 if (GetNLinks() > 1 && mldAddress.has_value())
892 {
893 // trace the AP MLD address
894 m_deAssocLogger(*mldAddress);
895 }
896 else
897 {
898 m_deAssocLogger(GetBssid(linkId));
899 }
900 m_aid = 0; // reset AID
901 // ensure all links are on
902 for (const auto& [id, lnk] : GetLinks())
903 {
904 lnk->phy->ResumeFromOff();
905 }
907}
908
909void
911{
912 NS_LOG_FUNCTION(this << delay << +linkId);
913 auto& link = GetLink(linkId);
914 link.beaconWatchdogEnd = std::max(Simulator::Now() + delay, link.beaconWatchdogEnd);
915 if (Simulator::GetDelayLeft(link.beaconWatchdog) < delay && link.beaconWatchdog.IsExpired())
916 {
917 NS_LOG_DEBUG("really restart watchdog.");
918 link.beaconWatchdog = Simulator::Schedule(delay, &StaWifiMac::MissedBeacons, this, linkId);
919 }
920}
921
922bool
924{
925 return m_state == ASSOCIATED;
926}
927
928bool
930{
931 return m_state == WAIT_ASSOC_RESP;
932}
933
934std::set<uint8_t>
936{
937 if (!IsAssociated())
938 {
939 return {};
940 }
941
942 std::set<uint8_t> linkIds;
943 for (const auto& [id, link] : GetLinks())
944 {
945 if (GetStaLink(link).bssid)
946 {
947 linkIds.insert(id);
948 }
949 }
950 return linkIds;
951}
952
955{
956 auto linkIds = GetSetupLinkIds();
957 NS_ASSERT_MSG(!linkIds.empty(), "Not associated");
958 uint8_t linkId = *linkIds.begin();
959 return GetFrameExchangeManager(linkId)->GetAddress();
960}
961
962bool
964{
965 return (IsAssociated());
966}
967
968void
970{
971 NS_LOG_FUNCTION(this << packet << to);
972 if (!CanForwardPacketsTo(to))
973 {
974 NotifyTxDrop(packet);
976 return;
977 }
978 WifiMacHeader hdr;
979
980 // If we are not a QoS AP then we definitely want to use AC_BE to
981 // transmit the packet. A TID of zero will map to AC_BE (through \c
982 // QosUtilsMapTidToAc()), so we use that as our default here.
983 uint8_t tid = 0;
984
985 // For now, an AP that supports QoS does not support non-QoS
986 // associations, and vice versa. In future the AP model should
987 // support simultaneously associated QoS and non-QoS STAs, at which
988 // point there will need to be per-association QoS state maintained
989 // by the association state machine, and consulted here.
990 if (GetQosSupported())
991 {
994 hdr.SetQosNoEosp();
995 hdr.SetQosNoAmsdu();
996 // Transmission of multiple frames in the same TXOP is not
997 // supported for now
998 hdr.SetQosTxopLimit(0);
999
1000 // Fill in the QoS control field in the MAC header
1001 tid = QosUtilsGetTidForPacket(packet);
1002 // Any value greater than 7 is invalid and likely indicates that
1003 // the packet had no QoS tag, so we revert to zero, which'll
1004 // mean that AC_BE is used.
1005 if (tid > 7)
1006 {
1007 tid = 0;
1008 }
1009 hdr.SetQosTid(tid);
1010 }
1011 else
1012 {
1014 }
1015 if (GetQosSupported())
1016 {
1017 hdr.SetNoOrder(); // explicitly set to 0 for the time being since HT control field is not
1018 // yet implemented (set it to 1 when implemented)
1019 }
1020
1021 // the Receiver Address (RA) and the Transmitter Address (TA) are the MLD addresses only for
1022 // non-broadcast data frames exchanged between two MLDs
1023 auto linkIds = GetSetupLinkIds();
1024 NS_ASSERT(!linkIds.empty());
1025 uint8_t linkId = *linkIds.begin();
1026 if (const auto apMldAddr = GetWifiRemoteStationManager(linkId)->GetMldAddress(GetBssid(linkId)))
1027 {
1028 hdr.SetAddr1(*apMldAddr);
1029 hdr.SetAddr2(GetAddress());
1030 }
1031 else
1032 {
1033 hdr.SetAddr1(GetBssid(linkId));
1035 }
1036
1037 hdr.SetAddr3(to);
1038 hdr.SetDsNotFrom();
1039 hdr.SetDsTo();
1040
1041 if (GetQosSupported())
1042 {
1043 // Sanity check that the TID is valid
1044 NS_ASSERT(tid < 8);
1045 GetQosTxop(tid)->Queue(packet, hdr);
1046 }
1047 else
1048 {
1049 GetTxop()->Queue(packet, hdr);
1050 }
1051}
1052
1053void
1055{
1056 NS_LOG_FUNCTION(this << linkId << reason);
1057
1058 auto bssid = GetBssid(linkId);
1059 auto apAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(bssid).value_or(bssid);
1060
1061 BlockUnicastTxOnLinks(reason, apAddress, {linkId});
1062 // the only type of broadcast frames that a non-AP STA can send are management frames
1063 for (const auto [acIndex, ac] : wifiAcList)
1064 {
1065 GetMacQueueScheduler()->BlockQueues(reason,
1066 acIndex,
1069 GetFrameExchangeManager(linkId)->GetAddress(),
1070 {},
1071 {linkId});
1072 }
1073}
1074
1075void
1077{
1078 NS_LOG_FUNCTION(this << linkId << reason);
1079
1080 auto bssid = GetBssid(linkId);
1081 auto apAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(bssid).value_or(bssid);
1082
1083 UnblockUnicastTxOnLinks(reason, apAddress, {linkId});
1084 // the only type of broadcast frames that a non-AP STA can send are management frames
1085 for (const auto [acIndex, ac] : wifiAcList)
1086 {
1087 GetMacQueueScheduler()->UnblockQueues(reason,
1088 acIndex,
1091 GetFrameExchangeManager(linkId)->GetAddress(),
1092 {},
1093 {linkId});
1094 }
1095}
1096
1097void
1099{
1100 NS_LOG_FUNCTION(this << *mpdu << +linkId);
1101 // consider the MAC header of the original MPDU (makes a difference for data frames only)
1102 const WifiMacHeader* hdr = &mpdu->GetOriginal()->GetHeader();
1103 Ptr<const Packet> packet = mpdu->GetPacket();
1104 NS_ASSERT(!hdr->IsCtl());
1106 : GetFrameExchangeManager(linkId)->GetAddress();
1107 if (hdr->GetAddr3() == myAddr)
1108 {
1109 NS_LOG_LOGIC("packet sent by us.");
1110 return;
1111 }
1112 if (hdr->GetAddr1() != myAddr && !hdr->GetAddr1().IsGroup())
1113 {
1114 NS_LOG_LOGIC("packet is not for us");
1115 NotifyRxDrop(packet);
1116 return;
1117 }
1118 if (hdr->IsData())
1119 {
1120 if (!IsAssociated())
1121 {
1122 NS_LOG_LOGIC("Received data frame while not associated: ignore");
1123 NotifyRxDrop(packet);
1124 return;
1125 }
1126 if (!(hdr->IsFromDs() && !hdr->IsToDs()))
1127 {
1128 NS_LOG_LOGIC("Received data frame not from the DS: ignore");
1129 NotifyRxDrop(packet);
1130 return;
1131 }
1132 std::set<Mac48Address> apAddresses; // link addresses of AP
1133 for (auto id : GetSetupLinkIds())
1134 {
1135 apAddresses.insert(GetBssid(id));
1136 }
1137 if (apAddresses.count(mpdu->GetHeader().GetAddr2()) == 0)
1138 {
1139 NS_LOG_LOGIC("Received data frame not from the BSS we are associated with: ignore");
1140 NotifyRxDrop(packet);
1141 return;
1142 }
1143 if (!hdr->HasData())
1144 {
1145 NS_LOG_LOGIC("Received (QoS) Null Data frame: ignore");
1146 NotifyRxDrop(packet);
1147 return;
1148 }
1149 if (hdr->IsQosData())
1150 {
1151 if (hdr->IsQosAmsdu())
1152 {
1153 NS_ASSERT(apAddresses.count(mpdu->GetHeader().GetAddr3()) != 0);
1155 packet = nullptr;
1156 }
1157 else
1158 {
1159 ForwardUp(packet, hdr->GetAddr3(), hdr->GetAddr1());
1160 }
1161 }
1162 else
1163 {
1164 ForwardUp(packet, hdr->GetAddr3(), hdr->GetAddr1());
1165 }
1166 return;
1167 }
1168
1169 switch (hdr->GetType())
1170 {
1174 // This is a frame aimed at an AP, so we can safely ignore it.
1175 NotifyRxDrop(packet);
1176 break;
1177
1179 ReceiveBeacon(mpdu, linkId);
1180 break;
1181
1183 ReceiveProbeResp(mpdu, linkId);
1184 break;
1185
1188 ReceiveAssocResp(mpdu, linkId);
1189 break;
1190
1192 if (auto [category, action] = WifiActionHeader::Peek(packet);
1193 category == WifiActionHeader::PROTECTED_EHT &&
1194 action.protectedEhtAction ==
1196 {
1197 // this is handled by the EMLSR Manager
1198 break;
1199 }
1200
1201 default:
1202 // Invoke the receive handler of our parent class to deal with any
1203 // other frames. Specifically, this will handle Block Ack-related
1204 // Management Action frames.
1205 WifiMac::Receive(mpdu, linkId);
1206 }
1207
1208 if (m_emlsrManager)
1209 {
1210 m_emlsrManager->NotifyMgtFrameReceived(mpdu, linkId);
1211 }
1212}
1213
1214void
1216{
1217 NS_LOG_FUNCTION(this << *mpdu << +linkId);
1218 const WifiMacHeader& hdr = mpdu->GetHeader();
1219 NS_ASSERT(hdr.IsBeacon());
1220
1221 NS_LOG_DEBUG("Beacon received");
1222 MgtBeaconHeader beacon;
1223 mpdu->GetPacket()->PeekHeader(beacon);
1224 const auto& capabilities = beacon.Capabilities();
1225 NS_ASSERT(capabilities.IsEss());
1226 bool goodBeacon;
1227 if (IsWaitAssocResp() || IsAssociated())
1228 {
1229 // we have to process this Beacon only if sent by the AP we are associated
1230 // with or from which we are waiting an Association Response frame
1231 auto bssid = GetLink(linkId).bssid;
1232 goodBeacon = bssid.has_value() && (hdr.GetAddr3() == *bssid);
1233 }
1234 else
1235 {
1236 // we retain this Beacon as candidate AP if the supported rates fit the
1237 // configured BSS membership selector
1238 goodBeacon = CheckSupportedRates(beacon, linkId);
1239 }
1240
1241 SnrTag snrTag;
1242 bool found = mpdu->GetPacket()->PeekPacketTag(snrTag);
1243 NS_ASSERT(found);
1244 ApInfo apInfo = {.m_bssid = hdr.GetAddr3(),
1245 .m_apAddr = hdr.GetAddr2(),
1246 .m_snr = snrTag.Get(),
1247 .m_frame = std::move(beacon),
1248 .m_channel = {GetCurrentChannel(linkId)},
1249 .m_linkId = linkId};
1250
1251 if (!m_beaconInfo.IsEmpty())
1252 {
1253 m_beaconInfo(apInfo);
1254 }
1255
1256 if (!goodBeacon)
1257 {
1258 NS_LOG_LOGIC("Beacon is not for us");
1259 return;
1260 }
1261 if (m_state == ASSOCIATED)
1262 {
1264 Time delay = MicroSeconds(std::get<MgtBeaconHeader>(apInfo.m_frame).GetBeaconIntervalUs() *
1266 RestartBeaconWatchdog(delay, linkId);
1267 UpdateApInfo(apInfo.m_frame, hdr.GetAddr2(), hdr.GetAddr3(), linkId);
1268 }
1269 else
1270 {
1271 NS_LOG_DEBUG("Beacon received from " << hdr.GetAddr2());
1272 m_assocManager->NotifyApInfo(std::move(apInfo));
1273 }
1274}
1275
1276void
1278{
1279 NS_LOG_FUNCTION(this << *mpdu << +linkId);
1280 const WifiMacHeader& hdr = mpdu->GetHeader();
1281 NS_ASSERT(hdr.IsProbeResp());
1282
1283 NS_LOG_DEBUG("Probe response received from " << hdr.GetAddr2());
1284 MgtProbeResponseHeader probeResp;
1285 mpdu->GetPacket()->PeekHeader(probeResp);
1286 if (!CheckSupportedRates(probeResp, linkId))
1287 {
1288 return;
1289 }
1290 SnrTag snrTag;
1291 bool found = mpdu->GetPacket()->PeekPacketTag(snrTag);
1292 NS_ASSERT(found);
1293 m_assocManager->NotifyApInfo(ApInfo{.m_bssid = hdr.GetAddr3(),
1294 .m_apAddr = hdr.GetAddr2(),
1295 .m_snr = snrTag.Get(),
1296 .m_frame = std::move(probeResp),
1297 .m_channel = {GetCurrentChannel(linkId)},
1298 .m_linkId = linkId});
1299}
1300
1301void
1303{
1304 NS_LOG_FUNCTION(this << *mpdu << +linkId);
1305 const WifiMacHeader& hdr = mpdu->GetHeader();
1306 NS_ASSERT(hdr.IsAssocResp() || hdr.IsReassocResp());
1307
1308 if (m_state != WAIT_ASSOC_RESP)
1309 {
1310 return;
1311 }
1312
1313 std::optional<Mac48Address> apMldAddress;
1314 MgtAssocResponseHeader assocResp;
1315 mpdu->GetPacket()->PeekHeader(assocResp);
1317 {
1319 }
1320 if (assocResp.GetStatusCode().IsSuccess())
1321 {
1322 m_aid = assocResp.GetAssociationId();
1323 NS_LOG_DEBUG((hdr.IsReassocResp() ? "reassociation done" : "association completed"));
1324 UpdateApInfo(assocResp, hdr.GetAddr2(), hdr.GetAddr3(), linkId);
1325 NS_ASSERT(GetLink(linkId).bssid.has_value() && *GetLink(linkId).bssid == hdr.GetAddr3());
1326 SetBssid(hdr.GetAddr3(), linkId);
1328 if ((GetNLinks() > 1) && assocResp.Get<MultiLinkElement>().has_value())
1329 {
1330 // this is an ML setup, trace the setup link
1331 m_setupCompleted(linkId, hdr.GetAddr3());
1332 apMldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(hdr.GetAddr3());
1333 NS_ASSERT(apMldAddress);
1334
1335 if (const auto& mldCapabilities =
1336 GetWifiRemoteStationManager(linkId)->GetStationMldCapabilities(hdr.GetAddr3());
1337 mldCapabilities && mldCapabilities->get().tidToLinkMappingSupport > 0)
1338 {
1339 // the AP MLD supports TID-to-Link Mapping negotiation, hence we included
1340 // TID-to-Link Mapping element(s) in the Association Request.
1341 if (assocResp.Get<TidToLinkMapping>().empty())
1342 {
1343 // The AP MLD did not include a TID-to-Link Mapping element in the Association
1344 // Response, hence it accepted the mapping, which we can now store.
1345 UpdateTidToLinkMapping(*apMldAddress,
1348 UpdateTidToLinkMapping(*apMldAddress,
1351
1352 // Apply the negotiated TID-to-Link Mapping (if any) for UL direction
1354 }
1355 }
1356 }
1357 else
1358 {
1359 m_assocLogger(hdr.GetAddr3());
1360 }
1361 if (!m_linkUp.IsNull())
1362 {
1363 m_linkUp();
1364 }
1365 }
1366 else
1367 {
1368 // If the link on which the (Re)Association Request frame was received cannot be
1369 // accepted by the AP MLD, the AP MLD shall treat the multi-link (re)setup as a
1370 // failure and shall not accept any requested links. If the link on which the
1371 // (Re)Association Request frame was received is accepted by the AP MLD, the
1372 // multi-link (re)setup is successful. (Sec. 35.3.5.1 of 802.11be D3.1)
1373 NS_LOG_DEBUG("association refused");
1375 StartScanning();
1376 return;
1377 }
1378
1379 // if this is an MLD, check if we can setup (other) links
1380 if (GetNLinks() > 1)
1381 {
1382 // create a list of all local Link IDs. IDs are removed as we find a corresponding
1383 // Per-STA Profile Subelements indicating successful association. Links with
1384 // remaining IDs are not setup
1385 std::list<uint8_t> setupLinks;
1386 for (const auto& [id, link] : GetLinks())
1387 {
1388 setupLinks.push_back(id);
1389 }
1390 if (assocResp.GetStatusCode().IsSuccess())
1391 {
1392 setupLinks.remove(linkId);
1393 }
1394
1395 // if a Multi-Link Element is present, check its content
1396 if (const auto& mle = assocResp.Get<MultiLinkElement>())
1397 {
1398 NS_ABORT_MSG_IF(!GetLink(linkId).bssid.has_value(),
1399 "The link on which the Association Response was received "
1400 "is not a link we requested to setup");
1401 NS_ABORT_MSG_IF(linkId != mle->GetLinkIdInfo(),
1402 "The link ID of the AP that transmitted the Association "
1403 "Response does not match the stored link ID");
1405 mle->GetMldMacAddress(),
1406 "The AP MLD MAC address in the received Multi-Link Element does not "
1407 "match the address stored in the station manager for link "
1408 << +linkId);
1409 // process the Per-STA Profile Subelements in the Multi-Link Element
1410 for (std::size_t elem = 0; elem < mle->GetNPerStaProfileSubelements(); elem++)
1411 {
1412 auto& perStaProfile = mle->GetPerStaProfile(elem);
1413 uint8_t apLinkId = perStaProfile.GetLinkId();
1414 auto it = GetLinks().find(apLinkId);
1415 uint8_t staLinkid = 0;
1416 std::optional<Mac48Address> bssid;
1417 NS_ABORT_MSG_IF(it == GetLinks().cend() ||
1418 !(bssid = GetLink((staLinkid = it->first)).bssid).has_value(),
1419 "Setup for AP link ID " << apLinkId << " was not requested");
1420 NS_ABORT_MSG_IF(*bssid != perStaProfile.GetStaMacAddress(),
1421 "The BSSID in the Per-STA Profile for link ID "
1422 << +staLinkid << " does not match the stored BSSID");
1425 perStaProfile.GetStaMacAddress()) != mle->GetMldMacAddress(),
1426 "The AP MLD MAC address in the received Multi-Link Element does not "
1427 "match the address stored in the station manager for link "
1428 << +staLinkid);
1429 // process the Association Response contained in this Per-STA Profile
1430 MgtAssocResponseHeader assoc = perStaProfile.GetAssocResponse();
1431 if (assoc.GetStatusCode().IsSuccess())
1432 {
1433 NS_ABORT_MSG_IF(m_aid != 0 && m_aid != assoc.GetAssociationId(),
1434 "AID should be the same for all the links");
1435 m_aid = assoc.GetAssociationId();
1436 NS_LOG_DEBUG("Setup on link " << staLinkid << " completed");
1437 UpdateApInfo(assoc, *bssid, *bssid, staLinkid);
1438 SetBssid(*bssid, staLinkid);
1439 m_setupCompleted(staLinkid, *bssid);
1441 apMldAddress = GetWifiRemoteStationManager(staLinkid)->GetMldAddress(*bssid);
1442 if (!m_linkUp.IsNull())
1443 {
1444 m_linkUp();
1445 }
1446 }
1447 // remove the ID of the link we setup
1448 setupLinks.remove(staLinkid);
1449 }
1450 }
1451 // remaining links in setupLinks are not setup and hence must be disabled
1452 for (const auto& id : setupLinks)
1453 {
1454 GetLink(id).bssid = std::nullopt;
1455 GetLink(id).phy->SetOffMode();
1456 }
1457 if (apMldAddress)
1458 {
1459 // this is an ML setup, trace the MLD address of the AP (only once)
1460 m_assocLogger(*apMldAddress);
1461 }
1462 }
1463
1465}
1466
1467void
1469{
1470 NS_LOG_FUNCTION(this << linkId);
1471
1472 // STAs operating on setup links may need to transition to a new PM mode after the
1473 // acknowledgement of the Association Response. For this purpose, we connect a callback to
1474 // the PHY TX begin trace to catch the Ack transmitted after the Association Response.
1476 [=](WifiConstPsduMap psduMap, WifiTxVector txVector, double /* txPowerW */) {
1477 NS_ASSERT_MSG(psduMap.size() == 1 && psduMap.begin()->second->GetNMpdus() == 1 &&
1478 psduMap.begin()->second->GetHeader(0).IsAck(),
1479 "Expected a Normal Ack after Association Response frame");
1480
1481 auto ackDuration =
1482 WifiPhy::CalculateTxDuration(psduMap, txVector, GetLink(linkId).phy->GetPhyBand());
1483
1484 for (const auto& [id, lnk] : GetLinks())
1485 {
1486 auto& link = GetStaLink(lnk);
1487
1488 if (!link.bssid)
1489 {
1490 // link has not been setup
1491 continue;
1492 }
1493
1494 if (id == linkId)
1495 {
1504 // if the user requested this link to be in powersave mode, we have to
1505 // switch PM mode
1506 if (link.pmMode == WIFI_PM_POWERSAVE)
1507 {
1508 Simulator::Schedule(ackDuration,
1510 this,
1511 std::pair<bool, uint8_t>{true, id});
1512 }
1513 link.pmMode = WIFI_PM_ACTIVE;
1514 }
1515 else
1516 {
1525 // if the user requested this link to be in active mode, we have to
1526 // switch PM mode
1527 if (link.pmMode == WIFI_PM_ACTIVE)
1528 {
1529 Simulator::Schedule(ackDuration,
1531 this,
1532 std::pair<bool, uint8_t>{false, id});
1533 }
1534 link.pmMode = WIFI_PM_POWERSAVE;
1535 }
1536 }
1537 });
1538
1539 // connect the callback to the PHY TX begin trace to catch the Ack and disconnect
1540 // after its transmission begins
1541 auto phy = GetLink(linkId).phy;
1542 phy->TraceConnectWithoutContext("PhyTxPsduBegin", cb);
1543 Simulator::Schedule(phy->GetSifs() + NanoSeconds(1),
1544 [=]() { phy->TraceDisconnectWithoutContext("PhyTxPsduBegin", cb); });
1545}
1546
1547bool
1548StaWifiMac::CheckSupportedRates(std::variant<MgtBeaconHeader, MgtProbeResponseHeader> frame,
1549 uint8_t linkId)
1550{
1551 NS_LOG_FUNCTION(this << +linkId);
1552
1553 // lambda to invoke on the current frame variant
1554 auto check = [&](auto&& mgtFrame) -> bool {
1555 // check supported rates
1556 NS_ASSERT(mgtFrame.template Get<SupportedRates>());
1557 const auto rates = AllSupportedRates{*mgtFrame.template Get<SupportedRates>(),
1558 mgtFrame.template Get<ExtendedSupportedRatesIE>()};
1559 for (const auto& selector : GetWifiPhy(linkId)->GetBssMembershipSelectorList())
1560 {
1561 if (!rates.IsBssMembershipSelectorRate(selector))
1562 {
1563 NS_LOG_DEBUG("Supported rates do not fit with the BSS membership selector");
1564 return false;
1565 }
1566 }
1567
1568 return true;
1569 };
1570
1571 return std::visit(check, frame);
1572}
1573
1574void
1576 const Mac48Address& apAddr,
1577 const Mac48Address& bssid,
1578 uint8_t linkId)
1579{
1580 NS_LOG_FUNCTION(this << frame.index() << apAddr << bssid << +linkId);
1581
1582 // ERP Information is not present in Association Response frames
1583 const std::optional<ErpInformation>* erpInformation = nullptr;
1584
1585 if (const auto* beacon = std::get_if<MgtBeaconHeader>(&frame))
1586 {
1587 erpInformation = &beacon->Get<ErpInformation>();
1588 }
1589 else if (const auto* probe = std::get_if<MgtProbeResponseHeader>(&frame))
1590 {
1591 erpInformation = &probe->Get<ErpInformation>();
1592 }
1593
1594 // lambda processing Information Elements included in all frame types
1595 auto commonOps = [&](auto&& frame) {
1596 const auto& capabilities = frame.Capabilities();
1597 NS_ASSERT(frame.template Get<SupportedRates>());
1598 const auto rates = AllSupportedRates{*frame.template Get<SupportedRates>(),
1599 frame.template Get<ExtendedSupportedRatesIE>()};
1600 for (const auto& mode : GetWifiPhy(linkId)->GetModeList())
1601 {
1602 if (rates.IsSupportedRate(mode.GetDataRate(GetWifiPhy(linkId)->GetChannelWidth())))
1603 {
1604 GetWifiRemoteStationManager(linkId)->AddSupportedMode(apAddr, mode);
1605 if (rates.IsBasicRate(mode.GetDataRate(GetWifiPhy(linkId)->GetChannelWidth())))
1606 {
1608 }
1609 }
1610 }
1611
1612 bool isShortPreambleEnabled = capabilities.IsShortPreamble();
1613 if (erpInformation && erpInformation->has_value() && GetErpSupported(linkId))
1614 {
1615 isShortPreambleEnabled &= !(*erpInformation)->GetBarkerPreambleMode();
1616 if ((*erpInformation)->GetUseProtection() != 0)
1617 {
1619 }
1620 else
1621 {
1623 }
1624 if (capabilities.IsShortSlotTime() == true)
1625 {
1626 // enable short slot time
1627 GetWifiPhy(linkId)->SetSlot(MicroSeconds(9));
1628 }
1629 else
1630 {
1631 // disable short slot time
1632 GetWifiPhy(linkId)->SetSlot(MicroSeconds(20));
1633 }
1634 }
1635 GetWifiRemoteStationManager(linkId)->SetShortPreambleEnabled(isShortPreambleEnabled);
1637 capabilities.IsShortSlotTime());
1638
1639 if (!GetQosSupported())
1640 {
1641 return;
1642 }
1643 /* QoS station */
1644 bool qosSupported = false;
1645 const auto& edcaParameters = frame.template Get<EdcaParameterSet>();
1646 if (edcaParameters.has_value())
1647 {
1648 qosSupported = true;
1649 // The value of the TXOP Limit field is specified as an unsigned integer, with the least
1650 // significant octet transmitted first, in units of 32 μs.
1652 edcaParameters->GetBeCWmin(),
1653 edcaParameters->GetBeCWmax(),
1654 edcaParameters->GetBeAifsn(),
1655 32 * MicroSeconds(edcaParameters->GetBeTxopLimit())},
1656 linkId);
1658 edcaParameters->GetBkCWmin(),
1659 edcaParameters->GetBkCWmax(),
1660 edcaParameters->GetBkAifsn(),
1661 32 * MicroSeconds(edcaParameters->GetBkTxopLimit())},
1662 linkId);
1664 edcaParameters->GetViCWmin(),
1665 edcaParameters->GetViCWmax(),
1666 edcaParameters->GetViAifsn(),
1667 32 * MicroSeconds(edcaParameters->GetViTxopLimit())},
1668 linkId);
1670 edcaParameters->GetVoCWmin(),
1671 edcaParameters->GetVoCWmax(),
1672 edcaParameters->GetVoAifsn(),
1673 32 * MicroSeconds(edcaParameters->GetVoTxopLimit())},
1674 linkId);
1675 }
1676 GetWifiRemoteStationManager(linkId)->SetQosSupport(apAddr, qosSupported);
1677
1678 if (!GetHtSupported())
1679 {
1680 return;
1681 }
1682 /* HT station */
1683 if (const auto& htCapabilities = frame.template Get<HtCapabilities>();
1684 htCapabilities.has_value())
1685 {
1686 if (!htCapabilities->IsSupportedMcs(0))
1687 {
1689 }
1690 else
1691 {
1693 *htCapabilities);
1694 }
1695 }
1696 // TODO: process ExtendedCapabilities
1697 // ExtendedCapabilities extendedCapabilities = frame.GetExtendedCapabilities ();
1698
1699 // we do not return if VHT is not supported because HE STAs operating in
1700 // the 2.4 GHz band do not support VHT
1701 if (GetVhtSupported(linkId))
1702 {
1703 const auto& vhtCapabilities = frame.template Get<VhtCapabilities>();
1704 // we will always fill in RxHighestSupportedLgiDataRate field at TX, so this can be used
1705 // to check whether it supports VHT
1706 if (vhtCapabilities.has_value() &&
1707 vhtCapabilities->GetRxHighestSupportedLgiDataRate() > 0)
1708 {
1710 *vhtCapabilities);
1711 // const auto& vhtOperation = frame.GetVhtOperation ();
1712 for (const auto& mcs : GetWifiPhy(linkId)->GetMcsList(WIFI_MOD_CLASS_VHT))
1713 {
1714 if (vhtCapabilities->IsSupportedRxMcs(mcs.GetMcsValue()))
1715 {
1716 GetWifiRemoteStationManager(linkId)->AddSupportedMcs(apAddr, mcs);
1717 }
1718 }
1719 }
1720 }
1721
1722 if (!GetHeSupported())
1723 {
1724 return;
1725 }
1726 /* HE station */
1727 const auto& heCapabilities = frame.template Get<HeCapabilities>();
1728 if (heCapabilities.has_value() && heCapabilities->GetSupportedMcsAndNss() != 0)
1729 {
1730 GetWifiRemoteStationManager(linkId)->AddStationHeCapabilities(apAddr, *heCapabilities);
1731 for (const auto& mcs : GetWifiPhy(linkId)->GetMcsList(WIFI_MOD_CLASS_HE))
1732 {
1733 if (heCapabilities->IsSupportedRxMcs(mcs.GetMcsValue()))
1734 {
1735 GetWifiRemoteStationManager(linkId)->AddSupportedMcs(apAddr, mcs);
1736 }
1737 }
1738 if (const auto& heOperation = frame.template Get<HeOperation>();
1739 heOperation.has_value())
1740 {
1741 GetHeConfiguration()->SetAttribute("BssColor",
1742 UintegerValue(heOperation->GetBssColor()));
1743 }
1744 }
1745
1746 const auto& muEdcaParameters = frame.template Get<MuEdcaParameterSet>();
1747 if (muEdcaParameters.has_value())
1748 {
1750 muEdcaParameters->GetMuCwMin(AC_BE),
1751 muEdcaParameters->GetMuCwMax(AC_BE),
1752 muEdcaParameters->GetMuAifsn(AC_BE),
1753 muEdcaParameters->GetMuEdcaTimer(AC_BE)},
1754 linkId);
1756 muEdcaParameters->GetMuCwMin(AC_BK),
1757 muEdcaParameters->GetMuCwMax(AC_BK),
1758 muEdcaParameters->GetMuAifsn(AC_BK),
1759 muEdcaParameters->GetMuEdcaTimer(AC_BK)},
1760 linkId);
1762 muEdcaParameters->GetMuCwMin(AC_VI),
1763 muEdcaParameters->GetMuCwMax(AC_VI),
1764 muEdcaParameters->GetMuAifsn(AC_VI),
1765 muEdcaParameters->GetMuEdcaTimer(AC_VI)},
1766 linkId);
1768 muEdcaParameters->GetMuCwMin(AC_VO),
1769 muEdcaParameters->GetMuCwMax(AC_VO),
1770 muEdcaParameters->GetMuAifsn(AC_VO),
1771 muEdcaParameters->GetMuEdcaTimer(AC_VO)},
1772 linkId);
1773 }
1774
1775 if (!GetEhtSupported())
1776 {
1777 return;
1778 }
1779 /* EHT station */
1780 const auto& ehtCapabilities = frame.template Get<EhtCapabilities>();
1781 // TODO: once we support non constant rate managers, we should add checks here whether EHT
1782 // is supported by the peer
1783 GetWifiRemoteStationManager(linkId)->AddStationEhtCapabilities(apAddr, *ehtCapabilities);
1784
1785 if (const auto& mle = frame.template Get<MultiLinkElement>();
1786 mle && mle->HasEmlCapabilities() && m_emlsrManager)
1787 {
1788 m_emlsrManager->SetTransitionTimeout(mle->GetTransitionTimeout());
1789 }
1790 };
1791
1792 // process Information Elements included in the current frame variant
1793 std::visit(commonOps, frame);
1794}
1795
1796void
1797StaWifiMac::SetPowerSaveMode(const std::pair<bool, uint8_t>& enableLinkIdPair)
1798{
1799 const auto [enable, linkId] = enableLinkIdPair;
1800 NS_LOG_FUNCTION(this << enable << linkId);
1801
1802 auto& link = GetLink(linkId);
1803
1804 if (!IsAssociated())
1805 {
1806 NS_LOG_DEBUG("Not associated yet, record the PM mode to switch to upon association");
1807 link.pmMode = enable ? WIFI_PM_POWERSAVE : WIFI_PM_ACTIVE;
1808 return;
1809 }
1810
1811 if (!link.bssid)
1812 {
1813 NS_LOG_DEBUG("Link " << +linkId << " has not been setup, ignore request");
1814 return;
1815 }
1816
1817 if ((enable && link.pmMode == WIFI_PM_POWERSAVE) || (!enable && link.pmMode == WIFI_PM_ACTIVE))
1818 {
1819 NS_LOG_DEBUG("No PM mode change needed");
1820 return;
1821 }
1822
1824
1825 // reschedule a call to this function to make sure that the PM mode switch
1826 // is eventually completed
1829 this,
1830 enableLinkIdPair);
1831
1832 if (HasFramesToTransmit(linkId))
1833 {
1834 NS_LOG_DEBUG("Next transmitted frame will be sent with PM=" << enable);
1835 return;
1836 }
1837
1838 // No queued frames. Enqueue a Data Null frame to inform the AP of the PM mode change
1840
1841 hdr.SetAddr1(GetBssid(linkId));
1843 hdr.SetAddr3(GetBssid(linkId));
1844 hdr.SetDsNotFrom();
1845 hdr.SetDsTo();
1846 enable ? hdr.SetPowerManagement() : hdr.SetNoPowerManagement();
1847 if (GetQosSupported())
1848 {
1849 GetQosTxop(AC_BE)->Queue(Create<WifiMpdu>(Create<Packet>(), hdr));
1850 }
1851 else
1852 {
1853 m_txop->Queue(Create<WifiMpdu>(Create<Packet>(), hdr));
1854 }
1855}
1856
1858StaWifiMac::GetPmMode(uint8_t linkId) const
1859{
1860 return GetLink(linkId).pmMode;
1861}
1862
1863void
1865{
1866 NS_LOG_FUNCTION(this << *mpdu);
1867
1868 auto linkId = GetLinkIdByAddress(mpdu->GetHeader().GetAddr2());
1869
1870 if (!linkId)
1871 {
1872 // the given MPDU may be the original copy containing MLD addresses and not carrying
1873 // a valid PM bit (which is set on the aliases).
1874 auto linkIds = mpdu->GetInFlightLinkIds();
1875 NS_ASSERT_MSG(!linkIds.empty(),
1876 "The TA of the acked MPDU (" << *mpdu
1877 << ") is not a link "
1878 "address and the MPDU is not inflight");
1879 // in case the ack'ed MPDU is inflight on multiple links, we cannot really know if
1880 // it was received by the AP on all links or only on some links. Hence, we only
1881 // consider the first link ID in the set, given that in the most common case of MPDUs
1882 // that cannot be sent concurrently on multiple links, there will be only one link ID
1883 linkId = *linkIds.begin();
1884 mpdu = GetTxopQueue(mpdu->GetQueueAc())->GetAlias(mpdu, *linkId);
1885 }
1886
1887 auto& link = GetLink(*linkId);
1888 const WifiMacHeader& hdr = mpdu->GetHeader();
1889
1890 // we received an acknowledgment while switching PM mode; the PM mode change is effective now
1891 if (hdr.IsPowerManagement() && link.pmMode == WIFI_PM_SWITCHING_TO_PS)
1892 {
1893 link.pmMode = WIFI_PM_POWERSAVE;
1894 }
1895 else if (!hdr.IsPowerManagement() && link.pmMode == WIFI_PM_SWITCHING_TO_ACTIVE)
1896 {
1897 link.pmMode = WIFI_PM_ACTIVE;
1898 }
1899}
1900
1903{
1904 AllSupportedRates rates;
1905 for (const auto& mode : GetWifiPhy(linkId)->GetModeList())
1906 {
1907 uint64_t modeDataRate = mode.GetDataRate(GetWifiPhy(linkId)->GetChannelWidth());
1908 NS_LOG_DEBUG("Adding supported rate of " << modeDataRate);
1909 rates.AddSupportedRate(modeDataRate);
1910 }
1911 if (GetHtSupported())
1912 {
1913 for (const auto& selector : GetWifiPhy(linkId)->GetBssMembershipSelectorList())
1914 {
1915 rates.AddBssMembershipSelectorRate(selector);
1916 }
1917 }
1918 return rates;
1919}
1920
1922StaWifiMac::GetCapabilities(uint8_t linkId) const
1923{
1924 CapabilityInformation capabilities;
1925 capabilities.SetShortPreamble(GetWifiPhy(linkId)->GetShortPhyPreambleSupported() ||
1926 GetErpSupported(linkId));
1928 return capabilities;
1929}
1930
1931void
1933{
1934 m_state = value;
1935}
1936
1937void
1938StaWifiMac::SetEdcaParameters(const EdcaParams& params, uint8_t linkId)
1939{
1940 Ptr<QosTxop> edca = GetQosTxop(params.ac);
1941 edca->SetMinCw(params.cwMin, linkId);
1942 edca->SetMaxCw(params.cwMax, linkId);
1943 edca->SetAifsn(params.aifsn, linkId);
1944 edca->SetTxopLimit(params.txopLimit, linkId);
1945}
1946
1947void
1948StaWifiMac::SetMuEdcaParameters(const MuEdcaParams& params, uint8_t linkId)
1949{
1950 Ptr<QosTxop> edca = GetQosTxop(params.ac);
1951 edca->SetMuCwMin(params.cwMin, linkId);
1952 edca->SetMuCwMax(params.cwMax, linkId);
1953 edca->SetMuAifsn(params.aifsn, linkId);
1954 edca->SetMuEdcaTimer(params.muEdcaTimer, linkId);
1955}
1956
1957void
1959{
1960 NS_LOG_FUNCTION(this);
1961 if (IsAssociated())
1962 {
1963 NS_LOG_DEBUG("PHY capabilities changed: send reassociation request");
1966 }
1967}
1968
2015void
2017{
2018 NS_LOG_FUNCTION(this << phy << linkId);
2019
2020 // if any link points to the PHY that switched channel, reset the phy pointer
2021 for (auto& [id, link] : GetLinks())
2022 {
2023 // auto& link = GetStaLink(lnk);
2024 if (link->phy == phy)
2025 {
2026 link->phy = nullptr;
2027 }
2028 }
2029
2030 auto& newLink = GetLink(linkId);
2031 // The MAC stack associated with the new link uses the given PHY
2032 newLink.phy = phy;
2033 // Setup a PHY listener for the given PHY on the CAM associated with the new link
2034 newLink.channelAccessManager->SetupPhyListener(phy);
2036 if (m_emlsrManager->GetCamStateReset())
2037 {
2038 newLink.channelAccessManager->ResetState();
2039 }
2040 // Disconnect the FEM on the new link from the current PHY
2041 newLink.feManager->ResetPhy();
2042 // Connect the FEM on the new link to the given PHY
2043 newLink.feManager->SetWifiPhy(phy);
2044}
2045
2046void
2048{
2049 NS_LOG_FUNCTION(this << +linkId);
2050
2052
2053 if (IsInitialized() && IsAssociated())
2054 {
2055 Disassociated(linkId);
2056 }
2057
2058 // notify association manager
2059 m_assocManager->NotifyChannelSwitched(linkId);
2060}
2061
2062std::ostream&
2063operator<<(std::ostream& os, const StaWifiMac::ApInfo& apInfo)
2064{
2065 os << "BSSID=" << apInfo.m_bssid << ", AP addr=" << apInfo.m_apAddr << ", SNR=" << apInfo.m_snr
2066 << ", Channel={" << apInfo.m_channel.number << "," << apInfo.m_channel.band
2067 << "}, Link ID=" << +apInfo.m_linkId << ", Frame=[";
2068 std::visit([&os](auto&& frame) { frame.Print(os); }, apInfo.m_frame);
2069 os << "]";
2070 return os;
2071}
2072
2073} // namespace ns3
A container for one type of attribute.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Base class for Callback class.
Definition: callback.h:360
Callback template class.
Definition: callback.h:438
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
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.
The IEEE 802.11be EHT Capabilities.
Hold variables of type enum.
Definition: enum.h:56
int Get() const
Definition: enum.cc:59
The ErpInformation Information Element.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
The Extended Capabilities Information Element.
The Extended Supported Rates Information Element.
The IEEE 802.11ax HE Capabilities.
The HT Capabilities Information Element.
an EUI-48 address
Definition: mac48-address.h:46
bool IsGroup() const
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
Implement the header for management frames of type association request.
Definition: mgt-headers.h:161
Implement the header for management frames of type association and reassociation response.
Definition: mgt-headers.h:338
StatusCode GetStatusCode()
Return the status code.
Definition: mgt-headers.cc:457
uint16_t GetAssociationId() const
Return the association ID.
Definition: mgt-headers.cc:487
Implement the header for management frames of type beacon.
Definition: mgt-headers.h:516
Implement the header for management frames of type probe request.
Definition: mgt-headers.h:436
Implement the header for management frames of type probe response.
Definition: mgt-headers.h:455
CapabilityInformation & Capabilities()
Definition: mgt-headers.cc:94
Implement the header for management frames of type reassociation request.
Definition: mgt-headers.h:245
void SetCurrentApAddress(Mac48Address currentApAddr)
Set the address of the current access point.
Definition: mgt-headers.cc:332
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:315
bool IsInitialized() const
Check if the object has been initialized.
Definition: object.cc:212
Hold objects of type std::pair<A, B>.
Definition: pair.h:56
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
virtual double GetValue()=0
Get the next random value drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:558
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:208
Introspection did not find any typical Config paths.
Definition: snr-tag.h:35
double Get() const
Return the SNR value.
Definition: snr-tag.cc:90
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
The Wifi MAC high model for a non-AP STA in a BSS.
Definition: sta-wifi-mac.h:144
std::set< uint8_t > GetSetupLinkIds() const
Get the IDs of the setup links (if any).
void ScanningTimeout(const std::optional< ApInfo > &bestAp)
This method is called after wait beacon timeout or wait probe request timeout has occurred.
Time m_waitBeaconTimeout
wait beacon timeout
Definition: sta-wifi-mac.h:630
void SetPowerSaveMode(const std::pair< bool, uint8_t > &enableLinkIdPair)
Enable or disable Power Save mode on the given link.
Ptr< WifiAssocManager > m_assocManager
Association Manager.
Definition: sta-wifi-mac.h:628
void MissedBeacons(uint8_t linkId)
This method is called after we have not received a beacon from the AP on the given link.
bool m_activeProbing
active probing
Definition: sta-wifi-mac.h:635
void DoInitialize() override
Initialize() implementation.
void SetAssocManager(Ptr< WifiAssocManager > assocManager)
Set the Association Manager.
bool CanForwardPacketsTo(Mac48Address to) const override
Return true if packets can be forwarded to the given destination, false otherwise.
std::unique_ptr< LinkEntity > CreateLinkEntity() const override
Create a LinkEntity object.
void SetState(MacState value)
Set the current MAC state.
AllSupportedRates GetSupportedRates(uint8_t linkId) const
Return an instance of SupportedRates that contains all rates that we support including HT rates.
void SetEdcaParameters(const EdcaParams &params, uint8_t linkId)
Set the EDCA parameters for the given link.
void UnblockTxOnLink(uint8_t linkId, WifiQueueBlockedReason reason)
Unblock transmissions on the given link for the given reason.
TracedCallback< Mac48Address > m_deAssocLogger
disassociation logger
Definition: sta-wifi-mac.h:647
MacState
The current MAC state of the STA.
Definition: sta-wifi-mac.h:389
void NotifyChannelSwitching(uint8_t linkId) override
Notify that channel on the given link has been switched.
bool GetActiveProbing() const
Return whether active probing is enabled.
void PhyCapabilitiesChanged()
Indicate that PHY capabilities have changed.
StaLinkEntity & GetStaLink(const std::unique_ptr< WifiMac::LinkEntity > &link) const
Cast the given LinkEntity object to StaLinkEntity.
void ReceiveProbeResp(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
Process the Probe Response frame received on the given link.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
void SetPmModeAfterAssociation(uint8_t linkId)
Set the Power Management mode of the setup links after association.
WifiScanParams::Channel GetCurrentChannel(uint8_t linkId) const
Get the current primary20 channel used on the given link as a (channel number, PHY band) pair.
uint16_t GetAssociationId() const
Return the association ID.
void TryToEnsureAssociated()
Try to ensure that we are associated with an AP by taking an appropriate action depending on the curr...
void ReceiveAssocResp(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
Process the (Re)Association Response frame received on the given link.
void RestartBeaconWatchdog(Time delay, uint8_t linkId)
Restarts the beacon timer for the given link.
std::variant< MgtAssocRequestHeader, MgtReassocRequestHeader > GetAssociationRequest(bool isReassoc, uint8_t linkId) const
Get the (Re)Association Request frame to send on a given link.
static TypeId GetTypeId()
Get the type ID.
Definition: sta-wifi-mac.cc:57
void DoDispose() override
Destructor implementation.
void SendProbeRequest(uint8_t linkId)
Enqueue a probe request packet for transmission on the given link.
void BlockTxOnLink(uint8_t linkId, WifiQueueBlockedReason reason)
Block transmissions on the given link for the given reason.
StaLinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
uint32_t m_maxMissedBeacons
maximum missed beacons
Definition: sta-wifi-mac.h:634
TracedCallback< uint8_t, Mac48Address > m_setupCompleted
link setup completed logger
Definition: sta-wifi-mac.h:646
TracedCallback< Mac48Address > m_assocLogger
association logger
Definition: sta-wifi-mac.h:645
void SetWifiPhys(const std::vector< Ptr< WifiPhy > > &phys) override
void SetMuEdcaParameters(const MuEdcaParams &params, uint8_t linkId)
Set the MU EDCA parameters for the given link.
void Disassociated(uint8_t linkId)
Check if any enabled link remains after the given link is disabled (because, e.g.,...
TracedCallback< uint8_t, Mac48Address > m_setupCanceled
link setup canceled logger
Definition: sta-wifi-mac.h:648
void NotifyEmlsrModeChanged(const std::set< uint8_t > &linkIds)
Notify the MAC that EMLSR mode has changed on the given set of links.
bool CheckSupportedRates(std::variant< MgtBeaconHeader, MgtProbeResponseHeader > frame, uint8_t linkId)
Determine whether the supported rates indicated in a given Beacon frame or Probe Response frame fit w...
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...
void SetEmlsrManager(Ptr< EmlsrManager > emlsrManager)
Set the EMLSR Manager.
Time m_pmModeSwitchTimeout
PM mode switch timeout.
Definition: sta-wifi-mac.h:638
Ptr< EmlsrManager > GetEmlsrManager() const
void TxOk(Ptr< const WifiMpdu > mpdu)
Notify that the MPDU we sent was successfully received by the receiver (i.e.
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...
WifiTidLinkMapping m_ulTidLinkMappingInAssocReq
store the UL TID-to-Link Mapping included in the Association Request frame
Definition: sta-wifi-mac.h:643
WifiPowerManagementMode GetPmMode(uint8_t linkId) const
Ptr< RandomVariableStream > m_probeDelay
RandomVariable used to randomize the time of the first Probe Response on each channel.
Definition: sta-wifi-mac.h:636
TracedCallback< ApInfo > m_beaconInfo
beacon info logger
Definition: sta-wifi-mac.h:650
uint16_t m_aid
Association AID.
Definition: sta-wifi-mac.h:627
MacState m_state
MAC state.
Definition: sta-wifi-mac.h:626
bool IsEmlsrLink(uint8_t linkId) const
void Enqueue(Ptr< Packet > packet, Mac48Address to) override
void StartScanning()
Start the scanning process which trigger active or passive scanning based on the active probing flag.
TracedCallback< Time > m_beaconArrival
beacon arrival logger
Definition: sta-wifi-mac.h:649
void AssocRequestTimeout()
This method is called after the association timeout occurred.
void NotifySwitchingEmlsrLink(Ptr< WifiPhy > phy, uint8_t linkId)
Notify that the given PHY switched channel to operate on another EMLSR link.
Ptr< EmlsrManager > m_emlsrManager
EMLSR Manager.
Definition: sta-wifi-mac.h:629
void UpdateApInfo(const MgtFrameType &frame, const Mac48Address &apAddr, const Mac48Address &bssid, uint8_t linkId)
Update associated AP's information from the given management frame (Beacon, Probe Response or Associa...
Time m_assocRequestTimeout
association request timeout
Definition: sta-wifi-mac.h:632
void ReceiveBeacon(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
Process the Beacon frame received on the given link.
Time m_probeRequestTimeout
probe request timeout
Definition: sta-wifi-mac.h:631
void SetActiveProbing(bool enable)
Enable or disable active probing.
CapabilityInformation GetCapabilities(uint8_t linkId) const
Return the Capability information for the given link.
bool IsAssociated() const
Return whether we are associated with an AP.
~StaWifiMac() override
std::variant< MgtBeaconHeader, MgtProbeResponseHeader, MgtAssocResponseHeader > MgtFrameType
type of the management frames used to get info about APs
Definition: sta-wifi-mac.h:157
bool IsWaitAssocResp() const
Return whether we are waiting for an association response from an AP.
std::vector< TidToLinkMapping > GetTidToLinkMappingElements(uint8_t apNegSupport)
MultiLinkElement GetMultiLinkElement(bool isReassoc, uint8_t linkId) const
Return the Multi-Link Element to include in the management frames transmitted on the given link.
EventId m_assocRequestEvent
association request event
Definition: sta-wifi-mac.h:633
void SendAssociationRequest(bool isReassoc)
Forward an association or reassociation request packet to the DCF.
WifiTidLinkMapping m_dlTidLinkMappingInAssocReq
store the DL TID-to-Link Mapping included in the Association Request frame
Definition: sta-wifi-mac.h:641
bool IsSuccess() const
Return whether the status code is success.
Definition: status-code.cc:42
Hold variables of type string.
Definition: string.h:56
The Supported Rates Information Element.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1412
Time Get() const
Definition: time.cc:530
virtual void Queue(Ptr< Packet > packet, const WifiMacHeader &hdr)
Definition: txop.cc:524
a unique identifier for an interface.
Definition: type-id.h:59
@ ATTR_GET
The attribute can be read.
Definition: type-id.h:64
@ ATTR_SET
The attribute can be written.
Definition: type-id.h:65
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:930
Hold an unsigned integer type.
Definition: uinteger.h:45
The IEEE 802.11ac VHT Capabilities.
static std::pair< CategoryValue, ActionValue > Peek(Ptr< const Packet > pkt)
Peek an Action header from the given packet.
@ PROTECTED_EHT_EML_OPERATING_MODE_NOTIFICATION
Definition: mgt-headers.h:714
Implements the IEEE 802.11 MAC header.
void SetQosAckPolicy(QosAckPolicy policy)
Set the QoS Ack policy in the QoS control field.
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 IsBeacon() const
Return true if the header is a Beacon header.
bool IsAssocResp() const
Return true if the header is an Association Response header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
void SetQosTxopLimit(uint8_t txop)
Set TXOP limit in the QoS control field.
virtual WifiMacType GetType() const
Return the type (WifiMacType)
bool IsCtl() const
Return true if the Type is Control.
void SetNoOrder()
Unset order bit in the frame control field.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
bool IsProbeResp() const
Return true if the header is a Probe Response header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
void SetQosNoAmsdu()
Set that A-MSDU is not present.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
bool HasData() const
Return true if the header type is DATA and is not DATA_NULL.
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 SetDsTo()
Set the To 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.
bool IsPowerManagement() const
Return if the Power Management bit is set.
void SetPowerManagement()
Set the Power Management bit in the Frame Control field.
void SetNoPowerManagement()
Un-set the Power Management bit in the Frame Control field.
base class for all MAC-level wifi objects.
Definition: wifi-mac.h:96
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:866
Ptr< QosTxop > GetBEQueue() const
Accessor for the AC_BE channel access function.
Definition: wifi-mac.cc:533
virtual void NotifyChannelSwitching(uint8_t linkId)
Notify that channel on the given link has been switched.
Definition: wifi-mac.cc:582
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Definition: wifi-mac.cc:1634
Mac48Address GetBssid(uint8_t linkId) const
Definition: wifi-mac.cc:478
Ptr< HeConfiguration > GetHeConfiguration() const
Definition: wifi-mac.cc:1751
const std::map< uint8_t, std::unique_ptr< LinkEntity > > & GetLinks() const
Definition: wifi-mac.cc:920
Ptr< Txop > GetTxop() const
Accessor for the Txop object.
Definition: wifi-mac.cc:493
VhtCapabilities GetVhtCapabilities(uint8_t linkId) const
Return the VHT capabilities of the device for the given link.
Definition: wifi-mac.cc:1988
Callback< void > m_linkDown
Callback when a link is down.
Definition: wifi-mac.h:877
bool GetQosSupported() const
Return whether the device supports QoS.
Definition: wifi-mac.cc:1224
Ptr< Txop > m_txop
TXOP used for transmission of frames to non-QoS peers.
Definition: wifi-mac.h:873
Ptr< WifiMacQueueScheduler > GetMacQueueScheduler() const
Get the wifi MAC queue scheduler.
Definition: wifi-mac.cc:576
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition: wifi-mac.cc:935
void SwapLinks(std::map< uint8_t, uint8_t > links)
Swap the links based on the information included in the given map.
Definition: wifi-mac.cc:997
void DoInitialize() override
Initialize() implementation.
Definition: wifi-mac.cc:354
void UnblockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Unblock the transmission on the given links of all unicast frames addressed to the station with the g...
Definition: wifi-mac.cc:1430
Ssid GetSsid() const
Definition: wifi-mac.cc:465
bool GetErpSupported(uint8_t linkId) const
Return whether the device supports ERP on the given link.
Definition: wifi-mac.cc:1230
bool GetHtSupported() const
Return whether the device supports HT.
Definition: wifi-mac.cc:1763
Ptr< QosTxop > GetVOQueue() const
Accessor for the AC_VO channel access function.
Definition: wifi-mac.cc:521
void SetTypeOfStation(TypeOfStation type)
This method is invoked by a subclass to specify what type of station it is implementing.
Definition: wifi-mac.cc:420
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:1173
void BlockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Block the transmission on the given links of all unicast frames addressed to the station with the giv...
Definition: wifi-mac.cc:1389
bool GetEhtSupported() const
Return whether the device supports EHT.
Definition: wifi-mac.cc:1782
bool GetHeSupported() const
Return whether the device supports HE.
Definition: wifi-mac.cc:1776
HtCapabilities GetHtCapabilities(uint8_t linkId) const
Return the HT capabilities of the device for the given link.
Definition: wifi-mac.cc:1931
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:963
virtual bool HasFramesToTransmit(uint8_t linkId)
Check if the MAC has frames to transmit over the given link.
Definition: wifi-mac.cc:552
void ApplyTidLinkMapping(const Mac48Address &mldAddr, WifiDirection dir)
Apply the TID-to-Link Mapping negotiated with the given MLD for the given direction by properly confi...
Definition: wifi-mac.cc:1307
Ptr< EhtConfiguration > GetEhtConfiguration() const
Definition: wifi-mac.cc:1757
bool GetVhtSupported(uint8_t linkId) const
Return whether the device supports VHT on the given link.
Definition: wifi-mac.cc:1769
virtual void DeaggregateAmsduAndForward(Ptr< const WifiMpdu > mpdu)
This method can be called to de-aggregate an A-MSDU and forward the constituent packets up the stack.
Definition: wifi-mac.cc:1622
void SetBssid(Mac48Address bssid, uint8_t linkId)
Definition: wifi-mac.cc:471
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition: wifi-mac.cc:439
void UpdateTidToLinkMapping(const Mac48Address &mldAddr, WifiDirection dir, const WifiTidLinkMapping &mapping)
Update the TID-to-Link Mappings for the given MLD in the given direction based on the given negotiate...
Definition: wifi-mac.cc:1068
ExtendedCapabilities GetExtendedCapabilities() const
Return the extended capabilities of the device.
Definition: wifi-mac.cc:1920
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:545
std::optional< uint8_t > GetLinkForPhy(Ptr< const WifiPhy > phy) const
Get the ID of the link (if any) on which the given PHY is operating.
Definition: wifi-mac.cc:976
bool GetShortSlotTimeSupported() const
Definition: wifi-mac.cc:1274
void NotifyRxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:621
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:908
void ForwardUp(Ptr< const Packet > packet, Mac48Address from, Mac48Address to)
Forward the packet up to the device.
Definition: wifi-mac.cc:1492
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:1499
Mac48Address GetAddress() const
Definition: wifi-mac.cc:452
EhtCapabilities GetEhtCapabilities(uint8_t linkId) const
Return the EHT capabilities of the device for the given link.
Definition: wifi-mac.cc:2125
Callback< void > m_linkUp
Callback when a link is up.
Definition: wifi-mac.h:876
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: wifi-mac.cc:926
HeCapabilities GetHeCapabilities(uint8_t linkId) const
Return the HE capabilities of the device for the given link.
Definition: wifi-mac.cc:2069
virtual void SetWifiPhys(const std::vector< Ptr< WifiPhy > > &phys)
Definition: wifi-mac.cc:1148
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:499
void NotifyTxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:603
void DoDispose() override
Destructor implementation.
Definition: wifi-mac.cc:378
Time GetDelayUntilIdle()
Definition: wifi-phy.cc:2073
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1496
void SetSlot(Time slot)
Set the slot duration for this PHY.
Definition: wifi-phy.cc:789
void SetOffMode()
Put in off mode.
Definition: wifi-phy.cc:1366
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...
void AddStationMleCommonInfo(Mac48Address from, const std::shared_ptr< CommonInfoBasicMle > &mleCommonInfo)
Records the Common Info field advertised by the given remote station in a Multi-Link Element.
void SetUseNonErpProtection(bool enable)
Enable or disable protection for non-ERP stations.
void AddSupportedMcs(Mac48Address address, WifiMode mcs)
Record the MCS index supported by the station.
void RemoveAllSupportedMcs(Mac48Address address)
Invoked in a STA or AP to delete all of the supported MCS by a destination.
void AddStationVhtCapabilities(Mac48Address from, VhtCapabilities vhtCapabilities)
Records VHT capabilities of the remote station.
void SetShortPreambleEnabled(bool enable)
Enable or disable short PHY preambles.
void SetQosSupport(Mac48Address from, bool qosSupported)
Records QoS support of the remote station.
void AddStationHeCapabilities(Mac48Address from, HeCapabilities heCapabilities)
Records HE capabilities of the remote station.
void AddSupportedMode(Mac48Address address, WifiMode mode)
Invoked in a STA or AP to store the set of modes supported by a destination which is also supported l...
void AddStationEhtCapabilities(Mac48Address from, EhtCapabilities ehtCapabilities)
Records EHT capabilities of the remote station.
void AddStationHtCapabilities(Mac48Address from, HtCapabilities htCapabilities)
Records HT capabilities of the remote station.
std::optional< Mac48Address > GetMldAddress(const Mac48Address &address) const
Get the address of the MLD the given station is affiliated with, if any.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1433
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1413
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#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_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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:1349
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1361
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1325
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1337
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiPowerManagementMode
Enumeration for power management modes.
Definition: sta-wifi-mac.h:92
uint8_t QosUtilsGetTidForPacket(Ptr< const Packet > packet)
If a QoS tag is attached to the packet, returns a value < 8.
Definition: qos-utils.cc:156
WifiQueueBlockedReason
Enumeration of the reasons to block container queues.
@ STA
Definition: wifi-mac.h:65
@ WIFI_PM_SWITCHING_TO_ACTIVE
Definition: sta-wifi-mac.h:96
@ WIFI_PM_POWERSAVE
Definition: sta-wifi-mac.h:95
@ WIFI_PM_SWITCHING_TO_PS
Definition: sta-wifi-mac.h:94
@ WIFI_PM_ACTIVE
Definition: sta-wifi-mac.h:93
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
Definition: wifi-phy-band.h:43
@ 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
-style-clang-format
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
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
@ WIFI_MAC_MGT_PROBE_REQUEST
@ WIFI_MAC_DATA_NULL
@ WIFI_MAC_MGT_BEACON
@ WIFI_MAC_MGT_ACTION
@ WIFI_MAC_MGT_ASSOCIATION_RESPONSE
@ WIFI_MAC_MGT_ASSOCIATION_REQUEST
@ WIFI_MAC_MGT_REASSOCIATION_REQUEST
@ WIFI_MAC_MGT_PROBE_RESPONSE
@ WIFI_MAC_DATA
@ WIFI_MAC_MGT_REASSOCIATION_RESPONSE
@ WIFI_MAC_QOSDATA
bool TidToLinkMappingValidForNegType1(const WifiTidLinkMapping &dlLinkMapping, const WifiTidLinkMapping &ulLinkMapping)
Check if the given TID-to-Link Mappings are valid for a negotiation type of 1.
Definition: wifi-utils.cc:148
Struct containing all supported rates.
void AddBssMembershipSelectorRate(uint64_t bs)
Add a special value to the supported rate set, corresponding to a BSS membership selector.
void AddSupportedRate(uint64_t bs)
Add the given rate to the supported rates.
std::optional< MldCapabilities > m_mldCapabilities
MLD Capabilities.
Struct to hold information regarding observed AP through active/passive scanning.
Definition: sta-wifi-mac.h:164
MgtFrameType m_frame
The body of the management frame used to update AP info.
Definition: sta-wifi-mac.h:178
WifiScanParams::Channel m_channel
The channel the management frame was received on.
Definition: sta-wifi-mac.h:179
Mac48Address m_apAddr
AP MAC address.
Definition: sta-wifi-mac.h:176
uint8_t m_linkId
ID of the link used to communicate with the AP.
Definition: sta-wifi-mac.h:180
Mac48Address m_bssid
BSSID.
Definition: sta-wifi-mac.h:175
double m_snr
SNR in linear scale.
Definition: sta-wifi-mac.h:177
Struct identifying a channel to scan.
Definition: sta-wifi-mac.h:70
WifiPhyBand band
PHY band.
Definition: sta-wifi-mac.h:72
uint16_t number
channel number
Definition: sta-wifi-mac.h:71
Structure holding scan parameters.
Definition: sta-wifi-mac.h:62
std::list< Channel > ChannelList
typedef for a list of channels
Definition: sta-wifi-mac.h:76
std::vector< ChannelList > channelList
list of channels to scan, for each link
Definition: sta-wifi-mac.h:80
Time probeDelay
delay prior to transmitting a Probe Request
Definition: sta-wifi-mac.h:81
WifiScanType type
indicates either active or passive scanning
Definition: sta-wifi-mac.h:78
Time maxChannelTime
maximum time to spend on each channel
Definition: sta-wifi-mac.h:83
Ssid ssid
desired SSID or wildcard SSID
Definition: sta-wifi-mac.h:79
Time minChannelTime
minimum time to spend on each channel
Definition: sta-wifi-mac.h:82