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
40
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(
110 "DefaultTxPowerLevel",
111 "Default power level to be used for transmissions. "
112 "This is the power level that is used by all those WifiManagers that do "
113 "not implement TX power control.",
114 UintegerValue(WIFI_MIN_TX_PWR_LEVEL), // corresponds to WifiPhy::TxPowerStart
117 std::numeric_limits<uint8_t>::max()))
118 .AddAttribute("ErpProtectionMode",
119 "Protection mode used when non-ERP STAs are connected to an ERP AP: "
120 "Rts-Cts or Cts-To-Self",
125 "Rts-Cts",
127 "Cts-To-Self"))
128 .AddAttribute("HtProtectionMode",
129 "Protection mode used when non-HT STAs are connected to a HT AP: Rts-Cts "
130 "or Cts-To-Self",
135 "Rts-Cts",
137 "Cts-To-Self"))
138 .AddTraceSource("MacTxRtsFailed",
139 "The transmission of a RTS by the MAC layer has failed",
141 "ns3::Mac48Address::TracedCallback")
142 .AddTraceSource("MacTxDataFailed",
143 "The transmission of a data packet by the MAC layer has failed",
145 "ns3::Mac48Address::TracedCallback")
146 .AddTraceSource(
147 "MacTxFinalRtsFailed",
148 "The transmission of a RTS has exceeded the maximum number of attempts",
150 "ns3::Mac48Address::TracedCallback")
151 .AddTraceSource(
152 "MacTxFinalDataFailed",
153 "The transmission of a data packet has exceeded the maximum number of attempts",
155 "ns3::Mac48Address::TracedCallback");
156 return tid;
157}
158
170
175
176void
182
183void
185{
186 NS_LOG_FUNCTION(this << phy);
187 // We need to track our PHY because it is the object that knows the
188 // full set of transmit rates that are supported. We need to know
189 // this in order to find the relevant mandatory rates when choosing a
190 // transmit rate for automatic control responses like
191 // acknowledgments.
192 m_wifiPhy = phy;
193}
194
195void
197{
198 NS_LOG_FUNCTION(this << mac);
199 // We need to track our MAC because it is the object that knows the
200 // full set of interframe spaces.
201 m_wifiMac = mac;
202}
203
204void
206{
207 NS_LOG_FUNCTION(this << +linkId);
208 m_linkId = linkId;
209}
210
211int64_t
213{
214 NS_LOG_FUNCTION(this << stream);
215 return 0;
216}
217
218void
220{
221 NS_LOG_FUNCTION(this << maxSsrc);
222 m_maxSsrc = maxSsrc;
223}
224
225void
227{
228 NS_LOG_FUNCTION(this << maxSlrc);
229 m_maxSlrc = maxSlrc;
230}
231
232void
234{
235 NS_LOG_FUNCTION(this << threshold);
236 m_rtsCtsThreshold = threshold;
237}
238
239void
245
246void
248{
249 NS_LOG_FUNCTION(this << enable);
250 m_shortPreambleEnabled = enable;
251}
252
253void
255{
256 NS_LOG_FUNCTION(this << enable);
257 m_shortSlotTimeEnabled = enable;
258}
259
260bool
265
266bool
271
272bool
274{
275 return (m_wifiPhy->GetDevice()->GetHtConfiguration() &&
276 m_wifiPhy->GetPhyBand() != WIFI_PHY_BAND_6GHZ);
277}
278
279bool
281{
282 return (m_wifiPhy->GetDevice()->GetVhtConfiguration() &&
283 m_wifiPhy->GetPhyBand() != WIFI_PHY_BAND_2_4GHZ &&
284 m_wifiPhy->GetPhyBand() != WIFI_PHY_BAND_6GHZ);
285}
286
287bool
289{
290 return bool(m_wifiPhy->GetDevice()->GetHeConfiguration());
291}
292
293bool
295{
296 return bool(m_wifiPhy->GetDevice()->GetEhtConfiguration());
297}
298
299bool
301{
302 if (auto htConfiguration = m_wifiPhy->GetDevice()->GetHtConfiguration())
303 {
304 return htConfiguration->m_ldpcSupported;
305 }
306 return false;
307}
308
309bool
311{
312 if (auto htConfiguration = m_wifiPhy->GetDevice()->GetHtConfiguration())
313 {
314 return htConfiguration->m_sgiSupported;
315 }
316 return false;
317}
318
319Time
321{
322 Time gi{};
323 if (GetHeSupported())
324 {
325 Ptr<HeConfiguration> heConfiguration = m_wifiPhy->GetDevice()->GetHeConfiguration();
326 NS_ASSERT(heConfiguration); // If HE is supported, we should have a HE configuration
327 // attached
328 gi = heConfiguration->GetGuardInterval();
329 }
330 return gi;
331}
332
338
339void
341 bool isShortPreambleSupported)
342{
343 NS_LOG_FUNCTION(this << address << isShortPreambleSupported);
344 NS_ASSERT(!address.IsGroup());
345 LookupState(address)->m_shortPreamble = isShortPreambleSupported;
346}
347
348void
350 bool isShortSlotTimeSupported)
351{
352 NS_LOG_FUNCTION(this << address << isShortSlotTimeSupported);
353 NS_ASSERT(!address.IsGroup());
354 LookupState(address)->m_shortSlotTime = isShortSlotTimeSupported;
355}
356
357void
359{
360 NS_LOG_FUNCTION(this << address << mode);
361 NS_ASSERT(!address.IsGroup());
362 auto state = LookupState(address);
363 for (const auto& i : state->m_operationalRateSet)
364 {
365 if (i == mode)
366 {
367 return; // already in
368 }
369 }
370 if ((mode.GetModulationClass() == WIFI_MOD_CLASS_DSSS) ||
372 {
373 state->m_dsssSupported = true;
374 }
376 {
377 state->m_erpOfdmSupported = true;
378 }
379 else if (mode.GetModulationClass() == WIFI_MOD_CLASS_OFDM)
380 {
381 state->m_ofdmSupported = true;
382 }
383 state->m_operationalRateSet.push_back(mode);
384}
385
386void
388{
389 NS_LOG_FUNCTION(this << address);
390 NS_ASSERT(!address.IsGroup());
391 auto state = LookupState(address);
392 state->m_operationalRateSet.clear();
393 for (const auto& mode : m_wifiPhy->GetModeList())
394 {
395 state->m_operationalRateSet.push_back(mode);
396 if (mode.IsMandatory())
397 {
398 AddBasicMode(mode);
399 }
400 }
401}
402
403void
405{
406 NS_LOG_FUNCTION(this << address);
407 NS_ASSERT(!address.IsGroup());
408 auto state = LookupState(address);
409
410 const auto& mcsList = m_wifiPhy->GetMcsList();
411 state->m_operationalMcsSet = WifiModeList(mcsList.begin(), mcsList.end());
412}
413
414void
416{
417 NS_LOG_FUNCTION(this << address);
418 NS_ASSERT(!address.IsGroup());
419 LookupState(address)->m_operationalMcsSet.clear();
420}
421
422void
424{
425 NS_LOG_FUNCTION(this << address << mcs);
426 NS_ASSERT(!address.IsGroup());
427 auto state = LookupState(address);
428 for (const auto& i : state->m_operationalMcsSet)
429 {
430 if (i == mcs)
431 {
432 return; // already in
433 }
434 }
435 state->m_operationalMcsSet.push_back(mcs);
436}
437
438bool
440{
441 return LookupState(address)->m_shortPreamble;
442}
443
444bool
446{
447 return LookupState(address)->m_shortSlotTime;
448}
449
450bool
452{
453 return LookupState(address)->m_qosSupported;
454}
455
456bool
458{
459 if (address.IsGroup())
460 {
461 return false;
462 }
463 return LookupState(address)->m_state == WifiRemoteStationState::BRAND_NEW;
464}
465
466bool
468{
469 if (address.IsGroup())
470 {
471 return true;
472 }
473 return LookupState(address)->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK;
474}
475
476bool
478{
479 if (address.IsGroup())
480 {
481 return false;
482 }
483 return LookupState(address)->m_state == WifiRemoteStationState::WAIT_ASSOC_TX_OK;
484}
485
486void
492
493void
499
500void
506
507void
513
514bool
516{
517 if (address.IsGroup())
518 {
519 return false;
520 }
521 return LookupState(address)->m_state == WifiRemoteStationState::ASSOC_REFUSED;
522}
523
524void
530
531uint16_t
533{
534 std::shared_ptr<WifiRemoteStationState> state;
535 if (!remoteAddress.IsGroup() &&
536 (state = LookupState(remoteAddress))->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK)
537 {
538 return state->m_aid;
539 }
540 return SU_STA_ID;
541}
542
543uint16_t
545{
546 NS_LOG_FUNCTION(this << address << txVector);
547
548 uint16_t staId = SU_STA_ID;
549
550 if (txVector.IsMu())
551 {
552 if (m_wifiMac->GetTypeOfStation() == AP)
553 {
554 staId = GetAssociationId(address);
555 }
556 else if (m_wifiMac->GetTypeOfStation() == STA)
557 {
559 if (staMac->IsAssociated())
560 {
561 staId = staMac->GetAssociationId();
562 }
563 }
564 }
565
566 NS_LOG_DEBUG("Returning STAID = " << staId);
567 return staId;
568}
569
570bool
572{
573 return LookupState(address)->m_isInPsMode;
574}
575
576void
577WifiRemoteStationManager::SetPsMode(const Mac48Address& address, bool isInPsMode)
578{
579 LookupState(address)->m_isInPsMode = isInPsMode;
580}
581
582std::optional<Mac48Address>
584{
585 if (auto stateIt = m_states.find(address);
586 stateIt != m_states.end() && stateIt->second->m_mleCommonInfo)
587 {
588 return stateIt->second->m_mleCommonInfo->m_mldMacAddress;
589 }
590
591 return std::nullopt;
592}
593
594std::optional<Mac48Address>
596{
597 auto stateIt = m_states.find(mldAddress);
598
599 if (stateIt == m_states.end() || !stateIt->second->m_mleCommonInfo)
600 {
601 // MLD address not found
602 return std::nullopt;
603 }
604
605 NS_ASSERT(stateIt->second->m_mleCommonInfo->m_mldMacAddress == mldAddress);
606 return stateIt->second->m_address;
607}
608
611{
612 NS_LOG_FUNCTION(this << header << allowedWidth);
613 const auto address = header.GetAddr1();
614 if (!header.IsMgt() && address.IsGroup())
615 {
616 return GetGroupcastTxVector(header, allowedWidth);
617 }
618 WifiTxVector txVector;
619 if (header.IsMgt())
620 {
621 // Use the lowest basic rate for management frames
622 WifiMode mgtMode;
623 if (GetNBasicModes() > 0)
624 {
625 mgtMode = GetBasicMode(0);
626 }
627 else
628 {
629 mgtMode = GetDefaultMode();
630 }
631 txVector.SetMode(mgtMode);
632 txVector.SetPreambleType(
635 auto channelWidth = allowedWidth;
636 if (!header.GetAddr1().IsGroup())
637 {
638 if (const auto rxWidth = GetChannelWidthSupported(header.GetAddr1());
639 rxWidth < channelWidth)
640 {
641 channelWidth = rxWidth;
642 }
643 }
644
645 txVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mgtMode, channelWidth));
646 txVector.SetGuardInterval(GetGuardIntervalForMode(mgtMode, m_wifiPhy->GetDevice()));
647 }
648 else
649 {
650 txVector = DoGetDataTxVector(Lookup(address), allowedWidth);
652 ? false
653 : UseLdpcForDestination(address));
654 }
655 Ptr<HeConfiguration> heConfiguration = m_wifiPhy->GetDevice()->GetHeConfiguration();
656 if (heConfiguration)
657 {
658 txVector.SetBssColor(heConfiguration->m_bssColor);
659 }
660 // If both the allowed width and the TXVECTOR channel width are integer multiple
661 // of 20 MHz, then the TXVECTOR channel width must not exceed the allowed width
662 NS_ASSERT_MSG((static_cast<uint16_t>(txVector.GetChannelWidth()) % 20 != 0) ||
663 (static_cast<uint16_t>(allowedWidth) % 20 != 0) ||
664 (txVector.GetChannelWidth() <= allowedWidth),
665 "TXVECTOR channel width (" << txVector.GetChannelWidth()
666 << " MHz) exceeds allowed width (" << allowedWidth
667 << " MHz)");
668 return txVector;
669}
670
673{
674 WifiMode defaultMode = GetDefaultMode();
675 WifiPreamble defaultPreamble;
676 if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_EHT)
677 {
678 defaultPreamble = WIFI_PREAMBLE_EHT_MU;
679 }
680 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HE)
681 {
682 defaultPreamble = WIFI_PREAMBLE_HE_SU;
683 }
684 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_VHT)
685 {
686 defaultPreamble = WIFI_PREAMBLE_VHT_SU;
687 }
688 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HT)
689 {
690 defaultPreamble = WIFI_PREAMBLE_HT_MF;
691 }
692 else
693 {
694 defaultPreamble = WIFI_PREAMBLE_LONG;
695 }
696
697 return WifiTxVector(defaultMode,
699 defaultPreamble,
700 GetGuardIntervalForMode(defaultMode, m_wifiPhy->GetDevice()),
702 1,
703 0,
704 m_wifiPhy->GetTxBandwidth(defaultMode),
705 false);
706}
707
708void
710 MHz_u allowedWidth) const
711{
712 NS_LOG_FUNCTION(this << txVector << allowedWidth);
713
714 auto modulation = txVector.GetModulationClass();
715
716 if (allowedWidth >= 40 &&
717 (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS))
718 {
719 // control frame must be sent in a non-HT duplicate PPDU because it must protect a frame
720 // being transmitted on at least 40 MHz. Change the modulation class to ERP-OFDM and the
721 // rate to 6 Mbps
723 modulation = txVector.GetModulationClass();
724 }
725 // do not set allowedWidth as the TX width if the modulation class is (HR-)DSSS (allowedWidth
726 // may be 20 MHz) or allowedWidth is 22 MHz (the selected modulation class may be OFDM)
727 if (modulation != WIFI_MOD_CLASS_DSSS && modulation != WIFI_MOD_CLASS_HR_DSSS &&
728 allowedWidth != 22)
729 {
730 txVector.SetChannelWidth(allowedWidth);
731 }
732}
733
736{
737 NS_LOG_FUNCTION(this << address << allowedWidth);
739 if (address.IsGroup())
740 {
742 v.SetMode(mode);
743 v.SetPreambleType(
745 v.SetTxPowerLevel(m_defaultTxPowerLevel);
746 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mode));
747 v.SetGuardInterval(GetGuardIntervalForMode(mode, m_wifiPhy->GetDevice()));
748 v.SetNTx(GetNumberOfAntennas());
749 v.SetNss(1);
750 v.SetNess(0);
751 }
752 else
753 {
754 v = DoGetRtsTxVector(Lookup(address));
755 }
756
757 AdjustTxVectorForCtlResponse(v, allowedWidth);
758
759 return v;
760}
761
764{
765 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
766 NS_ASSERT(!to.IsGroup() ||
767 (m_wifiMac && (m_wifiMac->GetTypeOfStation() == AP) && apMac->GetGcrManager()));
768 WifiMode ctsMode = GetControlAnswerMode(rtsTxMode);
770 v.SetMode(ctsMode);
771 v.SetPreambleType(
773 v.SetTxPowerLevel(GetDefaultTxPowerLevel());
774 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(ctsMode));
775 v.SetGuardInterval(GetGuardIntervalForMode(ctsMode, m_wifiPhy->GetDevice()));
776 v.SetNss(1);
777 return v;
778}
779
780void
782{
783 NS_LOG_FUNCTION(this << txVector);
784
785 auto txMode = txVector.GetMode();
786 if (txMode.GetModulationClass() >= WIFI_MOD_CLASS_HT)
787 {
788 auto rate = txMode.GetDataRate(txVector);
789 if (rate >= 24e6)
790 {
791 rate = 24e6;
792 }
793 else if (rate >= 12e6)
794 {
795 rate = 12e6;
796 }
797 else
798 {
799 rate = 6e6;
800 }
802 if (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
803 {
804 txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(rate));
805 }
806 else
807 {
808 txVector.SetMode(OfdmPhy::GetOfdmRate(rate));
809 }
810 }
811}
812
815{
816 NS_ASSERT(!to.IsGroup());
817 WifiMode ackMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
819 v.SetMode(ackMode);
820 v.SetPreambleType(
822 v.SetTxPowerLevel(GetDefaultTxPowerLevel());
823 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(ackMode));
824 v.SetGuardInterval(GetGuardIntervalForMode(ackMode, m_wifiPhy->GetDevice()));
825 v.SetNss(1);
826
828
829 return v;
830}
831
834 const WifiTxVector& dataTxVector) const
835{
836 NS_ASSERT(!to.IsGroup());
837 WifiMode blockAckMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
839 v.SetMode(blockAckMode);
840 v.SetPreambleType(
842 v.SetTxPowerLevel(GetDefaultTxPowerLevel());
843 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(blockAckMode));
844 v.SetGuardInterval(GetGuardIntervalForMode(blockAckMode, m_wifiPhy->GetDevice()));
845 v.SetNss(1);
846
848
849 return v;
850}
851
854{
855 /**
856 * The standard has relatively unambiguous rules for selecting a
857 * control response rate (the below is quoted from IEEE 802.11-2012,
858 * Section 9.7):
859 *
860 * To allow the transmitting STA to calculate the contents of the
861 * Duration/ID field, a STA responding to a received frame shall
862 * transmit its Control Response frame (either CTS or Ack), other
863 * than the BlockAck control frame, at the highest rate in the
864 * BSSBasicRateSet parameter that is less than or equal to the
865 * rate of the immediately previous frame in the frame exchange
866 * sequence (as defined in Annex G) and that is of the same
867 * modulation class (see Section 9.7.8) as the received frame...
868 */
869 NS_LOG_FUNCTION(this << reqMode);
870 WifiMode mode = GetDefaultMode();
871 bool found = false;
872 // First, search the BSS Basic Rate set
873 for (uint8_t i = 0; i < GetNBasicModes(); i++)
874 {
875 WifiMode testMode = GetBasicMode(i);
876 if ((!found || testMode.IsHigherDataRate(mode)) && (!testMode.IsHigherDataRate(reqMode)) &&
878 testMode.GetModulationClass())))
879 {
880 mode = testMode;
881 // We've found a potentially-suitable transmit rate, but we
882 // need to continue and consider all the basic rates before
883 // we can be sure we've got the right one.
884 found = true;
885 }
886 }
887 if (m_wifiPhy->GetDevice()->GetHtConfiguration())
888 {
889 if (!found)
890 {
891 mode = GetDefaultMcs();
892 for (uint8_t i = 0; i != GetNBasicMcs(); i++)
893 {
894 WifiMode testMode = GetBasicMcs(i);
895 if ((!found || testMode.IsHigherDataRate(mode)) &&
896 (!testMode.IsHigherDataRate(reqMode)) &&
897 (testMode.GetModulationClass() == reqMode.GetModulationClass()))
898 {
899 mode = testMode;
900 // We've found a potentially-suitable transmit rate, but we
901 // need to continue and consider all the basic rates before
902 // we can be sure we've got the right one.
903 found = true;
904 }
905 }
906 }
907 }
908 // If we found a suitable rate in the BSSBasicRateSet, then we are
909 // done and can return that mode.
910 if (found)
911 {
912 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
913 return mode;
914 }
915
916 /**
917 * If no suitable basic rate was found, we search the mandatory
918 * rates. The standard (IEEE 802.11-2007, Section 9.6) says:
919 *
920 * ...If no rate contained in the BSSBasicRateSet parameter meets
921 * these conditions, then the control frame sent in response to a
922 * received frame shall be transmitted at the highest mandatory
923 * rate of the PHY that is less than or equal to the rate of the
924 * received frame, and that is of the same modulation class as the
925 * received frame. In addition, the Control Response frame shall
926 * be sent using the same PHY options as the received frame,
927 * unless they conflict with the requirement to use the
928 * BSSBasicRateSet parameter.
929 *
930 * @todo Note that we're ignoring the last sentence for now, because
931 * there is not yet any manipulation here of PHY options.
932 */
933 for (const auto& thismode : m_wifiPhy->GetModeList())
934 {
935 /* If the rate:
936 *
937 * - is a mandatory rate for the PHY, and
938 * - is equal to or faster than our current best choice, and
939 * - is less than or equal to the rate of the received frame, and
940 * - is of the same modulation class as the received frame
941 *
942 * ...then it's our best choice so far.
943 */
944 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
945 (!thismode.IsHigherDataRate(reqMode)) &&
947 thismode.GetModulationClass())))
948 {
949 mode = thismode;
950 // As above; we've found a potentially-suitable transmit
951 // rate, but we need to continue and consider all the
952 // mandatory rates before we can be sure we've got the right one.
953 found = true;
954 }
955 }
956 if (m_wifiPhy->GetDevice()->GetHtConfiguration())
957 {
958 for (const auto& thismode : m_wifiPhy->GetMcsList())
959 {
960 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
961 (!thismode.IsHigherCodeRate(reqMode)) &&
962 (thismode.GetModulationClass() == reqMode.GetModulationClass()))
963 {
964 mode = thismode;
965 // As above; we've found a potentially-suitable transmit
966 // rate, but we need to continue and consider all the
967 // mandatory rates before we can be sure we've got the right one.
968 found = true;
969 }
970 }
971 }
972
973 /**
974 * If we still haven't found a suitable rate for the response then
975 * someone has messed up the simulation configuration. This probably means
976 * that the WifiPhyStandard is not set correctly, or that a rate that
977 * is not supported by the PHY has been explicitly requested.
978 *
979 * Either way, it is serious - we can either disobey the standard or
980 * fail, and I have chosen to do the latter...
981 */
982 if (!found)
983 {
984 NS_FATAL_ERROR("Can't find response rate for " << reqMode);
985 }
986
987 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
988 return mode;
989}
990
991void
993{
994 NS_LOG_FUNCTION(this << header);
995 const auto recipient = GetIndividuallyAddressedRecipient(m_wifiMac, header);
996 NS_ASSERT(!recipient.IsGroup());
997 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
998 m_ssrc[ac]++;
999 m_macTxRtsFailed(recipient);
1000 DoReportRtsFailed(Lookup(recipient));
1001}
1002
1003void
1005{
1006 NS_LOG_FUNCTION(this << *mpdu);
1007 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1008 AcIndex ac =
1009 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1010 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1011 if (longMpdu)
1012 {
1013 m_slrc[ac]++;
1014 }
1015 else
1016 {
1017 m_ssrc[ac]++;
1018 }
1019 m_macTxDataFailed(mpdu->GetHeader().GetAddr1());
1020 DoReportDataFailed(Lookup(mpdu->GetHeader().GetAddr1()));
1021}
1022
1023void
1025 double ctsSnr,
1026 WifiMode ctsMode,
1027 double rtsSnr)
1028{
1029 NS_LOG_FUNCTION(this << header << ctsSnr << ctsMode << rtsSnr);
1030 const auto recipient = GetIndividuallyAddressedRecipient(m_wifiMac, header);
1031 NS_ASSERT(!recipient.IsGroup());
1032 WifiRemoteStation* station = Lookup(recipient);
1033 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1034 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1035 m_ssrc[ac] = 0;
1036 DoReportRtsOk(station, ctsSnr, ctsMode, rtsSnr);
1037}
1038
1039void
1041 double ackSnr,
1042 WifiMode ackMode,
1043 double dataSnr,
1044 WifiTxVector dataTxVector)
1045{
1046 NS_LOG_FUNCTION(this << *mpdu << ackSnr << ackMode << dataSnr << dataTxVector);
1047 const WifiMacHeader& hdr = mpdu->GetHeader();
1048 NS_ASSERT(!hdr.GetAddr1().IsGroup());
1049 WifiRemoteStation* station = Lookup(hdr.GetAddr1());
1050 AcIndex ac = QosUtilsMapTidToAc((hdr.IsQosData()) ? hdr.GetQosTid() : 0);
1051 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1052 if (longMpdu)
1053 {
1054 station->m_state->m_info.NotifyTxSuccess(m_slrc[ac]);
1055 m_slrc[ac] = 0;
1056 }
1057 else
1058 {
1059 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1060 m_ssrc[ac] = 0;
1061 }
1062 DoReportDataOk(station,
1063 ackSnr,
1064 ackMode,
1065 dataSnr,
1066 dataTxVector.GetChannelWidth(),
1067 dataTxVector.GetNss(GetStaId(hdr.GetAddr1(), dataTxVector)));
1068}
1069
1070void
1072{
1073 NS_LOG_FUNCTION(this << header);
1074 NS_ASSERT(!header.GetAddr1().IsGroup());
1075 WifiRemoteStation* station = Lookup(header.GetAddr1());
1076 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1077 station->m_state->m_info.NotifyTxFailed();
1078 m_ssrc[ac] = 0;
1080 DoReportFinalRtsFailed(station);
1081}
1082
1083void
1085{
1086 NS_LOG_FUNCTION(this << *mpdu);
1087 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1088 WifiRemoteStation* station = Lookup(mpdu->GetHeader().GetAddr1());
1089 AcIndex ac =
1090 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1091 station->m_state->m_info.NotifyTxFailed();
1092 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1093 if (longMpdu)
1094 {
1095 m_slrc[ac] = 0;
1096 }
1097 else
1098 {
1099 m_ssrc[ac] = 0;
1100 }
1101 m_macTxFinalDataFailed(mpdu->GetHeader().GetAddr1());
1102 DoReportFinalDataFailed(station);
1103}
1104
1105void
1107 RxSignalInfo rxSignalInfo,
1108 const WifiTxVector& txVector)
1109{
1110 NS_LOG_FUNCTION(this << address << rxSignalInfo << txVector);
1111 if (address.IsGroup())
1112 {
1113 return;
1114 }
1115 WifiRemoteStation* station = Lookup(address);
1116 DoReportRxOk(station, rxSignalInfo.snr, txVector.GetMode(GetStaId(address, txVector)));
1117 station->m_rssiAndUpdateTimePair = std::make_pair(rxSignalInfo.rssi, Simulator::Now());
1118}
1119
1120void
1122 uint16_t nSuccessfulMpdus,
1123 uint16_t nFailedMpdus,
1124 double rxSnr,
1125 double dataSnr,
1126 WifiTxVector dataTxVector)
1127{
1128 NS_LOG_FUNCTION(this << address << nSuccessfulMpdus << nFailedMpdus << rxSnr << dataSnr
1129 << dataTxVector);
1130 NS_ASSERT(!address.IsGroup());
1131 for (uint16_t i = 0; i < nFailedMpdus; i++)
1132 {
1133 m_macTxDataFailed(address);
1134 }
1136 nSuccessfulMpdus,
1137 nFailedMpdus,
1138 rxSnr,
1139 dataSnr,
1140 dataTxVector.GetChannelWidth(),
1141 dataTxVector.GetNss(GetStaId(address, dataTxVector)));
1142}
1143
1144std::list<Ptr<WifiMpdu>>
1146{
1147 NS_LOG_FUNCTION(this << *psdu);
1148
1149 auto* station = Lookup(GetIndividuallyAddressedRecipient(m_wifiMac, psdu->GetHeader(0)));
1150
1151 DoIncrementRetryCountOnTxFailure(station, psdu);
1152 return DoGetMpdusToDropOnTxFailure(station, psdu);
1153}
1154
1155void
1157 Ptr<WifiPsdu> psdu)
1158{
1159 NS_LOG_FUNCTION(this << *psdu);
1160
1161 // The frame retry count for an MSDU or A-MSDU that is not part of a block ack agreement or
1162 // for an MMPDU shall be incremented every time transmission fails for that MSDU, A-MSDU, or
1163 // MMPDU, including of an associated RTS (Sec. 10.23.2.12.1 of 802.11-2020).
1164 // Frames for which the retry count needs to be incremented:
1165 // - management frames
1166 // - non-QoS Data frames
1167 // - QoS Data frames that are not part of a Block Ack agreement
1168 // - QoS Data frames that are part of a Block Ack agreement if the IncrementRetryCountUnderBa
1169 // attribute is set to true
1170 const auto& hdr = psdu->GetHeader(0);
1171
1172 if (hdr.IsMgt() || (hdr.IsData() && !hdr.IsQosData()) ||
1173 (hdr.IsQosData() &&
1174 (!m_wifiMac->GetBaAgreementEstablishedAsOriginator(hdr.GetAddr1(), hdr.GetQosTid()) ||
1176 {
1177 psdu->IncrementRetryCount();
1178 }
1179}
1180
1181std::list<Ptr<WifiMpdu>>
1183 Ptr<WifiPsdu> psdu)
1184{
1185 NS_LOG_FUNCTION(this << *psdu);
1186
1187 std::list<Ptr<WifiMpdu>> mpdusToDrop;
1188
1189 for (const auto& mpdu : *PeekPointer(psdu))
1190 {
1191 if (mpdu->GetRetryCount() == m_wifiMac->GetFrameRetryLimit())
1192 {
1193 // this MPDU needs to be dropped
1194 mpdusToDrop.push_back(mpdu);
1195 }
1196 }
1197
1198 return mpdusToDrop;
1199}
1200
1201bool
1203{
1204 NS_LOG_FUNCTION(this << header << &txParams);
1205 auto address = header.GetAddr1();
1206 const auto isGcr = IsGcr(m_wifiMac, header);
1207 if (!isGcr && address.IsGroup())
1208 {
1209 return false;
1210 }
1211 if (isGcr)
1212 {
1214 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
1215 apMac->GetGcrManager()->GetAttribute("GcrProtectionMode", enumValue);
1216 if (enumValue.Get() != GroupcastProtectionMode::RTS_CTS)
1217 {
1218 return false;
1219 }
1220 address = apMac->GetGcrManager()->GetIndividuallyAddressedRecipient(address);
1221 }
1222 const auto modulationClass = txParams.m_txVector.GetModulationClass();
1224 ((modulationClass == WIFI_MOD_CLASS_ERP_OFDM) || (modulationClass == WIFI_MOD_CLASS_HT) ||
1225 (modulationClass == WIFI_MOD_CLASS_VHT) || (modulationClass == WIFI_MOD_CLASS_HE) ||
1226 (modulationClass == WIFI_MOD_CLASS_EHT)) &&
1228 {
1230 "WifiRemoteStationManager::NeedRTS returning true to protect non-ERP stations");
1231 return true;
1232 }
1233 else if (m_htProtectionMode == RTS_CTS &&
1234 ((modulationClass == WIFI_MOD_CLASS_HT) || (modulationClass == WIFI_MOD_CLASS_VHT)) &&
1236 {
1237 NS_LOG_DEBUG("WifiRemoteStationManager::NeedRTS returning true to protect non-HT stations");
1238 return true;
1239 }
1240 NS_ASSERT(txParams.m_txDuration.has_value());
1241 auto size = txParams.GetSize(header.GetAddr1());
1242 bool normally =
1243 (size > m_rtsCtsThreshold) || (m_rtsCtsTxDurationThresh.IsStrictlyPositive() &&
1245 return DoNeedRts(Lookup(address), size, normally);
1246}
1247
1248bool
1250{
1251 NS_LOG_FUNCTION(this << txVector << header);
1254 (txVector.GetModulationClass() == WIFI_MOD_CLASS_HT) ||
1255 (txVector.GetModulationClass() == WIFI_MOD_CLASS_VHT) ||
1256 (txVector.GetModulationClass() == WIFI_MOD_CLASS_HE) ||
1257 (txVector.GetModulationClass() == WIFI_MOD_CLASS_EHT)))
1258 {
1260 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-ERP stations");
1261 return true;
1262 }
1263 else if (m_htProtectionMode == CTS_TO_SELF &&
1264 ((txVector.GetModulationClass() == WIFI_MOD_CLASS_HT) ||
1265 (txVector.GetModulationClass() == WIFI_MOD_CLASS_VHT)) &&
1267 {
1269 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-HT stations");
1270 return true;
1271 }
1272 else if (IsGcr(m_wifiMac, header))
1273 {
1275 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
1276 apMac->GetGcrManager()->GetAttribute("GcrProtectionMode", enumValue);
1277 if (enumValue.Get() == GroupcastProtectionMode::CTS_TO_SELF)
1278 {
1279 return true;
1280 }
1281 }
1282 // FIXME: commented out for now
1283 /*else if (!m_useNonErpProtection)
1284 {
1285 const auto mode = txVector.GetMode();
1286 // search for the BSS Basic Rate set, if the used mode is in the basic set then there is no
1287 // need for CTS To Self
1288 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
1289 {
1290 if (mode == *i)
1291 {
1292 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1293 return false;
1294 }
1295 }
1296 if (m_wifiPhy->GetDevice()->GetHtConfiguration())
1297 {
1298 // search for the BSS Basic MCS set, if the used mode is in the basic set then there is
1299 // no need for CTS To Self
1300 for (auto i = m_bssBasicMcsSet.begin(); i != m_bssBasicMcsSet.end(); i++)
1301 {
1302 if (mode == *i)
1303 {
1304 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1305 return false;
1306 }
1307 }
1308 }
1309 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning true");
1310 return true;
1311 }*/
1312 return false;
1313}
1314
1315void
1317{
1318 NS_LOG_FUNCTION(this << enable);
1319 m_useNonErpProtection = enable;
1320}
1321
1322bool
1327
1328void
1330{
1331 NS_LOG_FUNCTION(this << enable);
1332 m_useNonHtProtection = enable;
1333}
1334
1335bool
1340
1341bool
1343{
1344 NS_LOG_FUNCTION(this << *mpdu);
1345 if (mpdu->GetHeader().GetAddr1().IsGroup())
1346 {
1347 return false;
1348 }
1349 bool normally = mpdu->GetSize() > GetFragmentationThreshold();
1350 NS_LOG_DEBUG("WifiRemoteStationManager::NeedFragmentation result: " << std::boolalpha
1351 << normally);
1352 return DoNeedFragmentation(Lookup(mpdu->GetHeader().GetAddr1()), mpdu->GetPacket(), normally);
1353}
1354
1355void
1357{
1358 NS_LOG_FUNCTION(this << threshold);
1359 if (threshold < WIFI_MIN_FRAG_THRESHOLD)
1360 {
1361 NS_LOG_WARN("Fragmentation threshold should be larger than "
1362 << WIFI_MIN_FRAG_THRESHOLD << ". Setting to " << WIFI_MIN_FRAG_THRESHOLD
1363 << ".");
1365 }
1366 else
1367 {
1368 /*
1369 * The length of each fragment shall be an even number of octets, except for the last
1370 * fragment if an MSDU or MMPDU, which may be either an even or an odd number of octets.
1371 */
1372 if (threshold % 2 != 0)
1373 {
1374 NS_LOG_WARN("Fragmentation threshold should be an even number. Setting to "
1375 << threshold - 1);
1376 m_fragmentationThreshold = threshold - 1;
1377 }
1378 else
1379 {
1380 m_fragmentationThreshold = threshold;
1381 }
1382 }
1383}
1384
1390
1393{
1394 NS_LOG_FUNCTION(this << *mpdu);
1395 // The number of bytes a fragment can support is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS).
1396 uint32_t nFragments =
1397 (mpdu->GetPacket()->GetSize() /
1398 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH));
1399
1400 // If the size of the last fragment is not 0.
1401 if ((mpdu->GetPacket()->GetSize() %
1402 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH)) > 0)
1403 {
1404 nFragments++;
1405 }
1406 NS_LOG_DEBUG("WifiRemoteStationManager::GetNFragments returning " << nFragments);
1407 return nFragments;
1408}
1409
1412{
1413 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1414 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1415 uint32_t nFragment = GetNFragments(mpdu);
1416 if (fragmentNumber >= nFragment)
1417 {
1418 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning 0");
1419 return 0;
1420 }
1421 // Last fragment
1422 if (fragmentNumber == nFragment - 1)
1423 {
1424 uint32_t lastFragmentSize =
1425 mpdu->GetPacket()->GetSize() -
1426 (fragmentNumber *
1427 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH));
1428 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning " << lastFragmentSize);
1429 return lastFragmentSize;
1430 }
1431 // All fragments but the last, the number of bytes is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS).
1432 else
1433 {
1434 uint32_t fragmentSize =
1435 GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH;
1436 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning " << fragmentSize);
1437 return fragmentSize;
1438 }
1439}
1440
1443{
1444 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1445 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1446 NS_ASSERT(fragmentNumber < GetNFragments(mpdu));
1447 uint32_t fragmentOffset = fragmentNumber * (GetFragmentationThreshold() -
1448 mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH);
1449 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentOffset returning " << fragmentOffset);
1450 return fragmentOffset;
1451}
1452
1453bool
1455{
1456 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1457 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1458 bool isLast = fragmentNumber == (GetNFragments(mpdu) - 1);
1459 NS_LOG_DEBUG("WifiRemoteStationManager::IsLastFragment returning " << std::boolalpha << isLast);
1460 return isLast;
1461}
1462
1463uint8_t
1468
1471{
1472 return LookupState(address)->m_info;
1473}
1474
1475std::optional<dBm_u>
1477{
1478 auto station = Lookup(address);
1479 auto rssi = station->m_rssiAndUpdateTimePair.first;
1480 auto ts = station->m_rssiAndUpdateTimePair.second;
1481 if (ts.IsStrictlyPositive())
1482 {
1483 return rssi;
1484 }
1485 return std::nullopt;
1486}
1487
1488std::shared_ptr<WifiRemoteStationState>
1490{
1491 if (const auto stateIt = m_states.find(address); stateIt != m_states.cend())
1492 {
1493 return stateIt->second;
1494 }
1495
1496 auto state = std::make_shared<WifiRemoteStationState>();
1497 state->m_state = WifiRemoteStationState::BRAND_NEW;
1498 state->m_address = address;
1499 state->m_aid = 0;
1500 state->m_operationalRateSet.push_back(GetDefaultMode());
1501 state->m_operationalMcsSet.push_back(GetDefaultMcs());
1502 state->m_dsssSupported = false;
1503 state->m_erpOfdmSupported = false;
1504 state->m_ofdmSupported = false;
1505 state->m_htCapabilities = nullptr;
1506 state->m_htOperation = nullptr;
1507 state->m_vhtCapabilities = nullptr;
1508 state->m_vhtOperation = nullptr;
1509 state->m_heCapabilities = nullptr;
1510 state->m_heOperation = nullptr;
1511 state->m_ehtCapabilities = nullptr;
1512 state->m_ehtOperation = nullptr;
1513 state->m_mleCommonInfo = nullptr;
1514 state->m_emlsrEnabled = false;
1515 state->m_channelWidth = m_wifiPhy->GetChannelWidth();
1516 state->m_guardInterval = GetGuardInterval();
1517 state->m_ness = 0;
1518 state->m_aggregation = false;
1519 state->m_qosSupported = false;
1520 state->m_isInPsMode = false;
1521 const_cast<WifiRemoteStationManager*>(this)->m_states.insert({address, state});
1522 NS_LOG_DEBUG("WifiRemoteStationManager::LookupState returning new state");
1523 return state;
1524}
1525
1528{
1529 NS_LOG_FUNCTION(this << address);
1530 NS_ASSERT(!address.IsGroup());
1531 NS_ASSERT(address != m_wifiMac->GetAddress());
1532 auto stationIt = m_stations.find(address);
1533
1534 if (stationIt != m_stations.end())
1535 {
1536 return stationIt->second;
1537 }
1538
1540 station->m_state = LookupState(address).get();
1541 station->m_rssiAndUpdateTimePair = std::make_pair(dBm_u{0}, Seconds(0));
1542 const_cast<WifiRemoteStationManager*>(this)->m_stations.insert({address, station});
1543 return station;
1544}
1545
1546void
1548{
1549 NS_LOG_FUNCTION(this << remoteAddress << aid);
1550 LookupState(remoteAddress)->m_aid = aid;
1551}
1552
1553void
1555{
1556 NS_LOG_FUNCTION(this << from << qosSupported);
1557 LookupState(from)->m_qosSupported = qosSupported;
1558}
1559
1560void
1562{
1563 NS_LOG_FUNCTION(this << from << emlsrEnabled);
1564 LookupState(from)->m_emlsrEnabled = emlsrEnabled;
1565}
1566
1567void
1569 const HtCapabilities& htCapabilities)
1570{
1571 // Used by all stations to record HT capabilities of remote stations
1572 NS_LOG_FUNCTION(this << from << htCapabilities);
1573 auto state = LookupState(from);
1574 if (htCapabilities.GetSupportedChannelWidth() == 1)
1575 {
1576 state->m_channelWidth = MHz_u{40};
1577 }
1578 else
1579 {
1580 state->m_channelWidth = MHz_u{20};
1581 }
1582 SetQosSupport(from, true);
1583 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_HT))
1584 {
1585 if (htCapabilities.IsSupportedMcs(mcs.GetMcsValue()))
1586 {
1587 AddSupportedMcs(from, mcs);
1588 }
1589 }
1590 state->m_htCapabilities = Create<const HtCapabilities>(htCapabilities);
1591}
1592
1593void
1595{
1596 NS_LOG_FUNCTION(this << from << htOperation);
1597 auto state = LookupState(from);
1598 if (htOperation.GetStaChannelWidth() == 0)
1599 {
1600 state->m_channelWidth = MHz_u{20};
1601 }
1602 state->m_htOperation = Create<const HtOperation>(htOperation);
1603}
1604
1605void
1607 Mac48Address from,
1608 const ExtendedCapabilities& extendedCapabilities)
1609{
1610 NS_LOG_FUNCTION(this << from << extendedCapabilities);
1611 auto state = LookupState(from);
1612 state->m_extendedCapabilities = Create<const ExtendedCapabilities>(extendedCapabilities);
1613}
1614
1615void
1617 const VhtCapabilities& vhtCapabilities)
1618{
1619 // Used by all stations to record VHT capabilities of remote stations
1620 NS_LOG_FUNCTION(this << from << vhtCapabilities);
1621 auto state = LookupState(from);
1622 if (vhtCapabilities.GetSupportedChannelWidthSet() == 1)
1623 {
1624 state->m_channelWidth = MHz_u{160};
1625 }
1626 else
1627 {
1628 state->m_channelWidth = MHz_u{80};
1629 }
1630 for (uint8_t i = 1; i <= m_wifiPhy->GetMaxSupportedTxSpatialStreams(); i++)
1631 {
1632 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_VHT))
1633 {
1634 if (vhtCapabilities.IsSupportedMcs(mcs.GetMcsValue(), i))
1635 {
1636 AddSupportedMcs(from, mcs);
1637 }
1638 }
1639 }
1640 state->m_vhtCapabilities = Create<const VhtCapabilities>(vhtCapabilities);
1641}
1642
1643void
1645 const VhtOperation& vhtOperation)
1646{
1647 NS_LOG_FUNCTION(this << from << vhtOperation);
1648 auto state = LookupState(from);
1649 /*
1650 * Table 9-274 (VHT Operation Information subfields) of 802.11-2020:
1651 * Set to 0 for 20 MHz or 40 MHz BSS bandwidth.
1652 * Set to 1 for 80 MHz, 160 MHz or 80+80 MHz BSS bandwidth.
1653 */
1654 if (vhtOperation.GetChannelWidth() == 0)
1655 {
1656 state->m_channelWidth = std::min(MHz_u{40}, state->m_channelWidth);
1657 }
1658 else if (vhtOperation.GetChannelWidth() == 1)
1659 {
1660 state->m_channelWidth = std::min(MHz_u{160}, state->m_channelWidth);
1661 }
1662 state->m_vhtOperation = Create<const VhtOperation>(vhtOperation);
1663}
1664
1667{
1668 return LookupState(from)->m_vhtOperation;
1669}
1670
1671void
1673 const HeCapabilities& heCapabilities)
1674{
1675 // Used by all stations to record HE capabilities of remote stations
1676 NS_LOG_FUNCTION(this << from << heCapabilities);
1677 auto state = LookupState(from);
1678 if ((m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) ||
1679 (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_6GHZ))
1680 {
1681 if (heCapabilities.GetChannelWidthSet() & 0x04)
1682 {
1683 state->m_channelWidth = MHz_u{160};
1684 }
1685 else if (heCapabilities.GetChannelWidthSet() & 0x02)
1686 {
1687 state->m_channelWidth = MHz_u{80};
1688 }
1689 else if (heCapabilities.GetChannelWidthSet() == 0x00)
1690 {
1691 state->m_channelWidth = MHz_u{20};
1692 }
1693 // For other cases at 5 GHz, the supported channel width is set by the VHT capabilities
1694 }
1695 else if (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
1696 {
1697 if (heCapabilities.GetChannelWidthSet() & 0x01)
1698 {
1699 state->m_channelWidth = MHz_u{40};
1700 }
1701 else
1702 {
1703 state->m_channelWidth = MHz_u{20};
1704 }
1705 }
1706 if (heCapabilities.GetHeSuPpdu1xHeLtf800nsGi())
1707 {
1708 state->m_guardInterval = NanoSeconds(800);
1709 }
1710 else
1711 {
1712 // todo: Using 3200ns, default value for HeConfiguration::GuardInterval
1713 state->m_guardInterval = NanoSeconds(3200);
1714 }
1715 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_HE))
1716 {
1717 if (heCapabilities.GetHighestMcsSupported() >= mcs.GetMcsValue())
1718 {
1719 AddSupportedMcs(from, mcs);
1720 }
1721 }
1722 state->m_heCapabilities = Create<const HeCapabilities>(heCapabilities);
1723 SetQosSupport(from, true);
1724}
1725
1726void
1728{
1729 NS_LOG_FUNCTION(this << from << heOperation);
1730 auto state = LookupState(from);
1731 if (auto operation6GHz = heOperation.m_6GHzOpInfo)
1732 {
1733 switch (operation6GHz->m_chWid)
1734 {
1735 case 0:
1736 state->m_channelWidth = MHz_u{20};
1737 break;
1738 case 1:
1739 state->m_channelWidth = MHz_u{40};
1740 break;
1741 case 2:
1742 state->m_channelWidth = MHz_u{80};
1743 break;
1744 case 3:
1745 state->m_channelWidth = MHz_u{160};
1746 break;
1747 default:
1748 NS_FATAL_ERROR("Invalid channel width value in 6 GHz Operation Information field");
1749 }
1750 }
1751 state->m_heOperation = Create<const HeOperation>(heOperation);
1752}
1753
1754void
1756 const Mac48Address& from,
1757 const He6GhzBandCapabilities& he6GhzCapabilities)
1758{
1759 // Used by all stations to record HE 6GHz band capabilities of remote stations
1760 NS_LOG_FUNCTION(this << from << he6GhzCapabilities);
1761 auto state = LookupState(from);
1762 state->m_he6GhzBandCapabilities = Create<const He6GhzBandCapabilities>(he6GhzCapabilities);
1763 SetQosSupport(from, true);
1764}
1765
1766void
1768 const EhtCapabilities& ehtCapabilities)
1769{
1770 // Used by all stations to record EHT capabilities of remote stations
1771 NS_LOG_FUNCTION(this << from << ehtCapabilities);
1772 auto state = LookupState(from);
1773 if (ehtCapabilities.m_phyCapabilities.support320MhzIn6Ghz &&
1774 (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_6GHZ))
1775 {
1776 state->m_channelWidth = MHz_u{320};
1777 }
1778 // For other cases, the supported channel width is set by the HT/VHT capabilities
1779 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_EHT))
1780 {
1781 for (uint8_t mapType = 0; mapType < EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_MAX; ++mapType)
1782 {
1783 if (ehtCapabilities.GetHighestSupportedRxMcs(
1784 static_cast<EhtMcsAndNssSet::EhtMcsMapType>(mapType)) >= mcs.GetMcsValue())
1785 {
1786 AddSupportedMcs(from, mcs);
1787 }
1788 }
1789 }
1790 state->m_ehtCapabilities = Create<const EhtCapabilities>(ehtCapabilities);
1791 SetQosSupport(from, true);
1792}
1793
1794void
1796 const EhtOperation& ehtOperation)
1797{
1798 NS_LOG_FUNCTION(this << from << ehtOperation);
1799 auto state = LookupState(from);
1800 if (auto opControl = ehtOperation.m_opInfo)
1801 {
1802 switch (opControl->control.channelWidth)
1803 {
1804 case 0:
1805 state->m_channelWidth = MHz_u{20};
1806 break;
1807 case 1:
1808 state->m_channelWidth = MHz_u{40};
1809 break;
1810 case 2:
1811 state->m_channelWidth = MHz_u{80};
1812 break;
1813 case 3:
1814 state->m_channelWidth = MHz_u{160};
1815 break;
1816 case 4:
1817 state->m_channelWidth = MHz_u{320};
1818 break;
1819 default:
1820 NS_FATAL_ERROR("Invalid channel width value in EHT Operation Information field");
1821 }
1822 }
1823 state->m_ehtOperation = Create<const EhtOperation>(ehtOperation);
1824}
1825
1826void
1828 Mac48Address from,
1829 const std::shared_ptr<CommonInfoBasicMle>& mleCommonInfo)
1830{
1831 NS_LOG_FUNCTION(this << from);
1832 auto state = LookupState(from);
1833 state->m_mleCommonInfo = mleCommonInfo;
1834 // insert another entry in m_states indexed by the MLD address and pointing to the same state
1835 const_cast<WifiRemoteStationManager*>(this)->m_states.insert_or_assign(
1836 mleCommonInfo->m_mldMacAddress,
1837 state);
1838}
1839
1842{
1843 return LookupState(from)->m_htCapabilities;
1844}
1845
1848{
1849 return LookupState(from)->m_htOperation;
1850}
1851
1854{
1855 return LookupState(from)->m_extendedCapabilities;
1856}
1857
1860{
1861 return LookupState(from)->m_vhtCapabilities;
1862}
1863
1866{
1867 return LookupState(from)->m_heCapabilities;
1868}
1869
1872{
1873 return LookupState(from)->m_heOperation;
1874}
1875
1878{
1879 return LookupState(from)->m_he6GhzBandCapabilities;
1880}
1881
1884{
1885 return LookupState(from)->m_ehtCapabilities;
1886}
1887
1890{
1891 return LookupState(from)->m_ehtOperation;
1892}
1893
1894std::optional<std::reference_wrapper<CommonInfoBasicMle::EmlCapabilities>>
1896{
1897 if (auto state = LookupState(from);
1898 state->m_mleCommonInfo && state->m_mleCommonInfo->m_emlCapabilities)
1899 {
1900 return state->m_mleCommonInfo->m_emlCapabilities.value();
1901 }
1902 return std::nullopt;
1903}
1904
1905std::optional<std::reference_wrapper<CommonInfoBasicMle::MldCapabilities>>
1907{
1908 if (auto state = LookupState(from);
1909 state->m_mleCommonInfo && state->m_mleCommonInfo->m_mldCapabilities)
1910 {
1911 return state->m_mleCommonInfo->m_mldCapabilities.value();
1912 }
1913 return std::nullopt;
1914}
1915
1916bool
1918{
1919 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
1920 Ptr<const VhtCapabilities> vhtCapabilities = LookupState(address)->m_vhtCapabilities;
1921 Ptr<const HeCapabilities> heCapabilities = LookupState(address)->m_heCapabilities;
1922 bool supported = false;
1923 if (htCapabilities)
1924 {
1925 supported |= htCapabilities->GetLdpc();
1926 }
1927 if (vhtCapabilities)
1928 {
1929 supported |= vhtCapabilities->GetRxLdpc();
1930 }
1931 if (heCapabilities)
1932 {
1933 supported |= heCapabilities->GetLdpcCodingInPayload();
1934 }
1935 return supported;
1936}
1937
1940{
1942 auto defaultTxMode = m_wifiPhy->GetDefaultMode();
1943 NS_ASSERT(defaultTxMode.IsMandatory());
1944 return defaultTxMode;
1945}
1946
1952
1955{
1956 NS_LOG_FUNCTION(this << st);
1957
1958 if ((!m_wifiPhy->GetDevice()->GetHtConfiguration()) ||
1960 {
1961 return GetDefaultMode();
1962 }
1963
1964 // find the highest modulation class supported by both stations
1966 if (GetHeSupported() && GetHeSupported(st))
1967 {
1968 modClass = WIFI_MOD_CLASS_HE;
1969 }
1970 else if (GetVhtSupported() && GetVhtSupported(st))
1971 {
1972 modClass = WIFI_MOD_CLASS_VHT;
1973 }
1974
1975 // return the MCS with lowest index
1976 return *m_wifiPhy->GetPhyEntity(modClass)->begin();
1977}
1978
1979void
1981{
1982 NS_LOG_FUNCTION(this);
1983 m_states.clear();
1984 for (auto& state : m_stations)
1985 {
1986 delete (state.second);
1987 }
1988 m_stations.clear();
1989 m_bssBasicRateSet.clear();
1990 m_bssBasicMcsSet.clear();
1991 m_ssrc.fill(0);
1992 m_slrc.fill(0);
1993}
1994
1995void
1997{
1998 NS_LOG_FUNCTION(this << mode);
2000 {
2001 NS_FATAL_ERROR("It is not allowed to add a HT rate in the BSSBasicRateSet!");
2002 }
2003 for (uint8_t i = 0; i < GetNBasicModes(); i++)
2004 {
2005 if (GetBasicMode(i) == mode)
2006 {
2007 return;
2008 }
2009 }
2010 m_bssBasicRateSet.push_back(mode);
2011}
2012
2013uint8_t
2015{
2016 return static_cast<uint8_t>(m_bssBasicRateSet.size());
2017}
2018
2021{
2023 return m_bssBasicRateSet[i];
2024}
2025
2028{
2029 uint32_t size = 0;
2030 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
2031 {
2032 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
2033 {
2034 continue;
2035 }
2036 size++;
2037 }
2038 return size;
2039}
2040
2043{
2045 uint32_t index = 0;
2046 bool found = false;
2047 for (auto j = m_bssBasicRateSet.begin(); j != m_bssBasicRateSet.end();)
2048 {
2049 if (i == index)
2050 {
2051 found = true;
2052 }
2053 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
2054 {
2055 if (found)
2056 {
2057 break;
2058 }
2059 }
2060 index++;
2061 j++;
2062 }
2063 return m_bssBasicRateSet[index];
2064}
2065
2066void
2068{
2069 NS_LOG_FUNCTION(this << +mcs.GetMcsValue());
2070 for (uint8_t i = 0; i < GetNBasicMcs(); i++)
2071 {
2072 if (GetBasicMcs(i) == mcs)
2073 {
2074 return;
2075 }
2076 }
2077 m_bssBasicMcsSet.push_back(mcs);
2078}
2079
2080uint8_t
2082{
2083 return static_cast<uint8_t>(m_bssBasicMcsSet.size());
2084}
2085
2088{
2089 NS_ASSERT(i < GetNBasicMcs());
2090 return m_bssBasicMcsSet[i];
2091}
2092
2095{
2096 if (m_nonUnicastMode == WifiMode())
2097 {
2098 if (GetNBasicModes() > 0)
2099 {
2100 return GetBasicMode(0);
2101 }
2102 else
2103 {
2104 return GetDefaultMode();
2105 }
2106 }
2107 else
2108 {
2109 return m_nonUnicastMode;
2110 }
2111}
2112
2115{
2116 const auto& to = header.GetAddr1();
2117 NS_ASSERT(to.IsGroup());
2118
2119 WifiTxVector groupcastTxVector{};
2120 const auto mode = GetNonUnicastMode();
2121 groupcastTxVector.SetMode(mode);
2122 groupcastTxVector.SetPreambleType(
2123 GetPreambleForTransmission(mode.GetModulationClass(), GetShortPreambleEnabled()));
2124 groupcastTxVector.SetTxPowerLevel(m_defaultTxPowerLevel);
2125 groupcastTxVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mode, allowedWidth));
2126 groupcastTxVector.SetNTx(GetNumberOfAntennas());
2127
2128 if (to.IsBroadcast())
2129 {
2130 return groupcastTxVector;
2131 }
2132
2133 auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
2134 if (!apMac)
2135 {
2136 return groupcastTxVector;
2137 }
2138
2139 auto gcrManager = apMac->GetGcrManager();
2140 if (!gcrManager)
2141 {
2142 return groupcastTxVector;
2143 }
2144
2145 const auto& groupStas = gcrManager->GetMemberStasForGroupAddress(to);
2146 if (groupStas.empty())
2147 {
2148 return groupcastTxVector;
2149 }
2150
2151 if (!gcrManager->UseConcealment(header))
2152 {
2153 return groupcastTxVector;
2154 }
2155
2156 // If we are here, that means the mode will be used for the transmission of a groupcast frame
2157 // using the GCR service. We should loop over each member STA that is going to receive the
2158 // groupcast frame and select the highest possible mode over all STAs.
2159 std::optional<WifiMode> groupcastMode;
2160 auto maxWidth = allowedWidth;
2161 auto maxNss = m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2162 std::map<WifiModulationClass, Time> minGisPerMc{/* non-HT OFDM is always 800 ns */
2165 const std::map<WifiModulationClass, WifiModulationClass> giRefModClass{
2166 /* HT/VHT: short or long GI */
2169 /* HE/EHT: 3 possible GIs */
2172 for (const auto& staAddress : groupStas)
2173 {
2174 // Get the equivalent TXVECTOR if the frame would be a unicast frame to that STA in order to
2175 // get what rate would be selected for that STA.
2177 hdr.SetAddr1(staAddress);
2178 const auto unicastTxVector = GetDataTxVector(hdr, allowedWidth);
2179
2180 // update the groupcast mode if:
2181 // - this is the first mode to inspect;
2182 // - this mode has a lower modulation class than the currently selected groupcast mode;
2183 // - when the modulation class is similar, this mode has a lower MCS than the currently
2184 // selected groupcast mode.
2185 if (!groupcastMode.has_value() ||
2186 (unicastTxVector.GetModulationClass() < groupcastMode->GetModulationClass()) ||
2187 ((unicastTxVector.GetModulationClass() == groupcastMode->GetModulationClass()) &&
2188 (unicastTxVector.GetMode().GetMcsValue() < groupcastMode->GetMcsValue())))
2189 {
2190 groupcastMode = unicastTxVector.GetMode();
2191 }
2192 maxWidth = std::min(unicastTxVector.GetChannelWidth(), maxWidth);
2193 maxNss = std::min(unicastTxVector.GetNss(), maxNss);
2194 auto mc = unicastTxVector.GetModulationClass();
2195 if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
2196 {
2197 mc = it->second;
2198 }
2199 if (auto it = minGisPerMc.find(mc); it != minGisPerMc.end())
2200 {
2201 it->second = std::max(unicastTxVector.GetGuardInterval(), it->second);
2202 }
2203 }
2204 NS_ASSERT(groupcastMode.has_value());
2205
2206 groupcastTxVector.SetMode(*groupcastMode);
2207 groupcastTxVector.SetPreambleType(
2208 GetPreambleForTransmission(groupcastMode->GetModulationClass(), GetShortPreambleEnabled()));
2209 groupcastTxVector.SetChannelWidth(maxWidth);
2210 groupcastTxVector.SetNss(maxNss);
2211 auto mc = groupcastMode->GetModulationClass();
2212 if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
2213 {
2214 mc = it->second;
2215 }
2216 if (const auto it = minGisPerMc.find(mc); it != minGisPerMc.cend())
2217 {
2218 groupcastTxVector.SetGuardInterval(it->second);
2219 }
2220
2221 return groupcastTxVector;
2222}
2223
2224bool
2226{
2227 return normally;
2228}
2229
2230bool
2232 Ptr<const Packet> packet,
2233 bool normally)
2234{
2235 return normally;
2236}
2237
2238void
2240 uint16_t nSuccessfulMpdus,
2241 uint16_t nFailedMpdus,
2242 double rxSnr,
2243 double dataSnr,
2244 MHz_u dataChannelWidth,
2245 uint8_t dataNss)
2246{
2247 NS_LOG_DEBUG("DoReportAmpduTxStatus received but the manager does not handle A-MPDUs!");
2248}
2249
2252{
2253 NS_ASSERT(i < GetNSupported(station));
2254 return station->m_state->m_operationalRateSet[i];
2255}
2256
2259{
2260 NS_ASSERT(i < GetNMcsSupported(station));
2261 return station->m_state->m_operationalMcsSet[i];
2262}
2263
2266{
2267 NS_ASSERT(i < GetNNonErpSupported(station));
2268 // IEEE 802.11g standard defines that if the protection mechanism is enabled, RTS, CTS and
2269 // CTS-To-Self frames should select a rate in the BSSBasicRateSet that corresponds to an 802.11b
2270 // basic rate. This is a implemented here to avoid changes in every RAA, but should maybe be
2271 // moved in case it breaks standard rules.
2272 uint32_t index = 0;
2273 bool found = false;
2274 for (auto j = station->m_state->m_operationalRateSet.begin();
2275 j != station->m_state->m_operationalRateSet.end();)
2276 {
2277 if (i == index)
2278 {
2279 found = true;
2280 }
2281 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
2282 {
2283 if (found)
2284 {
2285 break;
2286 }
2287 }
2288 index++;
2289 j++;
2290 }
2291 return station->m_state->m_operationalRateSet[index];
2292}
2293
2296{
2297 return station->m_state->m_address;
2298}
2299
2300MHz_u
2302{
2303 return station->m_state->m_channelWidth;
2304}
2305
2306bool
2308{
2309 Ptr<const HtCapabilities> htCapabilities = station->m_state->m_htCapabilities;
2310
2311 if (!htCapabilities)
2312 {
2313 return false;
2314 }
2315 return htCapabilities->GetShortGuardInterval20();
2316}
2317
2318Time
2320{
2321 return station->m_state->m_guardInterval;
2322}
2323
2324bool
2326{
2327 return station->m_state->m_aggregation;
2328}
2329
2330uint8_t
2332{
2333 const auto htCapabilities = station->m_state->m_htCapabilities;
2334
2335 if (!htCapabilities)
2336 {
2337 if (const auto heCapabilities = station->m_state->m_heCapabilities)
2338 {
2339 return heCapabilities->GetHighestNssSupported();
2340 }
2341 return 1;
2342 }
2343 return htCapabilities->GetRxHighestSupportedAntennas();
2344}
2345
2346uint8_t
2348{
2349 return station->m_state->m_ness;
2350}
2351
2354{
2355 return m_wifiPhy;
2356}
2357
2360{
2361 return m_wifiMac;
2362}
2363
2364uint8_t
2366{
2367 return static_cast<uint8_t>(station->m_state->m_operationalRateSet.size());
2368}
2369
2370bool
2372{
2373 return station->m_state->m_qosSupported;
2374}
2375
2376bool
2378{
2379 return bool(station->m_state->m_htCapabilities);
2380}
2381
2382bool
2384{
2385 return bool(station->m_state->m_vhtCapabilities);
2386}
2387
2388bool
2390{
2391 return bool(station->m_state->m_heCapabilities);
2392}
2393
2394bool
2396{
2397 return (bool)(station->m_state->m_ehtCapabilities);
2398}
2399
2400bool
2402{
2403 auto mleCommonInfo = station->m_state->m_mleCommonInfo;
2404 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2405 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2406}
2407
2408bool
2410{
2411 return station->m_state->m_emlsrEnabled;
2412}
2413
2414uint8_t
2416{
2417 return static_cast<uint8_t>(station->m_state->m_operationalMcsSet.size());
2418}
2419
2422{
2423 uint32_t size = 0;
2424 for (auto i = station->m_state->m_operationalRateSet.begin();
2425 i != station->m_state->m_operationalRateSet.end();
2426 i++)
2427 {
2428 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
2429 {
2430 continue;
2431 }
2432 size++;
2433 }
2434 return size;
2435}
2436
2437MHz_u
2439{
2440 return LookupState(address)->m_channelWidth;
2441}
2442
2443bool
2445{
2446 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2447
2448 if (!htCapabilities)
2449 {
2450 return false;
2451 }
2452 return htCapabilities->GetShortGuardInterval20();
2453}
2454
2455uint8_t
2457{
2458 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2459
2460 if (!htCapabilities)
2461 {
2462 return 1;
2463 }
2464 return htCapabilities->GetRxHighestSupportedAntennas();
2465}
2466
2467uint8_t
2469{
2470 return static_cast<uint8_t>(LookupState(address)->m_operationalMcsSet.size());
2471}
2472
2473bool
2475{
2476 return (LookupState(address)->m_dsssSupported);
2477}
2478
2479bool
2481{
2482 return (LookupState(address)->m_erpOfdmSupported);
2483}
2484
2485bool
2487{
2488 return (LookupState(address)->m_ofdmSupported);
2489}
2490
2491bool
2493{
2494 return bool(LookupState(address)->m_htCapabilities);
2495}
2496
2497bool
2499{
2500 return bool(LookupState(address)->m_vhtCapabilities);
2501}
2502
2503bool
2505{
2506 return bool(LookupState(address)->m_heCapabilities);
2507}
2508
2509bool
2511{
2512 return (bool)(LookupState(address)->m_ehtCapabilities);
2513}
2514
2515bool
2517{
2518 auto mleCommonInfo = LookupState(address)->m_mleCommonInfo;
2519 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2520 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2521}
2522
2523bool
2525{
2526 if (auto stateIt = m_states.find(address); stateIt != m_states.cend())
2527 {
2528 return stateIt->second->m_emlsrEnabled;
2529 }
2530 return false;
2531}
2532
2533void
2538
2539uint8_t
2541{
2542 return m_wifiPhy->GetNumberOfAntennas();
2543}
2544
2545uint8_t
2547{
2548 return m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2549}
2550
2551bool
2556
2557} // namespace ns3
uint32_t v
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.
static WifiMode GetHtMcs0()
Return MCS 0 from HT MCS values.
an EUI-48 address
bool IsGroup() const
Object()
Constructor.
Definition object.cc:96
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.
Definition ptr.h:67
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
AttributeValue implementation for Time.
Definition nstime.h:1456
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.
Definition type-id.h:66
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
uint8_t GetMcsValue() const
Definition wifi-mode.cc:151
AttributeValue implementation for WifiMode.
Definition wifi-mode.h:244
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.
void AddStationHeOperation(Mac48Address from, const HeOperation &heOperation)
Records HE operation of the remote station.
bool GetQosSupported(Mac48Address address) const
Return whether the given station is QoS capable.
virtual WifiTxVector DoGetDataTxVector(WifiRemoteStation *station, MHz_u allowedWidth)=0
uint8_t GetNumberOfSupportedStreams(Mac48Address address) const
Return the number of spatial streams supported by the station.
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.
uint8_t GetNess(const WifiRemoteStation *station) const
void AddBasicMode(WifiMode mode)
Invoked in a STA upon association to store the set of rates which belong to the BSSBasicRateSet of th...
bool GetEmlsrEnabled(const Mac48Address &address) const
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Ptr< const HeOperation > GetStationHeOperation(Mac48Address from)
Return the HE operation sent by the remote station.
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.
WifiMode GetDefaultModeForSta(const WifiRemoteStation *st) const
Return the default MCS to use to transmit frames to the given station.
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.
void AddStationHtOperation(Mac48Address from, const HtOperation &htOperation)
Records HT operation of the remote station.
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 AddStationHeCapabilities(Mac48Address from, const HeCapabilities &heCapabilities)
Records HE capabilities of the remote station.
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.
void AddStationMleCommonInfo(Mac48Address from, const std::shared_ptr< CommonInfoBasicMle > &mleCommonInfo)
Records the Common Info field advertised by the given remote station in a Multi-Link Element.
virtual void DoReportDataFailed(WifiRemoteStation *station)=0
This method is a pure virtual method that must be implemented by the sub-class.
Ptr< const VhtOperation > GetStationVhtOperation(Mac48Address from)
Return the VHT operation sent by the remote station.
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.
uint32_t GetNNonErpBasicModes() const
Return the number of non-ERP basic modes we support.
void SetUseNonErpProtection(bool enable)
Enable or disable protection for non-ERP stations.
uint8_t GetNSupported(const WifiRemoteStation *station) const
Return the number of modes supported by the given station.
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.
Ptr< const EhtOperation > GetStationEhtOperation(Mac48Address from)
Return the EHT operation sent by the remote station.
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...
WifiMode GetNonErpBasicMode(uint8_t i) const
Return a basic mode from the set of basic modes that is not an ERP mode.
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.
Ptr< WifiPhy > GetPhy() const
Return the WifiPhy.
void AddSupportedMcs(Mac48Address address, WifiMode mcs)
Record the MCS index supported by the station.
std::optional< std::reference_wrapper< CommonInfoBasicMle::EmlCapabilities > > GetStationEmlCapabilities(const Mac48Address &from)
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.
MHz_u GetChannelWidth(const WifiRemoteStation *station) const
Return the channel width supported by the station.
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...
void AddBasicMcs(WifiMode mcs)
Add a given Modulation and Coding Scheme (MCS) index to the set of basic MCS.
uint8_t m_defaultTxPowerLevel
Default transmission power level.
bool GetErpOfdmSupported(const Mac48Address &address) const
Return whether the station supports ERP OFDM or not.
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.
Ptr< const HtCapabilities > GetStationHtCapabilities(Mac48Address from)
Return the HT capabilities sent by the remote station.
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...
Ptr< const He6GhzBandCapabilities > GetStationHe6GhzCapabilities(const Mac48Address &from) const
Return the HE 6 GHz Band Capabilities sent by a remote station.
bool GetDsssSupported(const Mac48Address &address) const
Return whether the station supports DSSS or not.
uint32_t GetFragmentOffset(Ptr< const WifiMpdu > mpdu, uint32_t fragmentNumber)
void SetQosSupport(Mac48Address from, bool qosSupported)
Records QoS support of the remote station.
void AddStationHe6GhzCapabilities(const Mac48Address &from, const He6GhzBandCapabilities &he6GhzCapabilities)
Records HE 6 GHz Band Capabilities of a remote station.
WifiRemoteStationInfo GetInfo(Mac48Address address)
bool GetOfdmSupported(const Mac48Address &address) const
Return whether the station supports OFDM or not.
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 GetAggregation(const WifiRemoteStation *station) const
Return whether the given station supports A-MPDU.
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.
void AddStationVhtCapabilities(Mac48Address from, const VhtCapabilities &vhtCapabilities)
Records VHT capabilities of the remote station.
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.
Ptr< WifiMac > GetMac() const
Return the WifiMac.
bool m_incrRetryCountUnderBa
whether to increment the retry count of frames that are part of a Block Ack agreement
WifiMode GetNonErpSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether non-ERP mode associated with the specified station at the specified index.
std::array< uint32_t, AC_BE_NQOS > m_ssrc
short retry count per AC
void AddStationEhtCapabilities(Mac48Address from, const EhtCapabilities &ehtCapabilities)
Records EHT capabilities of the remote station.
Ptr< const EhtCapabilities > GetStationEhtCapabilities(Mac48Address from)
Return the EHT capabilities sent by the remote station.
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).
Ptr< const HeCapabilities > GetStationHeCapabilities(Mac48Address from)
Return the HE capabilities sent by the remote station.
WifiMode GetBasicMcs(uint8_t i) const
Return the MCS at the given list index.
uint8_t GetNMcsSupported(Mac48Address address) const
Return the number of MCS supported by the station.
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 GetEmlsrSupported(const Mac48Address &address) const
Ptr< const ExtendedCapabilities > GetStationExtendedCapabilities(const Mac48Address &from)
Return the extended capabilities sent by the remote station.
bool GetShortGuardIntervalSupported() const
Return whether the device has SGI support enabled.
Mac48Address GetAddress(const WifiRemoteStation *station) const
Return the address of the station.
Ptr< const HtOperation > GetStationHtOperation(Mac48Address from)
Return the HT operation sent by the remote station.
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 SetDefaultTxPowerLevel(uint8_t txPower)
Set the default transmission power level.
void RecordDisassociated(Mac48Address address)
Records that the STA was disassociated.
Stations m_stations
Information for each known stations.
virtual WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station)=0
WifiMode GetMcsSupported(const WifiRemoteStation *station, uint8_t i) const
Return the WifiMode supported by the specified station at the specified index.
std::optional< std::reference_wrapper< CommonInfoBasicMle::MldCapabilities > > GetStationMldCapabilities(const Mac48Address &from)
uint32_t GetNNonErpSupported(const WifiRemoteStation *station) const
Return the number of non-ERP modes supported by the given station.
uint32_t m_maxSlrc
Maximum STA long retry count (SLRC).
virtual WifiRemoteStation * DoCreateStation() const =0
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.
void SetAssociationId(Mac48Address remoteAddress, uint16_t aid)
Record the AID of a remote station.
bool GetVhtSupported() const
Return whether the device has VHT capability support enabled on the link this manager is associated w...
Ptr< const VhtCapabilities > GetStationVhtCapabilities(Mac48Address from)
Return the VHT capabilities sent by the remote station.
void AddStationHtCapabilities(Mac48Address from, const HtCapabilities &htCapabilities)
Records HT capabilities of the remote station.
ProtectionMode m_erpProtectionMode
Protection mode for ERP stations when non-ERP stations are detected.
WifiModeList m_bssBasicRateSet
This member is the list of WifiMode objects that comprise the BSSBasicRateSet parameter.
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
WifiMode GetSupported(const WifiRemoteStation *station, uint8_t i) const
Return whether mode associated with the specified station at the specified index.
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 SetEmlsrEnabled(const Mac48Address &from, bool emlsrEnabled)
void AddStationExtendedCapabilities(Mac48Address from, const ExtendedCapabilities &extendedCapabilities)
Records extended capabilities of the remote station.
void AddStationVhtOperation(Mac48Address from, const VhtOperation &vhtOperation)
Records VHT operation of the remote station.
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.
void AddStationEhtOperation(Mac48Address from, const EhtOperation &ehtOperation)
Records EHT operation of the remote station.
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 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:114
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:1457
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1477
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
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:439
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1405
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
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:63
@ 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:448
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.
static constexpr uint8_t WIFI_MIN_TX_PWR_LEVEL
minimum TX power level value
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:585
static constexpr uint32_t WIFI_MIN_RTS_THRESHOLD
The minimum value for dot11RTSThreshold (C.3 MIB detail in IEEE Std 802.11-2020).
double dBm_u
dBm weak type
Definition wifi-units.h:27
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:592
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
uint32_t GetSize(Ptr< const Packet > packet, const WifiMacHeader *hdr, bool isAmpdu)
Return the total size of the packet after WifiMacHeader and FCS trailer have been added.
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:84
double snr
SNR in linear scale.
Definition wifi-types.h:85
dBm_u rssi
RSSI.
Definition wifi-types.h:86
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