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 if (const auto stateIt = m_states.find(address); stateIt != m_states.cend())
1490 {
1491 return stateIt->second;
1492 }
1493
1494 auto state = std::make_shared<WifiRemoteStationState>();
1495 state->m_state = WifiRemoteStationState::BRAND_NEW;
1496 state->m_address = address;
1497 state->m_aid = 0;
1498 state->m_operationalRateSet.push_back(GetDefaultMode());
1499 state->m_operationalMcsSet.push_back(GetDefaultMcs());
1500 state->m_dsssSupported = false;
1501 state->m_erpOfdmSupported = false;
1502 state->m_ofdmSupported = false;
1503 state->m_htCapabilities = nullptr;
1504 state->m_htOperation = nullptr;
1505 state->m_vhtCapabilities = nullptr;
1506 state->m_vhtOperation = nullptr;
1507 state->m_heCapabilities = nullptr;
1508 state->m_heOperation = nullptr;
1509 state->m_ehtCapabilities = nullptr;
1510 state->m_ehtOperation = 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::AddStationHtOperation(Mac48Address from, const HtOperation& htOperation)
1593{
1594 NS_LOG_FUNCTION(this << from << htOperation);
1595 auto state = LookupState(from);
1596 if (htOperation.GetStaChannelWidth() == 0)
1597 {
1598 state->m_channelWidth = MHz_u{20};
1599 }
1600 state->m_htOperation = Create<const HtOperation>(htOperation);
1601}
1602
1603void
1604WifiRemoteStationManager::AddStationExtendedCapabilities(
1605 Mac48Address from,
1606 const ExtendedCapabilities& extendedCapabilities)
1607{
1608 NS_LOG_FUNCTION(this << from << extendedCapabilities);
1609 auto state = LookupState(from);
1610 state->m_extendedCapabilities = Create<const ExtendedCapabilities>(extendedCapabilities);
1611}
1612
1613void
1614WifiRemoteStationManager::AddStationVhtCapabilities(Mac48Address from,
1615 const VhtCapabilities& vhtCapabilities)
1616{
1617 // Used by all stations to record VHT capabilities of remote stations
1618 NS_LOG_FUNCTION(this << from << vhtCapabilities);
1619 auto state = LookupState(from);
1620 if (vhtCapabilities.GetSupportedChannelWidthSet() == 1)
1621 {
1622 state->m_channelWidth = MHz_u{160};
1623 }
1624 else
1625 {
1626 state->m_channelWidth = MHz_u{80};
1627 }
1628 for (uint8_t i = 1; i <= m_wifiPhy->GetMaxSupportedTxSpatialStreams(); i++)
1629 {
1630 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_VHT))
1631 {
1632 if (vhtCapabilities.IsSupportedMcs(mcs.GetMcsValue(), i))
1633 {
1634 AddSupportedMcs(from, mcs);
1635 }
1636 }
1637 }
1638 state->m_vhtCapabilities = Create<const VhtCapabilities>(vhtCapabilities);
1639}
1640
1641void
1642WifiRemoteStationManager::AddStationVhtOperation(Mac48Address from,
1643 const VhtOperation& vhtOperation)
1644{
1645 NS_LOG_FUNCTION(this << from << vhtOperation);
1646 auto state = LookupState(from);
1647 /*
1648 * Table 9-274 (VHT Operation Information subfields) of 802.11-2020:
1649 * Set to 0 for 20 MHz or 40 MHz BSS bandwidth.
1650 * Set to 1 for 80 MHz, 160 MHz or 80+80 MHz BSS bandwidth.
1651 */
1652 if (vhtOperation.GetChannelWidth() == 0)
1653 {
1654 state->m_channelWidth = std::min(MHz_u{40}, state->m_channelWidth);
1655 }
1656 else if (vhtOperation.GetChannelWidth() == 1)
1657 {
1658 state->m_channelWidth = std::min(MHz_u{160}, state->m_channelWidth);
1659 }
1660 state->m_vhtOperation = Create<const VhtOperation>(vhtOperation);
1661}
1662
1664WifiRemoteStationManager::GetStationVhtOperation(Mac48Address from)
1665{
1666 return LookupState(from)->m_vhtOperation;
1667}
1668
1669void
1670WifiRemoteStationManager::AddStationHeCapabilities(Mac48Address from,
1671 const HeCapabilities& heCapabilities)
1672{
1673 // Used by all stations to record HE capabilities of remote stations
1674 NS_LOG_FUNCTION(this << from << heCapabilities);
1675 auto state = LookupState(from);
1676 if ((m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) ||
1677 (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_6GHZ))
1678 {
1679 if (heCapabilities.GetChannelWidthSet() & 0x04)
1680 {
1681 state->m_channelWidth = MHz_u{160};
1682 }
1683 else if (heCapabilities.GetChannelWidthSet() & 0x02)
1684 {
1685 state->m_channelWidth = MHz_u{80};
1686 }
1687 else if (heCapabilities.GetChannelWidthSet() == 0x00)
1688 {
1689 state->m_channelWidth = MHz_u{20};
1690 }
1691 // For other cases at 5 GHz, the supported channel width is set by the VHT capabilities
1692 }
1693 else if (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
1694 {
1695 if (heCapabilities.GetChannelWidthSet() & 0x01)
1696 {
1697 state->m_channelWidth = MHz_u{40};
1698 }
1699 else
1700 {
1701 state->m_channelWidth = MHz_u{20};
1702 }
1703 }
1704 if (heCapabilities.GetHeSuPpdu1xHeLtf800nsGi())
1705 {
1706 state->m_guardInterval = NanoSeconds(800);
1707 }
1708 else
1709 {
1710 // todo: Using 3200ns, default value for HeConfiguration::GuardInterval
1711 state->m_guardInterval = NanoSeconds(3200);
1712 }
1713 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_HE))
1714 {
1715 if (heCapabilities.GetHighestMcsSupported() >= mcs.GetMcsValue())
1716 {
1717 AddSupportedMcs(from, mcs);
1718 }
1719 }
1720 state->m_heCapabilities = Create<const HeCapabilities>(heCapabilities);
1721 SetQosSupport(from, true);
1722}
1723
1724void
1725WifiRemoteStationManager::AddStationHeOperation(Mac48Address from, const HeOperation& heOperation)
1726{
1727 NS_LOG_FUNCTION(this << from << heOperation);
1728 auto state = LookupState(from);
1729 if (auto operation6GHz = heOperation.m_6GHzOpInfo)
1730 {
1731 switch (operation6GHz->m_chWid)
1732 {
1733 case 0:
1734 state->m_channelWidth = MHz_u{20};
1735 break;
1736 case 1:
1737 state->m_channelWidth = MHz_u{40};
1738 break;
1739 case 2:
1740 state->m_channelWidth = MHz_u{80};
1741 break;
1742 case 3:
1743 state->m_channelWidth = MHz_u{160};
1744 break;
1745 default:
1746 NS_FATAL_ERROR("Invalid channel width value in 6 GHz Operation Information field");
1747 }
1748 }
1749 state->m_heOperation = Create<const HeOperation>(heOperation);
1750}
1751
1752void
1753WifiRemoteStationManager::AddStationHe6GhzCapabilities(
1754 const Mac48Address& from,
1755 const He6GhzBandCapabilities& he6GhzCapabilities)
1756{
1757 // Used by all stations to record HE 6GHz band capabilities of remote stations
1758 NS_LOG_FUNCTION(this << from << he6GhzCapabilities);
1759 auto state = LookupState(from);
1760 state->m_he6GhzBandCapabilities = Create<const He6GhzBandCapabilities>(he6GhzCapabilities);
1761 SetQosSupport(from, true);
1762}
1763
1764void
1765WifiRemoteStationManager::AddStationEhtCapabilities(Mac48Address from,
1766 const EhtCapabilities& ehtCapabilities)
1767{
1768 // Used by all stations to record EHT capabilities of remote stations
1769 NS_LOG_FUNCTION(this << from << ehtCapabilities);
1770 auto state = LookupState(from);
1771 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_EHT))
1772 {
1773 for (uint8_t mapType = 0; mapType < EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_MAX; ++mapType)
1774 {
1775 if (ehtCapabilities.GetHighestSupportedRxMcs(
1776 static_cast<EhtMcsAndNssSet::EhtMcsMapType>(mapType)) >= mcs.GetMcsValue())
1777 {
1778 AddSupportedMcs(from, mcs);
1779 }
1780 }
1781 }
1782 state->m_ehtCapabilities = Create<const EhtCapabilities>(ehtCapabilities);
1783 SetQosSupport(from, true);
1784}
1785
1786void
1787WifiRemoteStationManager::AddStationEhtOperation(Mac48Address from,
1788 const EhtOperation& ehtOperation)
1789{
1790 NS_LOG_FUNCTION(this << from << ehtOperation);
1791 auto state = LookupState(from);
1792 if (auto opControl = ehtOperation.m_opInfo)
1793 {
1794 switch (opControl->control.channelWidth)
1795 {
1796 case 0:
1797 state->m_channelWidth = MHz_u{20};
1798 break;
1799 case 1:
1800 state->m_channelWidth = MHz_u{40};
1801 break;
1802 case 2:
1803 state->m_channelWidth = MHz_u{80};
1804 break;
1805 case 3:
1806 state->m_channelWidth = MHz_u{160};
1807 break;
1808 default:
1809 NS_FATAL_ERROR("Invalid channel width value in EHT Operation Information field");
1810 }
1811 }
1812 state->m_ehtOperation = Create<const EhtOperation>(ehtOperation);
1813}
1814
1815void
1816WifiRemoteStationManager::AddStationMleCommonInfo(
1817 Mac48Address from,
1818 const std::shared_ptr<CommonInfoBasicMle>& mleCommonInfo)
1819{
1820 NS_LOG_FUNCTION(this << from);
1821 auto state = LookupState(from);
1822 state->m_mleCommonInfo = mleCommonInfo;
1823 // insert another entry in m_states indexed by the MLD address and pointing to the same state
1824 const_cast<WifiRemoteStationManager*>(this)->m_states.insert_or_assign(
1825 mleCommonInfo->m_mldMacAddress,
1826 state);
1827}
1828
1830WifiRemoteStationManager::GetStationHtCapabilities(Mac48Address from)
1831{
1832 return LookupState(from)->m_htCapabilities;
1833}
1834
1836WifiRemoteStationManager::GetStationHtOperation(Mac48Address from)
1837{
1838 return LookupState(from)->m_htOperation;
1839}
1840
1842WifiRemoteStationManager::GetStationExtendedCapabilities(const Mac48Address& from)
1843{
1844 return LookupState(from)->m_extendedCapabilities;
1845}
1846
1848WifiRemoteStationManager::GetStationVhtCapabilities(Mac48Address from)
1849{
1850 return LookupState(from)->m_vhtCapabilities;
1851}
1852
1854WifiRemoteStationManager::GetStationHeCapabilities(Mac48Address from)
1855{
1856 return LookupState(from)->m_heCapabilities;
1857}
1858
1860WifiRemoteStationManager::GetStationHeOperation(Mac48Address from)
1861{
1862 return LookupState(from)->m_heOperation;
1863}
1864
1866WifiRemoteStationManager::GetStationHe6GhzCapabilities(const Mac48Address& from) const
1867{
1868 return LookupState(from)->m_he6GhzBandCapabilities;
1869}
1870
1872WifiRemoteStationManager::GetStationEhtCapabilities(Mac48Address from)
1873{
1874 return LookupState(from)->m_ehtCapabilities;
1875}
1876
1878WifiRemoteStationManager::GetStationEhtOperation(Mac48Address from)
1879{
1880 return LookupState(from)->m_ehtOperation;
1881}
1882
1883std::optional<std::reference_wrapper<CommonInfoBasicMle::EmlCapabilities>>
1884WifiRemoteStationManager::GetStationEmlCapabilities(const Mac48Address& from)
1885{
1886 if (auto state = LookupState(from);
1887 state->m_mleCommonInfo && state->m_mleCommonInfo->m_emlCapabilities)
1888 {
1889 return state->m_mleCommonInfo->m_emlCapabilities.value();
1890 }
1891 return std::nullopt;
1892}
1893
1894std::optional<std::reference_wrapper<CommonInfoBasicMle::MldCapabilities>>
1895WifiRemoteStationManager::GetStationMldCapabilities(const Mac48Address& from)
1896{
1897 if (auto state = LookupState(from);
1898 state->m_mleCommonInfo && state->m_mleCommonInfo->m_mldCapabilities)
1899 {
1900 return state->m_mleCommonInfo->m_mldCapabilities.value();
1901 }
1902 return std::nullopt;
1903}
1904
1905bool
1906WifiRemoteStationManager::GetLdpcSupported(Mac48Address address) const
1907{
1908 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
1909 Ptr<const VhtCapabilities> vhtCapabilities = LookupState(address)->m_vhtCapabilities;
1910 Ptr<const HeCapabilities> heCapabilities = LookupState(address)->m_heCapabilities;
1911 bool supported = false;
1912 if (htCapabilities)
1913 {
1914 supported |= htCapabilities->GetLdpc();
1915 }
1916 if (vhtCapabilities)
1917 {
1918 supported |= vhtCapabilities->GetRxLdpc();
1919 }
1920 if (heCapabilities)
1921 {
1922 supported |= heCapabilities->GetLdpcCodingInPayload();
1923 }
1924 return supported;
1925}
1926
1928WifiRemoteStationManager::GetDefaultMode() const
1929{
1930 NS_ASSERT(m_wifiPhy);
1931 auto defaultTxMode = m_wifiPhy->GetDefaultMode();
1932 NS_ASSERT(defaultTxMode.IsMandatory());
1933 return defaultTxMode;
1934}
1935
1937WifiRemoteStationManager::GetDefaultMcs() const
1938{
1939 return HtPhy::GetHtMcs0();
1940}
1941
1943WifiRemoteStationManager::GetDefaultModeForSta(const WifiRemoteStation* st) const
1944{
1945 NS_LOG_FUNCTION(this << st);
1946
1947 if ((!m_wifiPhy->GetDevice()->GetHtConfiguration()) ||
1948 (!GetHtSupported(st) && !GetStationHe6GhzCapabilities(st->m_state->m_address)))
1949 {
1950 return GetDefaultMode();
1951 }
1952
1953 // find the highest modulation class supported by both stations
1955 if (GetHeSupported() && GetHeSupported(st))
1956 {
1957 modClass = WIFI_MOD_CLASS_HE;
1958 }
1959 else if (GetVhtSupported() && GetVhtSupported(st))
1960 {
1961 modClass = WIFI_MOD_CLASS_VHT;
1962 }
1963
1964 // return the MCS with lowest index
1965 return *m_wifiPhy->GetPhyEntity(modClass)->begin();
1966}
1967
1968void
1969WifiRemoteStationManager::Reset()
1970{
1971 NS_LOG_FUNCTION(this);
1972 m_states.clear();
1973 for (auto& state : m_stations)
1974 {
1975 delete (state.second);
1976 }
1977 m_stations.clear();
1978 m_bssBasicRateSet.clear();
1979 m_bssBasicMcsSet.clear();
1980 m_ssrc.fill(0);
1981 m_slrc.fill(0);
1982}
1983
1984void
1985WifiRemoteStationManager::AddBasicMode(WifiMode mode)
1986{
1987 NS_LOG_FUNCTION(this << mode);
1989 {
1990 NS_FATAL_ERROR("It is not allowed to add a HT rate in the BSSBasicRateSet!");
1991 }
1992 for (uint8_t i = 0; i < GetNBasicModes(); i++)
1993 {
1994 if (GetBasicMode(i) == mode)
1995 {
1996 return;
1997 }
1998 }
1999 m_bssBasicRateSet.push_back(mode);
2000}
2001
2002uint8_t
2003WifiRemoteStationManager::GetNBasicModes() const
2004{
2005 return static_cast<uint8_t>(m_bssBasicRateSet.size());
2006}
2007
2009WifiRemoteStationManager::GetBasicMode(uint8_t i) const
2010{
2011 NS_ASSERT(i < GetNBasicModes());
2012 return m_bssBasicRateSet[i];
2013}
2014
2016WifiRemoteStationManager::GetNNonErpBasicModes() const
2017{
2018 uint32_t size = 0;
2019 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
2020 {
2021 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
2022 {
2023 continue;
2024 }
2025 size++;
2026 }
2027 return size;
2028}
2029
2031WifiRemoteStationManager::GetNonErpBasicMode(uint8_t i) const
2032{
2033 NS_ASSERT(i < GetNNonErpBasicModes());
2034 uint32_t index = 0;
2035 bool found = false;
2036 for (auto j = m_bssBasicRateSet.begin(); j != m_bssBasicRateSet.end();)
2037 {
2038 if (i == index)
2039 {
2040 found = true;
2041 }
2042 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
2043 {
2044 if (found)
2045 {
2046 break;
2047 }
2048 }
2049 index++;
2050 j++;
2051 }
2052 return m_bssBasicRateSet[index];
2053}
2054
2055void
2056WifiRemoteStationManager::AddBasicMcs(WifiMode mcs)
2057{
2058 NS_LOG_FUNCTION(this << +mcs.GetMcsValue());
2059 for (uint8_t i = 0; i < GetNBasicMcs(); i++)
2060 {
2061 if (GetBasicMcs(i) == mcs)
2062 {
2063 return;
2064 }
2065 }
2066 m_bssBasicMcsSet.push_back(mcs);
2067}
2068
2069uint8_t
2070WifiRemoteStationManager::GetNBasicMcs() const
2071{
2072 return static_cast<uint8_t>(m_bssBasicMcsSet.size());
2073}
2074
2076WifiRemoteStationManager::GetBasicMcs(uint8_t i) const
2077{
2078 NS_ASSERT(i < GetNBasicMcs());
2079 return m_bssBasicMcsSet[i];
2080}
2081
2083WifiRemoteStationManager::GetNonUnicastMode() const
2084{
2085 if (m_nonUnicastMode == WifiMode())
2086 {
2087 if (GetNBasicModes() > 0)
2088 {
2089 return GetBasicMode(0);
2090 }
2091 else
2092 {
2093 return GetDefaultMode();
2094 }
2095 }
2096 else
2097 {
2098 return m_nonUnicastMode;
2099 }
2100}
2101
2103WifiRemoteStationManager::GetGroupcastTxVector(const WifiMacHeader& header, MHz_u allowedWidth)
2104{
2105 const auto& to = header.GetAddr1();
2106 NS_ASSERT(to.IsGroup());
2107
2108 WifiTxVector groupcastTxVector{};
2109 const auto mode = GetNonUnicastMode();
2110 groupcastTxVector.SetMode(mode);
2111 groupcastTxVector.SetPreambleType(
2112 GetPreambleForTransmission(mode.GetModulationClass(), GetShortPreambleEnabled()));
2113 groupcastTxVector.SetTxPowerLevel(m_defaultTxPowerLevel);
2114 groupcastTxVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mode, allowedWidth));
2115 groupcastTxVector.SetNTx(GetNumberOfAntennas());
2116
2117 if (to.IsBroadcast())
2118 {
2119 return groupcastTxVector;
2120 }
2121
2122 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
2123 if (!apMac)
2124 {
2125 return groupcastTxVector;
2126 }
2127
2128 auto gcrManager = apMac->GetGcrManager();
2129 if (!gcrManager)
2130 {
2131 return groupcastTxVector;
2132 }
2133
2134 const auto& groupStas = gcrManager->GetMemberStasForGroupAddress(to);
2135 if (groupStas.empty())
2136 {
2137 return groupcastTxVector;
2138 }
2139
2140 if (!gcrManager->UseConcealment(header))
2141 {
2142 return groupcastTxVector;
2143 }
2144
2145 // If we are here, that means the mode will be used for the transmission of a groupcast frame
2146 // using the GCR service. We should loop over each member STA that is going to receive the
2147 // groupcast frame and select the highest possible mode over all STAs.
2148 std::optional<WifiMode> groupcastMode;
2149 auto maxWidth = allowedWidth;
2150 auto maxNss = m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2151 std::map<WifiModulationClass, Time> minGisPerMc{/* non-HT OFDM is always 800 ns */
2154 const std::map<WifiModulationClass, WifiModulationClass> giRefModClass{
2155 /* HT/VHT: short or long GI */
2158 /* HE/EHT: 3 possible GIs */
2161 for (const auto& staAddress : groupStas)
2162 {
2163 // Get the equivalent TXVECTOR if the frame would be a unicast frame to that STA in order to
2164 // get what rate would be selected for that STA.
2166 hdr.SetAddr1(staAddress);
2167 const auto unicastTxVector = GetDataTxVector(hdr, allowedWidth);
2168
2169 // update the groupcast mode if:
2170 // - this is the first mode to inspect;
2171 // - this mode has a lower modulation class than the currently selected groupcast mode;
2172 // - when the modulation class is similar, this mode has a lower MCS than the currently
2173 // selected groupcast mode.
2174 if (!groupcastMode.has_value() ||
2175 (unicastTxVector.GetModulationClass() < groupcastMode->GetModulationClass()) ||
2176 ((unicastTxVector.GetModulationClass() == groupcastMode->GetModulationClass()) &&
2177 (unicastTxVector.GetMode().GetMcsValue() < groupcastMode->GetMcsValue())))
2178 {
2179 groupcastMode = unicastTxVector.GetMode();
2180 }
2181 maxWidth = std::min(unicastTxVector.GetChannelWidth(), maxWidth);
2182 maxNss = std::min(unicastTxVector.GetNss(), maxNss);
2183 auto mc = unicastTxVector.GetModulationClass();
2184 if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
2185 {
2186 mc = it->second;
2187 }
2188 if (auto it = minGisPerMc.find(mc); it != minGisPerMc.end())
2189 {
2190 it->second = std::max(unicastTxVector.GetGuardInterval(), it->second);
2191 }
2192 }
2193 NS_ASSERT(groupcastMode.has_value());
2194
2195 groupcastTxVector.SetMode(*groupcastMode);
2196 groupcastTxVector.SetPreambleType(
2197 GetPreambleForTransmission(groupcastMode->GetModulationClass(), GetShortPreambleEnabled()));
2198 groupcastTxVector.SetChannelWidth(maxWidth);
2199 groupcastTxVector.SetNss(maxNss);
2200 auto mc = groupcastMode->GetModulationClass();
2201 if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
2202 {
2203 mc = it->second;
2204 }
2205 if (const auto it = minGisPerMc.find(mc); it != minGisPerMc.cend())
2206 {
2207 groupcastTxVector.SetGuardInterval(it->second);
2208 }
2209
2210 return groupcastTxVector;
2211}
2212
2213bool
2214WifiRemoteStationManager::DoNeedRts(WifiRemoteStation* station, uint32_t size, bool normally)
2215{
2216 return normally;
2217}
2218
2219bool
2220WifiRemoteStationManager::DoNeedFragmentation(WifiRemoteStation* station,
2221 Ptr<const Packet> packet,
2222 bool normally)
2223{
2224 return normally;
2225}
2226
2227void
2228WifiRemoteStationManager::DoReportAmpduTxStatus(WifiRemoteStation* station,
2229 uint16_t nSuccessfulMpdus,
2230 uint16_t nFailedMpdus,
2231 double rxSnr,
2232 double dataSnr,
2233 MHz_u dataChannelWidth,
2234 uint8_t dataNss)
2235{
2236 NS_LOG_DEBUG("DoReportAmpduTxStatus received but the manager does not handle A-MPDUs!");
2237}
2238
2240WifiRemoteStationManager::GetSupported(const WifiRemoteStation* station, uint8_t i) const
2241{
2242 NS_ASSERT(i < GetNSupported(station));
2243 return station->m_state->m_operationalRateSet[i];
2244}
2245
2247WifiRemoteStationManager::GetMcsSupported(const WifiRemoteStation* station, uint8_t i) const
2248{
2249 NS_ASSERT(i < GetNMcsSupported(station));
2250 return station->m_state->m_operationalMcsSet[i];
2251}
2252
2254WifiRemoteStationManager::GetNonErpSupported(const WifiRemoteStation* station, uint8_t i) const
2255{
2256 NS_ASSERT(i < GetNNonErpSupported(station));
2257 // IEEE 802.11g standard defines that if the protection mechanism is enabled, RTS, CTS and
2258 // CTS-To-Self frames should select a rate in the BSSBasicRateSet that corresponds to an 802.11b
2259 // basic rate. This is a implemented here to avoid changes in every RAA, but should maybe be
2260 // moved in case it breaks standard rules.
2261 uint32_t index = 0;
2262 bool found = false;
2263 for (auto j = station->m_state->m_operationalRateSet.begin();
2264 j != station->m_state->m_operationalRateSet.end();)
2265 {
2266 if (i == index)
2267 {
2268 found = true;
2269 }
2270 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
2271 {
2272 if (found)
2273 {
2274 break;
2275 }
2276 }
2277 index++;
2278 j++;
2279 }
2280 return station->m_state->m_operationalRateSet[index];
2281}
2282
2284WifiRemoteStationManager::GetAddress(const WifiRemoteStation* station) const
2285{
2286 return station->m_state->m_address;
2287}
2288
2289MHz_u
2290WifiRemoteStationManager::GetChannelWidth(const WifiRemoteStation* station) const
2291{
2292 return station->m_state->m_channelWidth;
2293}
2294
2295bool
2296WifiRemoteStationManager::GetShortGuardIntervalSupported(const WifiRemoteStation* station) const
2297{
2298 Ptr<const HtCapabilities> htCapabilities = station->m_state->m_htCapabilities;
2299
2300 if (!htCapabilities)
2301 {
2302 return false;
2303 }
2304 return htCapabilities->GetShortGuardInterval20();
2305}
2306
2307Time
2308WifiRemoteStationManager::GetGuardInterval(const WifiRemoteStation* station) const
2309{
2310 return station->m_state->m_guardInterval;
2311}
2312
2313bool
2314WifiRemoteStationManager::GetAggregation(const WifiRemoteStation* station) const
2315{
2316 return station->m_state->m_aggregation;
2317}
2318
2319uint8_t
2320WifiRemoteStationManager::GetNumberOfSupportedStreams(const WifiRemoteStation* station) const
2321{
2322 const auto htCapabilities = station->m_state->m_htCapabilities;
2323
2324 if (!htCapabilities)
2325 {
2326 if (const auto heCapabilities = station->m_state->m_heCapabilities)
2327 {
2328 return heCapabilities->GetHighestNssSupported();
2329 }
2330 return 1;
2331 }
2332 return htCapabilities->GetRxHighestSupportedAntennas();
2333}
2334
2335uint8_t
2336WifiRemoteStationManager::GetNess(const WifiRemoteStation* station) const
2337{
2338 return station->m_state->m_ness;
2339}
2340
2342WifiRemoteStationManager::GetPhy() const
2343{
2344 return m_wifiPhy;
2345}
2346
2348WifiRemoteStationManager::GetMac() const
2349{
2350 return m_wifiMac;
2351}
2352
2353uint8_t
2354WifiRemoteStationManager::GetNSupported(const WifiRemoteStation* station) const
2355{
2356 return static_cast<uint8_t>(station->m_state->m_operationalRateSet.size());
2357}
2358
2359bool
2360WifiRemoteStationManager::GetQosSupported(const WifiRemoteStation* station) const
2361{
2362 return station->m_state->m_qosSupported;
2363}
2364
2365bool
2366WifiRemoteStationManager::GetHtSupported(const WifiRemoteStation* station) const
2367{
2368 return bool(station->m_state->m_htCapabilities);
2369}
2370
2371bool
2372WifiRemoteStationManager::GetVhtSupported(const WifiRemoteStation* station) const
2373{
2374 return bool(station->m_state->m_vhtCapabilities);
2375}
2376
2377bool
2378WifiRemoteStationManager::GetHeSupported(const WifiRemoteStation* station) const
2379{
2380 return bool(station->m_state->m_heCapabilities);
2381}
2382
2383bool
2384WifiRemoteStationManager::GetEhtSupported(const WifiRemoteStation* station) const
2385{
2386 return (bool)(station->m_state->m_ehtCapabilities);
2387}
2388
2389bool
2390WifiRemoteStationManager::GetEmlsrSupported(const WifiRemoteStation* station) const
2391{
2392 auto mleCommonInfo = station->m_state->m_mleCommonInfo;
2393 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2394 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2395}
2396
2397bool
2398WifiRemoteStationManager::GetEmlsrEnabled(const WifiRemoteStation* station) const
2399{
2400 return station->m_state->m_emlsrEnabled;
2401}
2402
2403uint8_t
2404WifiRemoteStationManager::GetNMcsSupported(const WifiRemoteStation* station) const
2405{
2406 return static_cast<uint8_t>(station->m_state->m_operationalMcsSet.size());
2407}
2408
2410WifiRemoteStationManager::GetNNonErpSupported(const WifiRemoteStation* station) const
2411{
2412 uint32_t size = 0;
2413 for (auto i = station->m_state->m_operationalRateSet.begin();
2414 i != station->m_state->m_operationalRateSet.end();
2415 i++)
2416 {
2417 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
2418 {
2419 continue;
2420 }
2421 size++;
2422 }
2423 return size;
2424}
2425
2426MHz_u
2427WifiRemoteStationManager::GetChannelWidthSupported(Mac48Address address) const
2428{
2429 return LookupState(address)->m_channelWidth;
2430}
2431
2432bool
2433WifiRemoteStationManager::GetShortGuardIntervalSupported(Mac48Address address) const
2434{
2435 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2436
2437 if (!htCapabilities)
2438 {
2439 return false;
2440 }
2441 return htCapabilities->GetShortGuardInterval20();
2442}
2443
2444uint8_t
2445WifiRemoteStationManager::GetNumberOfSupportedStreams(Mac48Address address) const
2446{
2447 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2448
2449 if (!htCapabilities)
2450 {
2451 return 1;
2452 }
2453 return htCapabilities->GetRxHighestSupportedAntennas();
2454}
2455
2456uint8_t
2457WifiRemoteStationManager::GetNMcsSupported(Mac48Address address) const
2458{
2459 return static_cast<uint8_t>(LookupState(address)->m_operationalMcsSet.size());
2460}
2461
2462bool
2463WifiRemoteStationManager::GetDsssSupported(const Mac48Address& address) const
2464{
2465 return (LookupState(address)->m_dsssSupported);
2466}
2467
2468bool
2469WifiRemoteStationManager::GetErpOfdmSupported(const Mac48Address& address) const
2470{
2471 return (LookupState(address)->m_erpOfdmSupported);
2472}
2473
2474bool
2475WifiRemoteStationManager::GetOfdmSupported(const Mac48Address& address) const
2476{
2477 return (LookupState(address)->m_ofdmSupported);
2478}
2479
2480bool
2481WifiRemoteStationManager::GetHtSupported(Mac48Address address) const
2482{
2483 return bool(LookupState(address)->m_htCapabilities);
2484}
2485
2486bool
2487WifiRemoteStationManager::GetVhtSupported(Mac48Address address) const
2488{
2489 return bool(LookupState(address)->m_vhtCapabilities);
2490}
2491
2492bool
2493WifiRemoteStationManager::GetHeSupported(Mac48Address address) const
2494{
2495 return bool(LookupState(address)->m_heCapabilities);
2496}
2497
2498bool
2499WifiRemoteStationManager::GetEhtSupported(Mac48Address address) const
2500{
2501 return (bool)(LookupState(address)->m_ehtCapabilities);
2502}
2503
2504bool
2505WifiRemoteStationManager::GetEmlsrSupported(const Mac48Address& address) const
2506{
2507 auto mleCommonInfo = LookupState(address)->m_mleCommonInfo;
2508 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2509 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2510}
2511
2512bool
2513WifiRemoteStationManager::GetEmlsrEnabled(const Mac48Address& address) const
2514{
2515 if (auto stateIt = m_states.find(address); stateIt != m_states.cend())
2516 {
2517 return stateIt->second->m_emlsrEnabled;
2518 }
2519 return false;
2520}
2521
2522void
2523WifiRemoteStationManager::SetDefaultTxPowerLevel(uint8_t txPower)
2524{
2525 m_defaultTxPowerLevel = txPower;
2526}
2527
2528uint8_t
2529WifiRemoteStationManager::GetNumberOfAntennas() const
2530{
2531 return m_wifiPhy->GetNumberOfAntennas();
2532}
2533
2534uint8_t
2535WifiRemoteStationManager::GetMaxNumberOfTransmitStreams() const
2536{
2537 return m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2538}
2539
2540bool
2541WifiRemoteStationManager::UseLdpcForDestination(Mac48Address dest) const
2542{
2543 return (GetLdpcSupported() && GetLdpcSupported(dest));
2544}
2545
2546} // 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.
EHT Operation Information Element.
std::optional< EhtOpInfo > m_opInfo
EHT Operation Information.
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 HE Operation Information Element.
OptFieldWithPresenceInd< OpInfo6GHz > m_6GHzOpInfo
6 GHz Operation Information field
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.
The HT Operation Information Element.
uint8_t GetStaChannelWidth() const
Return the STA channel width.
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.
The VHT Operation Information Element.
uint8_t GetChannelWidth() const
Return the Channel Width field in the VHT Operation information element.
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
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:1111
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition wifi-phy.cc:1057
MHz_u GetChannelWidth() const
Definition wifi-phy.cc:1087
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition wifi-phy.cc:655
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:2109
std::list< WifiMode > GetModeList() const
The WifiPhy::GetModeList() method is used (e.g., by a WifiRemoteStationManager) to determine the set ...
Definition wifi-phy.cc:2060
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