A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-remote-station-manager.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006,2007 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8
10
11#include "ap-wifi-mac.h"
12#include "gcr-manager.h"
13#include "sta-wifi-mac.h"
14#include "wifi-mac-header.h"
15#include "wifi-mac-trailer.h"
16#include "wifi-mpdu.h"
17#include "wifi-net-device.h"
18#include "wifi-phy.h"
19#include "wifi-psdu.h"
20#include "wifi-tx-parameters.h"
21
22#include "ns3/boolean.h"
23#include "ns3/eht-configuration.h"
24#include "ns3/enum.h"
25#include "ns3/erp-ofdm-phy.h"
26#include "ns3/he-configuration.h"
27#include "ns3/ht-configuration.h"
28#include "ns3/ht-phy.h"
29#include "ns3/log.h"
30#include "ns3/simulator.h"
31#include "ns3/uinteger.h"
32#include "ns3/vht-configuration.h"
33
34namespace ns3
35{
36
37NS_LOG_COMPONENT_DEFINE("WifiRemoteStationManager");
38
39NS_OBJECT_ENSURE_REGISTERED(WifiRemoteStationManager);
40
41TypeId
43{
44 static TypeId tid =
45 TypeId("ns3::WifiRemoteStationManager")
47 .SetGroupName("Wifi")
48 // NS_DEPRECATED_3_44
49 .AddAttribute("MaxSsrc",
50 "The maximum number of retransmission attempts for any packet with size "
51 "<= RtsCtsThreshold. "
52 "This value will not have any effect on some rate control algorithms.",
57 "Use WifiMac::FrameRetryLimit instead")
58 // NS_DEPRECATED_3_44
59 .AddAttribute("MaxSlrc",
60 "The maximum number of retransmission attempts for any packet with size "
61 "> RtsCtsThreshold. "
62 "This value will not have any effect on some rate control algorithms.",
67 "Use WifiMac::FrameRetryLimit instead")
68 .AddAttribute(
69 "IncrementRetryCountUnderBa",
70 "The 802.11-2020 standard states that the retry count for frames that are part of "
71 "a Block Ack agreement shall not be incremented when a transmission fails. As a "
72 "consequence, frames that are part of a Block Ack agreement are not dropped based "
73 "on the number of retries. Set this attribute to true to override the standard "
74 "behavior and increment the retry count (and eventually drop) frames that are "
75 "part of a Block Ack agreement.",
76 BooleanValue(false),
79 .AddAttribute("RtsCtsThreshold",
80 "If the size of the PSDU is bigger than this value, we use an RTS/CTS "
81 "handshake before sending the data frame."
82 "This value will not have any effect on some rate control algorithms.",
83 UintegerValue(4692480),
86 .AddAttribute("RtsCtsTxDurationThresh",
87 "If this threshold is a strictly positive value and the TX duration of "
88 "the PSDU is greater than or equal to this threshold, we use an RTS/CTS "
89 "handshake before sending the data frame.",
90 TimeValue(Time{0}),
93 .AddAttribute(
94 "FragmentationThreshold",
95 "If the size of the PSDU is bigger than this value, we fragment it such that the "
96 "size of the fragments are equal or smaller. "
97 "This value does not apply when it is carried in an A-MPDU. "
98 "This value will not have any effect on some rate control algorithms.",
99 UintegerValue(65535),
103 .AddAttribute("NonUnicastMode",
104 "Wifi mode used for non-unicast transmissions.",
108 .AddAttribute("DefaultTxPowerLevel",
109 "Default power level to be used for transmissions. "
110 "This is the power level that is used by all those WifiManagers that do "
111 "not implement TX power control.",
112 UintegerValue(0),
115 .AddAttribute("ErpProtectionMode",
116 "Protection mode used when non-ERP STAs are connected to an ERP AP: "
117 "Rts-Cts or Cts-To-Self",
122 "Rts-Cts",
124 "Cts-To-Self"))
125 .AddAttribute("HtProtectionMode",
126 "Protection mode used when non-HT STAs are connected to a HT AP: Rts-Cts "
127 "or Cts-To-Self",
132 "Rts-Cts",
134 "Cts-To-Self"))
135 .AddTraceSource("MacTxRtsFailed",
136 "The transmission of a RTS by the MAC layer has failed",
138 "ns3::Mac48Address::TracedCallback")
139 .AddTraceSource("MacTxDataFailed",
140 "The transmission of a data packet by the MAC layer has failed",
142 "ns3::Mac48Address::TracedCallback")
143 .AddTraceSource(
144 "MacTxFinalRtsFailed",
145 "The transmission of a RTS has exceeded the maximum number of attempts",
147 "ns3::Mac48Address::TracedCallback")
148 .AddTraceSource(
149 "MacTxFinalDataFailed",
150 "The transmission of a data packet has exceeded the maximum number of attempts",
152 "ns3::Mac48Address::TracedCallback");
153 return tid;
154}
155
157 : m_linkId(0),
158 m_useNonErpProtection(false),
159 m_useNonHtProtection(false),
160 m_shortPreambleEnabled(false),
161 m_shortSlotTimeEnabled(false)
162{
163 NS_LOG_FUNCTION(this);
164 m_ssrc.fill(0);
165 m_slrc.fill(0);
166}
167
172
173void
179
180void
182{
183 NS_LOG_FUNCTION(this << phy);
184 // We need to track our PHY because it is the object that knows the
185 // full set of transmit rates that are supported. We need to know
186 // this in order to find the relevant mandatory rates when choosing a
187 // transmit rate for automatic control responses like
188 // acknowledgments.
189 m_wifiPhy = phy;
190}
191
192void
194{
195 NS_LOG_FUNCTION(this << mac);
196 // We need to track our MAC because it is the object that knows the
197 // full set of interframe spaces.
198 m_wifiMac = mac;
199}
200
201void
203{
204 NS_LOG_FUNCTION(this << +linkId);
205 m_linkId = linkId;
206}
207
208int64_t
210{
211 NS_LOG_FUNCTION(this << stream);
212 return 0;
213}
214
215void
217{
218 NS_LOG_FUNCTION(this << maxSsrc);
219 m_maxSsrc = maxSsrc;
220}
221
222void
224{
225 NS_LOG_FUNCTION(this << maxSlrc);
226 m_maxSlrc = maxSlrc;
227}
228
229void
231{
232 NS_LOG_FUNCTION(this << threshold);
233 m_rtsCtsThreshold = threshold;
234}
235
236void
242
243void
245{
246 NS_LOG_FUNCTION(this << enable);
247 m_shortPreambleEnabled = enable;
248}
249
250void
252{
253 NS_LOG_FUNCTION(this << enable);
254 m_shortSlotTimeEnabled = enable;
255}
256
257bool
262
263bool
268
269bool
271{
272 return (m_wifiPhy->GetDevice()->GetHtConfiguration() &&
274}
275
276bool
278{
279 return (m_wifiPhy->GetDevice()->GetVhtConfiguration() &&
282}
283
284bool
286{
287 return bool(m_wifiPhy->GetDevice()->GetHeConfiguration());
288}
289
290bool
292{
293 return bool(m_wifiPhy->GetDevice()->GetEhtConfiguration());
294}
295
296bool
298{
299 if (auto htConfiguration = m_wifiPhy->GetDevice()->GetHtConfiguration())
300 {
301 return htConfiguration->m_ldpcSupported;
302 }
303 return false;
304}
305
306bool
308{
309 if (auto htConfiguration = m_wifiPhy->GetDevice()->GetHtConfiguration())
310 {
311 return htConfiguration->m_sgiSupported;
312 }
313 return false;
314}
315
316Time
318{
319 Time gi{};
320 if (GetHeSupported())
321 {
322 Ptr<HeConfiguration> heConfiguration = m_wifiPhy->GetDevice()->GetHeConfiguration();
323 NS_ASSERT(heConfiguration); // If HE is supported, we should have a HE configuration
324 // attached
325 gi = heConfiguration->GetGuardInterval();
326 }
327 return gi;
328}
329
335
336void
338 bool isShortPreambleSupported)
339{
340 NS_LOG_FUNCTION(this << address << isShortPreambleSupported);
341 NS_ASSERT(!address.IsGroup());
342 LookupState(address)->m_shortPreamble = isShortPreambleSupported;
343}
344
345void
347 bool isShortSlotTimeSupported)
348{
349 NS_LOG_FUNCTION(this << address << isShortSlotTimeSupported);
350 NS_ASSERT(!address.IsGroup());
351 LookupState(address)->m_shortSlotTime = isShortSlotTimeSupported;
352}
353
354void
356{
357 NS_LOG_FUNCTION(this << address << mode);
358 NS_ASSERT(!address.IsGroup());
359 auto state = LookupState(address);
360 for (const auto& i : state->m_operationalRateSet)
361 {
362 if (i == mode)
363 {
364 return; // already in
365 }
366 }
367 if ((mode.GetModulationClass() == WIFI_MOD_CLASS_DSSS) ||
369 {
370 state->m_dsssSupported = true;
371 }
373 {
374 state->m_erpOfdmSupported = true;
375 }
376 else if (mode.GetModulationClass() == WIFI_MOD_CLASS_OFDM)
377 {
378 state->m_ofdmSupported = true;
379 }
380 state->m_operationalRateSet.push_back(mode);
381}
382
383void
385{
386 NS_LOG_FUNCTION(this << address);
387 NS_ASSERT(!address.IsGroup());
388 auto state = LookupState(address);
389 state->m_operationalRateSet.clear();
390 for (const auto& mode : m_wifiPhy->GetModeList())
391 {
392 state->m_operationalRateSet.push_back(mode);
393 if (mode.IsMandatory())
394 {
395 AddBasicMode(mode);
396 }
397 }
398}
399
400void
402{
403 NS_LOG_FUNCTION(this << address);
404 NS_ASSERT(!address.IsGroup());
405 auto state = LookupState(address);
406
407 const auto& mcsList = m_wifiPhy->GetMcsList();
408 state->m_operationalMcsSet = WifiModeList(mcsList.begin(), mcsList.end());
409}
410
411void
413{
414 NS_LOG_FUNCTION(this << address);
415 NS_ASSERT(!address.IsGroup());
416 LookupState(address)->m_operationalMcsSet.clear();
417}
418
419void
421{
422 NS_LOG_FUNCTION(this << address << mcs);
423 NS_ASSERT(!address.IsGroup());
424 auto state = LookupState(address);
425 for (const auto& i : state->m_operationalMcsSet)
426 {
427 if (i == mcs)
428 {
429 return; // already in
430 }
431 }
432 state->m_operationalMcsSet.push_back(mcs);
433}
434
435bool
437{
438 return LookupState(address)->m_shortPreamble;
439}
440
441bool
443{
444 return LookupState(address)->m_shortSlotTime;
445}
446
447bool
449{
450 return LookupState(address)->m_qosSupported;
451}
452
453bool
455{
456 if (address.IsGroup())
457 {
458 return false;
459 }
460 return LookupState(address)->m_state == WifiRemoteStationState::BRAND_NEW;
461}
462
463bool
465{
466 if (address.IsGroup())
467 {
468 return true;
469 }
470 return LookupState(address)->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK;
471}
472
473bool
475{
476 if (address.IsGroup())
477 {
478 return false;
479 }
480 return LookupState(address)->m_state == WifiRemoteStationState::WAIT_ASSOC_TX_OK;
481}
482
483void
489
490void
496
497void
503
504void
510
511bool
513{
514 if (address.IsGroup())
515 {
516 return false;
517 }
518 return LookupState(address)->m_state == WifiRemoteStationState::ASSOC_REFUSED;
519}
520
521void
527
528uint16_t
530{
531 std::shared_ptr<WifiRemoteStationState> state;
532 if (!remoteAddress.IsGroup() &&
533 (state = LookupState(remoteAddress))->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK)
534 {
535 return state->m_aid;
536 }
537 return SU_STA_ID;
538}
539
540uint16_t
542{
543 NS_LOG_FUNCTION(this << address << txVector);
544
545 uint16_t staId = SU_STA_ID;
546
547 if (txVector.IsMu())
548 {
549 if (m_wifiMac->GetTypeOfStation() == AP)
550 {
551 staId = GetAssociationId(address);
552 }
553 else if (m_wifiMac->GetTypeOfStation() == STA)
554 {
556 if (staMac->IsAssociated())
557 {
558 staId = staMac->GetAssociationId();
559 }
560 }
561 }
562
563 NS_LOG_DEBUG("Returning STAID = " << staId);
564 return staId;
565}
566
567bool
569{
570 return LookupState(address)->m_isInPsMode;
571}
572
573void
574WifiRemoteStationManager::SetPsMode(const Mac48Address& address, bool isInPsMode)
575{
576 LookupState(address)->m_isInPsMode = isInPsMode;
577}
578
579std::optional<Mac48Address>
581{
582 if (auto stateIt = m_states.find(address);
583 stateIt != m_states.end() && stateIt->second->m_mleCommonInfo)
584 {
585 return stateIt->second->m_mleCommonInfo->m_mldMacAddress;
586 }
587
588 return std::nullopt;
589}
590
591std::optional<Mac48Address>
593{
594 auto stateIt = m_states.find(mldAddress);
595
596 if (stateIt == m_states.end() || !stateIt->second->m_mleCommonInfo)
597 {
598 // MLD address not found
599 return std::nullopt;
600 }
601
602 NS_ASSERT(stateIt->second->m_mleCommonInfo->m_mldMacAddress == mldAddress);
603 return stateIt->second->m_address;
604}
605
608{
609 NS_LOG_FUNCTION(this << header << allowedWidth);
610 const auto address = header.GetAddr1();
611 if (!header.IsMgt() && address.IsGroup())
612 {
613 return GetGroupcastTxVector(header, allowedWidth);
614 }
615 WifiTxVector txVector;
616 if (header.IsMgt())
617 {
618 // Use the lowest basic rate for management frames
619 WifiMode mgtMode;
620 if (GetNBasicModes() > 0)
621 {
622 mgtMode = GetBasicMode(0);
623 }
624 else
625 {
626 mgtMode = GetDefaultMode();
627 }
628 txVector.SetMode(mgtMode);
629 txVector.SetPreambleType(
632 auto channelWidth = allowedWidth;
633 if (!header.GetAddr1().IsGroup())
634 {
635 if (const auto rxWidth = GetChannelWidthSupported(header.GetAddr1());
636 rxWidth < channelWidth)
637 {
638 channelWidth = rxWidth;
639 }
640 }
641
642 txVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mgtMode, channelWidth));
644 }
645 else
646 {
647 txVector = DoGetDataTxVector(Lookup(address), allowedWidth);
649 ? false
650 : UseLdpcForDestination(address));
651 }
652 Ptr<HeConfiguration> heConfiguration = m_wifiPhy->GetDevice()->GetHeConfiguration();
653 if (heConfiguration)
654 {
655 txVector.SetBssColor(heConfiguration->m_bssColor);
656 }
657 // If both the allowed width and the TXVECTOR channel width are integer multiple
658 // of 20 MHz, then the TXVECTOR channel width must not exceed the allowed width
659 NS_ASSERT_MSG((static_cast<uint16_t>(txVector.GetChannelWidth()) % 20 != 0) ||
660 (static_cast<uint16_t>(allowedWidth) % 20 != 0) ||
661 (txVector.GetChannelWidth() <= allowedWidth),
662 "TXVECTOR channel width (" << txVector.GetChannelWidth()
663 << " MHz) exceeds allowed width (" << allowedWidth
664 << " MHz)");
665 return txVector;
666}
667
670{
671 WifiMode defaultMode = GetDefaultMode();
672 WifiPreamble defaultPreamble;
673 if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_EHT)
674 {
675 defaultPreamble = WIFI_PREAMBLE_EHT_MU;
676 }
677 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HE)
678 {
679 defaultPreamble = WIFI_PREAMBLE_HE_SU;
680 }
681 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_VHT)
682 {
683 defaultPreamble = WIFI_PREAMBLE_VHT_SU;
684 }
685 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HT)
686 {
687 defaultPreamble = WIFI_PREAMBLE_HT_MF;
688 }
689 else
690 {
691 defaultPreamble = WIFI_PREAMBLE_LONG;
692 }
693
694 return WifiTxVector(defaultMode,
696 defaultPreamble,
699 1,
700 0,
701 m_wifiPhy->GetTxBandwidth(defaultMode),
702 false);
703}
704
705void
707 MHz_u allowedWidth) const
708{
709 NS_LOG_FUNCTION(this << txVector << allowedWidth);
710
711 auto modulation = txVector.GetModulationClass();
712
713 if (allowedWidth >= 40 &&
714 (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS))
715 {
716 // control frame must be sent in a non-HT duplicate PPDU because it must protect a frame
717 // being transmitted on at least 40 MHz. Change the modulation class to ERP-OFDM and the
718 // rate to 6 Mbps
720 modulation = txVector.GetModulationClass();
721 }
722 // do not set allowedWidth as the TX width if the modulation class is (HR-)DSSS (allowedWidth
723 // may be 20 MHz) or allowedWidth is 22 MHz (the selected modulation class may be OFDM)
724 if (modulation != WIFI_MOD_CLASS_DSSS && modulation != WIFI_MOD_CLASS_HR_DSSS &&
725 allowedWidth != 22)
726 {
727 txVector.SetChannelWidth(allowedWidth);
728 }
729}
730
733{
734 NS_LOG_FUNCTION(this << address << allowedWidth);
735 WifiTxVector v;
736 if (address.IsGroup())
737 {
739 v.SetMode(mode);
746 v.SetNss(1);
747 v.SetNess(0);
748 }
749 else
750 {
751 v = DoGetRtsTxVector(Lookup(address));
752 }
753
754 AdjustTxVectorForCtlResponse(v, allowedWidth);
755
756 return v;
757}
758
761{
762 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
763 NS_ASSERT(!to.IsGroup() ||
764 (m_wifiMac && (m_wifiMac->GetTypeOfStation() == AP) && apMac->GetGcrManager()));
765 WifiMode ctsMode = GetControlAnswerMode(rtsTxMode);
766 WifiTxVector v;
767 v.SetMode(ctsMode);
773 v.SetNss(1);
774 return v;
775}
776
777void
779{
780 NS_LOG_FUNCTION(this << txVector);
781
782 auto txMode = txVector.GetMode();
783 if (txMode.GetModulationClass() >= WIFI_MOD_CLASS_HT)
784 {
785 auto rate = txMode.GetDataRate(txVector);
786 if (rate >= 24e6)
787 {
788 rate = 24e6;
789 }
790 else if (rate >= 12e6)
791 {
792 rate = 12e6;
793 }
794 else
795 {
796 rate = 6e6;
797 }
800 {
801 txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(rate));
802 }
803 else
804 {
805 txVector.SetMode(OfdmPhy::GetOfdmRate(rate));
806 }
807 }
808}
809
812{
813 NS_ASSERT(!to.IsGroup());
814 WifiMode ackMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
815 WifiTxVector v;
816 v.SetMode(ackMode);
822 v.SetNss(1);
823
825
826 return v;
827}
828
831 const WifiTxVector& dataTxVector) const
832{
833 NS_ASSERT(!to.IsGroup());
834 WifiMode blockAckMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
835 WifiTxVector v;
836 v.SetMode(blockAckMode);
840 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(blockAckMode));
842 v.SetNss(1);
843
845
846 return v;
847}
848
851{
852 /**
853 * The standard has relatively unambiguous rules for selecting a
854 * control response rate (the below is quoted from IEEE 802.11-2012,
855 * Section 9.7):
856 *
857 * To allow the transmitting STA to calculate the contents of the
858 * Duration/ID field, a STA responding to a received frame shall
859 * transmit its Control Response frame (either CTS or Ack), other
860 * than the BlockAck control frame, at the highest rate in the
861 * BSSBasicRateSet parameter that is less than or equal to the
862 * rate of the immediately previous frame in the frame exchange
863 * sequence (as defined in Annex G) and that is of the same
864 * modulation class (see Section 9.7.8) as the received frame...
865 */
866 NS_LOG_FUNCTION(this << reqMode);
867 WifiMode mode = GetDefaultMode();
868 bool found = false;
869 // First, search the BSS Basic Rate set
870 for (uint8_t i = 0; i < GetNBasicModes(); i++)
871 {
872 WifiMode testMode = GetBasicMode(i);
873 if ((!found || testMode.IsHigherDataRate(mode)) && (!testMode.IsHigherDataRate(reqMode)) &&
875 testMode.GetModulationClass())))
876 {
877 mode = testMode;
878 // We've found a potentially-suitable transmit rate, but we
879 // need to continue and consider all the basic rates before
880 // we can be sure we've got the right one.
881 found = true;
882 }
883 }
884 if (m_wifiPhy->GetDevice()->GetHtConfiguration())
885 {
886 if (!found)
887 {
888 mode = GetDefaultMcs();
889 for (uint8_t i = 0; i != GetNBasicMcs(); i++)
890 {
891 WifiMode testMode = GetBasicMcs(i);
892 if ((!found || testMode.IsHigherDataRate(mode)) &&
893 (!testMode.IsHigherDataRate(reqMode)) &&
894 (testMode.GetModulationClass() == reqMode.GetModulationClass()))
895 {
896 mode = testMode;
897 // We've found a potentially-suitable transmit rate, but we
898 // need to continue and consider all the basic rates before
899 // we can be sure we've got the right one.
900 found = true;
901 }
902 }
903 }
904 }
905 // If we found a suitable rate in the BSSBasicRateSet, then we are
906 // done and can return that mode.
907 if (found)
908 {
909 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
910 return mode;
911 }
912
913 /**
914 * If no suitable basic rate was found, we search the mandatory
915 * rates. The standard (IEEE 802.11-2007, Section 9.6) says:
916 *
917 * ...If no rate contained in the BSSBasicRateSet parameter meets
918 * these conditions, then the control frame sent in response to a
919 * received frame shall be transmitted at the highest mandatory
920 * rate of the PHY that is less than or equal to the rate of the
921 * received frame, and that is of the same modulation class as the
922 * received frame. In addition, the Control Response frame shall
923 * be sent using the same PHY options as the received frame,
924 * unless they conflict with the requirement to use the
925 * BSSBasicRateSet parameter.
926 *
927 * @todo Note that we're ignoring the last sentence for now, because
928 * there is not yet any manipulation here of PHY options.
929 */
930 for (const auto& thismode : m_wifiPhy->GetModeList())
931 {
932 /* If the rate:
933 *
934 * - is a mandatory rate for the PHY, and
935 * - is equal to or faster than our current best choice, and
936 * - is less than or equal to the rate of the received frame, and
937 * - is of the same modulation class as the received frame
938 *
939 * ...then it's our best choice so far.
940 */
941 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
942 (!thismode.IsHigherDataRate(reqMode)) &&
944 thismode.GetModulationClass())))
945 {
946 mode = thismode;
947 // As above; we've found a potentially-suitable transmit
948 // rate, but we need to continue and consider all the
949 // mandatory rates before we can be sure we've got the right one.
950 found = true;
951 }
952 }
953 if (m_wifiPhy->GetDevice()->GetHtConfiguration())
954 {
955 for (const auto& thismode : m_wifiPhy->GetMcsList())
956 {
957 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
958 (!thismode.IsHigherCodeRate(reqMode)) &&
959 (thismode.GetModulationClass() == reqMode.GetModulationClass()))
960 {
961 mode = thismode;
962 // As above; we've found a potentially-suitable transmit
963 // rate, but we need to continue and consider all the
964 // mandatory rates before we can be sure we've got the right one.
965 found = true;
966 }
967 }
968 }
969
970 /**
971 * If we still haven't found a suitable rate for the response then
972 * someone has messed up the simulation configuration. This probably means
973 * that the WifiPhyStandard is not set correctly, or that a rate that
974 * is not supported by the PHY has been explicitly requested.
975 *
976 * Either way, it is serious - we can either disobey the standard or
977 * fail, and I have chosen to do the latter...
978 */
979 if (!found)
980 {
981 NS_FATAL_ERROR("Can't find response rate for " << reqMode);
982 }
983
984 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
985 return mode;
986}
987
988void
990{
991 NS_LOG_FUNCTION(this << header);
992 const auto recipient = GetIndividuallyAddressedRecipient(m_wifiMac, header);
993 NS_ASSERT(!recipient.IsGroup());
994 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
995 m_ssrc[ac]++;
996 m_macTxRtsFailed(recipient);
997 DoReportRtsFailed(Lookup(recipient));
998}
999
1000void
1002{
1003 NS_LOG_FUNCTION(this << *mpdu);
1004 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1005 AcIndex ac =
1006 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1007 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1008 if (longMpdu)
1009 {
1010 m_slrc[ac]++;
1011 }
1012 else
1013 {
1014 m_ssrc[ac]++;
1015 }
1016 m_macTxDataFailed(mpdu->GetHeader().GetAddr1());
1017 DoReportDataFailed(Lookup(mpdu->GetHeader().GetAddr1()));
1018}
1019
1020void
1022 double ctsSnr,
1023 WifiMode ctsMode,
1024 double rtsSnr)
1025{
1026 NS_LOG_FUNCTION(this << header << ctsSnr << ctsMode << rtsSnr);
1027 const auto recipient = GetIndividuallyAddressedRecipient(m_wifiMac, header);
1028 NS_ASSERT(!recipient.IsGroup());
1029 WifiRemoteStation* station = Lookup(recipient);
1030 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1031 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1032 m_ssrc[ac] = 0;
1033 DoReportRtsOk(station, ctsSnr, ctsMode, rtsSnr);
1034}
1035
1036void
1038 double ackSnr,
1039 WifiMode ackMode,
1040 double dataSnr,
1041 WifiTxVector dataTxVector)
1042{
1043 NS_LOG_FUNCTION(this << *mpdu << ackSnr << ackMode << dataSnr << dataTxVector);
1044 const WifiMacHeader& hdr = mpdu->GetHeader();
1045 NS_ASSERT(!hdr.GetAddr1().IsGroup());
1046 WifiRemoteStation* station = Lookup(hdr.GetAddr1());
1047 AcIndex ac = QosUtilsMapTidToAc((hdr.IsQosData()) ? hdr.GetQosTid() : 0);
1048 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1049 if (longMpdu)
1050 {
1051 station->m_state->m_info.NotifyTxSuccess(m_slrc[ac]);
1052 m_slrc[ac] = 0;
1053 }
1054 else
1055 {
1056 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1057 m_ssrc[ac] = 0;
1058 }
1059 DoReportDataOk(station,
1060 ackSnr,
1061 ackMode,
1062 dataSnr,
1063 dataTxVector.GetChannelWidth(),
1064 dataTxVector.GetNss(GetStaId(hdr.GetAddr1(), dataTxVector)));
1065}
1066
1067void
1069{
1070 NS_LOG_FUNCTION(this << header);
1071 NS_ASSERT(!header.GetAddr1().IsGroup());
1072 WifiRemoteStation* station = Lookup(header.GetAddr1());
1073 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1074 station->m_state->m_info.NotifyTxFailed();
1075 m_ssrc[ac] = 0;
1077 DoReportFinalRtsFailed(station);
1078}
1079
1080void
1082{
1083 NS_LOG_FUNCTION(this << *mpdu);
1084 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1085 WifiRemoteStation* station = Lookup(mpdu->GetHeader().GetAddr1());
1086 AcIndex ac =
1087 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1088 station->m_state->m_info.NotifyTxFailed();
1089 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1090 if (longMpdu)
1091 {
1092 m_slrc[ac] = 0;
1093 }
1094 else
1095 {
1096 m_ssrc[ac] = 0;
1097 }
1098 m_macTxFinalDataFailed(mpdu->GetHeader().GetAddr1());
1099 DoReportFinalDataFailed(station);
1100}
1101
1102void
1104 RxSignalInfo rxSignalInfo,
1105 const WifiTxVector& txVector)
1106{
1107 NS_LOG_FUNCTION(this << address << rxSignalInfo << txVector);
1108 if (address.IsGroup())
1109 {
1110 return;
1111 }
1112 WifiRemoteStation* station = Lookup(address);
1113 DoReportRxOk(station, rxSignalInfo.snr, txVector.GetMode(GetStaId(address, txVector)));
1114 station->m_rssiAndUpdateTimePair = std::make_pair(rxSignalInfo.rssi, Simulator::Now());
1115}
1116
1117void
1119 uint16_t nSuccessfulMpdus,
1120 uint16_t nFailedMpdus,
1121 double rxSnr,
1122 double dataSnr,
1123 WifiTxVector dataTxVector)
1124{
1125 NS_LOG_FUNCTION(this << address << nSuccessfulMpdus << nFailedMpdus << rxSnr << dataSnr
1126 << dataTxVector);
1127 NS_ASSERT(!address.IsGroup());
1128 for (uint16_t i = 0; i < nFailedMpdus; i++)
1129 {
1130 m_macTxDataFailed(address);
1131 }
1133 nSuccessfulMpdus,
1134 nFailedMpdus,
1135 rxSnr,
1136 dataSnr,
1137 dataTxVector.GetChannelWidth(),
1138 dataTxVector.GetNss(GetStaId(address, dataTxVector)));
1139}
1140
1141std::list<Ptr<WifiMpdu>>
1143{
1144 NS_LOG_FUNCTION(this << *psdu);
1145
1146 auto* station = Lookup(GetIndividuallyAddressedRecipient(m_wifiMac, psdu->GetHeader(0)));
1147
1148 DoIncrementRetryCountOnTxFailure(station, psdu);
1149 return DoGetMpdusToDropOnTxFailure(station, psdu);
1150}
1151
1152void
1154 Ptr<WifiPsdu> psdu)
1155{
1156 NS_LOG_FUNCTION(this << *psdu);
1157
1158 // The frame retry count for an MSDU or A-MSDU that is not part of a block ack agreement or
1159 // for an MMPDU shall be incremented every time transmission fails for that MSDU, A-MSDU, or
1160 // MMPDU, including of an associated RTS (Sec. 10.23.2.12.1 of 802.11-2020).
1161 // Frames for which the retry count needs to be incremented:
1162 // - management frames
1163 // - non-QoS Data frames
1164 // - QoS Data frames that are not part of a Block Ack agreement
1165 // - QoS Data frames that are part of a Block Ack agreement if the IncrementRetryCountUnderBa
1166 // attribute is set to true
1167 const auto& hdr = psdu->GetHeader(0);
1168
1169 if (hdr.IsMgt() || (hdr.IsData() && !hdr.IsQosData()) ||
1170 (hdr.IsQosData() && (!m_wifiMac->GetBaAgreementEstablishedAsOriginator(
1171 hdr.GetAddr1(),
1172 hdr.GetQosTid() || m_incrRetryCountUnderBa))))
1173 {
1174 psdu->IncrementRetryCount();
1175 }
1176}
1177
1178std::list<Ptr<WifiMpdu>>
1180 Ptr<WifiPsdu> psdu)
1181{
1182 NS_LOG_FUNCTION(this << *psdu);
1183
1184 std::list<Ptr<WifiMpdu>> mpdusToDrop;
1185
1186 for (const auto& mpdu : *PeekPointer(psdu))
1187 {
1188 if (mpdu->GetRetryCount() == m_wifiMac->GetFrameRetryLimit())
1189 {
1190 // this MPDU needs to be dropped
1191 mpdusToDrop.push_back(mpdu);
1192 }
1193 }
1194
1195 return mpdusToDrop;
1196}
1197
1198bool
1200{
1201 NS_LOG_FUNCTION(this << header << &txParams);
1202 auto address = header.GetAddr1();
1203 const auto isGcr = IsGcr(m_wifiMac, header);
1204 if (!isGcr && address.IsGroup())
1205 {
1206 return false;
1207 }
1208 if (isGcr)
1209 {
1211 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
1212 apMac->GetGcrManager()->GetAttribute("GcrProtectionMode", enumValue);
1213 if (enumValue.Get() != GroupcastProtectionMode::RTS_CTS)
1214 {
1215 return false;
1216 }
1217 address = apMac->GetGcrManager()->GetIndividuallyAddressedRecipient(address);
1218 }
1219 const auto modulationClass = txParams.m_txVector.GetModulationClass();
1221 ((modulationClass == WIFI_MOD_CLASS_ERP_OFDM) || (modulationClass == WIFI_MOD_CLASS_HT) ||
1222 (modulationClass == WIFI_MOD_CLASS_VHT) || (modulationClass == WIFI_MOD_CLASS_HE) ||
1223 (modulationClass == WIFI_MOD_CLASS_EHT)) &&
1225 {
1227 "WifiRemoteStationManager::NeedRTS returning true to protect non-ERP stations");
1228 return true;
1229 }
1230 else if (m_htProtectionMode == RTS_CTS &&
1231 ((modulationClass == WIFI_MOD_CLASS_HT) || (modulationClass == WIFI_MOD_CLASS_VHT)) &&
1233 {
1234 NS_LOG_DEBUG("WifiRemoteStationManager::NeedRTS returning true to protect non-HT stations");
1235 return true;
1236 }
1237 NS_ASSERT(txParams.m_txDuration.has_value());
1238 auto size = txParams.GetSize(header.GetAddr1());
1239 bool normally =
1242 return DoNeedRts(Lookup(address), size, normally);
1243}
1244
1245bool
1247{
1248 NS_LOG_FUNCTION(this << txVector << header);
1251 (txVector.GetModulationClass() == WIFI_MOD_CLASS_HT) ||
1252 (txVector.GetModulationClass() == WIFI_MOD_CLASS_VHT) ||
1253 (txVector.GetModulationClass() == WIFI_MOD_CLASS_HE) ||
1254 (txVector.GetModulationClass() == WIFI_MOD_CLASS_EHT)))
1255 {
1257 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-ERP stations");
1258 return true;
1259 }
1260 else if (m_htProtectionMode == CTS_TO_SELF &&
1261 ((txVector.GetModulationClass() == WIFI_MOD_CLASS_HT) ||
1262 (txVector.GetModulationClass() == WIFI_MOD_CLASS_VHT)) &&
1264 {
1266 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-HT stations");
1267 return true;
1268 }
1269 else if (IsGcr(m_wifiMac, header))
1270 {
1272 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
1273 apMac->GetGcrManager()->GetAttribute("GcrProtectionMode", enumValue);
1274 if (enumValue.Get() == GroupcastProtectionMode::CTS_TO_SELF)
1275 {
1276 return true;
1277 }
1278 }
1279 // FIXME: commented out for now
1280 /*else if (!m_useNonErpProtection)
1281 {
1282 const auto mode = txVector.GetMode();
1283 // search for the BSS Basic Rate set, if the used mode is in the basic set then there is no
1284 // need for CTS To Self
1285 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
1286 {
1287 if (mode == *i)
1288 {
1289 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1290 return false;
1291 }
1292 }
1293 if (m_wifiPhy->GetDevice()->GetHtConfiguration())
1294 {
1295 // search for the BSS Basic MCS set, if the used mode is in the basic set then there is
1296 // no need for CTS To Self
1297 for (auto i = m_bssBasicMcsSet.begin(); i != m_bssBasicMcsSet.end(); i++)
1298 {
1299 if (mode == *i)
1300 {
1301 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1302 return false;
1303 }
1304 }
1305 }
1306 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning true");
1307 return true;
1308 }*/
1309 return false;
1310}
1311
1312void
1314{
1315 NS_LOG_FUNCTION(this << enable);
1316 m_useNonErpProtection = enable;
1317}
1318
1319bool
1324
1325void
1327{
1328 NS_LOG_FUNCTION(this << enable);
1329 m_useNonHtProtection = enable;
1330}
1331
1332bool
1337
1338bool
1340{
1341 NS_LOG_FUNCTION(this << *mpdu);
1342 if (mpdu->GetHeader().GetAddr1().IsGroup())
1343 {
1344 return false;
1345 }
1346 bool normally = mpdu->GetSize() > GetFragmentationThreshold();
1347 NS_LOG_DEBUG("WifiRemoteStationManager::NeedFragmentation result: " << std::boolalpha
1348 << normally);
1349 return DoNeedFragmentation(Lookup(mpdu->GetHeader().GetAddr1()), mpdu->GetPacket(), normally);
1350}
1351
1352void
1354{
1355 NS_LOG_FUNCTION(this << threshold);
1356 if (threshold < 256)
1357 {
1358 /*
1359 * ASN.1 encoding of the MAC and PHY MIB (256 ... 8000)
1360 */
1361 NS_LOG_WARN("Fragmentation threshold should be larger than 256. Setting to 256.");
1363 }
1364 else
1365 {
1366 /*
1367 * The length of each fragment shall be an even number of octets, except for the last
1368 * fragment if an MSDU or MMPDU, which may be either an even or an odd number of octets.
1369 */
1370 if (threshold % 2 != 0)
1371 {
1372 NS_LOG_WARN("Fragmentation threshold should be an even number. Setting to "
1373 << threshold - 1);
1374 m_fragmentationThreshold = threshold - 1;
1375 }
1376 else
1377 {
1378 m_fragmentationThreshold = threshold;
1379 }
1380 }
1381}
1382
1388
1391{
1392 NS_LOG_FUNCTION(this << *mpdu);
1393 // The number of bytes a fragment can support is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS).
1394 uint32_t nFragments =
1395 (mpdu->GetPacket()->GetSize() /
1396 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH));
1397
1398 // If the size of the last fragment is not 0.
1399 if ((mpdu->GetPacket()->GetSize() %
1400 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH)) > 0)
1401 {
1402 nFragments++;
1403 }
1404 NS_LOG_DEBUG("WifiRemoteStationManager::GetNFragments returning " << nFragments);
1405 return nFragments;
1406}
1407
1410{
1411 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1412 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1413 uint32_t nFragment = GetNFragments(mpdu);
1414 if (fragmentNumber >= nFragment)
1415 {
1416 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning 0");
1417 return 0;
1418 }
1419 // Last fragment
1420 if (fragmentNumber == nFragment - 1)
1421 {
1422 uint32_t lastFragmentSize =
1423 mpdu->GetPacket()->GetSize() -
1424 (fragmentNumber *
1425 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH));
1426 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning " << lastFragmentSize);
1427 return lastFragmentSize;
1428 }
1429 // All fragments but the last, the number of bytes is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS).
1430 else
1431 {
1432 uint32_t fragmentSize =
1433 GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH;
1434 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning " << fragmentSize);
1435 return fragmentSize;
1436 }
1437}
1438
1441{
1442 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1443 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1444 NS_ASSERT(fragmentNumber < GetNFragments(mpdu));
1445 uint32_t fragmentOffset = fragmentNumber * (GetFragmentationThreshold() -
1446 mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH);
1447 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentOffset returning " << fragmentOffset);
1448 return fragmentOffset;
1449}
1450
1451bool
1453{
1454 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1455 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1456 bool isLast = fragmentNumber == (GetNFragments(mpdu) - 1);
1457 NS_LOG_DEBUG("WifiRemoteStationManager::IsLastFragment returning " << std::boolalpha << isLast);
1458 return isLast;
1459}
1460
1461uint8_t
1466
1469{
1470 return LookupState(address)->m_info;
1471}
1472
1473std::optional<dBm_u>
1475{
1476 auto station = Lookup(address);
1477 auto rssi = station->m_rssiAndUpdateTimePair.first;
1478 auto ts = station->m_rssiAndUpdateTimePair.second;
1479 if (ts.IsStrictlyPositive())
1480 {
1481 return rssi;
1482 }
1483 return std::nullopt;
1484}
1485
1486std::shared_ptr<WifiRemoteStationState>
1488{
1489 NS_LOG_FUNCTION(this << address);
1490 auto stateIt = m_states.find(address);
1491
1492 if (stateIt != m_states.end())
1493 {
1494 NS_LOG_DEBUG("WifiRemoteStationManager::LookupState returning existing state");
1495 return stateIt->second;
1496 }
1497
1498 auto state = std::make_shared<WifiRemoteStationState>();
1499 state->m_state = WifiRemoteStationState::BRAND_NEW;
1500 state->m_address = address;
1501 state->m_aid = 0;
1502 state->m_operationalRateSet.push_back(GetDefaultMode());
1503 state->m_operationalMcsSet.push_back(GetDefaultMcs());
1504 state->m_dsssSupported = false;
1505 state->m_erpOfdmSupported = false;
1506 state->m_ofdmSupported = false;
1507 state->m_htCapabilities = nullptr;
1508 state->m_vhtCapabilities = nullptr;
1509 state->m_heCapabilities = nullptr;
1510 state->m_ehtCapabilities = nullptr;
1511 state->m_mleCommonInfo = nullptr;
1512 state->m_emlsrEnabled = false;
1513 state->m_channelWidth = m_wifiPhy->GetChannelWidth();
1514 state->m_guardInterval = GetGuardInterval();
1515 state->m_ness = 0;
1516 state->m_aggregation = false;
1517 state->m_qosSupported = false;
1518 state->m_isInPsMode = false;
1519 const_cast<WifiRemoteStationManager*>(this)->m_states.insert({address, state});
1520 NS_LOG_DEBUG("WifiRemoteStationManager::LookupState returning new state");
1521 return state;
1522}
1523
1524WifiRemoteStation*
1525WifiRemoteStationManager::Lookup(Mac48Address address) const
1526{
1527 NS_LOG_FUNCTION(this << address);
1528 NS_ASSERT(!address.IsGroup());
1529 NS_ASSERT(address != m_wifiMac->GetAddress());
1530 auto stationIt = m_stations.find(address);
1531
1532 if (stationIt != m_stations.end())
1533 {
1534 return stationIt->second;
1535 }
1536
1537 WifiRemoteStation* station = DoCreateStation();
1538 station->m_state = LookupState(address).get();
1539 station->m_rssiAndUpdateTimePair = std::make_pair(dBm_u{0}, Seconds(0));
1540 const_cast<WifiRemoteStationManager*>(this)->m_stations.insert({address, station});
1541 return station;
1542}
1543
1544void
1545WifiRemoteStationManager::SetAssociationId(Mac48Address remoteAddress, uint16_t aid)
1546{
1547 NS_LOG_FUNCTION(this << remoteAddress << aid);
1548 LookupState(remoteAddress)->m_aid = aid;
1549}
1550
1551void
1552WifiRemoteStationManager::SetQosSupport(Mac48Address from, bool qosSupported)
1553{
1554 NS_LOG_FUNCTION(this << from << qosSupported);
1555 LookupState(from)->m_qosSupported = qosSupported;
1556}
1557
1558void
1559WifiRemoteStationManager::SetEmlsrEnabled(const Mac48Address& from, bool emlsrEnabled)
1560{
1561 NS_LOG_FUNCTION(this << from << emlsrEnabled);
1562 LookupState(from)->m_emlsrEnabled = emlsrEnabled;
1563}
1564
1565void
1566WifiRemoteStationManager::AddStationHtCapabilities(Mac48Address from,
1567 const HtCapabilities& htCapabilities)
1568{
1569 // Used by all stations to record HT capabilities of remote stations
1570 NS_LOG_FUNCTION(this << from << htCapabilities);
1571 auto state = LookupState(from);
1572 if (htCapabilities.GetSupportedChannelWidth() == 1)
1573 {
1574 state->m_channelWidth = MHz_u{40};
1575 }
1576 else
1577 {
1578 state->m_channelWidth = MHz_u{20};
1579 }
1580 SetQosSupport(from, true);
1581 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_HT))
1582 {
1583 if (htCapabilities.IsSupportedMcs(mcs.GetMcsValue()))
1584 {
1585 AddSupportedMcs(from, mcs);
1586 }
1587 }
1588 state->m_htCapabilities = Create<const HtCapabilities>(htCapabilities);
1589}
1590
1591void
1592WifiRemoteStationManager::AddStationExtendedCapabilities(
1593 Mac48Address from,
1594 const ExtendedCapabilities& extendedCapabilities)
1595{
1596 NS_LOG_FUNCTION(this << from << extendedCapabilities);
1597 auto state = LookupState(from);
1598 state->m_extendedCapabilities = Create<const ExtendedCapabilities>(extendedCapabilities);
1599}
1600
1601void
1602WifiRemoteStationManager::AddStationVhtCapabilities(Mac48Address from,
1603 const VhtCapabilities& vhtCapabilities)
1604{
1605 // Used by all stations to record VHT capabilities of remote stations
1606 NS_LOG_FUNCTION(this << from << vhtCapabilities);
1607 auto state = LookupState(from);
1608 if (vhtCapabilities.GetSupportedChannelWidthSet() == 1)
1609 {
1610 state->m_channelWidth = MHz_u{160};
1611 }
1612 else
1613 {
1614 state->m_channelWidth = MHz_u{80};
1615 }
1616 for (uint8_t i = 1; i <= m_wifiPhy->GetMaxSupportedTxSpatialStreams(); i++)
1617 {
1618 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_VHT))
1619 {
1620 if (vhtCapabilities.IsSupportedMcs(mcs.GetMcsValue(), i))
1621 {
1622 AddSupportedMcs(from, mcs);
1623 }
1624 }
1625 }
1626 state->m_vhtCapabilities = Create<const VhtCapabilities>(vhtCapabilities);
1627}
1628
1629void
1630WifiRemoteStationManager::AddStationHeCapabilities(Mac48Address from,
1631 const HeCapabilities& heCapabilities)
1632{
1633 // Used by all stations to record HE capabilities of remote stations
1634 NS_LOG_FUNCTION(this << from << heCapabilities);
1635 auto state = LookupState(from);
1636 if ((m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) ||
1637 (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_6GHZ))
1638 {
1639 if (heCapabilities.GetChannelWidthSet() & 0x04)
1640 {
1641 state->m_channelWidth = MHz_u{160};
1642 }
1643 else if (heCapabilities.GetChannelWidthSet() & 0x02)
1644 {
1645 state->m_channelWidth = MHz_u{80};
1646 }
1647 // For other cases at 5 GHz, the supported channel width is set by the VHT capabilities
1648 }
1649 else if (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
1650 {
1651 if (heCapabilities.GetChannelWidthSet() & 0x01)
1652 {
1653 state->m_channelWidth = MHz_u{40};
1654 }
1655 else
1656 {
1657 state->m_channelWidth = MHz_u{20};
1658 }
1659 }
1660 if (heCapabilities.GetHeSuPpdu1xHeLtf800nsGi())
1661 {
1662 state->m_guardInterval = NanoSeconds(800);
1663 }
1664 else
1665 {
1666 // todo: Using 3200ns, default value for HeConfiguration::GuardInterval
1667 state->m_guardInterval = NanoSeconds(3200);
1668 }
1669 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_HE))
1670 {
1671 if (heCapabilities.GetHighestMcsSupported() >= mcs.GetMcsValue())
1672 {
1673 AddSupportedMcs(from, mcs);
1674 }
1675 }
1676 state->m_heCapabilities = Create<const HeCapabilities>(heCapabilities);
1677 SetQosSupport(from, true);
1678}
1679
1680void
1681WifiRemoteStationManager::AddStationHe6GhzCapabilities(
1682 const Mac48Address& from,
1683 const He6GhzBandCapabilities& he6GhzCapabilities)
1684{
1685 // Used by all stations to record HE 6GHz band capabilities of remote stations
1686 NS_LOG_FUNCTION(this << from << he6GhzCapabilities);
1687 auto state = LookupState(from);
1688 state->m_he6GhzBandCapabilities = Create<const He6GhzBandCapabilities>(he6GhzCapabilities);
1689 SetQosSupport(from, true);
1690}
1691
1692void
1693WifiRemoteStationManager::AddStationEhtCapabilities(Mac48Address from,
1694 const EhtCapabilities& ehtCapabilities)
1695{
1696 // Used by all stations to record EHT capabilities of remote stations
1697 NS_LOG_FUNCTION(this << from << ehtCapabilities);
1698 auto state = LookupState(from);
1699 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_EHT))
1700 {
1701 for (uint8_t mapType = 0; mapType < EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_MAX; ++mapType)
1702 {
1703 if (ehtCapabilities.GetHighestSupportedRxMcs(
1704 static_cast<EhtMcsAndNssSet::EhtMcsMapType>(mapType)) >= mcs.GetMcsValue())
1705 {
1706 AddSupportedMcs(from, mcs);
1707 }
1708 }
1709 }
1710 state->m_ehtCapabilities = Create<const EhtCapabilities>(ehtCapabilities);
1711 SetQosSupport(from, true);
1712}
1713
1714void
1715WifiRemoteStationManager::AddStationMleCommonInfo(
1716 Mac48Address from,
1717 const std::shared_ptr<CommonInfoBasicMle>& mleCommonInfo)
1718{
1719 NS_LOG_FUNCTION(this << from);
1720 auto state = LookupState(from);
1721 state->m_mleCommonInfo = mleCommonInfo;
1722 // insert another entry in m_states indexed by the MLD address and pointing to the same state
1723 const_cast<WifiRemoteStationManager*>(this)->m_states.insert_or_assign(
1724 mleCommonInfo->m_mldMacAddress,
1725 state);
1726}
1727
1729WifiRemoteStationManager::GetStationHtCapabilities(Mac48Address from)
1730{
1731 return LookupState(from)->m_htCapabilities;
1732}
1733
1735WifiRemoteStationManager::GetStationExtendedCapabilities(const Mac48Address& from)
1736{
1737 return LookupState(from)->m_extendedCapabilities;
1738}
1739
1741WifiRemoteStationManager::GetStationVhtCapabilities(Mac48Address from)
1742{
1743 return LookupState(from)->m_vhtCapabilities;
1744}
1745
1747WifiRemoteStationManager::GetStationHeCapabilities(Mac48Address from)
1748{
1749 return LookupState(from)->m_heCapabilities;
1750}
1751
1753WifiRemoteStationManager::GetStationHe6GhzCapabilities(const Mac48Address& from) const
1754{
1755 return LookupState(from)->m_he6GhzBandCapabilities;
1756}
1757
1759WifiRemoteStationManager::GetStationEhtCapabilities(Mac48Address from)
1760{
1761 return LookupState(from)->m_ehtCapabilities;
1762}
1763
1764std::optional<std::reference_wrapper<CommonInfoBasicMle::EmlCapabilities>>
1765WifiRemoteStationManager::GetStationEmlCapabilities(const Mac48Address& from)
1766{
1767 if (auto state = LookupState(from);
1768 state->m_mleCommonInfo && state->m_mleCommonInfo->m_emlCapabilities)
1769 {
1770 return state->m_mleCommonInfo->m_emlCapabilities.value();
1771 }
1772 return std::nullopt;
1773}
1774
1775std::optional<std::reference_wrapper<CommonInfoBasicMle::MldCapabilities>>
1776WifiRemoteStationManager::GetStationMldCapabilities(const Mac48Address& from)
1777{
1778 if (auto state = LookupState(from);
1779 state->m_mleCommonInfo && state->m_mleCommonInfo->m_mldCapabilities)
1780 {
1781 return state->m_mleCommonInfo->m_mldCapabilities.value();
1782 }
1783 return std::nullopt;
1784}
1785
1786bool
1787WifiRemoteStationManager::GetLdpcSupported(Mac48Address address) const
1788{
1789 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
1790 Ptr<const VhtCapabilities> vhtCapabilities = LookupState(address)->m_vhtCapabilities;
1791 Ptr<const HeCapabilities> heCapabilities = LookupState(address)->m_heCapabilities;
1792 bool supported = false;
1793 if (htCapabilities)
1794 {
1795 supported |= htCapabilities->GetLdpc();
1796 }
1797 if (vhtCapabilities)
1798 {
1799 supported |= vhtCapabilities->GetRxLdpc();
1800 }
1801 if (heCapabilities)
1802 {
1803 supported |= heCapabilities->GetLdpcCodingInPayload();
1804 }
1805 return supported;
1806}
1807
1809WifiRemoteStationManager::GetDefaultMode() const
1810{
1811 NS_ASSERT(m_wifiPhy);
1812 auto defaultTxMode = m_wifiPhy->GetDefaultMode();
1813 NS_ASSERT(defaultTxMode.IsMandatory());
1814 return defaultTxMode;
1815}
1816
1818WifiRemoteStationManager::GetDefaultMcs() const
1819{
1820 return HtPhy::GetHtMcs0();
1821}
1822
1824WifiRemoteStationManager::GetDefaultModeForSta(const WifiRemoteStation* st) const
1825{
1826 NS_LOG_FUNCTION(this << st);
1827
1828 if ((!m_wifiPhy->GetDevice()->GetHtConfiguration()) ||
1829 (!GetHtSupported(st) && !GetStationHe6GhzCapabilities(st->m_state->m_address)))
1830 {
1831 return GetDefaultMode();
1832 }
1833
1834 // find the highest modulation class supported by both stations
1836 if (GetHeSupported() && GetHeSupported(st))
1837 {
1838 modClass = WIFI_MOD_CLASS_HE;
1839 }
1840 else if (GetVhtSupported() && GetVhtSupported(st))
1841 {
1842 modClass = WIFI_MOD_CLASS_VHT;
1843 }
1844
1845 // return the MCS with lowest index
1846 return *m_wifiPhy->GetPhyEntity(modClass)->begin();
1847}
1848
1849void
1850WifiRemoteStationManager::Reset()
1851{
1852 NS_LOG_FUNCTION(this);
1853 m_states.clear();
1854 for (auto& state : m_stations)
1855 {
1856 delete (state.second);
1857 }
1858 m_stations.clear();
1859 m_bssBasicRateSet.clear();
1860 m_bssBasicMcsSet.clear();
1861 m_ssrc.fill(0);
1862 m_slrc.fill(0);
1863}
1864
1865void
1866WifiRemoteStationManager::AddBasicMode(WifiMode mode)
1867{
1868 NS_LOG_FUNCTION(this << mode);
1870 {
1871 NS_FATAL_ERROR("It is not allowed to add a HT rate in the BSSBasicRateSet!");
1872 }
1873 for (uint8_t i = 0; i < GetNBasicModes(); i++)
1874 {
1875 if (GetBasicMode(i) == mode)
1876 {
1877 return;
1878 }
1879 }
1880 m_bssBasicRateSet.push_back(mode);
1881}
1882
1883uint8_t
1884WifiRemoteStationManager::GetNBasicModes() const
1885{
1886 return static_cast<uint8_t>(m_bssBasicRateSet.size());
1887}
1888
1890WifiRemoteStationManager::GetBasicMode(uint8_t i) const
1891{
1892 NS_ASSERT(i < GetNBasicModes());
1893 return m_bssBasicRateSet[i];
1894}
1895
1897WifiRemoteStationManager::GetNNonErpBasicModes() const
1898{
1899 uint32_t size = 0;
1900 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
1901 {
1902 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
1903 {
1904 continue;
1905 }
1906 size++;
1907 }
1908 return size;
1909}
1910
1912WifiRemoteStationManager::GetNonErpBasicMode(uint8_t i) const
1913{
1914 NS_ASSERT(i < GetNNonErpBasicModes());
1915 uint32_t index = 0;
1916 bool found = false;
1917 for (auto j = m_bssBasicRateSet.begin(); j != m_bssBasicRateSet.end();)
1918 {
1919 if (i == index)
1920 {
1921 found = true;
1922 }
1923 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
1924 {
1925 if (found)
1926 {
1927 break;
1928 }
1929 }
1930 index++;
1931 j++;
1932 }
1933 return m_bssBasicRateSet[index];
1934}
1935
1936void
1937WifiRemoteStationManager::AddBasicMcs(WifiMode mcs)
1938{
1939 NS_LOG_FUNCTION(this << +mcs.GetMcsValue());
1940 for (uint8_t i = 0; i < GetNBasicMcs(); i++)
1941 {
1942 if (GetBasicMcs(i) == mcs)
1943 {
1944 return;
1945 }
1946 }
1947 m_bssBasicMcsSet.push_back(mcs);
1948}
1949
1950uint8_t
1951WifiRemoteStationManager::GetNBasicMcs() const
1952{
1953 return static_cast<uint8_t>(m_bssBasicMcsSet.size());
1954}
1955
1957WifiRemoteStationManager::GetBasicMcs(uint8_t i) const
1958{
1959 NS_ASSERT(i < GetNBasicMcs());
1960 return m_bssBasicMcsSet[i];
1961}
1962
1964WifiRemoteStationManager::GetNonUnicastMode() const
1965{
1966 if (m_nonUnicastMode == WifiMode())
1967 {
1968 if (GetNBasicModes() > 0)
1969 {
1970 return GetBasicMode(0);
1971 }
1972 else
1973 {
1974 return GetDefaultMode();
1975 }
1976 }
1977 else
1978 {
1979 return m_nonUnicastMode;
1980 }
1981}
1982
1984WifiRemoteStationManager::GetGroupcastTxVector(const WifiMacHeader& header, MHz_u allowedWidth)
1985{
1986 const auto& to = header.GetAddr1();
1987 NS_ASSERT(to.IsGroup());
1988
1989 WifiTxVector groupcastTxVector{};
1990 const auto mode = GetNonUnicastMode();
1991 groupcastTxVector.SetMode(mode);
1992 groupcastTxVector.SetPreambleType(
1993 GetPreambleForTransmission(mode.GetModulationClass(), GetShortPreambleEnabled()));
1994 groupcastTxVector.SetTxPowerLevel(m_defaultTxPowerLevel);
1995 groupcastTxVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mode, allowedWidth));
1996 groupcastTxVector.SetNTx(GetNumberOfAntennas());
1997
1998 if (to.IsBroadcast())
1999 {
2000 return groupcastTxVector;
2001 }
2002
2003 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
2004 if (!apMac)
2005 {
2006 return groupcastTxVector;
2007 }
2008
2009 auto gcrManager = apMac->GetGcrManager();
2010 if (!gcrManager)
2011 {
2012 return groupcastTxVector;
2013 }
2014
2015 const auto& groupStas = gcrManager->GetMemberStasForGroupAddress(to);
2016 if (groupStas.empty())
2017 {
2018 return groupcastTxVector;
2019 }
2020
2021 if (!gcrManager->UseConcealment(header))
2022 {
2023 return groupcastTxVector;
2024 }
2025
2026 // If we are here, that means the mode will be used for the transmission of a groupcast frame
2027 // using the GCR service. We should loop over each member STA that is going to receive the
2028 // groupcast frame and select the highest possible mode over all STAs.
2029 std::optional<WifiMode> groupcastMode;
2030 auto maxWidth = allowedWidth;
2031 auto maxNss = m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2032 std::map<WifiModulationClass, Time> minGisPerMc{/* non-HT OFDM is always 800 ns */
2035 const std::map<WifiModulationClass, WifiModulationClass> giRefModClass{
2036 /* HT/VHT: short or long GI */
2039 /* HE/EHT: 3 possible GIs */
2042 for (const auto& staAddress : groupStas)
2043 {
2044 // Get the equivalent TXVECTOR if the frame would be a unicast frame to that STA in order to
2045 // get what rate would be selected for that STA.
2047 hdr.SetAddr1(staAddress);
2048 const auto unicastTxVector = GetDataTxVector(hdr, allowedWidth);
2049
2050 // update the groupcast mode if:
2051 // - this is the first mode to inspect;
2052 // - this mode has a lower modulation class than the currently selected groupcast mode;
2053 // - when the modulation class is similar, this mode has a lower MCS than the currently
2054 // selected groupcast mode.
2055 if (!groupcastMode.has_value() ||
2056 (unicastTxVector.GetModulationClass() < groupcastMode->GetModulationClass()) ||
2057 ((unicastTxVector.GetModulationClass() == groupcastMode->GetModulationClass()) &&
2058 (unicastTxVector.GetMode().GetMcsValue() < groupcastMode->GetMcsValue())))
2059 {
2060 groupcastMode = unicastTxVector.GetMode();
2061 }
2062 maxWidth = std::min(unicastTxVector.GetChannelWidth(), maxWidth);
2063 maxNss = std::min(unicastTxVector.GetNss(), maxNss);
2064 auto mc = unicastTxVector.GetModulationClass();
2065 if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
2066 {
2067 mc = it->second;
2068 }
2069 if (auto it = minGisPerMc.find(mc); it != minGisPerMc.end())
2070 {
2071 it->second = std::max(unicastTxVector.GetGuardInterval(), it->second);
2072 }
2073 }
2074 NS_ASSERT(groupcastMode.has_value());
2075
2076 groupcastTxVector.SetMode(*groupcastMode);
2077 groupcastTxVector.SetPreambleType(
2078 GetPreambleForTransmission(groupcastMode->GetModulationClass(), GetShortPreambleEnabled()));
2079 groupcastTxVector.SetChannelWidth(maxWidth);
2080 groupcastTxVector.SetNss(maxNss);
2081 auto mc = groupcastMode->GetModulationClass();
2082 if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
2083 {
2084 mc = it->second;
2085 }
2086 if (const auto it = minGisPerMc.find(mc); it != minGisPerMc.cend())
2087 {
2088 groupcastTxVector.SetGuardInterval(it->second);
2089 }
2090
2091 return groupcastTxVector;
2092}
2093
2094bool
2095WifiRemoteStationManager::DoNeedRts(WifiRemoteStation* station, uint32_t size, bool normally)
2096{
2097 return normally;
2098}
2099
2100bool
2101WifiRemoteStationManager::DoNeedFragmentation(WifiRemoteStation* station,
2102 Ptr<const Packet> packet,
2103 bool normally)
2104{
2105 return normally;
2106}
2107
2108void
2109WifiRemoteStationManager::DoReportAmpduTxStatus(WifiRemoteStation* station,
2110 uint16_t nSuccessfulMpdus,
2111 uint16_t nFailedMpdus,
2112 double rxSnr,
2113 double dataSnr,
2114 MHz_u dataChannelWidth,
2115 uint8_t dataNss)
2116{
2117 NS_LOG_DEBUG("DoReportAmpduTxStatus received but the manager does not handle A-MPDUs!");
2118}
2119
2121WifiRemoteStationManager::GetSupported(const WifiRemoteStation* station, uint8_t i) const
2122{
2123 NS_ASSERT(i < GetNSupported(station));
2124 return station->m_state->m_operationalRateSet[i];
2125}
2126
2128WifiRemoteStationManager::GetMcsSupported(const WifiRemoteStation* station, uint8_t i) const
2129{
2130 NS_ASSERT(i < GetNMcsSupported(station));
2131 return station->m_state->m_operationalMcsSet[i];
2132}
2133
2135WifiRemoteStationManager::GetNonErpSupported(const WifiRemoteStation* station, uint8_t i) const
2136{
2137 NS_ASSERT(i < GetNNonErpSupported(station));
2138 // IEEE 802.11g standard defines that if the protection mechanism is enabled, RTS, CTS and
2139 // CTS-To-Self frames should select a rate in the BSSBasicRateSet that corresponds to an 802.11b
2140 // basic rate. This is a implemented here to avoid changes in every RAA, but should maybe be
2141 // moved in case it breaks standard rules.
2142 uint32_t index = 0;
2143 bool found = false;
2144 for (auto j = station->m_state->m_operationalRateSet.begin();
2145 j != station->m_state->m_operationalRateSet.end();)
2146 {
2147 if (i == index)
2148 {
2149 found = true;
2150 }
2151 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
2152 {
2153 if (found)
2154 {
2155 break;
2156 }
2157 }
2158 index++;
2159 j++;
2160 }
2161 return station->m_state->m_operationalRateSet[index];
2162}
2163
2165WifiRemoteStationManager::GetAddress(const WifiRemoteStation* station) const
2166{
2167 return station->m_state->m_address;
2168}
2169
2170MHz_u
2171WifiRemoteStationManager::GetChannelWidth(const WifiRemoteStation* station) const
2172{
2173 return station->m_state->m_channelWidth;
2174}
2175
2176bool
2177WifiRemoteStationManager::GetShortGuardIntervalSupported(const WifiRemoteStation* station) const
2178{
2179 Ptr<const HtCapabilities> htCapabilities = station->m_state->m_htCapabilities;
2180
2181 if (!htCapabilities)
2182 {
2183 return false;
2184 }
2185 return htCapabilities->GetShortGuardInterval20();
2186}
2187
2188Time
2189WifiRemoteStationManager::GetGuardInterval(const WifiRemoteStation* station) const
2190{
2191 return station->m_state->m_guardInterval;
2192}
2193
2194bool
2195WifiRemoteStationManager::GetAggregation(const WifiRemoteStation* station) const
2196{
2197 return station->m_state->m_aggregation;
2198}
2199
2200uint8_t
2201WifiRemoteStationManager::GetNumberOfSupportedStreams(const WifiRemoteStation* station) const
2202{
2203 const auto htCapabilities = station->m_state->m_htCapabilities;
2204
2205 if (!htCapabilities)
2206 {
2207 if (const auto heCapabilities = station->m_state->m_heCapabilities)
2208 {
2209 return heCapabilities->GetHighestNssSupported();
2210 }
2211 return 1;
2212 }
2213 return htCapabilities->GetRxHighestSupportedAntennas();
2214}
2215
2216uint8_t
2217WifiRemoteStationManager::GetNess(const WifiRemoteStation* station) const
2218{
2219 return station->m_state->m_ness;
2220}
2221
2223WifiRemoteStationManager::GetPhy() const
2224{
2225 return m_wifiPhy;
2226}
2227
2229WifiRemoteStationManager::GetMac() const
2230{
2231 return m_wifiMac;
2232}
2233
2234uint8_t
2235WifiRemoteStationManager::GetNSupported(const WifiRemoteStation* station) const
2236{
2237 return static_cast<uint8_t>(station->m_state->m_operationalRateSet.size());
2238}
2239
2240bool
2241WifiRemoteStationManager::GetQosSupported(const WifiRemoteStation* station) const
2242{
2243 return station->m_state->m_qosSupported;
2244}
2245
2246bool
2247WifiRemoteStationManager::GetHtSupported(const WifiRemoteStation* station) const
2248{
2249 return bool(station->m_state->m_htCapabilities);
2250}
2251
2252bool
2253WifiRemoteStationManager::GetVhtSupported(const WifiRemoteStation* station) const
2254{
2255 return bool(station->m_state->m_vhtCapabilities);
2256}
2257
2258bool
2259WifiRemoteStationManager::GetHeSupported(const WifiRemoteStation* station) const
2260{
2261 return bool(station->m_state->m_heCapabilities);
2262}
2263
2264bool
2265WifiRemoteStationManager::GetEhtSupported(const WifiRemoteStation* station) const
2266{
2267 return (bool)(station->m_state->m_ehtCapabilities);
2268}
2269
2270bool
2271WifiRemoteStationManager::GetEmlsrSupported(const WifiRemoteStation* station) const
2272{
2273 auto mleCommonInfo = station->m_state->m_mleCommonInfo;
2274 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2275 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2276}
2277
2278bool
2279WifiRemoteStationManager::GetEmlsrEnabled(const WifiRemoteStation* station) const
2280{
2281 return station->m_state->m_emlsrEnabled;
2282}
2283
2284uint8_t
2285WifiRemoteStationManager::GetNMcsSupported(const WifiRemoteStation* station) const
2286{
2287 return static_cast<uint8_t>(station->m_state->m_operationalMcsSet.size());
2288}
2289
2291WifiRemoteStationManager::GetNNonErpSupported(const WifiRemoteStation* station) const
2292{
2293 uint32_t size = 0;
2294 for (auto i = station->m_state->m_operationalRateSet.begin();
2295 i != station->m_state->m_operationalRateSet.end();
2296 i++)
2297 {
2298 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
2299 {
2300 continue;
2301 }
2302 size++;
2303 }
2304 return size;
2305}
2306
2307MHz_u
2308WifiRemoteStationManager::GetChannelWidthSupported(Mac48Address address) const
2309{
2310 return LookupState(address)->m_channelWidth;
2311}
2312
2313bool
2314WifiRemoteStationManager::GetShortGuardIntervalSupported(Mac48Address address) const
2315{
2316 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2317
2318 if (!htCapabilities)
2319 {
2320 return false;
2321 }
2322 return htCapabilities->GetShortGuardInterval20();
2323}
2324
2325uint8_t
2326WifiRemoteStationManager::GetNumberOfSupportedStreams(Mac48Address address) const
2327{
2328 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2329
2330 if (!htCapabilities)
2331 {
2332 return 1;
2333 }
2334 return htCapabilities->GetRxHighestSupportedAntennas();
2335}
2336
2337uint8_t
2338WifiRemoteStationManager::GetNMcsSupported(Mac48Address address) const
2339{
2340 return static_cast<uint8_t>(LookupState(address)->m_operationalMcsSet.size());
2341}
2342
2343bool
2344WifiRemoteStationManager::GetDsssSupported(const Mac48Address& address) const
2345{
2346 return (LookupState(address)->m_dsssSupported);
2347}
2348
2349bool
2350WifiRemoteStationManager::GetErpOfdmSupported(const Mac48Address& address) const
2351{
2352 return (LookupState(address)->m_erpOfdmSupported);
2353}
2354
2355bool
2356WifiRemoteStationManager::GetOfdmSupported(const Mac48Address& address) const
2357{
2358 return (LookupState(address)->m_ofdmSupported);
2359}
2360
2361bool
2362WifiRemoteStationManager::GetHtSupported(Mac48Address address) const
2363{
2364 return bool(LookupState(address)->m_htCapabilities);
2365}
2366
2367bool
2368WifiRemoteStationManager::GetVhtSupported(Mac48Address address) const
2369{
2370 return bool(LookupState(address)->m_vhtCapabilities);
2371}
2372
2373bool
2374WifiRemoteStationManager::GetHeSupported(Mac48Address address) const
2375{
2376 return bool(LookupState(address)->m_heCapabilities);
2377}
2378
2379bool
2380WifiRemoteStationManager::GetEhtSupported(Mac48Address address) const
2381{
2382 return (bool)(LookupState(address)->m_ehtCapabilities);
2383}
2384
2385bool
2386WifiRemoteStationManager::GetEmlsrSupported(const Mac48Address& address) const
2387{
2388 auto mleCommonInfo = LookupState(address)->m_mleCommonInfo;
2389 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2390 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2391}
2392
2393bool
2394WifiRemoteStationManager::GetEmlsrEnabled(const Mac48Address& address) const
2395{
2396 if (auto stateIt = m_states.find(address); stateIt != m_states.cend())
2397 {
2398 return stateIt->second->m_emlsrEnabled;
2399 }
2400 return false;
2401}
2402
2403void
2404WifiRemoteStationManager::SetDefaultTxPowerLevel(uint8_t txPower)
2405{
2406 m_defaultTxPowerLevel = txPower;
2407}
2408
2409uint8_t
2410WifiRemoteStationManager::GetNumberOfAntennas() const
2411{
2412 return m_wifiPhy->GetNumberOfAntennas();
2413}
2414
2415uint8_t
2416WifiRemoteStationManager::GetMaxNumberOfTransmitStreams() const
2417{
2418 return m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2419}
2420
2421bool
2422WifiRemoteStationManager::UseLdpcForDestination(Mac48Address dest) const
2423{
2424 return (GetLdpcSupported() && GetLdpcSupported(dest));
2425}
2426
2427} // namespace ns3
AttributeValue implementation for Boolean.
Definition boolean.h:26
The IEEE 802.11be EHT Capabilities.
uint8_t GetHighestSupportedRxMcs(EhtMcsAndNssSet::EhtMcsMapType mapType) const
Get the highest supported RX MCS for a given EHT-MCS map type.
Hold variables of type enum.
Definition enum.h:52
T Get() const
Definition enum.h:87
static WifiMode GetErpOfdmRate(uint64_t rate)
Return a WifiMode for ERP-OFDM corresponding to the provided rate.
static WifiMode GetErpOfdmRate6Mbps()
Return a WifiMode for ERP-OFDM at 6 Mbps.
The Extended Capabilities Information Element.
The HE 6 GHz Band Capabilities (IEEE 802.11ax-2021 9.4.2.263)
The IEEE 802.11ax HE Capabilities.
uint8_t GetHighestMcsSupported() const
Get highest MCS supported.
bool GetHeSuPpdu1xHeLtf800nsGi() const
Get 1xHE-LTF and 800ns GI in HE SU PPDU reception support.
uint8_t GetChannelWidthSet() const
Get channel width set.
The HT Capabilities Information Element.
uint8_t GetSupportedChannelWidth() const
Return the supported channel width.
bool IsSupportedMcs(uint8_t mcs) const
Return the is MCS supported flag.
an EUI-48 address
bool IsGroup() const
A base class which provides memory management and object aggregation.
Definition object.h:78
static WifiMode GetOfdmRate(uint64_t rate, MHz_u bw=MHz_u{20})
Return a WifiMode for OFDM corresponding to the provided rate and the channel bandwidth (20,...
Definition ofdm-phy.cc:404
Smart pointer class similar to boost::intrusive_ptr.
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:340
AttributeValue implementation for Time.
Definition nstime.h:1432
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
@ OBSOLETE
Attribute or trace source is not used anymore; simulation fails.
Hold an unsigned integer type.
Definition uinteger.h:34
The IEEE 802.11ac VHT Capabilities.
bool IsSupportedMcs(uint8_t mcs, uint8_t nss) const
Get the is MCS supported.
uint8_t GetSupportedChannelWidthSet() const
Get the supported channel width set.
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
bool IsMgt() const
Return true if the Type is Management.
void SetAddr1(Mac48Address address)
Fill the Address 1 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.
represent a single transmission mode
Definition wifi-mode.h:40
bool IsHigherDataRate(WifiMode mode) const
Definition wifi-mode.cc:195
WifiModulationClass GetModulationClass() const
Definition wifi-mode.cc:172
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:110
uint8_t GetMcsValue() const
Definition wifi-mode.cc:151
AttributeValue implementation for WifiMode.
Definition wifi-mode.h:246
MHz_u GetTxBandwidth(WifiMode mode, MHz_u maxAllowedBandWidth=MHz_u{ std::numeric_limits< double >::max()}) const
Get the bandwidth for a transmission occurring on the current operating channel and using the given W...
Definition wifi-phy.cc:1102
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition wifi-phy.cc:1048
MHz_u GetChannelWidth() const
Definition wifi-phy.cc:1078
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition wifi-phy.cc:646
std::list< WifiMode > GetMcsList() const
The WifiPhy::GetMcsList() method is used (e.g., by a WifiRemoteStationManager) to determine the set o...
Definition wifi-phy.cc:2110
std::list< WifiMode > GetModeList() const
The WifiPhy::GetModeList() method is used (e.g., by a WifiRemoteStationManager) to determine the set ...
Definition wifi-phy.cc:2061
TID independent remote station statistics.
void NotifyTxSuccess(uint32_t retryCounter)
Updates average frame error rate when data or RTS was transmitted successfully.
void NotifyTxFailed()
Updates average frame error rate when final data or RTS has failed.
hold a list of per-remote-station state.
void ReportDataFailed(Ptr< const WifiMpdu > mpdu)
Should be invoked whenever the AckTimeout associated to a transmission attempt expires.
bool GetQosSupported(Mac48Address address) const
Return whether the given station is QoS capable.
virtual WifiTxVector DoGetDataTxVector(WifiRemoteStation *station, MHz_u allowedWidth)=0
WifiTxVector GetAckTxVector(Mac48Address to, const WifiTxVector &dataTxVector) const
Return a TXVECTOR for the Ack frame given the destination and the mode of the Data used by the sender...
virtual bool DoNeedFragmentation(WifiRemoteStation *station, Ptr< const Packet > packet, bool normally)
uint32_t m_fragmentationThreshold
Current threshold for fragmentation.
void SetShortSlotTimeEnabled(bool enable)
Enable or disable short slot time.
void SetPsMode(const Mac48Address &address, bool isInPsMode)
Register whether the STA is in Power Save mode or not.
void AddBasicMode(WifiMode mode)
Invoked in a STA upon association to store the set of rates which belong to the BSSBasicRateSet of th...
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
uint32_t GetNFragments(Ptr< const WifiMpdu > mpdu)
Return the number of fragments needed for the given packet.
uint16_t GetAssociationId(Mac48Address remoteAddress) const
Get the AID of a remote station.
virtual void DoIncrementRetryCountOnTxFailure(WifiRemoteStation *station, Ptr< WifiPsdu > psdu)
Increment the retry count (if needed) for the given PSDU, whose transmission failed.
ProtectionMode m_htProtectionMode
Protection mode for HT stations when non-HT stations are detected.
void AdjustTxVectorForIcf(WifiTxVector &txVector) const
Adjust the TXVECTOR for an initial Control frame to ensure that the modulation class is non-HT and th...
std::array< uint32_t, AC_BE_NQOS > m_slrc
long retry count per AC
WifiRemoteStation * Lookup(Mac48Address address) const
Return the station associated with the given address.
uint32_t GetFragmentationThreshold() const
Return the fragmentation threshold.
uint8_t GetNBasicModes() const
Return the number of basic modes we support.
bool UseLdpcForDestination(Mac48Address dest) const
uint32_t m_maxSsrc
Maximum STA short retry count (SSRC)
void SetRtsCtsThreshold(uint32_t threshold)
Sets the RTS threshold.
void AddAllSupportedMcs(Mac48Address address)
Invoked in a STA or AP to store all of the MCS supported by a destination which is also supported loc...
TracedCallback< Mac48Address > m_macTxRtsFailed
The trace source fired when the transmission of a single RTS has failed.
virtual bool DoNeedRts(WifiRemoteStation *station, uint32_t size, bool normally)
Time GetGuardInterval() const
Return the shortest supported HE guard interval duration.
WifiTxVector GetRtsTxVector(Mac48Address address, MHz_u allowedWidth)
void DoSetFragmentationThreshold(uint32_t threshold)
Actually sets the fragmentation threshold, it also checks the validity of the given threshold.
bool IsBrandNew(Mac48Address address) const
Return whether the station state is brand new.
virtual void DoReportFinalDataFailed(WifiRemoteStation *station)=0
This method is a pure virtual method that must be implemented by the sub-class.
virtual void DoReportRtsOk(WifiRemoteStation *station, double ctsSnr, WifiMode ctsMode, double rtsSnr)=0
This method is a pure virtual method that must be implemented by the sub-class.
void AdjustTxVectorForCtlResponse(WifiTxVector &txVector, MHz_u allowedWidth) const
Adjust the TXVECTOR for a control response frame to ensure that, if appropriate, the non-HT duplicate...
Time m_rtsCtsTxDurationThresh
TX duration threshold for RTS/CTS.
bool GetShortSlotTimeEnabled() const
Return whether the device uses short slot time.
void DoDispose() override
Destructor implementation.
virtual void DoReportDataFailed(WifiRemoteStation *station)=0
This method is a pure virtual method that must be implemented by the sub-class.
bool IsLastFragment(Ptr< const WifiMpdu > mpdu, uint32_t fragmentNumber)
void ReportFinalDataFailed(Ptr< const WifiMpdu > mpdu)
Should be invoked after calling ReportDataFailed if frames are dropped.
void SetUseNonErpProtection(bool enable)
Enable or disable protection for non-ERP stations.
bool m_useNonHtProtection
flag if protection for non-HT stations against HT transmissions is enabled
bool GetShortPreambleSupported(Mac48Address address) const
Return whether the station supports short PHY preamble or not.
void AddAllSupportedModes(Mac48Address address)
Invoked in a STA or AP to store all of the modes supported by a destination which is also supported l...
virtual void DoReportAmpduTxStatus(WifiRemoteStation *station, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus, double rxSnr, double dataSnr, MHz_u dataChannelWidth, uint8_t dataNss)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
std::optional< Mac48Address > GetAffiliatedStaAddress(const Mac48Address &mldAddress) const
Get the address of the remote station operating on this link and affiliated with the MLD having the g...
std::list< Ptr< WifiMpdu > > GetMpdusToDropOnTxFailure(Ptr< WifiPsdu > psdu)
Increment the retry count for all the MPDUs (if needed) in the given PSDU and find the MPDUs to drop ...
WifiTxVector GetDataTxVector(const WifiMacHeader &header, MHz_u allowedWidth)
std::optional< dBm_u > GetMostRecentRssi(Mac48Address address) const
void ReportRtsOk(const WifiMacHeader &header, double ctsSnr, WifiMode ctsMode, double rtsSnr)
Should be invoked whenever we receive the CTS associated to an RTS we just sent.
void AddSupportedMcs(Mac48Address address, WifiMode mcs)
Record the MCS index supported by the station.
WifiTxVector GetBlockAckTxVector(Mac48Address to, const WifiTxVector &dataTxVector) const
Return a TXVECTOR for the BlockAck frame given the destination and the mode of the Data used by the s...
void RemoveAllSupportedMcs(Mac48Address address)
Invoked in a STA or AP to delete all of the supported MCS by a destination.
void ReportRxOk(Mac48Address address, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector)
uint32_t DoGetFragmentationThreshold() const
Return the current fragmentation threshold.
TracedCallback< Mac48Address > m_macTxFinalRtsFailed
The trace source fired when the transmission of a RTS has exceeded the maximum number of attempts.
WifiMode GetNonUnicastMode() const
Return a mode for non-unicast packets.
bool m_shortPreambleEnabled
flag if short PHY preamble is enabled
WifiTxVector GetGroupcastTxVector(const WifiMacHeader &header, MHz_u allowedWidth)
Return the TXVECTOR to use for a groupcast packet.
bool GetShortSlotTimeSupported(Mac48Address address) const
Return whether the station supports short ERP slot time or not.
void SetShortPreambleEnabled(bool enable)
Enable or disable short PHY preambles.
WifiMode GetDefaultMcs() const
Return the default Modulation and Coding Scheme (MCS) index.
Ptr< WifiPhy > m_wifiPhy
This is a pointer to the WifiPhy associated with this WifiRemoteStationManager that is set on call to...
uint8_t m_defaultTxPowerLevel
Default transmission power level.
static TypeId GetTypeId()
Get the type ID.
WifiMode m_nonUnicastMode
Transmission mode for non-unicast Data frames.
void SetUseNonHtProtection(bool enable)
Enable or disable protection for non-HT stations.
MHz_u GetChannelWidthSupported(Mac48Address address) const
Return the channel width supported by the station.
bool IsAssociated(Mac48Address address) const
Return whether the station associated.
bool NeedFragmentation(Ptr< const WifiMpdu > mpdu)
void ReportAmpduTxStatus(Mac48Address address, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus, double rxSnr, double dataSnr, WifiTxVector dataTxVector)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
uint32_t GetFragmentOffset(Ptr< const WifiMpdu > mpdu, uint32_t fragmentNumber)
WifiRemoteStationInfo GetInfo(Mac48Address address)
uint32_t GetFragmentSize(Ptr< const WifiMpdu > mpdu, uint32_t fragmentNumber)
WifiTxVector GetCtsToSelfTxVector()
Since CTS-to-self parameters are not dependent on the station, it is implemented in wifi remote stati...
uint8_t GetNBasicMcs() const
Return the number of basic MCS index.
bool GetHtSupported() const
Return whether the device has HT capability support enabled on the link this manager is associated wi...
void RecordWaitAssocTxOk(Mac48Address address)
Records that we are waiting for an ACK for the association response we sent.
void SetFragmentationThreshold(uint32_t threshold)
Sets a fragmentation threshold.
Ptr< WifiMac > m_wifiMac
This is a pointer to the WifiMac associated with this WifiRemoteStationManager that is set on call to...
void RecordGotAssocTxOk(Mac48Address address)
Records that we got an ACK for the association response we sent.
bool GetLdpcSupported() const
Return whether the device has LDPC support enabled.
bool GetEhtSupported() const
Return whether the device has EHT capability support enabled.
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...
std::shared_ptr< WifiRemoteStationState > LookupState(Mac48Address address) const
Return the state of the station associated with the given address.
bool m_incrRetryCountUnderBa
whether to increment the retry count of frames that are part of a Block Ack agreement
std::array< uint32_t, AC_BE_NQOS > m_ssrc
short retry count per AC
virtual std::list< Ptr< WifiMpdu > > DoGetMpdusToDropOnTxFailure(WifiRemoteStation *station, Ptr< WifiPsdu > psdu)
Find the MPDUs to drop (possibly based on their frame retry count) in the given PSDU,...
void RecordAssocRefused(Mac48Address address)
Records that association request was refused.
bool IsInPsMode(const Mac48Address &address) const
Return whether the STA is currently in Power Save mode.
void ReportFinalRtsFailed(const WifiMacHeader &header)
Should be invoked after calling ReportRtsFailed if frames are dropped.
StationStates m_states
States of known stations.
WifiTxVector GetCtsTxVector(Mac48Address to, WifiMode rtsTxMode) const
Return a TXVECTOR for the CTS frame given the destination and the mode of the RTS used by the sender.
bool NeedCtsToSelf(const WifiTxVector &txVector, const WifiMacHeader &header)
Return if we need to do CTS-to-self before sending a DATA.
void SetMaxSsrc(uint32_t maxSsrc)
Sets the maximum STA short retry count (SSRC).
WifiMode GetBasicMcs(uint8_t i) const
Return the MCS at the given list index.
TracedCallback< Mac48Address > m_macTxDataFailed
The trace source fired when the transmission of a single data packet has failed.
uint16_t GetStaId(Mac48Address address, const WifiTxVector &txVector) const
If the given TXVECTOR is used for a MU transmission, return the STAID of the station with the given a...
virtual void DoReportDataOk(WifiRemoteStation *station, double ackSnr, WifiMode ackMode, double dataSnr, MHz_u dataChannelWidth, uint8_t dataNss)=0
This method is a pure virtual method that must be implemented by the sub-class.
WifiMode GetBasicMode(uint8_t i) const
Return a basic mode from the set of basic modes.
void AddSupportedPhyPreamble(Mac48Address address, bool isShortPreambleSupported)
Record whether the short PHY preamble is supported by the station.
bool GetShortGuardIntervalSupported() const
Return whether the device has SGI support enabled.
virtual void SetupPhy(const Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
virtual void DoReportRtsFailed(WifiRemoteStation *station)=0
This method is a pure virtual method that must be implemented by the sub-class.
void RecordDisassociated(Mac48Address address)
Records that the STA was disassociated.
virtual WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station)=0
uint32_t m_maxSlrc
Maximum STA long retry count (SLRC)
void Reset()
Reset the station, invoked in a STA upon dis-association or in an AP upon reboot.
bool GetUseNonErpProtection() const
Return whether the device supports protection of non-ERP stations.
bool IsAssocRefused(Mac48Address address) const
Return whether we refused an association request from the given station.
bool GetVhtSupported() const
Return whether the device has VHT capability support enabled on the link this manager is associated w...
ProtectionMode m_erpProtectionMode
Protection mode for ERP stations when non-ERP stations are detected.
void ReportDataOk(Ptr< const WifiMpdu > mpdu, double ackSnr, WifiMode ackMode, double dataSnr, WifiTxVector dataTxVector)
Should be invoked whenever we receive the ACK associated to a data packet we just sent.
void ReportRtsFailed(const WifiMacHeader &header)
Should be invoked whenever the RtsTimeout associated to a transmission attempt expires.
void AddSupportedErpSlotTime(Mac48Address address, bool isShortSlotTimeSupported)
Record whether the short ERP slot time is supported by the station.
bool GetShortPreambleEnabled() const
Return whether the device uses short PHY preambles.
uint8_t m_linkId
the ID of the link this object is associated with
bool GetHeSupported() const
Return whether the device has HE capability support enabled.
virtual void DoReportRxOk(WifiRemoteStation *station, double rxSnr, WifiMode txMode)=0
This method is a pure virtual method that must be implemented by the sub-class.
WifiMode GetDefaultMode() const
Return the default transmission mode.
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.
virtual void DoReportFinalRtsFailed(WifiRemoteStation *station)=0
This method is a pure virtual method that must be implemented by the sub-class.
virtual void SetupMac(const Ptr< WifiMac > mac)
Set up MAC associated with this device since it is the object that knows the full set of timing param...
void SetLinkId(uint8_t linkId)
Set the ID of the link this Remote Station Manager is associated with.
bool NeedRts(const WifiMacHeader &header, const WifiTxParameters &txParams)
uint32_t m_rtsCtsThreshold
Threshold for RTS/CTS.
bool m_useNonErpProtection
flag if protection for non-ERP stations against ERP transmissions is enabled
WifiMode GetControlAnswerMode(WifiMode reqMode) const
Get control answer mode function.
bool m_shortSlotTimeEnabled
flag if short slot time is enabled
bool IsWaitAssocTxOk(Mac48Address address) const
Return whether we are waiting for an ACK for the association response we sent.
void SetMaxSlrc(uint32_t maxSlrc)
Sets the maximum STA long retry count (SLRC).
TracedCallback< Mac48Address > m_macTxFinalDataFailed
The trace source fired when the transmission of a data packet has exceeded the maximum number of atte...
bool GetUseNonHtProtection() const
Return whether the device supports protection of non-HT stations.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
std::optional< Time > m_txDuration
TX duration of the frame.
uint32_t GetSize(Mac48Address receiver) const
Get the size in bytes of the (A-)MPDU addressed to the given receiver.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetNess(uint8_t ness)
Sets the Ness number.
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
void SetLdpc(bool ldpc)
Sets if LDPC FEC coding is being used.
void SetGuardInterval(Time guardInterval)
Sets the guard interval duration (in nanoseconds)
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
void SetChannelWidth(MHz_u channelWidth)
Sets the selected channelWidth.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
MHz_u GetChannelWidth() const
void SetBssColor(uint8_t color)
Set the BSS color.
void SetNTx(uint8_t nTx)
Sets the number of TX antennas.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition enum.h:221
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1433
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1453
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
Ptr< const AttributeAccessor > MakeWifiModeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition wifi-mode.h:246
Ptr< const AttributeChecker > MakeWifiModeChecker()
Definition wifi-mode.cc:250
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Maps TID (Traffic ID) to Access classes.
Definition qos-utils.cc:123
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition qos-utils.h:62
@ STA
Definition wifi-mac.h:59
@ AP
Definition wifi-mac.h:60
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_EHT_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PREAMBLE_VHT_SU
@ WIFI_PREAMBLE_HT_MF
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_MOD_CLASS_OFDM
OFDM (Clause 17)
@ 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)
@ WIFI_MOD_CLASS_DSSS
DSSS (Clause 15)
@ WIFI_MOD_CLASS_ERP_OFDM
ERP-OFDM (18.4)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:443
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octets of the IEEE 802.11 MAC FCS field.
Time GetGuardIntervalForMode(WifiMode mode, const Ptr< WifiNetDevice > device)
Get the guard interval for a given WifiMode.
bool IsAllowedControlAnswerModulationClass(WifiModulationClass modClassReq, WifiModulationClass modClassAnswer)
Return whether the modulation class of the selected mode for the control answer frame is allowed.
double MHz_u
MHz weak type.
Definition wifi-units.h:31
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition enum.h:179
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
@ WIFI_MAC_QOSDATA
@ CTS_TO_SELF
Definition gcr-manager.h:40
@ RTS_CTS
Definition gcr-manager.h:39
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587
std::vector< WifiMode > WifiModeList
In various parts of the code, folk are interested in maintaining a list of transmission modes.
Definition wifi-mode.h:254
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
bool IsGcr(Ptr< WifiMac > mac, const WifiMacHeader &hdr)
Return whether a given packet is transmitted using the GCR service.
WifiPreamble GetPreambleForTransmission(WifiModulationClass modulation, bool useShortPreamble)
Return the preamble to be used for the transmission.
Mac48Address GetIndividuallyAddressedRecipient(Ptr< WifiMac > mac, const WifiMacHeader &hdr)
Get the MAC address of the individually addressed recipient to use for a given packet.
EhtMcsMapType
The different EHT-MCS map types as defined in 9.4.2.313.4 Supported EHT-MCS And NSS Set field.
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:78
double snr
SNR in linear scale.
Definition wifi-types.h:79
dBm_u rssi
RSSI.
Definition wifi-types.h:80
hold per-remote-station state.
WifiRemoteStationState * m_state
Remote station state.
std::pair< dBm_u, Time > m_rssiAndUpdateTimePair
RSSI of the most recent packet received from the remote station along with update time.
std::shared_ptr< CommonInfoBasicMle > m_mleCommonInfo
remote station Multi-Link Element Common Info
Mac48Address m_address
Mac48Address of the remote station.
MHz_u m_channelWidth
Channel width supported by the remote station.
uint8_t m_ness
Number of extended spatial streams of the remote station.
bool m_aggregation
Flag if MPDU aggregation is used by the remote station.
bool m_qosSupported
Flag if QoS is supported by the station.
WifiModeList m_operationalRateSet
This member is the list of WifiMode objects that comprise the OperationalRateSet parameter for this r...
WifiModeList m_operationalMcsSet
operational MCS set
Ptr< const EhtCapabilities > m_ehtCapabilities
remote station EHT capabilities
Ptr< const VhtCapabilities > m_vhtCapabilities
remote station VHT capabilities
WifiRemoteStationInfo m_info
remote station info
bool m_emlsrEnabled
whether EMLSR mode is enabled on this link
Ptr< const HtCapabilities > m_htCapabilities
remote station HT capabilities
Time m_guardInterval
HE Guard interval durationsupported by the remote station.
Ptr< const HeCapabilities > m_heCapabilities
remote station HE capabilities