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(
80 "RtsCtsThreshold",
81 "If the size of the PSDU is bigger than this value, we use an RTS/CTS "
82 "handshake before sending the data frame."
83 "This value will not have any effect on some rate control algorithms.",
87 .AddAttribute("RtsCtsTxDurationThresh",
88 "If this threshold is a strictly positive value and the TX duration of "
89 "the PSDU is greater than or equal to this threshold, we use an RTS/CTS "
90 "handshake before sending the data frame.",
91 TimeValue(),
94 .AddAttribute(
95 "FragmentationThreshold",
96 "If the size of the PSDU is bigger than this value, we fragment it such that the "
97 "size of the fragments are equal or smaller. "
98 "This value does not apply when it is carried in an A-MPDU. "
99 "This value will not have any effect on some rate control algorithms.",
104 .AddAttribute("NonUnicastMode",
105 "Wifi mode used for non-unicast transmissions.",
109 .AddAttribute("DefaultTxPowerLevel",
110 "Default power level to be used for transmissions. "
111 "This is the power level that is used by all those WifiManagers that do "
112 "not implement TX power control.",
113 UintegerValue(0),
116 .AddAttribute("ErpProtectionMode",
117 "Protection mode used when non-ERP STAs are connected to an ERP AP: "
118 "Rts-Cts or Cts-To-Self",
123 "Rts-Cts",
125 "Cts-To-Self"))
126 .AddAttribute("HtProtectionMode",
127 "Protection mode used when non-HT STAs are connected to a HT AP: Rts-Cts "
128 "or Cts-To-Self",
133 "Rts-Cts",
135 "Cts-To-Self"))
136 .AddTraceSource("MacTxRtsFailed",
137 "The transmission of a RTS by the MAC layer has failed",
139 "ns3::Mac48Address::TracedCallback")
140 .AddTraceSource("MacTxDataFailed",
141 "The transmission of a data packet by the MAC layer has failed",
143 "ns3::Mac48Address::TracedCallback")
144 .AddTraceSource(
145 "MacTxFinalRtsFailed",
146 "The transmission of a RTS has exceeded the maximum number of attempts",
148 "ns3::Mac48Address::TracedCallback")
149 .AddTraceSource(
150 "MacTxFinalDataFailed",
151 "The transmission of a data packet has exceeded the maximum number of attempts",
153 "ns3::Mac48Address::TracedCallback");
154 return tid;
155}
156
158 : m_linkId(0),
159 m_useNonErpProtection(false),
160 m_useNonHtProtection(false),
161 m_shortPreambleEnabled(false),
162 m_shortSlotTimeEnabled(false)
163{
164 NS_LOG_FUNCTION(this);
165 m_ssrc.fill(0);
166 m_slrc.fill(0);
167}
168
173
174void
180
181void
183{
184 NS_LOG_FUNCTION(this << phy);
185 // We need to track our PHY because it is the object that knows the
186 // full set of transmit rates that are supported. We need to know
187 // this in order to find the relevant mandatory rates when choosing a
188 // transmit rate for automatic control responses like
189 // acknowledgments.
190 m_wifiPhy = phy;
191}
192
193void
195{
196 NS_LOG_FUNCTION(this << mac);
197 // We need to track our MAC because it is the object that knows the
198 // full set of interframe spaces.
199 m_wifiMac = mac;
200}
201
202void
204{
205 NS_LOG_FUNCTION(this << +linkId);
206 m_linkId = linkId;
207}
208
209int64_t
211{
212 NS_LOG_FUNCTION(this << stream);
213 return 0;
214}
215
216void
218{
219 NS_LOG_FUNCTION(this << maxSsrc);
220 m_maxSsrc = maxSsrc;
221}
222
223void
225{
226 NS_LOG_FUNCTION(this << maxSlrc);
227 m_maxSlrc = maxSlrc;
228}
229
230void
232{
233 NS_LOG_FUNCTION(this << threshold);
234 m_rtsCtsThreshold = threshold;
235}
236
237void
243
244void
246{
247 NS_LOG_FUNCTION(this << enable);
248 m_shortPreambleEnabled = enable;
249}
250
251void
253{
254 NS_LOG_FUNCTION(this << enable);
255 m_shortSlotTimeEnabled = enable;
256}
257
258bool
263
264bool
269
270bool
272{
273 return (m_wifiPhy->GetDevice()->GetHtConfiguration() &&
275}
276
277bool
279{
280 return (m_wifiPhy->GetDevice()->GetVhtConfiguration() &&
283}
284
285bool
287{
288 return bool(m_wifiPhy->GetDevice()->GetHeConfiguration());
289}
290
291bool
293{
294 return bool(m_wifiPhy->GetDevice()->GetEhtConfiguration());
295}
296
297bool
299{
300 if (auto htConfiguration = m_wifiPhy->GetDevice()->GetHtConfiguration())
301 {
302 return htConfiguration->m_ldpcSupported;
303 }
304 return false;
305}
306
307bool
309{
310 if (auto htConfiguration = m_wifiPhy->GetDevice()->GetHtConfiguration())
311 {
312 return htConfiguration->m_sgiSupported;
313 }
314 return false;
315}
316
317Time
319{
320 Time gi{};
321 if (GetHeSupported())
322 {
323 Ptr<HeConfiguration> heConfiguration = m_wifiPhy->GetDevice()->GetHeConfiguration();
324 NS_ASSERT(heConfiguration); // If HE is supported, we should have a HE configuration
325 // attached
326 gi = heConfiguration->GetGuardInterval();
327 }
328 return gi;
329}
330
336
337void
339 bool isShortPreambleSupported)
340{
341 NS_LOG_FUNCTION(this << address << isShortPreambleSupported);
342 NS_ASSERT(!address.IsGroup());
343 LookupState(address)->m_shortPreamble = isShortPreambleSupported;
344}
345
346void
348 bool isShortSlotTimeSupported)
349{
350 NS_LOG_FUNCTION(this << address << isShortSlotTimeSupported);
351 NS_ASSERT(!address.IsGroup());
352 LookupState(address)->m_shortSlotTime = isShortSlotTimeSupported;
353}
354
355void
357{
358 NS_LOG_FUNCTION(this << address << mode);
359 NS_ASSERT(!address.IsGroup());
360 auto state = LookupState(address);
361 for (const auto& i : state->m_operationalRateSet)
362 {
363 if (i == mode)
364 {
365 return; // already in
366 }
367 }
368 if ((mode.GetModulationClass() == WIFI_MOD_CLASS_DSSS) ||
370 {
371 state->m_dsssSupported = true;
372 }
374 {
375 state->m_erpOfdmSupported = true;
376 }
377 else if (mode.GetModulationClass() == WIFI_MOD_CLASS_OFDM)
378 {
379 state->m_ofdmSupported = true;
380 }
381 state->m_operationalRateSet.push_back(mode);
382}
383
384void
386{
387 NS_LOG_FUNCTION(this << address);
388 NS_ASSERT(!address.IsGroup());
389 auto state = LookupState(address);
390 state->m_operationalRateSet.clear();
391 for (const auto& mode : m_wifiPhy->GetModeList())
392 {
393 state->m_operationalRateSet.push_back(mode);
394 if (mode.IsMandatory())
395 {
396 AddBasicMode(mode);
397 }
398 }
399}
400
401void
403{
404 NS_LOG_FUNCTION(this << address);
405 NS_ASSERT(!address.IsGroup());
406 auto state = LookupState(address);
407
408 const auto& mcsList = m_wifiPhy->GetMcsList();
409 state->m_operationalMcsSet = WifiModeList(mcsList.begin(), mcsList.end());
410}
411
412void
414{
415 NS_LOG_FUNCTION(this << address);
416 NS_ASSERT(!address.IsGroup());
417 LookupState(address)->m_operationalMcsSet.clear();
418}
419
420void
422{
423 NS_LOG_FUNCTION(this << address << mcs);
424 NS_ASSERT(!address.IsGroup());
425 auto state = LookupState(address);
426 for (const auto& i : state->m_operationalMcsSet)
427 {
428 if (i == mcs)
429 {
430 return; // already in
431 }
432 }
433 state->m_operationalMcsSet.push_back(mcs);
434}
435
436bool
438{
439 return LookupState(address)->m_shortPreamble;
440}
441
442bool
444{
445 return LookupState(address)->m_shortSlotTime;
446}
447
448bool
450{
451 return LookupState(address)->m_qosSupported;
452}
453
454bool
456{
457 if (address.IsGroup())
458 {
459 return false;
460 }
461 return LookupState(address)->m_state == WifiRemoteStationState::BRAND_NEW;
462}
463
464bool
466{
467 if (address.IsGroup())
468 {
469 return true;
470 }
471 return LookupState(address)->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK;
472}
473
474bool
476{
477 if (address.IsGroup())
478 {
479 return false;
480 }
481 return LookupState(address)->m_state == WifiRemoteStationState::WAIT_ASSOC_TX_OK;
482}
483
484void
490
491void
497
498void
504
505void
511
512bool
514{
515 if (address.IsGroup())
516 {
517 return false;
518 }
519 return LookupState(address)->m_state == WifiRemoteStationState::ASSOC_REFUSED;
520}
521
522void
528
529uint16_t
531{
532 std::shared_ptr<WifiRemoteStationState> state;
533 if (!remoteAddress.IsGroup() &&
534 (state = LookupState(remoteAddress))->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK)
535 {
536 return state->m_aid;
537 }
538 return SU_STA_ID;
539}
540
541uint16_t
543{
544 NS_LOG_FUNCTION(this << address << txVector);
545
546 uint16_t staId = SU_STA_ID;
547
548 if (txVector.IsMu())
549 {
550 if (m_wifiMac->GetTypeOfStation() == AP)
551 {
552 staId = GetAssociationId(address);
553 }
554 else if (m_wifiMac->GetTypeOfStation() == STA)
555 {
557 if (staMac->IsAssociated())
558 {
559 staId = staMac->GetAssociationId();
560 }
561 }
562 }
563
564 NS_LOG_DEBUG("Returning STAID = " << staId);
565 return staId;
566}
567
568bool
570{
571 return LookupState(address)->m_isInPsMode;
572}
573
574void
575WifiRemoteStationManager::SetPsMode(const Mac48Address& address, bool isInPsMode)
576{
577 LookupState(address)->m_isInPsMode = isInPsMode;
578}
579
580std::optional<Mac48Address>
582{
583 if (auto stateIt = m_states.find(address);
584 stateIt != m_states.end() && stateIt->second->m_mleCommonInfo)
585 {
586 return stateIt->second->m_mleCommonInfo->m_mldMacAddress;
587 }
588
589 return std::nullopt;
590}
591
592std::optional<Mac48Address>
594{
595 auto stateIt = m_states.find(mldAddress);
596
597 if (stateIt == m_states.end() || !stateIt->second->m_mleCommonInfo)
598 {
599 // MLD address not found
600 return std::nullopt;
601 }
602
603 NS_ASSERT(stateIt->second->m_mleCommonInfo->m_mldMacAddress == mldAddress);
604 return stateIt->second->m_address;
605}
606
609{
610 NS_LOG_FUNCTION(this << header << allowedWidth);
611 const auto address = header.GetAddr1();
612 if (!header.IsMgt() && address.IsGroup())
613 {
614 return GetGroupcastTxVector(header, allowedWidth);
615 }
616 WifiTxVector txVector;
617 if (header.IsMgt())
618 {
619 // Use the lowest basic rate for management frames
620 WifiMode mgtMode;
621 if (GetNBasicModes() > 0)
622 {
623 mgtMode = GetBasicMode(0);
624 }
625 else
626 {
627 mgtMode = GetDefaultMode();
628 }
629 txVector.SetMode(mgtMode);
630 txVector.SetPreambleType(
633 auto channelWidth = allowedWidth;
634 if (!header.GetAddr1().IsGroup())
635 {
636 if (const auto rxWidth = GetChannelWidthSupported(header.GetAddr1());
637 rxWidth < channelWidth)
638 {
639 channelWidth = rxWidth;
640 }
641 }
642
643 txVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mgtMode, channelWidth));
645 }
646 else
647 {
648 txVector = DoGetDataTxVector(Lookup(address), allowedWidth);
650 ? false
651 : UseLdpcForDestination(address));
652 }
653 Ptr<HeConfiguration> heConfiguration = m_wifiPhy->GetDevice()->GetHeConfiguration();
654 if (heConfiguration)
655 {
656 txVector.SetBssColor(heConfiguration->m_bssColor);
657 }
658 // If both the allowed width and the TXVECTOR channel width are integer multiple
659 // of 20 MHz, then the TXVECTOR channel width must not exceed the allowed width
660 NS_ASSERT_MSG((static_cast<uint16_t>(txVector.GetChannelWidth()) % 20 != 0) ||
661 (static_cast<uint16_t>(allowedWidth) % 20 != 0) ||
662 (txVector.GetChannelWidth() <= allowedWidth),
663 "TXVECTOR channel width (" << txVector.GetChannelWidth()
664 << " MHz) exceeds allowed width (" << allowedWidth
665 << " MHz)");
666 return txVector;
667}
668
671{
672 WifiMode defaultMode = GetDefaultMode();
673 WifiPreamble defaultPreamble;
674 if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_EHT)
675 {
676 defaultPreamble = WIFI_PREAMBLE_EHT_MU;
677 }
678 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HE)
679 {
680 defaultPreamble = WIFI_PREAMBLE_HE_SU;
681 }
682 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_VHT)
683 {
684 defaultPreamble = WIFI_PREAMBLE_VHT_SU;
685 }
686 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HT)
687 {
688 defaultPreamble = WIFI_PREAMBLE_HT_MF;
689 }
690 else
691 {
692 defaultPreamble = WIFI_PREAMBLE_LONG;
693 }
694
695 return WifiTxVector(defaultMode,
697 defaultPreamble,
700 1,
701 0,
702 m_wifiPhy->GetTxBandwidth(defaultMode),
703 false);
704}
705
706void
708 MHz_u allowedWidth) const
709{
710 NS_LOG_FUNCTION(this << txVector << allowedWidth);
711
712 auto modulation = txVector.GetModulationClass();
713
714 if (allowedWidth >= 40 &&
715 (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS))
716 {
717 // control frame must be sent in a non-HT duplicate PPDU because it must protect a frame
718 // being transmitted on at least 40 MHz. Change the modulation class to ERP-OFDM and the
719 // rate to 6 Mbps
721 modulation = txVector.GetModulationClass();
722 }
723 // do not set allowedWidth as the TX width if the modulation class is (HR-)DSSS (allowedWidth
724 // may be 20 MHz) or allowedWidth is 22 MHz (the selected modulation class may be OFDM)
725 if (modulation != WIFI_MOD_CLASS_DSSS && modulation != WIFI_MOD_CLASS_HR_DSSS &&
726 allowedWidth != 22)
727 {
728 txVector.SetChannelWidth(allowedWidth);
729 }
730}
731
734{
735 NS_LOG_FUNCTION(this << address << allowedWidth);
736 WifiTxVector v;
737 if (address.IsGroup())
738 {
740 v.SetMode(mode);
747 v.SetNss(1);
748 v.SetNess(0);
749 }
750 else
751 {
752 v = DoGetRtsTxVector(Lookup(address));
753 }
754
755 AdjustTxVectorForCtlResponse(v, allowedWidth);
756
757 return v;
758}
759
762{
763 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
764 NS_ASSERT(!to.IsGroup() ||
765 (m_wifiMac && (m_wifiMac->GetTypeOfStation() == AP) && apMac->GetGcrManager()));
766 WifiMode ctsMode = GetControlAnswerMode(rtsTxMode);
767 WifiTxVector v;
768 v.SetMode(ctsMode);
774 v.SetNss(1);
775 return v;
776}
777
778void
780{
781 NS_LOG_FUNCTION(this << txVector);
782
783 auto txMode = txVector.GetMode();
784 if (txMode.GetModulationClass() >= WIFI_MOD_CLASS_HT)
785 {
786 auto rate = txMode.GetDataRate(txVector);
787 if (rate >= 24e6)
788 {
789 rate = 24e6;
790 }
791 else if (rate >= 12e6)
792 {
793 rate = 12e6;
794 }
795 else
796 {
797 rate = 6e6;
798 }
801 {
802 txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(rate));
803 }
804 else
805 {
806 txVector.SetMode(OfdmPhy::GetOfdmRate(rate));
807 }
808 }
809}
810
813{
814 NS_ASSERT(!to.IsGroup());
815 WifiMode ackMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
816 WifiTxVector v;
817 v.SetMode(ackMode);
823 v.SetNss(1);
824
826
827 return v;
828}
829
832 const WifiTxVector& dataTxVector) const
833{
834 NS_ASSERT(!to.IsGroup());
835 WifiMode blockAckMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
836 WifiTxVector v;
837 v.SetMode(blockAckMode);
841 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(blockAckMode));
843 v.SetNss(1);
844
846
847 return v;
848}
849
852{
853 /**
854 * The standard has relatively unambiguous rules for selecting a
855 * control response rate (the below is quoted from IEEE 802.11-2012,
856 * Section 9.7):
857 *
858 * To allow the transmitting STA to calculate the contents of the
859 * Duration/ID field, a STA responding to a received frame shall
860 * transmit its Control Response frame (either CTS or Ack), other
861 * than the BlockAck control frame, at the highest rate in the
862 * BSSBasicRateSet parameter that is less than or equal to the
863 * rate of the immediately previous frame in the frame exchange
864 * sequence (as defined in Annex G) and that is of the same
865 * modulation class (see Section 9.7.8) as the received frame...
866 */
867 NS_LOG_FUNCTION(this << reqMode);
868 WifiMode mode = GetDefaultMode();
869 bool found = false;
870 // First, search the BSS Basic Rate set
871 for (uint8_t i = 0; i < GetNBasicModes(); i++)
872 {
873 WifiMode testMode = GetBasicMode(i);
874 if ((!found || testMode.IsHigherDataRate(mode)) && (!testMode.IsHigherDataRate(reqMode)) &&
876 testMode.GetModulationClass())))
877 {
878 mode = testMode;
879 // We've found a potentially-suitable transmit rate, but we
880 // need to continue and consider all the basic rates before
881 // we can be sure we've got the right one.
882 found = true;
883 }
884 }
885 if (m_wifiPhy->GetDevice()->GetHtConfiguration())
886 {
887 if (!found)
888 {
889 mode = GetDefaultMcs();
890 for (uint8_t i = 0; i != GetNBasicMcs(); i++)
891 {
892 WifiMode testMode = GetBasicMcs(i);
893 if ((!found || testMode.IsHigherDataRate(mode)) &&
894 (!testMode.IsHigherDataRate(reqMode)) &&
895 (testMode.GetModulationClass() == reqMode.GetModulationClass()))
896 {
897 mode = testMode;
898 // We've found a potentially-suitable transmit rate, but we
899 // need to continue and consider all the basic rates before
900 // we can be sure we've got the right one.
901 found = true;
902 }
903 }
904 }
905 }
906 // If we found a suitable rate in the BSSBasicRateSet, then we are
907 // done and can return that mode.
908 if (found)
909 {
910 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
911 return mode;
912 }
913
914 /**
915 * If no suitable basic rate was found, we search the mandatory
916 * rates. The standard (IEEE 802.11-2007, Section 9.6) says:
917 *
918 * ...If no rate contained in the BSSBasicRateSet parameter meets
919 * these conditions, then the control frame sent in response to a
920 * received frame shall be transmitted at the highest mandatory
921 * rate of the PHY that is less than or equal to the rate of the
922 * received frame, and that is of the same modulation class as the
923 * received frame. In addition, the Control Response frame shall
924 * be sent using the same PHY options as the received frame,
925 * unless they conflict with the requirement to use the
926 * BSSBasicRateSet parameter.
927 *
928 * @todo Note that we're ignoring the last sentence for now, because
929 * there is not yet any manipulation here of PHY options.
930 */
931 for (const auto& thismode : m_wifiPhy->GetModeList())
932 {
933 /* If the rate:
934 *
935 * - is a mandatory rate for the PHY, and
936 * - is equal to or faster than our current best choice, and
937 * - is less than or equal to the rate of the received frame, and
938 * - is of the same modulation class as the received frame
939 *
940 * ...then it's our best choice so far.
941 */
942 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
943 (!thismode.IsHigherDataRate(reqMode)) &&
945 thismode.GetModulationClass())))
946 {
947 mode = thismode;
948 // As above; we've found a potentially-suitable transmit
949 // rate, but we need to continue and consider all the
950 // mandatory rates before we can be sure we've got the right one.
951 found = true;
952 }
953 }
954 if (m_wifiPhy->GetDevice()->GetHtConfiguration())
955 {
956 for (const auto& thismode : m_wifiPhy->GetMcsList())
957 {
958 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
959 (!thismode.IsHigherCodeRate(reqMode)) &&
960 (thismode.GetModulationClass() == reqMode.GetModulationClass()))
961 {
962 mode = thismode;
963 // As above; we've found a potentially-suitable transmit
964 // rate, but we need to continue and consider all the
965 // mandatory rates before we can be sure we've got the right one.
966 found = true;
967 }
968 }
969 }
970
971 /**
972 * If we still haven't found a suitable rate for the response then
973 * someone has messed up the simulation configuration. This probably means
974 * that the WifiPhyStandard is not set correctly, or that a rate that
975 * is not supported by the PHY has been explicitly requested.
976 *
977 * Either way, it is serious - we can either disobey the standard or
978 * fail, and I have chosen to do the latter...
979 */
980 if (!found)
981 {
982 NS_FATAL_ERROR("Can't find response rate for " << reqMode);
983 }
984
985 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
986 return mode;
987}
988
989void
991{
992 NS_LOG_FUNCTION(this << header);
993 const auto recipient = GetIndividuallyAddressedRecipient(m_wifiMac, header);
994 NS_ASSERT(!recipient.IsGroup());
995 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
996 m_ssrc[ac]++;
997 m_macTxRtsFailed(recipient);
998 DoReportRtsFailed(Lookup(recipient));
999}
1000
1001void
1003{
1004 NS_LOG_FUNCTION(this << *mpdu);
1005 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1006 AcIndex ac =
1007 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1008 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1009 if (longMpdu)
1010 {
1011 m_slrc[ac]++;
1012 }
1013 else
1014 {
1015 m_ssrc[ac]++;
1016 }
1017 m_macTxDataFailed(mpdu->GetHeader().GetAddr1());
1018 DoReportDataFailed(Lookup(mpdu->GetHeader().GetAddr1()));
1019}
1020
1021void
1023 double ctsSnr,
1024 WifiMode ctsMode,
1025 double rtsSnr)
1026{
1027 NS_LOG_FUNCTION(this << header << ctsSnr << ctsMode << rtsSnr);
1028 const auto recipient = GetIndividuallyAddressedRecipient(m_wifiMac, header);
1029 NS_ASSERT(!recipient.IsGroup());
1030 WifiRemoteStation* station = Lookup(recipient);
1031 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1032 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1033 m_ssrc[ac] = 0;
1034 DoReportRtsOk(station, ctsSnr, ctsMode, rtsSnr);
1035}
1036
1037void
1039 double ackSnr,
1040 WifiMode ackMode,
1041 double dataSnr,
1042 WifiTxVector dataTxVector)
1043{
1044 NS_LOG_FUNCTION(this << *mpdu << ackSnr << ackMode << dataSnr << dataTxVector);
1045 const WifiMacHeader& hdr = mpdu->GetHeader();
1046 NS_ASSERT(!hdr.GetAddr1().IsGroup());
1047 WifiRemoteStation* station = Lookup(hdr.GetAddr1());
1048 AcIndex ac = QosUtilsMapTidToAc((hdr.IsQosData()) ? hdr.GetQosTid() : 0);
1049 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1050 if (longMpdu)
1051 {
1052 station->m_state->m_info.NotifyTxSuccess(m_slrc[ac]);
1053 m_slrc[ac] = 0;
1054 }
1055 else
1056 {
1057 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1058 m_ssrc[ac] = 0;
1059 }
1060 DoReportDataOk(station,
1061 ackSnr,
1062 ackMode,
1063 dataSnr,
1064 dataTxVector.GetChannelWidth(),
1065 dataTxVector.GetNss(GetStaId(hdr.GetAddr1(), dataTxVector)));
1066}
1067
1068void
1070{
1071 NS_LOG_FUNCTION(this << header);
1072 NS_ASSERT(!header.GetAddr1().IsGroup());
1073 WifiRemoteStation* station = Lookup(header.GetAddr1());
1074 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1075 station->m_state->m_info.NotifyTxFailed();
1076 m_ssrc[ac] = 0;
1078 DoReportFinalRtsFailed(station);
1079}
1080
1081void
1083{
1084 NS_LOG_FUNCTION(this << *mpdu);
1085 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1086 WifiRemoteStation* station = Lookup(mpdu->GetHeader().GetAddr1());
1087 AcIndex ac =
1088 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1089 station->m_state->m_info.NotifyTxFailed();
1090 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1091 if (longMpdu)
1092 {
1093 m_slrc[ac] = 0;
1094 }
1095 else
1096 {
1097 m_ssrc[ac] = 0;
1098 }
1099 m_macTxFinalDataFailed(mpdu->GetHeader().GetAddr1());
1100 DoReportFinalDataFailed(station);
1101}
1102
1103void
1105 RxSignalInfo rxSignalInfo,
1106 const WifiTxVector& txVector)
1107{
1108 NS_LOG_FUNCTION(this << address << rxSignalInfo << txVector);
1109 if (address.IsGroup())
1110 {
1111 return;
1112 }
1113 WifiRemoteStation* station = Lookup(address);
1114 DoReportRxOk(station, rxSignalInfo.snr, txVector.GetMode(GetStaId(address, txVector)));
1115 station->m_rssiAndUpdateTimePair = std::make_pair(rxSignalInfo.rssi, Simulator::Now());
1116}
1117
1118void
1120 uint16_t nSuccessfulMpdus,
1121 uint16_t nFailedMpdus,
1122 double rxSnr,
1123 double dataSnr,
1124 WifiTxVector dataTxVector)
1125{
1126 NS_LOG_FUNCTION(this << address << nSuccessfulMpdus << nFailedMpdus << rxSnr << dataSnr
1127 << dataTxVector);
1128 NS_ASSERT(!address.IsGroup());
1129 for (uint16_t i = 0; i < nFailedMpdus; i++)
1130 {
1131 m_macTxDataFailed(address);
1132 }
1134 nSuccessfulMpdus,
1135 nFailedMpdus,
1136 rxSnr,
1137 dataSnr,
1138 dataTxVector.GetChannelWidth(),
1139 dataTxVector.GetNss(GetStaId(address, dataTxVector)));
1140}
1141
1142std::list<Ptr<WifiMpdu>>
1144{
1145 NS_LOG_FUNCTION(this << *psdu);
1146
1147 auto* station = Lookup(GetIndividuallyAddressedRecipient(m_wifiMac, psdu->GetHeader(0)));
1148
1149 DoIncrementRetryCountOnTxFailure(station, psdu);
1150 return DoGetMpdusToDropOnTxFailure(station, psdu);
1151}
1152
1153void
1155 Ptr<WifiPsdu> psdu)
1156{
1157 NS_LOG_FUNCTION(this << *psdu);
1158
1159 // The frame retry count for an MSDU or A-MSDU that is not part of a block ack agreement or
1160 // for an MMPDU shall be incremented every time transmission fails for that MSDU, A-MSDU, or
1161 // MMPDU, including of an associated RTS (Sec. 10.23.2.12.1 of 802.11-2020).
1162 // Frames for which the retry count needs to be incremented:
1163 // - management frames
1164 // - non-QoS Data frames
1165 // - QoS Data frames that are not part of a Block Ack agreement
1166 // - QoS Data frames that are part of a Block Ack agreement if the IncrementRetryCountUnderBa
1167 // attribute is set to true
1168 const auto& hdr = psdu->GetHeader(0);
1169
1170 if (hdr.IsMgt() || (hdr.IsData() && !hdr.IsQosData()) ||
1171 (hdr.IsQosData() && (!m_wifiMac->GetBaAgreementEstablishedAsOriginator(
1172 hdr.GetAddr1(),
1173 hdr.GetQosTid() || m_incrRetryCountUnderBa))))
1174 {
1175 psdu->IncrementRetryCount();
1176 }
1177}
1178
1179std::list<Ptr<WifiMpdu>>
1181 Ptr<WifiPsdu> psdu)
1182{
1183 NS_LOG_FUNCTION(this << *psdu);
1184
1185 std::list<Ptr<WifiMpdu>> mpdusToDrop;
1186
1187 for (const auto& mpdu : *PeekPointer(psdu))
1188 {
1189 if (mpdu->GetRetryCount() == m_wifiMac->GetFrameRetryLimit())
1190 {
1191 // this MPDU needs to be dropped
1192 mpdusToDrop.push_back(mpdu);
1193 }
1194 }
1195
1196 return mpdusToDrop;
1197}
1198
1199bool
1201{
1202 NS_LOG_FUNCTION(this << header << &txParams);
1203 auto address = header.GetAddr1();
1204 const auto isGcr = IsGcr(m_wifiMac, header);
1205 if (!isGcr && address.IsGroup())
1206 {
1207 return false;
1208 }
1209 if (isGcr)
1210 {
1212 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
1213 apMac->GetGcrManager()->GetAttribute("GcrProtectionMode", enumValue);
1214 if (enumValue.Get() != GroupcastProtectionMode::RTS_CTS)
1215 {
1216 return false;
1217 }
1218 address = apMac->GetGcrManager()->GetIndividuallyAddressedRecipient(address);
1219 }
1220 const auto modulationClass = txParams.m_txVector.GetModulationClass();
1222 ((modulationClass == WIFI_MOD_CLASS_ERP_OFDM) || (modulationClass == WIFI_MOD_CLASS_HT) ||
1223 (modulationClass == WIFI_MOD_CLASS_VHT) || (modulationClass == WIFI_MOD_CLASS_HE) ||
1224 (modulationClass == WIFI_MOD_CLASS_EHT)) &&
1226 {
1228 "WifiRemoteStationManager::NeedRTS returning true to protect non-ERP stations");
1229 return true;
1230 }
1231 else if (m_htProtectionMode == RTS_CTS &&
1232 ((modulationClass == WIFI_MOD_CLASS_HT) || (modulationClass == WIFI_MOD_CLASS_VHT)) &&
1234 {
1235 NS_LOG_DEBUG("WifiRemoteStationManager::NeedRTS returning true to protect non-HT stations");
1236 return true;
1237 }
1238 NS_ASSERT(txParams.m_txDuration.has_value());
1239 auto size = txParams.GetSize(header.GetAddr1());
1240 bool normally =
1243 return DoNeedRts(Lookup(address), size, normally);
1244}
1245
1246bool
1248{
1249 NS_LOG_FUNCTION(this << txVector << header);
1252 (txVector.GetModulationClass() == WIFI_MOD_CLASS_HT) ||
1253 (txVector.GetModulationClass() == WIFI_MOD_CLASS_VHT) ||
1254 (txVector.GetModulationClass() == WIFI_MOD_CLASS_HE) ||
1255 (txVector.GetModulationClass() == WIFI_MOD_CLASS_EHT)))
1256 {
1258 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-ERP stations");
1259 return true;
1260 }
1261 else if (m_htProtectionMode == CTS_TO_SELF &&
1262 ((txVector.GetModulationClass() == WIFI_MOD_CLASS_HT) ||
1263 (txVector.GetModulationClass() == WIFI_MOD_CLASS_VHT)) &&
1265 {
1267 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-HT stations");
1268 return true;
1269 }
1270 else if (IsGcr(m_wifiMac, header))
1271 {
1273 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
1274 apMac->GetGcrManager()->GetAttribute("GcrProtectionMode", enumValue);
1275 if (enumValue.Get() == GroupcastProtectionMode::CTS_TO_SELF)
1276 {
1277 return true;
1278 }
1279 }
1280 // FIXME: commented out for now
1281 /*else if (!m_useNonErpProtection)
1282 {
1283 const auto mode = txVector.GetMode();
1284 // search for the BSS Basic Rate set, if the used mode is in the basic set then there is no
1285 // need for CTS To Self
1286 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
1287 {
1288 if (mode == *i)
1289 {
1290 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1291 return false;
1292 }
1293 }
1294 if (m_wifiPhy->GetDevice()->GetHtConfiguration())
1295 {
1296 // search for the BSS Basic MCS set, if the used mode is in the basic set then there is
1297 // no need for CTS To Self
1298 for (auto i = m_bssBasicMcsSet.begin(); i != m_bssBasicMcsSet.end(); i++)
1299 {
1300 if (mode == *i)
1301 {
1302 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1303 return false;
1304 }
1305 }
1306 }
1307 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning true");
1308 return true;
1309 }*/
1310 return false;
1311}
1312
1313void
1315{
1316 NS_LOG_FUNCTION(this << enable);
1317 m_useNonErpProtection = enable;
1318}
1319
1320bool
1325
1326void
1328{
1329 NS_LOG_FUNCTION(this << enable);
1330 m_useNonHtProtection = enable;
1331}
1332
1333bool
1338
1339bool
1341{
1342 NS_LOG_FUNCTION(this << *mpdu);
1343 if (mpdu->GetHeader().GetAddr1().IsGroup())
1344 {
1345 return false;
1346 }
1347 bool normally = mpdu->GetSize() > GetFragmentationThreshold();
1348 NS_LOG_DEBUG("WifiRemoteStationManager::NeedFragmentation result: " << std::boolalpha
1349 << normally);
1350 return DoNeedFragmentation(Lookup(mpdu->GetHeader().GetAddr1()), mpdu->GetPacket(), normally);
1351}
1352
1353void
1355{
1356 NS_LOG_FUNCTION(this << threshold);
1357 if (threshold < WIFI_MIN_FRAG_THRESHOLD)
1358 {
1359 NS_LOG_WARN("Fragmentation threshold should be larger than "
1360 << WIFI_MIN_FRAG_THRESHOLD << ". Setting to " << WIFI_MIN_FRAG_THRESHOLD
1361 << ".");
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 if (ehtCapabilities.m_phyCapabilities.support320MhzIn6Ghz &&
1772 (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_6GHZ))
1773 {
1774 state->m_channelWidth = MHz_u{320};
1775 }
1776 // For other cases, the supported channel width is set by the HT/VHT capabilities
1777 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_EHT))
1778 {
1779 for (uint8_t mapType = 0; mapType < EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_MAX; ++mapType)
1780 {
1781 if (ehtCapabilities.GetHighestSupportedRxMcs(
1782 static_cast<EhtMcsAndNssSet::EhtMcsMapType>(mapType)) >= mcs.GetMcsValue())
1783 {
1784 AddSupportedMcs(from, mcs);
1785 }
1786 }
1787 }
1788 state->m_ehtCapabilities = Create<const EhtCapabilities>(ehtCapabilities);
1789 SetQosSupport(from, true);
1790}
1791
1792void
1793WifiRemoteStationManager::AddStationEhtOperation(Mac48Address from,
1794 const EhtOperation& ehtOperation)
1795{
1796 NS_LOG_FUNCTION(this << from << ehtOperation);
1797 auto state = LookupState(from);
1798 if (auto opControl = ehtOperation.m_opInfo)
1799 {
1800 switch (opControl->control.channelWidth)
1801 {
1802 case 0:
1803 state->m_channelWidth = MHz_u{20};
1804 break;
1805 case 1:
1806 state->m_channelWidth = MHz_u{40};
1807 break;
1808 case 2:
1809 state->m_channelWidth = MHz_u{80};
1810 break;
1811 case 3:
1812 state->m_channelWidth = MHz_u{160};
1813 break;
1814 case 4:
1815 state->m_channelWidth = MHz_u{320};
1816 break;
1817 default:
1818 NS_FATAL_ERROR("Invalid channel width value in EHT Operation Information field");
1819 }
1820 }
1821 state->m_ehtOperation = Create<const EhtOperation>(ehtOperation);
1822}
1823
1824void
1825WifiRemoteStationManager::AddStationMleCommonInfo(
1826 Mac48Address from,
1827 const std::shared_ptr<CommonInfoBasicMle>& mleCommonInfo)
1828{
1829 NS_LOG_FUNCTION(this << from);
1830 auto state = LookupState(from);
1831 state->m_mleCommonInfo = mleCommonInfo;
1832 // insert another entry in m_states indexed by the MLD address and pointing to the same state
1833 const_cast<WifiRemoteStationManager*>(this)->m_states.insert_or_assign(
1834 mleCommonInfo->m_mldMacAddress,
1835 state);
1836}
1837
1839WifiRemoteStationManager::GetStationHtCapabilities(Mac48Address from)
1840{
1841 return LookupState(from)->m_htCapabilities;
1842}
1843
1845WifiRemoteStationManager::GetStationHtOperation(Mac48Address from)
1846{
1847 return LookupState(from)->m_htOperation;
1848}
1849
1851WifiRemoteStationManager::GetStationExtendedCapabilities(const Mac48Address& from)
1852{
1853 return LookupState(from)->m_extendedCapabilities;
1854}
1855
1857WifiRemoteStationManager::GetStationVhtCapabilities(Mac48Address from)
1858{
1859 return LookupState(from)->m_vhtCapabilities;
1860}
1861
1863WifiRemoteStationManager::GetStationHeCapabilities(Mac48Address from)
1864{
1865 return LookupState(from)->m_heCapabilities;
1866}
1867
1869WifiRemoteStationManager::GetStationHeOperation(Mac48Address from)
1870{
1871 return LookupState(from)->m_heOperation;
1872}
1873
1875WifiRemoteStationManager::GetStationHe6GhzCapabilities(const Mac48Address& from) const
1876{
1877 return LookupState(from)->m_he6GhzBandCapabilities;
1878}
1879
1881WifiRemoteStationManager::GetStationEhtCapabilities(Mac48Address from)
1882{
1883 return LookupState(from)->m_ehtCapabilities;
1884}
1885
1887WifiRemoteStationManager::GetStationEhtOperation(Mac48Address from)
1888{
1889 return LookupState(from)->m_ehtOperation;
1890}
1891
1892std::optional<std::reference_wrapper<CommonInfoBasicMle::EmlCapabilities>>
1893WifiRemoteStationManager::GetStationEmlCapabilities(const Mac48Address& from)
1894{
1895 if (auto state = LookupState(from);
1896 state->m_mleCommonInfo && state->m_mleCommonInfo->m_emlCapabilities)
1897 {
1898 return state->m_mleCommonInfo->m_emlCapabilities.value();
1899 }
1900 return std::nullopt;
1901}
1902
1903std::optional<std::reference_wrapper<CommonInfoBasicMle::MldCapabilities>>
1904WifiRemoteStationManager::GetStationMldCapabilities(const Mac48Address& from)
1905{
1906 if (auto state = LookupState(from);
1907 state->m_mleCommonInfo && state->m_mleCommonInfo->m_mldCapabilities)
1908 {
1909 return state->m_mleCommonInfo->m_mldCapabilities.value();
1910 }
1911 return std::nullopt;
1912}
1913
1914bool
1915WifiRemoteStationManager::GetLdpcSupported(Mac48Address address) const
1916{
1917 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
1918 Ptr<const VhtCapabilities> vhtCapabilities = LookupState(address)->m_vhtCapabilities;
1919 Ptr<const HeCapabilities> heCapabilities = LookupState(address)->m_heCapabilities;
1920 bool supported = false;
1921 if (htCapabilities)
1922 {
1923 supported |= htCapabilities->GetLdpc();
1924 }
1925 if (vhtCapabilities)
1926 {
1927 supported |= vhtCapabilities->GetRxLdpc();
1928 }
1929 if (heCapabilities)
1930 {
1931 supported |= heCapabilities->GetLdpcCodingInPayload();
1932 }
1933 return supported;
1934}
1935
1937WifiRemoteStationManager::GetDefaultMode() const
1938{
1939 NS_ASSERT(m_wifiPhy);
1940 auto defaultTxMode = m_wifiPhy->GetDefaultMode();
1941 NS_ASSERT(defaultTxMode.IsMandatory());
1942 return defaultTxMode;
1943}
1944
1946WifiRemoteStationManager::GetDefaultMcs() const
1947{
1948 return HtPhy::GetHtMcs0();
1949}
1950
1952WifiRemoteStationManager::GetDefaultModeForSta(const WifiRemoteStation* st) const
1953{
1954 NS_LOG_FUNCTION(this << st);
1955
1956 if ((!m_wifiPhy->GetDevice()->GetHtConfiguration()) ||
1957 (!GetHtSupported(st) && !GetStationHe6GhzCapabilities(st->m_state->m_address)))
1958 {
1959 return GetDefaultMode();
1960 }
1961
1962 // find the highest modulation class supported by both stations
1964 if (GetHeSupported() && GetHeSupported(st))
1965 {
1966 modClass = WIFI_MOD_CLASS_HE;
1967 }
1968 else if (GetVhtSupported() && GetVhtSupported(st))
1969 {
1970 modClass = WIFI_MOD_CLASS_VHT;
1971 }
1972
1973 // return the MCS with lowest index
1974 return *m_wifiPhy->GetPhyEntity(modClass)->begin();
1975}
1976
1977void
1978WifiRemoteStationManager::Reset()
1979{
1980 NS_LOG_FUNCTION(this);
1981 m_states.clear();
1982 for (auto& state : m_stations)
1983 {
1984 delete (state.second);
1985 }
1986 m_stations.clear();
1987 m_bssBasicRateSet.clear();
1988 m_bssBasicMcsSet.clear();
1989 m_ssrc.fill(0);
1990 m_slrc.fill(0);
1991}
1992
1993void
1994WifiRemoteStationManager::AddBasicMode(WifiMode mode)
1995{
1996 NS_LOG_FUNCTION(this << mode);
1998 {
1999 NS_FATAL_ERROR("It is not allowed to add a HT rate in the BSSBasicRateSet!");
2000 }
2001 for (uint8_t i = 0; i < GetNBasicModes(); i++)
2002 {
2003 if (GetBasicMode(i) == mode)
2004 {
2005 return;
2006 }
2007 }
2008 m_bssBasicRateSet.push_back(mode);
2009}
2010
2011uint8_t
2012WifiRemoteStationManager::GetNBasicModes() const
2013{
2014 return static_cast<uint8_t>(m_bssBasicRateSet.size());
2015}
2016
2018WifiRemoteStationManager::GetBasicMode(uint8_t i) const
2019{
2020 NS_ASSERT(i < GetNBasicModes());
2021 return m_bssBasicRateSet[i];
2022}
2023
2025WifiRemoteStationManager::GetNNonErpBasicModes() const
2026{
2027 uint32_t size = 0;
2028 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
2029 {
2030 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
2031 {
2032 continue;
2033 }
2034 size++;
2035 }
2036 return size;
2037}
2038
2040WifiRemoteStationManager::GetNonErpBasicMode(uint8_t i) const
2041{
2042 NS_ASSERT(i < GetNNonErpBasicModes());
2043 uint32_t index = 0;
2044 bool found = false;
2045 for (auto j = m_bssBasicRateSet.begin(); j != m_bssBasicRateSet.end();)
2046 {
2047 if (i == index)
2048 {
2049 found = true;
2050 }
2051 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
2052 {
2053 if (found)
2054 {
2055 break;
2056 }
2057 }
2058 index++;
2059 j++;
2060 }
2061 return m_bssBasicRateSet[index];
2062}
2063
2064void
2065WifiRemoteStationManager::AddBasicMcs(WifiMode mcs)
2066{
2067 NS_LOG_FUNCTION(this << +mcs.GetMcsValue());
2068 for (uint8_t i = 0; i < GetNBasicMcs(); i++)
2069 {
2070 if (GetBasicMcs(i) == mcs)
2071 {
2072 return;
2073 }
2074 }
2075 m_bssBasicMcsSet.push_back(mcs);
2076}
2077
2078uint8_t
2079WifiRemoteStationManager::GetNBasicMcs() const
2080{
2081 return static_cast<uint8_t>(m_bssBasicMcsSet.size());
2082}
2083
2085WifiRemoteStationManager::GetBasicMcs(uint8_t i) const
2086{
2087 NS_ASSERT(i < GetNBasicMcs());
2088 return m_bssBasicMcsSet[i];
2089}
2090
2092WifiRemoteStationManager::GetNonUnicastMode() const
2093{
2094 if (m_nonUnicastMode == WifiMode())
2095 {
2096 if (GetNBasicModes() > 0)
2097 {
2098 return GetBasicMode(0);
2099 }
2100 else
2101 {
2102 return GetDefaultMode();
2103 }
2104 }
2105 else
2106 {
2107 return m_nonUnicastMode;
2108 }
2109}
2110
2112WifiRemoteStationManager::GetGroupcastTxVector(const WifiMacHeader& header, MHz_u allowedWidth)
2113{
2114 const auto& to = header.GetAddr1();
2115 NS_ASSERT(to.IsGroup());
2116
2117 WifiTxVector groupcastTxVector{};
2118 const auto mode = GetNonUnicastMode();
2119 groupcastTxVector.SetMode(mode);
2120 groupcastTxVector.SetPreambleType(
2121 GetPreambleForTransmission(mode.GetModulationClass(), GetShortPreambleEnabled()));
2122 groupcastTxVector.SetTxPowerLevel(m_defaultTxPowerLevel);
2123 groupcastTxVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mode, allowedWidth));
2124 groupcastTxVector.SetNTx(GetNumberOfAntennas());
2125
2126 if (to.IsBroadcast())
2127 {
2128 return groupcastTxVector;
2129 }
2130
2131 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
2132 if (!apMac)
2133 {
2134 return groupcastTxVector;
2135 }
2136
2137 auto gcrManager = apMac->GetGcrManager();
2138 if (!gcrManager)
2139 {
2140 return groupcastTxVector;
2141 }
2142
2143 const auto& groupStas = gcrManager->GetMemberStasForGroupAddress(to);
2144 if (groupStas.empty())
2145 {
2146 return groupcastTxVector;
2147 }
2148
2149 if (!gcrManager->UseConcealment(header))
2150 {
2151 return groupcastTxVector;
2152 }
2153
2154 // If we are here, that means the mode will be used for the transmission of a groupcast frame
2155 // using the GCR service. We should loop over each member STA that is going to receive the
2156 // groupcast frame and select the highest possible mode over all STAs.
2157 std::optional<WifiMode> groupcastMode;
2158 auto maxWidth = allowedWidth;
2159 auto maxNss = m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2160 std::map<WifiModulationClass, Time> minGisPerMc{/* non-HT OFDM is always 800 ns */
2163 const std::map<WifiModulationClass, WifiModulationClass> giRefModClass{
2164 /* HT/VHT: short or long GI */
2167 /* HE/EHT: 3 possible GIs */
2170 for (const auto& staAddress : groupStas)
2171 {
2172 // Get the equivalent TXVECTOR if the frame would be a unicast frame to that STA in order to
2173 // get what rate would be selected for that STA.
2175 hdr.SetAddr1(staAddress);
2176 const auto unicastTxVector = GetDataTxVector(hdr, allowedWidth);
2177
2178 // update the groupcast mode if:
2179 // - this is the first mode to inspect;
2180 // - this mode has a lower modulation class than the currently selected groupcast mode;
2181 // - when the modulation class is similar, this mode has a lower MCS than the currently
2182 // selected groupcast mode.
2183 if (!groupcastMode.has_value() ||
2184 (unicastTxVector.GetModulationClass() < groupcastMode->GetModulationClass()) ||
2185 ((unicastTxVector.GetModulationClass() == groupcastMode->GetModulationClass()) &&
2186 (unicastTxVector.GetMode().GetMcsValue() < groupcastMode->GetMcsValue())))
2187 {
2188 groupcastMode = unicastTxVector.GetMode();
2189 }
2190 maxWidth = std::min(unicastTxVector.GetChannelWidth(), maxWidth);
2191 maxNss = std::min(unicastTxVector.GetNss(), maxNss);
2192 auto mc = unicastTxVector.GetModulationClass();
2193 if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
2194 {
2195 mc = it->second;
2196 }
2197 if (auto it = minGisPerMc.find(mc); it != minGisPerMc.end())
2198 {
2199 it->second = std::max(unicastTxVector.GetGuardInterval(), it->second);
2200 }
2201 }
2202 NS_ASSERT(groupcastMode.has_value());
2203
2204 groupcastTxVector.SetMode(*groupcastMode);
2205 groupcastTxVector.SetPreambleType(
2206 GetPreambleForTransmission(groupcastMode->GetModulationClass(), GetShortPreambleEnabled()));
2207 groupcastTxVector.SetChannelWidth(maxWidth);
2208 groupcastTxVector.SetNss(maxNss);
2209 auto mc = groupcastMode->GetModulationClass();
2210 if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
2211 {
2212 mc = it->second;
2213 }
2214 if (const auto it = minGisPerMc.find(mc); it != minGisPerMc.cend())
2215 {
2216 groupcastTxVector.SetGuardInterval(it->second);
2217 }
2218
2219 return groupcastTxVector;
2220}
2221
2222bool
2223WifiRemoteStationManager::DoNeedRts(WifiRemoteStation* station, uint32_t size, bool normally)
2224{
2225 return normally;
2226}
2227
2228bool
2229WifiRemoteStationManager::DoNeedFragmentation(WifiRemoteStation* station,
2230 Ptr<const Packet> packet,
2231 bool normally)
2232{
2233 return normally;
2234}
2235
2236void
2237WifiRemoteStationManager::DoReportAmpduTxStatus(WifiRemoteStation* station,
2238 uint16_t nSuccessfulMpdus,
2239 uint16_t nFailedMpdus,
2240 double rxSnr,
2241 double dataSnr,
2242 MHz_u dataChannelWidth,
2243 uint8_t dataNss)
2244{
2245 NS_LOG_DEBUG("DoReportAmpduTxStatus received but the manager does not handle A-MPDUs!");
2246}
2247
2249WifiRemoteStationManager::GetSupported(const WifiRemoteStation* station, uint8_t i) const
2250{
2251 NS_ASSERT(i < GetNSupported(station));
2252 return station->m_state->m_operationalRateSet[i];
2253}
2254
2256WifiRemoteStationManager::GetMcsSupported(const WifiRemoteStation* station, uint8_t i) const
2257{
2258 NS_ASSERT(i < GetNMcsSupported(station));
2259 return station->m_state->m_operationalMcsSet[i];
2260}
2261
2263WifiRemoteStationManager::GetNonErpSupported(const WifiRemoteStation* station, uint8_t i) const
2264{
2265 NS_ASSERT(i < GetNNonErpSupported(station));
2266 // IEEE 802.11g standard defines that if the protection mechanism is enabled, RTS, CTS and
2267 // CTS-To-Self frames should select a rate in the BSSBasicRateSet that corresponds to an 802.11b
2268 // basic rate. This is a implemented here to avoid changes in every RAA, but should maybe be
2269 // moved in case it breaks standard rules.
2270 uint32_t index = 0;
2271 bool found = false;
2272 for (auto j = station->m_state->m_operationalRateSet.begin();
2273 j != station->m_state->m_operationalRateSet.end();)
2274 {
2275 if (i == index)
2276 {
2277 found = true;
2278 }
2279 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
2280 {
2281 if (found)
2282 {
2283 break;
2284 }
2285 }
2286 index++;
2287 j++;
2288 }
2289 return station->m_state->m_operationalRateSet[index];
2290}
2291
2293WifiRemoteStationManager::GetAddress(const WifiRemoteStation* station) const
2294{
2295 return station->m_state->m_address;
2296}
2297
2298MHz_u
2299WifiRemoteStationManager::GetChannelWidth(const WifiRemoteStation* station) const
2300{
2301 return station->m_state->m_channelWidth;
2302}
2303
2304bool
2305WifiRemoteStationManager::GetShortGuardIntervalSupported(const WifiRemoteStation* station) const
2306{
2307 Ptr<const HtCapabilities> htCapabilities = station->m_state->m_htCapabilities;
2308
2309 if (!htCapabilities)
2310 {
2311 return false;
2312 }
2313 return htCapabilities->GetShortGuardInterval20();
2314}
2315
2316Time
2317WifiRemoteStationManager::GetGuardInterval(const WifiRemoteStation* station) const
2318{
2319 return station->m_state->m_guardInterval;
2320}
2321
2322bool
2323WifiRemoteStationManager::GetAggregation(const WifiRemoteStation* station) const
2324{
2325 return station->m_state->m_aggregation;
2326}
2327
2328uint8_t
2329WifiRemoteStationManager::GetNumberOfSupportedStreams(const WifiRemoteStation* station) const
2330{
2331 const auto htCapabilities = station->m_state->m_htCapabilities;
2332
2333 if (!htCapabilities)
2334 {
2335 if (const auto heCapabilities = station->m_state->m_heCapabilities)
2336 {
2337 return heCapabilities->GetHighestNssSupported();
2338 }
2339 return 1;
2340 }
2341 return htCapabilities->GetRxHighestSupportedAntennas();
2342}
2343
2344uint8_t
2345WifiRemoteStationManager::GetNess(const WifiRemoteStation* station) const
2346{
2347 return station->m_state->m_ness;
2348}
2349
2351WifiRemoteStationManager::GetPhy() const
2352{
2353 return m_wifiPhy;
2354}
2355
2357WifiRemoteStationManager::GetMac() const
2358{
2359 return m_wifiMac;
2360}
2361
2362uint8_t
2363WifiRemoteStationManager::GetNSupported(const WifiRemoteStation* station) const
2364{
2365 return static_cast<uint8_t>(station->m_state->m_operationalRateSet.size());
2366}
2367
2368bool
2369WifiRemoteStationManager::GetQosSupported(const WifiRemoteStation* station) const
2370{
2371 return station->m_state->m_qosSupported;
2372}
2373
2374bool
2375WifiRemoteStationManager::GetHtSupported(const WifiRemoteStation* station) const
2376{
2377 return bool(station->m_state->m_htCapabilities);
2378}
2379
2380bool
2381WifiRemoteStationManager::GetVhtSupported(const WifiRemoteStation* station) const
2382{
2383 return bool(station->m_state->m_vhtCapabilities);
2384}
2385
2386bool
2387WifiRemoteStationManager::GetHeSupported(const WifiRemoteStation* station) const
2388{
2389 return bool(station->m_state->m_heCapabilities);
2390}
2391
2392bool
2393WifiRemoteStationManager::GetEhtSupported(const WifiRemoteStation* station) const
2394{
2395 return (bool)(station->m_state->m_ehtCapabilities);
2396}
2397
2398bool
2399WifiRemoteStationManager::GetEmlsrSupported(const WifiRemoteStation* station) const
2400{
2401 auto mleCommonInfo = station->m_state->m_mleCommonInfo;
2402 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2403 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2404}
2405
2406bool
2407WifiRemoteStationManager::GetEmlsrEnabled(const WifiRemoteStation* station) const
2408{
2409 return station->m_state->m_emlsrEnabled;
2410}
2411
2412uint8_t
2413WifiRemoteStationManager::GetNMcsSupported(const WifiRemoteStation* station) const
2414{
2415 return static_cast<uint8_t>(station->m_state->m_operationalMcsSet.size());
2416}
2417
2419WifiRemoteStationManager::GetNNonErpSupported(const WifiRemoteStation* station) const
2420{
2421 uint32_t size = 0;
2422 for (auto i = station->m_state->m_operationalRateSet.begin();
2423 i != station->m_state->m_operationalRateSet.end();
2424 i++)
2425 {
2426 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
2427 {
2428 continue;
2429 }
2430 size++;
2431 }
2432 return size;
2433}
2434
2435MHz_u
2436WifiRemoteStationManager::GetChannelWidthSupported(Mac48Address address) const
2437{
2438 return LookupState(address)->m_channelWidth;
2439}
2440
2441bool
2442WifiRemoteStationManager::GetShortGuardIntervalSupported(Mac48Address address) const
2443{
2444 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2445
2446 if (!htCapabilities)
2447 {
2448 return false;
2449 }
2450 return htCapabilities->GetShortGuardInterval20();
2451}
2452
2453uint8_t
2454WifiRemoteStationManager::GetNumberOfSupportedStreams(Mac48Address address) const
2455{
2456 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2457
2458 if (!htCapabilities)
2459 {
2460 return 1;
2461 }
2462 return htCapabilities->GetRxHighestSupportedAntennas();
2463}
2464
2465uint8_t
2466WifiRemoteStationManager::GetNMcsSupported(Mac48Address address) const
2467{
2468 return static_cast<uint8_t>(LookupState(address)->m_operationalMcsSet.size());
2469}
2470
2471bool
2472WifiRemoteStationManager::GetDsssSupported(const Mac48Address& address) const
2473{
2474 return (LookupState(address)->m_dsssSupported);
2475}
2476
2477bool
2478WifiRemoteStationManager::GetErpOfdmSupported(const Mac48Address& address) const
2479{
2480 return (LookupState(address)->m_erpOfdmSupported);
2481}
2482
2483bool
2484WifiRemoteStationManager::GetOfdmSupported(const Mac48Address& address) const
2485{
2486 return (LookupState(address)->m_ofdmSupported);
2487}
2488
2489bool
2490WifiRemoteStationManager::GetHtSupported(Mac48Address address) const
2491{
2492 return bool(LookupState(address)->m_htCapabilities);
2493}
2494
2495bool
2496WifiRemoteStationManager::GetVhtSupported(Mac48Address address) const
2497{
2498 return bool(LookupState(address)->m_vhtCapabilities);
2499}
2500
2501bool
2502WifiRemoteStationManager::GetHeSupported(Mac48Address address) const
2503{
2504 return bool(LookupState(address)->m_heCapabilities);
2505}
2506
2507bool
2508WifiRemoteStationManager::GetEhtSupported(Mac48Address address) const
2509{
2510 return (bool)(LookupState(address)->m_ehtCapabilities);
2511}
2512
2513bool
2514WifiRemoteStationManager::GetEmlsrSupported(const Mac48Address& address) const
2515{
2516 auto mleCommonInfo = LookupState(address)->m_mleCommonInfo;
2517 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2518 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2519}
2520
2521bool
2522WifiRemoteStationManager::GetEmlsrEnabled(const Mac48Address& address) const
2523{
2524 if (auto stateIt = m_states.find(address); stateIt != m_states.cend())
2525 {
2526 return stateIt->second->m_emlsrEnabled;
2527 }
2528 return false;
2529}
2530
2531void
2532WifiRemoteStationManager::SetDefaultTxPowerLevel(uint8_t txPower)
2533{
2534 m_defaultTxPowerLevel = txPower;
2535}
2536
2537uint8_t
2538WifiRemoteStationManager::GetNumberOfAntennas() const
2539{
2540 return m_wifiPhy->GetNumberOfAntennas();
2541}
2542
2543uint8_t
2544WifiRemoteStationManager::GetMaxNumberOfTransmitStreams() const
2545{
2546 return m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2547}
2548
2549bool
2550WifiRemoteStationManager::UseLdpcForDestination(Mac48Address dest) const
2551{
2552 return (GetLdpcSupported() && GetLdpcSupported(dest));
2553}
2554
2555} // namespace ns3
AttributeValue implementation for Boolean.
Definition boolean.h:26
The IEEE 802.11be EHT Capabilities.
EhtPhyCapabilities m_phyCapabilities
EHT PHY Capabilities Info subfield.
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:403
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:38
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:244
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:656
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:2111
std::list< WifiMode > GetModeList() const
The WifiPhy::GetModeList() method is used (e.g., by a WifiRemoteStationManager) to determine the set ...
Definition wifi-phy.cc:2062
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:244
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 constexpr uint32_t WIFI_DEFAULT_FRAG_THRESHOLD
The default value for dot11FragmentationThreshold (C.3 MIB detail in IEEE Std 802....
Time GetGuardIntervalForMode(WifiMode mode, const Ptr< WifiNetDevice > device)
Get the guard interval for a given WifiMode.
static constexpr uint16_t WIFI_MAC_FCS_LENGTH
The length in octets of the IEEE 802.11 MAC FCS field.
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
static constexpr uint32_t WIFI_MIN_RTS_THRESHOLD
The minimum value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
static constexpr uint32_t WIFI_MIN_FRAG_THRESHOLD
The minimum value for dot11FragmentationThreshold (C.3 MIB detail in IEEE Std 802....
static constexpr uint32_t WIFI_MAX_FRAG_THRESHOLD
The maximum value for dot11FragmentationThreshold (C.3 MIB detail in IEEE Std 802....
@ WIFI_MAC_QOSDATA
@ CTS_TO_SELF
Definition gcr-manager.h:40
@ RTS_CTS
Definition gcr-manager.h:39
static constexpr uint32_t WIFI_DEFAULT_RTS_THRESHOLD
The default value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
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:252
static constexpr uint32_t WIFI_MAX_RTS_THRESHOLD
The maximum value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020)
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
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.
uint8_t support320MhzIn6Ghz
Support For 320 MHz In 6 GHz.
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:79
double snr
SNR in linear scale.
Definition wifi-types.h:80
dBm_u rssi
RSSI.
Definition wifi-types.h:81
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