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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19
21
22#include "ap-wifi-mac.h"
23#include "sta-wifi-mac.h"
24#include "wifi-mac-header.h"
25#include "wifi-mac-trailer.h"
26#include "wifi-mpdu.h"
27#include "wifi-net-device.h"
28#include "wifi-phy.h"
29
30#include "ns3/boolean.h"
31#include "ns3/eht-configuration.h"
32#include "ns3/enum.h"
33#include "ns3/erp-ofdm-phy.h"
34#include "ns3/he-configuration.h"
35#include "ns3/ht-configuration.h"
36#include "ns3/ht-phy.h"
37#include "ns3/log.h"
38#include "ns3/simulator.h"
39#include "ns3/uinteger.h"
40#include "ns3/vht-configuration.h"
41
42namespace ns3
43{
44
45NS_LOG_COMPONENT_DEFINE("WifiRemoteStationManager");
46
47NS_OBJECT_ENSURE_REGISTERED(WifiRemoteStationManager);
48
49TypeId
51{
52 static TypeId tid =
53 TypeId("ns3::WifiRemoteStationManager")
55 .SetGroupName("Wifi")
56 .AddAttribute("MaxSsrc",
57 "The maximum number of retransmission attempts for any packet with size "
58 "<= RtsCtsThreshold. "
59 "This value will not have any effect on some rate control algorithms.",
62 MakeUintegerChecker<uint32_t>())
63 .AddAttribute("MaxSlrc",
64 "The maximum number of retransmission attempts for any packet with size "
65 "> RtsCtsThreshold. "
66 "This value will not have any effect on some rate control algorithms.",
69 MakeUintegerChecker<uint32_t>())
70 .AddAttribute("RtsCtsThreshold",
71 "If the size of the PSDU is bigger than this value, we use an RTS/CTS "
72 "handshake before sending the data frame."
73 "This value will not have any effect on some rate control algorithms.",
74 UintegerValue(4692480),
76 MakeUintegerChecker<uint32_t>(0, 4692480))
77 .AddAttribute(
78 "FragmentationThreshold",
79 "If the size of the PSDU is bigger than this value, we fragment it such that the "
80 "size of the fragments are equal or smaller. "
81 "This value does not apply when it is carried in an A-MPDU. "
82 "This value will not have any effect on some rate control algorithms.",
83 UintegerValue(65535),
86 MakeUintegerChecker<uint32_t>())
87 .AddAttribute("NonUnicastMode",
88 "Wifi mode used for non-unicast transmissions.",
92 .AddAttribute("DefaultTxPowerLevel",
93 "Default power level to be used for transmissions. "
94 "This is the power level that is used by all those WifiManagers that do "
95 "not implement TX power control.",
98 MakeUintegerChecker<uint8_t>())
99 .AddAttribute("ErpProtectionMode",
100 "Protection mode used when non-ERP STAs are connected to an ERP AP: "
101 "Rts-Cts or Cts-To-Self",
103 MakeEnumAccessor<WifiRemoteStationManager::ProtectionMode>(
106 "Rts-Cts",
108 "Cts-To-Self"))
109 .AddAttribute("HtProtectionMode",
110 "Protection mode used when non-HT STAs are connected to a HT AP: Rts-Cts "
111 "or Cts-To-Self",
113 MakeEnumAccessor<WifiRemoteStationManager::ProtectionMode>(
116 "Rts-Cts",
118 "Cts-To-Self"))
119 .AddTraceSource("MacTxRtsFailed",
120 "The transmission of a RTS by the MAC layer has failed",
122 "ns3::Mac48Address::TracedCallback")
123 .AddTraceSource("MacTxDataFailed",
124 "The transmission of a data packet by the MAC layer has failed",
126 "ns3::Mac48Address::TracedCallback")
127 .AddTraceSource(
128 "MacTxFinalRtsFailed",
129 "The transmission of a RTS has exceeded the maximum number of attempts",
131 "ns3::Mac48Address::TracedCallback")
132 .AddTraceSource(
133 "MacTxFinalDataFailed",
134 "The transmission of a data packet has exceeded the maximum number of attempts",
136 "ns3::Mac48Address::TracedCallback");
137 return tid;
138}
139
141 : m_useNonErpProtection(false),
142 m_useNonHtProtection(false),
143 m_shortPreambleEnabled(false),
144 m_shortSlotTimeEnabled(false)
145{
146 NS_LOG_FUNCTION(this);
147 m_ssrc.fill(0);
148 m_slrc.fill(0);
149}
150
152{
153 NS_LOG_FUNCTION(this);
154}
155
156void
158{
159 NS_LOG_FUNCTION(this);
160 Reset();
161}
162
163void
165{
166 NS_LOG_FUNCTION(this << phy);
167 // We need to track our PHY because it is the object that knows the
168 // full set of transmit rates that are supported. We need to know
169 // this in order to find the relevant mandatory rates when choosing a
170 // transmit rate for automatic control responses like
171 // acknowledgments.
172 m_wifiPhy = phy;
173}
174
175void
177{
178 NS_LOG_FUNCTION(this << mac);
179 // We need to track our MAC because it is the object that knows the
180 // full set of interframe spaces.
181 m_wifiMac = mac;
182}
183
184int64_t
186{
187 NS_LOG_FUNCTION(this << stream);
188 return 0;
189}
190
191void
193{
194 NS_LOG_FUNCTION(this << maxSsrc);
195 m_maxSsrc = maxSsrc;
196}
197
198void
200{
201 NS_LOG_FUNCTION(this << maxSlrc);
202 m_maxSlrc = maxSlrc;
203}
204
205void
207{
208 NS_LOG_FUNCTION(this << threshold);
209 m_rtsCtsThreshold = threshold;
210}
211
212void
214{
215 NS_LOG_FUNCTION(this << threshold);
217}
218
219void
221{
222 NS_LOG_FUNCTION(this << enable);
223 m_shortPreambleEnabled = enable;
224}
225
226void
228{
229 NS_LOG_FUNCTION(this << enable);
230 m_shortSlotTimeEnabled = enable;
231}
232
233bool
235{
237}
238
239bool
241{
243}
244
245bool
247{
248 return bool(m_wifiPhy->GetDevice()->GetHtConfiguration());
249}
250
251bool
253{
256}
257
258bool
260{
261 return bool(m_wifiPhy->GetDevice()->GetHeConfiguration());
262}
263
264bool
266{
267 return bool(m_wifiPhy->GetDevice()->GetEhtConfiguration());
268}
269
270bool
272{
273 if (GetHtSupported())
274 {
276 NS_ASSERT(htConfiguration); // If HT is supported, we should have a HT configuration
277 // attached
278 return htConfiguration->GetLdpcSupported();
279 }
280 return false;
281}
282
283bool
285{
286 if (GetHtSupported())
287 {
289 NS_ASSERT(htConfiguration); // If HT is supported, we should have a HT configuration
290 // attached
291 if (htConfiguration->GetShortGuardIntervalSupported())
292 {
293 return true;
294 }
295 }
296 return false;
297}
298
299uint16_t
301{
302 uint16_t gi = 0;
303 if (GetHeSupported())
304 {
306 NS_ASSERT(heConfiguration); // If HE is supported, we should have a HE configuration
307 // attached
308 gi = static_cast<uint16_t>(heConfiguration->GetGuardInterval().GetNanoSeconds());
309 }
310 return gi;
311}
312
315{
317}
318
319void
321 bool isShortPreambleSupported)
322{
323 NS_LOG_FUNCTION(this << address << isShortPreambleSupported);
324 NS_ASSERT(!address.IsGroup());
325 LookupState(address)->m_shortPreamble = isShortPreambleSupported;
326}
327
328void
330 bool isShortSlotTimeSupported)
331{
332 NS_LOG_FUNCTION(this << address << isShortSlotTimeSupported);
333 NS_ASSERT(!address.IsGroup());
334 LookupState(address)->m_shortSlotTime = isShortSlotTimeSupported;
335}
336
337void
339{
340 NS_LOG_FUNCTION(this << address << mode);
341 NS_ASSERT(!address.IsGroup());
342 auto state = LookupState(address);
343 for (const auto& i : state->m_operationalRateSet)
344 {
345 if (i == mode)
346 {
347 return; // already in
348 }
349 }
350 if ((mode.GetModulationClass() == WIFI_MOD_CLASS_DSSS) ||
352 {
353 state->m_dsssSupported = true;
354 }
356 {
357 state->m_erpOfdmSupported = true;
358 }
359 else if (mode.GetModulationClass() == WIFI_MOD_CLASS_OFDM)
360 {
361 state->m_ofdmSupported = true;
362 }
363 state->m_operationalRateSet.push_back(mode);
364}
365
366void
368{
369 NS_LOG_FUNCTION(this << address);
370 NS_ASSERT(!address.IsGroup());
371 auto state = LookupState(address);
372 state->m_operationalRateSet.clear();
373 for (const auto& mode : m_wifiPhy->GetModeList())
374 {
375 state->m_operationalRateSet.push_back(mode);
376 if (mode.IsMandatory())
377 {
378 AddBasicMode(mode);
379 }
380 }
381}
382
383void
385{
386 NS_LOG_FUNCTION(this << address);
387 NS_ASSERT(!address.IsGroup());
388 auto state = LookupState(address);
389
390 const auto& mcsList = m_wifiPhy->GetMcsList();
391 state->m_operationalMcsSet = WifiModeList(mcsList.begin(), mcsList.end());
392}
393
394void
396{
397 NS_LOG_FUNCTION(this << address);
398 NS_ASSERT(!address.IsGroup());
399 LookupState(address)->m_operationalMcsSet.clear();
400}
401
402void
404{
405 NS_LOG_FUNCTION(this << address << mcs);
406 NS_ASSERT(!address.IsGroup());
407 auto state = LookupState(address);
408 for (const auto& i : state->m_operationalMcsSet)
409 {
410 if (i == mcs)
411 {
412 return; // already in
413 }
414 }
415 state->m_operationalMcsSet.push_back(mcs);
416}
417
418bool
420{
421 return LookupState(address)->m_shortPreamble;
422}
423
424bool
426{
427 return LookupState(address)->m_shortSlotTime;
428}
429
430bool
432{
433 return LookupState(address)->m_qosSupported;
434}
435
436bool
438{
439 if (address.IsGroup())
440 {
441 return false;
442 }
443 return LookupState(address)->m_state == WifiRemoteStationState::BRAND_NEW;
444}
445
446bool
448{
449 if (address.IsGroup())
450 {
451 return true;
452 }
453 return LookupState(address)->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK;
454}
455
456bool
458{
459 if (address.IsGroup())
460 {
461 return false;
462 }
463 return LookupState(address)->m_state == WifiRemoteStationState::WAIT_ASSOC_TX_OK;
464}
465
466void
468{
469 NS_ASSERT(!address.IsGroup());
471}
472
473void
475{
476 NS_ASSERT(!address.IsGroup());
478}
479
480void
482{
483 NS_ASSERT(!address.IsGroup());
485}
486
487void
489{
490 NS_ASSERT(!address.IsGroup());
492}
493
494bool
496{
497 if (address.IsGroup())
498 {
499 return false;
500 }
501 return LookupState(address)->m_state == WifiRemoteStationState::ASSOC_REFUSED;
502}
503
504void
506{
507 NS_ASSERT(!address.IsGroup());
509}
510
511uint16_t
513{
514 std::shared_ptr<WifiRemoteStationState> state;
515 if (!remoteAddress.IsGroup() &&
516 (state = LookupState(remoteAddress))->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK)
517 {
518 return state->m_aid;
519 }
520 return SU_STA_ID;
521}
522
523uint16_t
525{
526 NS_LOG_FUNCTION(this << address << txVector);
527
528 uint16_t staId = SU_STA_ID;
529
530 if (txVector.IsMu())
531 {
532 if (m_wifiMac->GetTypeOfStation() == AP)
533 {
534 staId = GetAssociationId(address);
535 }
536 else if (m_wifiMac->GetTypeOfStation() == STA)
537 {
538 Ptr<StaWifiMac> staMac = StaticCast<StaWifiMac>(m_wifiMac);
539 if (staMac->IsAssociated())
540 {
541 staId = staMac->GetAssociationId();
542 }
543 }
544 }
545
546 NS_LOG_DEBUG("Returning STAID = " << staId);
547 return staId;
548}
549
550bool
552{
553 return LookupState(address)->m_isInPsMode;
554}
555
556void
557WifiRemoteStationManager::SetPsMode(const Mac48Address& address, bool isInPsMode)
558{
559 LookupState(address)->m_isInPsMode = isInPsMode;
560}
561
562std::optional<Mac48Address>
564{
565 if (auto stateIt = m_states.find(address);
566 stateIt != m_states.end() && stateIt->second->m_mleCommonInfo)
567 {
568 return stateIt->second->m_mleCommonInfo->m_mldMacAddress;
569 }
570
571 return std::nullopt;
572}
573
574std::optional<Mac48Address>
576{
577 auto stateIt = m_states.find(mldAddress);
578
579 if (stateIt == m_states.end() || !stateIt->second->m_mleCommonInfo)
580 {
581 // MLD address not found
582 return std::nullopt;
583 }
584
585 NS_ASSERT(stateIt->second->m_mleCommonInfo->m_mldMacAddress == mldAddress);
586 return stateIt->second->m_address;
587}
588
590WifiRemoteStationManager::GetDataTxVector(const WifiMacHeader& header, uint16_t allowedWidth)
591{
592 NS_LOG_FUNCTION(this << header << allowedWidth);
593 Mac48Address address = header.GetAddr1();
594 if (!header.IsMgt() && address.IsGroup())
595 {
597 WifiTxVector v;
598 v.SetMode(mode);
602 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mode, allowedWidth));
605 v.SetNss(1);
606 v.SetNess(0);
607 return v;
608 }
609 WifiTxVector txVector;
610 if (header.IsMgt())
611 {
612 // Use the lowest basic rate for management frames
613 WifiMode mgtMode;
614 if (GetNBasicModes() > 0)
615 {
616 mgtMode = GetBasicMode(0);
617 }
618 else
619 {
620 mgtMode = GetDefaultMode();
621 }
622 txVector.SetMode(mgtMode);
623 txVector.SetPreambleType(
626 uint16_t channelWidth = allowedWidth;
627 if (!header.GetAddr1().IsGroup())
628 {
629 if (uint16_t rxWidth = GetChannelWidthSupported(header.GetAddr1());
630 rxWidth < channelWidth)
631 {
632 channelWidth = rxWidth;
633 }
634 }
635
636 txVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mgtMode, channelWidth));
637 txVector.SetGuardInterval(
639 }
640 else
641 {
642 txVector = DoGetDataTxVector(Lookup(address), allowedWidth);
644 ? false
645 : UseLdpcForDestination(address));
646 }
648 if (heConfiguration)
649 {
650 txVector.SetBssColor(heConfiguration->GetBssColor());
651 }
652 // If both the allowed width and the TXVECTOR channel width are integer multiple
653 // of 20 MHz, then the TXVECTOR channel width must not exceed the allowed width
654 NS_ASSERT_MSG((txVector.GetChannelWidth() % 20 != 0) || (allowedWidth % 20 != 0) ||
655 (txVector.GetChannelWidth() <= allowedWidth),
656 "TXVECTOR channel width (" << txVector.GetChannelWidth()
657 << " MHz) exceeds allowed width (" << allowedWidth
658 << " MHz)");
659 return txVector;
660}
661
664{
665 WifiMode defaultMode = GetDefaultMode();
666 WifiPreamble defaultPreamble;
667 if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_EHT)
668 {
669 defaultPreamble = WIFI_PREAMBLE_EHT_MU;
670 }
671 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HE)
672 {
673 defaultPreamble = WIFI_PREAMBLE_HE_SU;
674 }
675 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_VHT)
676 {
677 defaultPreamble = WIFI_PREAMBLE_VHT_SU;
678 }
679 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HT)
680 {
681 defaultPreamble = WIFI_PREAMBLE_HT_MF;
682 }
683 else
684 {
685 defaultPreamble = WIFI_PREAMBLE_LONG;
686 }
687
688 return WifiTxVector(defaultMode,
690 defaultPreamble,
693 1,
694 0,
695 m_wifiPhy->GetTxBandwidth(defaultMode),
696 false);
697}
698
701{
702 NS_LOG_FUNCTION(this << address << allowedWidth);
703 WifiTxVector v;
704 if (address.IsGroup())
705 {
707 v.SetMode(mode);
714 v.SetNss(1);
715 v.SetNess(0);
716 }
717 else
718 {
719 v = DoGetRtsTxVector(Lookup(address));
720 }
721 auto modulation = v.GetModulationClass();
722
723 if (allowedWidth >= 40 &&
724 (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS))
725 {
726 // RTS must be sent in a non-HT duplicate PPDU because it must protect a frame being
727 // transmitted on at least 40 MHz. Change the modulation class to ERP-OFDM and the rate
728 // to 6 Mbps
730 modulation = v.GetModulationClass();
731 }
732 // do not set allowedWidth as the TX width if the modulation class is (HR-)DSSS (allowedWidth
733 // may be >= 40 MHz) or allowedWidth is 22 MHz (the selected modulation class may be OFDM)
734 if (modulation != WIFI_MOD_CLASS_DSSS && modulation != WIFI_MOD_CLASS_HR_DSSS &&
735 allowedWidth != 22)
736 {
737 v.SetChannelWidth(allowedWidth);
738 }
739
740 return v;
741}
742
745{
746 NS_ASSERT(!to.IsGroup());
747 WifiMode ctsMode = GetControlAnswerMode(rtsTxMode);
748 WifiTxVector v;
749 v.SetMode(ctsMode);
754 uint16_t ctsTxGuardInterval =
756 v.SetGuardInterval(ctsTxGuardInterval);
757 v.SetNss(1);
758 return v;
759}
760
761void
763{
764 NS_LOG_FUNCTION(this << txVector);
765
766 auto txMode = txVector.GetMode();
767 if (txMode.GetModulationClass() >= WIFI_MOD_CLASS_HT)
768 {
769 auto rate = txMode.GetDataRate(txVector);
770 if (rate >= 24e6)
771 {
772 rate = 24e6;
773 }
774 else if (rate >= 12e6)
775 {
776 rate = 12e6;
777 }
778 else
779 {
780 rate = 6e6;
781 }
784 {
785 txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(rate));
786 }
787 else
788 {
789 txVector.SetMode(OfdmPhy::GetOfdmRate(rate));
790 }
791 }
792}
793
796{
797 NS_ASSERT(!to.IsGroup());
798 WifiMode ackMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
799 WifiTxVector v;
800 v.SetMode(ackMode);
805 uint16_t ackTxGuardInterval =
807 v.SetGuardInterval(ackTxGuardInterval);
808 v.SetNss(1);
809 return v;
810}
811
814 const WifiTxVector& dataTxVector) const
815{
816 NS_ASSERT(!to.IsGroup());
817 WifiMode blockAckMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
818 WifiTxVector v;
819 v.SetMode(blockAckMode);
823 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(blockAckMode));
824 uint16_t blockAckTxGuardInterval =
826 v.SetGuardInterval(blockAckTxGuardInterval);
827 v.SetNss(1);
828 return v;
829}
830
833{
834 /**
835 * The standard has relatively unambiguous rules for selecting a
836 * control response rate (the below is quoted from IEEE 802.11-2012,
837 * Section 9.7):
838 *
839 * To allow the transmitting STA to calculate the contents of the
840 * Duration/ID field, a STA responding to a received frame shall
841 * transmit its Control Response frame (either CTS or Ack), other
842 * than the BlockAck control frame, at the highest rate in the
843 * BSSBasicRateSet parameter that is less than or equal to the
844 * rate of the immediately previous frame in the frame exchange
845 * sequence (as defined in Annex G) and that is of the same
846 * modulation class (see Section 9.7.8) as the received frame...
847 */
848 NS_LOG_FUNCTION(this << reqMode);
849 WifiMode mode = GetDefaultMode();
850 bool found = false;
851 // First, search the BSS Basic Rate set
852 for (uint8_t i = 0; i < GetNBasicModes(); i++)
853 {
854 WifiMode testMode = GetBasicMode(i);
855 if ((!found || testMode.IsHigherDataRate(mode)) && (!testMode.IsHigherDataRate(reqMode)) &&
857 testMode.GetModulationClass())))
858 {
859 mode = testMode;
860 // We've found a potentially-suitable transmit rate, but we
861 // need to continue and consider all the basic rates before
862 // we can be sure we've got the right one.
863 found = true;
864 }
865 }
866 if (GetHtSupported())
867 {
868 if (!found)
869 {
870 mode = GetDefaultMcs();
871 for (uint8_t i = 0; i != GetNBasicMcs(); i++)
872 {
873 WifiMode testMode = GetBasicMcs(i);
874 if ((!found || testMode.IsHigherDataRate(mode)) &&
875 (!testMode.IsHigherDataRate(reqMode)) &&
876 (testMode.GetModulationClass() == reqMode.GetModulationClass()))
877 {
878 mode = testMode;
879 // We've found a potentially-suitable transmit rate, but we
880 // need to continue and consider all the basic rates before
881 // we can be sure we've got the right one.
882 found = true;
883 }
884 }
885 }
886 }
887 // If we found a suitable rate in the BSSBasicRateSet, then we are
888 // done and can return that mode.
889 if (found)
890 {
891 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
892 return mode;
893 }
894
895 /**
896 * If no suitable basic rate was found, we search the mandatory
897 * rates. The standard (IEEE 802.11-2007, Section 9.6) says:
898 *
899 * ...If no rate contained in the BSSBasicRateSet parameter meets
900 * these conditions, then the control frame sent in response to a
901 * received frame shall be transmitted at the highest mandatory
902 * rate of the PHY that is less than or equal to the rate of the
903 * received frame, and that is of the same modulation class as the
904 * received frame. In addition, the Control Response frame shall
905 * be sent using the same PHY options as the received frame,
906 * unless they conflict with the requirement to use the
907 * BSSBasicRateSet parameter.
908 *
909 * \todo Note that we're ignoring the last sentence for now, because
910 * there is not yet any manipulation here of PHY options.
911 */
912 for (const auto& thismode : m_wifiPhy->GetModeList())
913 {
914 /* If the rate:
915 *
916 * - is a mandatory rate for the PHY, and
917 * - is equal to or faster than our current best choice, and
918 * - is less than or equal to the rate of the received frame, and
919 * - is of the same modulation class as the received frame
920 *
921 * ...then it's our best choice so far.
922 */
923 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
924 (!thismode.IsHigherDataRate(reqMode)) &&
926 thismode.GetModulationClass())))
927 {
928 mode = thismode;
929 // As above; we've found a potentially-suitable transmit
930 // rate, but we need to continue and consider all the
931 // mandatory rates before we can be sure we've got the right one.
932 found = true;
933 }
934 }
935 if (GetHtSupported())
936 {
937 for (const auto& thismode : m_wifiPhy->GetMcsList())
938 {
939 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
940 (!thismode.IsHigherCodeRate(reqMode)) &&
941 (thismode.GetModulationClass() == reqMode.GetModulationClass()))
942 {
943 mode = thismode;
944 // As above; we've found a potentially-suitable transmit
945 // rate, but we need to continue and consider all the
946 // mandatory rates before we can be sure we've got the right one.
947 found = true;
948 }
949 }
950 }
951
952 /**
953 * If we still haven't found a suitable rate for the response then
954 * someone has messed up the simulation configuration. This probably means
955 * that the WifiPhyStandard is not set correctly, or that a rate that
956 * is not supported by the PHY has been explicitly requested.
957 *
958 * Either way, it is serious - we can either disobey the standard or
959 * fail, and I have chosen to do the latter...
960 */
961 if (!found)
962 {
963 NS_FATAL_ERROR("Can't find response rate for " << reqMode);
964 }
965
966 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
967 return mode;
968}
969
970void
972{
973 NS_LOG_FUNCTION(this << header);
974 NS_ASSERT(!header.GetAddr1().IsGroup());
975 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
976 m_ssrc[ac]++;
977 m_macTxRtsFailed(header.GetAddr1());
979}
980
981void
983{
984 NS_LOG_FUNCTION(this << *mpdu);
985 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
986 AcIndex ac =
987 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
988 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
989 if (longMpdu)
990 {
991 m_slrc[ac]++;
992 }
993 else
994 {
995 m_ssrc[ac]++;
996 }
997 m_macTxDataFailed(mpdu->GetHeader().GetAddr1());
998 DoReportDataFailed(Lookup(mpdu->GetHeader().GetAddr1()));
999}
1000
1001void
1003 double ctsSnr,
1004 WifiMode ctsMode,
1005 double rtsSnr)
1006{
1007 NS_LOG_FUNCTION(this << header << ctsSnr << ctsMode << rtsSnr);
1008 NS_ASSERT(!header.GetAddr1().IsGroup());
1009 WifiRemoteStation* station = Lookup(header.GetAddr1());
1010 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1011 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1012 m_ssrc[ac] = 0;
1013 DoReportRtsOk(station, ctsSnr, ctsMode, rtsSnr);
1014}
1015
1016void
1018 double ackSnr,
1019 WifiMode ackMode,
1020 double dataSnr,
1021 WifiTxVector dataTxVector)
1022{
1023 NS_LOG_FUNCTION(this << *mpdu << ackSnr << ackMode << dataSnr << dataTxVector);
1024 const WifiMacHeader& hdr = mpdu->GetHeader();
1025 NS_ASSERT(!hdr.GetAddr1().IsGroup());
1026 WifiRemoteStation* station = Lookup(hdr.GetAddr1());
1027 AcIndex ac = QosUtilsMapTidToAc((hdr.IsQosData()) ? hdr.GetQosTid() : 0);
1028 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1029 if (longMpdu)
1030 {
1031 station->m_state->m_info.NotifyTxSuccess(m_slrc[ac]);
1032 m_slrc[ac] = 0;
1033 }
1034 else
1035 {
1036 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1037 m_ssrc[ac] = 0;
1038 }
1039 DoReportDataOk(station,
1040 ackSnr,
1041 ackMode,
1042 dataSnr,
1043 dataTxVector.GetChannelWidth(),
1044 dataTxVector.GetNss(GetStaId(hdr.GetAddr1(), dataTxVector)));
1045}
1046
1047void
1049{
1050 NS_LOG_FUNCTION(this << header);
1051 NS_ASSERT(!header.GetAddr1().IsGroup());
1052 WifiRemoteStation* station = Lookup(header.GetAddr1());
1053 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1054 station->m_state->m_info.NotifyTxFailed();
1055 m_ssrc[ac] = 0;
1057 DoReportFinalRtsFailed(station);
1058}
1059
1060void
1062{
1063 NS_LOG_FUNCTION(this << *mpdu);
1064 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1065 WifiRemoteStation* station = Lookup(mpdu->GetHeader().GetAddr1());
1066 AcIndex ac =
1067 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1068 station->m_state->m_info.NotifyTxFailed();
1069 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1070 if (longMpdu)
1071 {
1072 m_slrc[ac] = 0;
1073 }
1074 else
1075 {
1076 m_ssrc[ac] = 0;
1077 }
1078 m_macTxFinalDataFailed(mpdu->GetHeader().GetAddr1());
1079 DoReportFinalDataFailed(station);
1080}
1081
1082void
1084 RxSignalInfo rxSignalInfo,
1085 WifiTxVector txVector)
1086{
1087 NS_LOG_FUNCTION(this << address << rxSignalInfo << txVector);
1088 if (address.IsGroup())
1089 {
1090 return;
1091 }
1092 WifiRemoteStation* station = Lookup(address);
1093 DoReportRxOk(station, rxSignalInfo.snr, txVector.GetMode(GetStaId(address, txVector)));
1094 station->m_rssiAndUpdateTimePair = std::make_pair(rxSignalInfo.rssi, Simulator::Now());
1095}
1096
1097void
1099 uint16_t nSuccessfulMpdus,
1100 uint16_t nFailedMpdus,
1101 double rxSnr,
1102 double dataSnr,
1103 WifiTxVector dataTxVector)
1104{
1105 NS_LOG_FUNCTION(this << address << nSuccessfulMpdus << nFailedMpdus << rxSnr << dataSnr
1106 << dataTxVector);
1107 NS_ASSERT(!address.IsGroup());
1108 for (uint16_t i = 0; i < nFailedMpdus; i++)
1109 {
1110 m_macTxDataFailed(address);
1111 }
1113 nSuccessfulMpdus,
1114 nFailedMpdus,
1115 rxSnr,
1116 dataSnr,
1117 dataTxVector.GetChannelWidth(),
1118 dataTxVector.GetNss(GetStaId(address, dataTxVector)));
1119}
1120
1121bool
1123{
1124 NS_LOG_FUNCTION(this << header << size);
1125 Mac48Address address = header.GetAddr1();
1127 const auto modulationClass = txVector.GetModulationClass();
1128 if (address.IsGroup())
1129 {
1130 return false;
1131 }
1133 ((modulationClass == WIFI_MOD_CLASS_ERP_OFDM) || (modulationClass == WIFI_MOD_CLASS_HT) ||
1134 (modulationClass == WIFI_MOD_CLASS_VHT) || (modulationClass == WIFI_MOD_CLASS_HE) ||
1135 (modulationClass == WIFI_MOD_CLASS_EHT)) &&
1137 {
1139 "WifiRemoteStationManager::NeedRTS returning true to protect non-ERP stations");
1140 return true;
1141 }
1142 else if (m_htProtectionMode == RTS_CTS &&
1143 ((modulationClass == WIFI_MOD_CLASS_HT) || (modulationClass == WIFI_MOD_CLASS_VHT)) &&
1145 {
1146 NS_LOG_DEBUG("WifiRemoteStationManager::NeedRTS returning true to protect non-HT stations");
1147 return true;
1148 }
1149 bool normally = (size > m_rtsCtsThreshold);
1150 return DoNeedRts(Lookup(address), size, normally);
1151}
1152
1153bool
1155{
1156 WifiMode mode = txVector.GetMode();
1157 NS_LOG_FUNCTION(this << mode);
1165 {
1167 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-ERP stations");
1168 return true;
1169 }
1170 else if (m_htProtectionMode == CTS_TO_SELF &&
1174 {
1176 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-HT stations");
1177 return true;
1178 }
1179 else if (!m_useNonErpProtection)
1180 {
1181 // search for the BSS Basic Rate set, if the used mode is in the basic set then there is no
1182 // need for CTS To Self
1183 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
1184 {
1185 if (mode == *i)
1186 {
1187 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1188 return false;
1189 }
1190 }
1191 if (GetHtSupported())
1192 {
1193 // search for the BSS Basic MCS set, if the used mode is in the basic set then there is
1194 // no need for CTS To Self
1195 for (auto i = m_bssBasicMcsSet.begin(); i != m_bssBasicMcsSet.end(); i++)
1196 {
1197 if (mode == *i)
1198 {
1199 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1200 return false;
1201 }
1202 }
1203 }
1204 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning true");
1205 return true;
1206 }
1207 return false;
1208}
1209
1210void
1212{
1213 NS_LOG_FUNCTION(this << enable);
1214 m_useNonErpProtection = enable;
1215}
1216
1217bool
1219{
1220 return m_useNonErpProtection;
1221}
1222
1223void
1225{
1226 NS_LOG_FUNCTION(this << enable);
1227 m_useNonHtProtection = enable;
1228}
1229
1230bool
1232{
1233 return m_useNonHtProtection;
1234}
1235
1236bool
1238{
1239 NS_LOG_FUNCTION(this << *mpdu);
1240 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1241 AcIndex ac =
1242 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1243 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1244 uint32_t retryCount;
1245 uint32_t maxRetryCount;
1246 if (longMpdu)
1247 {
1248 retryCount = m_slrc[ac];
1249 maxRetryCount = m_maxSlrc;
1250 }
1251 else
1252 {
1253 retryCount = m_ssrc[ac];
1254 maxRetryCount = m_maxSsrc;
1255 }
1256 bool normally = retryCount < maxRetryCount;
1257 NS_LOG_DEBUG("WifiRemoteStationManager::NeedRetransmission count: "
1258 << retryCount << " result: " << std::boolalpha << normally);
1259 return DoNeedRetransmission(Lookup(mpdu->GetHeader().GetAddr1()), mpdu->GetPacket(), normally);
1260}
1261
1262bool
1264{
1265 NS_LOG_FUNCTION(this << *mpdu);
1266 if (mpdu->GetHeader().GetAddr1().IsGroup())
1267 {
1268 return false;
1269 }
1270 bool normally = mpdu->GetSize() > GetFragmentationThreshold();
1271 NS_LOG_DEBUG("WifiRemoteStationManager::NeedFragmentation result: " << std::boolalpha
1272 << normally);
1273 return DoNeedFragmentation(Lookup(mpdu->GetHeader().GetAddr1()), mpdu->GetPacket(), normally);
1274}
1275
1276void
1278{
1279 NS_LOG_FUNCTION(this << threshold);
1280 if (threshold < 256)
1281 {
1282 /*
1283 * ASN.1 encoding of the MAC and PHY MIB (256 ... 8000)
1284 */
1285 NS_LOG_WARN("Fragmentation threshold should be larger than 256. Setting to 256.");
1287 }
1288 else
1289 {
1290 /*
1291 * The length of each fragment shall be an even number of octets, except for the last
1292 * fragment if an MSDU or MMPDU, which may be either an even or an odd number of octets.
1293 */
1294 if (threshold % 2 != 0)
1295 {
1296 NS_LOG_WARN("Fragmentation threshold should be an even number. Setting to "
1297 << threshold - 1);
1298 m_fragmentationThreshold = threshold - 1;
1299 }
1300 else
1301 {
1302 m_fragmentationThreshold = threshold;
1303 }
1304 }
1305}
1306
1309{
1311}
1312
1315{
1316 NS_LOG_FUNCTION(this << *mpdu);
1317 // The number of bytes a fragment can support is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS).
1318 uint32_t nFragments =
1319 (mpdu->GetPacket()->GetSize() /
1320 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH));
1321
1322 // If the size of the last fragment is not 0.
1323 if ((mpdu->GetPacket()->GetSize() %
1324 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH)) > 0)
1325 {
1326 nFragments++;
1327 }
1328 NS_LOG_DEBUG("WifiRemoteStationManager::GetNFragments returning " << nFragments);
1329 return nFragments;
1330}
1331
1334{
1335 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1336 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1337 uint32_t nFragment = GetNFragments(mpdu);
1338 if (fragmentNumber >= nFragment)
1339 {
1340 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning 0");
1341 return 0;
1342 }
1343 // Last fragment
1344 if (fragmentNumber == nFragment - 1)
1345 {
1346 uint32_t lastFragmentSize =
1347 mpdu->GetPacket()->GetSize() -
1348 (fragmentNumber *
1349 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH));
1350 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning " << lastFragmentSize);
1351 return lastFragmentSize;
1352 }
1353 // All fragments but the last, the number of bytes is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS).
1354 else
1355 {
1356 uint32_t fragmentSize =
1357 GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH;
1358 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning " << fragmentSize);
1359 return fragmentSize;
1360 }
1361}
1362
1365{
1366 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1367 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1368 NS_ASSERT(fragmentNumber < GetNFragments(mpdu));
1369 uint32_t fragmentOffset = fragmentNumber * (GetFragmentationThreshold() -
1370 mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH);
1371 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentOffset returning " << fragmentOffset);
1372 return fragmentOffset;
1373}
1374
1375bool
1377{
1378 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1379 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1380 bool isLast = fragmentNumber == (GetNFragments(mpdu) - 1);
1381 NS_LOG_DEBUG("WifiRemoteStationManager::IsLastFragment returning " << std::boolalpha << isLast);
1382 return isLast;
1383}
1384
1385uint8_t
1387{
1388 return m_defaultTxPowerLevel;
1389}
1390
1393{
1394 return LookupState(address)->m_info;
1395}
1396
1397std::optional<double>
1399{
1400 auto station = Lookup(address);
1401 auto rssi = station->m_rssiAndUpdateTimePair.first;
1402 auto ts = station->m_rssiAndUpdateTimePair.second;
1403 if (ts.IsStrictlyPositive())
1404 {
1405 return rssi;
1406 }
1407 return std::nullopt;
1408}
1409
1410std::shared_ptr<WifiRemoteStationState>
1412{
1413 NS_LOG_FUNCTION(this << address);
1414 auto stateIt = m_states.find(address);
1415
1416 if (stateIt != m_states.end())
1417 {
1418 NS_LOG_DEBUG("WifiRemoteStationManager::LookupState returning existing state");
1419 return stateIt->second;
1420 }
1421
1422 auto state = std::make_shared<WifiRemoteStationState>();
1423 state->m_state = WifiRemoteStationState::BRAND_NEW;
1424 state->m_address = address;
1425 state->m_aid = 0;
1426 state->m_operationalRateSet.push_back(GetDefaultMode());
1427 state->m_operationalMcsSet.push_back(GetDefaultMcs());
1428 state->m_dsssSupported = false;
1429 state->m_erpOfdmSupported = false;
1430 state->m_ofdmSupported = false;
1431 state->m_htCapabilities = nullptr;
1432 state->m_vhtCapabilities = nullptr;
1433 state->m_heCapabilities = nullptr;
1434 state->m_ehtCapabilities = nullptr;
1435 state->m_mleCommonInfo = nullptr;
1436 state->m_emlsrEnabled = false;
1437 state->m_channelWidth = m_wifiPhy->GetChannelWidth();
1438 state->m_guardInterval = GetGuardInterval();
1439 state->m_ness = 0;
1440 state->m_aggregation = false;
1441 state->m_qosSupported = false;
1442 state->m_isInPsMode = false;
1443 const_cast<WifiRemoteStationManager*>(this)->m_states.insert({address, state});
1444 NS_LOG_DEBUG("WifiRemoteStationManager::LookupState returning new state");
1445 return state;
1446}
1447
1448WifiRemoteStation*
1449WifiRemoteStationManager::Lookup(Mac48Address address) const
1450{
1451 NS_LOG_FUNCTION(this << address);
1452 NS_ASSERT(!address.IsGroup());
1453 NS_ASSERT(address != m_wifiMac->GetAddress());
1454 auto stationIt = m_stations.find(address);
1455
1456 if (stationIt != m_stations.end())
1457 {
1458 return stationIt->second;
1459 }
1460
1461 WifiRemoteStation* station = DoCreateStation();
1462 station->m_state = LookupState(address).get();
1463 station->m_rssiAndUpdateTimePair = std::make_pair(0, Seconds(0));
1464 const_cast<WifiRemoteStationManager*>(this)->m_stations.insert({address, station});
1465 return station;
1466}
1467
1468void
1469WifiRemoteStationManager::SetAssociationId(Mac48Address remoteAddress, uint16_t aid)
1470{
1471 NS_LOG_FUNCTION(this << remoteAddress << aid);
1472 LookupState(remoteAddress)->m_aid = aid;
1473}
1474
1475void
1476WifiRemoteStationManager::SetQosSupport(Mac48Address from, bool qosSupported)
1477{
1478 NS_LOG_FUNCTION(this << from << qosSupported);
1479 LookupState(from)->m_qosSupported = qosSupported;
1480}
1481
1482void
1483WifiRemoteStationManager::SetEmlsrEnabled(const Mac48Address& from, bool emlsrEnabled)
1484{
1485 NS_LOG_FUNCTION(this << from << emlsrEnabled);
1486 LookupState(from)->m_emlsrEnabled = emlsrEnabled;
1487}
1488
1489void
1490WifiRemoteStationManager::AddStationHtCapabilities(Mac48Address from, HtCapabilities htCapabilities)
1491{
1492 // Used by all stations to record HT capabilities of remote stations
1493 NS_LOG_FUNCTION(this << from << htCapabilities);
1494 auto state = LookupState(from);
1495 if (htCapabilities.GetSupportedChannelWidth() == 1)
1496 {
1497 state->m_channelWidth = 40;
1498 }
1499 else
1500 {
1501 state->m_channelWidth = 20;
1502 }
1503 SetQosSupport(from, true);
1504 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_HT))
1505 {
1506 if (htCapabilities.IsSupportedMcs(mcs.GetMcsValue()))
1507 {
1508 AddSupportedMcs(from, mcs);
1509 }
1510 }
1511 state->m_htCapabilities = Create<const HtCapabilities>(htCapabilities);
1512}
1513
1514void
1515WifiRemoteStationManager::AddStationVhtCapabilities(Mac48Address from,
1516 VhtCapabilities vhtCapabilities)
1517{
1518 // Used by all stations to record VHT capabilities of remote stations
1519 NS_LOG_FUNCTION(this << from << vhtCapabilities);
1520 auto state = LookupState(from);
1521 if (vhtCapabilities.GetSupportedChannelWidthSet() == 1)
1522 {
1523 state->m_channelWidth = 160;
1524 }
1525 else
1526 {
1527 state->m_channelWidth = 80;
1528 }
1529 for (uint8_t i = 1; i <= m_wifiPhy->GetMaxSupportedTxSpatialStreams(); i++)
1530 {
1531 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_VHT))
1532 {
1533 if (vhtCapabilities.IsSupportedMcs(mcs.GetMcsValue(), i))
1534 {
1535 AddSupportedMcs(from, mcs);
1536 }
1537 }
1538 }
1539 state->m_vhtCapabilities = Create<const VhtCapabilities>(vhtCapabilities);
1540}
1541
1542void
1543WifiRemoteStationManager::AddStationHeCapabilities(Mac48Address from, HeCapabilities heCapabilities)
1544{
1545 // Used by all stations to record HE capabilities of remote stations
1546 NS_LOG_FUNCTION(this << from << heCapabilities);
1547 auto state = LookupState(from);
1548 if ((m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) ||
1549 (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_6GHZ))
1550 {
1551 if (heCapabilities.GetChannelWidthSet() & 0x04)
1552 {
1553 state->m_channelWidth = 160;
1554 }
1555 else if (heCapabilities.GetChannelWidthSet() & 0x02)
1556 {
1557 state->m_channelWidth = 80;
1558 }
1559 // For other cases at 5 GHz, the supported channel width is set by the VHT capabilities
1560 }
1561 else if (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
1562 {
1563 if (heCapabilities.GetChannelWidthSet() & 0x01)
1564 {
1565 state->m_channelWidth = 40;
1566 }
1567 else
1568 {
1569 state->m_channelWidth = 20;
1570 }
1571 }
1572 if (heCapabilities.GetHeSuPpdu1xHeLtf800nsGi())
1573 {
1574 state->m_guardInterval = 800;
1575 }
1576 else
1577 {
1578 // todo: Using 3200ns, default value for HeConfiguration::GuardInterval
1579 state->m_guardInterval = 3200;
1580 }
1581 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_HE))
1582 {
1583 if (heCapabilities.GetHighestMcsSupported() >= mcs.GetMcsValue())
1584 {
1585 AddSupportedMcs(from, mcs);
1586 }
1587 }
1588 state->m_heCapabilities = Create<const HeCapabilities>(heCapabilities);
1589 SetQosSupport(from, true);
1590}
1591
1592void
1593WifiRemoteStationManager::AddStationEhtCapabilities(Mac48Address from,
1594 EhtCapabilities ehtCapabilities)
1595{
1596 // Used by all stations to record EHT capabilities of remote stations
1597 NS_LOG_FUNCTION(this << from << ehtCapabilities);
1598 auto state = LookupState(from);
1599 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_EHT))
1600 {
1601 for (uint8_t mapType = 0; mapType < EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_MAX; ++mapType)
1602 {
1603 if (ehtCapabilities.GetHighestSupportedRxMcs(
1604 static_cast<EhtMcsAndNssSet::EhtMcsMapType>(mapType)) >= mcs.GetMcsValue())
1605 {
1606 AddSupportedMcs(from, mcs);
1607 }
1608 }
1609 }
1610 state->m_ehtCapabilities = Create<const EhtCapabilities>(ehtCapabilities);
1611 SetQosSupport(from, true);
1612}
1613
1614void
1615WifiRemoteStationManager::AddStationMleCommonInfo(
1616 Mac48Address from,
1617 const std::shared_ptr<CommonInfoBasicMle>& mleCommonInfo)
1618{
1619 NS_LOG_FUNCTION(this << from);
1620 auto state = LookupState(from);
1621 state->m_mleCommonInfo = mleCommonInfo;
1622 // insert another entry in m_states indexed by the MLD address and pointing to the same state
1623 const_cast<WifiRemoteStationManager*>(this)->m_states.insert(
1624 {mleCommonInfo->m_mldMacAddress, state});
1625}
1626
1627Ptr<const HtCapabilities>
1628WifiRemoteStationManager::GetStationHtCapabilities(Mac48Address from)
1629{
1630 return LookupState(from)->m_htCapabilities;
1631}
1632
1634WifiRemoteStationManager::GetStationVhtCapabilities(Mac48Address from)
1635{
1636 return LookupState(from)->m_vhtCapabilities;
1637}
1638
1640WifiRemoteStationManager::GetStationHeCapabilities(Mac48Address from)
1641{
1642 return LookupState(from)->m_heCapabilities;
1643}
1644
1646WifiRemoteStationManager::GetStationEhtCapabilities(Mac48Address from)
1647{
1648 return LookupState(from)->m_ehtCapabilities;
1649}
1650
1651std::optional<std::reference_wrapper<CommonInfoBasicMle::EmlCapabilities>>
1652WifiRemoteStationManager::GetStationEmlCapabilities(const Mac48Address& from)
1653{
1654 if (auto state = LookupState(from);
1655 state->m_mleCommonInfo && state->m_mleCommonInfo->m_emlCapabilities)
1656 {
1657 return state->m_mleCommonInfo->m_emlCapabilities.value();
1658 }
1659 return std::nullopt;
1660}
1661
1662std::optional<std::reference_wrapper<CommonInfoBasicMle::MldCapabilities>>
1663WifiRemoteStationManager::GetStationMldCapabilities(const Mac48Address& from)
1664{
1665 if (auto state = LookupState(from);
1666 state->m_mleCommonInfo && state->m_mleCommonInfo->m_mldCapabilities)
1667 {
1668 return state->m_mleCommonInfo->m_mldCapabilities.value();
1669 }
1670 return std::nullopt;
1671}
1672
1673bool
1674WifiRemoteStationManager::GetLdpcSupported(Mac48Address address) const
1675{
1676 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
1677 Ptr<const VhtCapabilities> vhtCapabilities = LookupState(address)->m_vhtCapabilities;
1678 Ptr<const HeCapabilities> heCapabilities = LookupState(address)->m_heCapabilities;
1679 bool supported = false;
1680 if (htCapabilities)
1681 {
1682 supported |= htCapabilities->GetLdpc();
1683 }
1684 if (vhtCapabilities)
1685 {
1686 supported |= vhtCapabilities->GetRxLdpc();
1687 }
1688 if (heCapabilities)
1689 {
1690 supported |= heCapabilities->GetLdpcCodingInPayload();
1691 }
1692 return supported;
1693}
1694
1696WifiRemoteStationManager::GetDefaultMode() const
1697{
1698 NS_ASSERT(m_wifiPhy);
1699 auto defaultTxMode = m_wifiPhy->GetDefaultMode();
1700 NS_ASSERT(defaultTxMode.IsMandatory());
1701 return defaultTxMode;
1702}
1703
1705WifiRemoteStationManager::GetDefaultMcs() const
1706{
1707 return HtPhy::GetHtMcs0();
1708}
1709
1711WifiRemoteStationManager::GetDefaultModeForSta(const WifiRemoteStation* st) const
1712{
1713 NS_LOG_FUNCTION(this << st);
1714
1715 if (!GetHtSupported() || !GetHtSupported(st))
1716 {
1717 return GetDefaultMode();
1718 }
1719
1720 // find the highest modulation class supported by both stations
1722 if (GetHeSupported() && GetHeSupported(st))
1723 {
1724 modClass = WIFI_MOD_CLASS_HE;
1725 }
1726 else if (GetVhtSupported() && GetVhtSupported(st))
1727 {
1728 modClass = WIFI_MOD_CLASS_VHT;
1729 }
1730
1731 // return the MCS with lowest index
1732 return *m_wifiPhy->GetPhyEntity(modClass)->begin();
1733}
1734
1735void
1736WifiRemoteStationManager::Reset()
1737{
1738 NS_LOG_FUNCTION(this);
1739 m_states.clear();
1740 for (auto& state : m_stations)
1741 {
1742 delete (state.second);
1743 }
1744 m_stations.clear();
1745 m_bssBasicRateSet.clear();
1746 m_bssBasicMcsSet.clear();
1747 m_ssrc.fill(0);
1748 m_slrc.fill(0);
1749}
1750
1751void
1752WifiRemoteStationManager::AddBasicMode(WifiMode mode)
1753{
1754 NS_LOG_FUNCTION(this << mode);
1756 {
1757 NS_FATAL_ERROR("It is not allowed to add a HT rate in the BSSBasicRateSet!");
1758 }
1759 for (uint8_t i = 0; i < GetNBasicModes(); i++)
1760 {
1761 if (GetBasicMode(i) == mode)
1762 {
1763 return;
1764 }
1765 }
1766 m_bssBasicRateSet.push_back(mode);
1767}
1768
1769uint8_t
1770WifiRemoteStationManager::GetNBasicModes() const
1771{
1772 return static_cast<uint8_t>(m_bssBasicRateSet.size());
1773}
1774
1776WifiRemoteStationManager::GetBasicMode(uint8_t i) const
1777{
1778 NS_ASSERT(i < GetNBasicModes());
1779 return m_bssBasicRateSet[i];
1780}
1781
1783WifiRemoteStationManager::GetNNonErpBasicModes() const
1784{
1785 uint32_t size = 0;
1786 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
1787 {
1788 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
1789 {
1790 continue;
1791 }
1792 size++;
1793 }
1794 return size;
1795}
1796
1798WifiRemoteStationManager::GetNonErpBasicMode(uint8_t i) const
1799{
1800 NS_ASSERT(i < GetNNonErpBasicModes());
1801 uint32_t index = 0;
1802 bool found = false;
1803 for (auto j = m_bssBasicRateSet.begin(); j != m_bssBasicRateSet.end();)
1804 {
1805 if (i == index)
1806 {
1807 found = true;
1808 }
1809 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
1810 {
1811 if (found)
1812 {
1813 break;
1814 }
1815 }
1816 index++;
1817 j++;
1818 }
1819 return m_bssBasicRateSet[index];
1820}
1821
1822void
1823WifiRemoteStationManager::AddBasicMcs(WifiMode mcs)
1824{
1825 NS_LOG_FUNCTION(this << +mcs.GetMcsValue());
1826 for (uint8_t i = 0; i < GetNBasicMcs(); i++)
1827 {
1828 if (GetBasicMcs(i) == mcs)
1829 {
1830 return;
1831 }
1832 }
1833 m_bssBasicMcsSet.push_back(mcs);
1834}
1835
1836uint8_t
1837WifiRemoteStationManager::GetNBasicMcs() const
1838{
1839 return static_cast<uint8_t>(m_bssBasicMcsSet.size());
1840}
1841
1843WifiRemoteStationManager::GetBasicMcs(uint8_t i) const
1844{
1845 NS_ASSERT(i < GetNBasicMcs());
1846 return m_bssBasicMcsSet[i];
1847}
1848
1850WifiRemoteStationManager::GetNonUnicastMode() const
1851{
1852 if (m_nonUnicastMode == WifiMode())
1853 {
1854 if (GetNBasicModes() > 0)
1855 {
1856 return GetBasicMode(0);
1857 }
1858 else
1859 {
1860 return GetDefaultMode();
1861 }
1862 }
1863 else
1864 {
1865 return m_nonUnicastMode;
1866 }
1867}
1868
1869bool
1870WifiRemoteStationManager::DoNeedRts(WifiRemoteStation* station, uint32_t size, bool normally)
1871{
1872 return normally;
1873}
1874
1875bool
1876WifiRemoteStationManager::DoNeedRetransmission(WifiRemoteStation* station,
1877 Ptr<const Packet> packet,
1878 bool normally)
1879{
1880 return normally;
1881}
1882
1883bool
1884WifiRemoteStationManager::DoNeedFragmentation(WifiRemoteStation* station,
1885 Ptr<const Packet> packet,
1886 bool normally)
1887{
1888 return normally;
1889}
1890
1891void
1892WifiRemoteStationManager::DoReportAmpduTxStatus(WifiRemoteStation* station,
1893 uint16_t nSuccessfulMpdus,
1894 uint16_t nFailedMpdus,
1895 double rxSnr,
1896 double dataSnr,
1897 uint16_t dataChannelWidth,
1898 uint8_t dataNss)
1899{
1900 NS_LOG_DEBUG("DoReportAmpduTxStatus received but the manager does not handle A-MPDUs!");
1901}
1902
1904WifiRemoteStationManager::GetSupported(const WifiRemoteStation* station, uint8_t i) const
1905{
1906 NS_ASSERT(i < GetNSupported(station));
1907 return station->m_state->m_operationalRateSet[i];
1908}
1909
1911WifiRemoteStationManager::GetMcsSupported(const WifiRemoteStation* station, uint8_t i) const
1912{
1913 NS_ASSERT(i < GetNMcsSupported(station));
1914 return station->m_state->m_operationalMcsSet[i];
1915}
1916
1918WifiRemoteStationManager::GetNonErpSupported(const WifiRemoteStation* station, uint8_t i) const
1919{
1920 NS_ASSERT(i < GetNNonErpSupported(station));
1921 // IEEE 802.11g standard defines that if the protection mechanism is enabled, RTS, CTS and
1922 // CTS-To-Self frames should select a rate in the BSSBasicRateSet that corresponds to an 802.11b
1923 // basic rate. This is a implemented here to avoid changes in every RAA, but should maybe be
1924 // moved in case it breaks standard rules.
1925 uint32_t index = 0;
1926 bool found = false;
1927 for (auto j = station->m_state->m_operationalRateSet.begin();
1928 j != station->m_state->m_operationalRateSet.end();)
1929 {
1930 if (i == index)
1931 {
1932 found = true;
1933 }
1934 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
1935 {
1936 if (found)
1937 {
1938 break;
1939 }
1940 }
1941 index++;
1942 j++;
1943 }
1944 return station->m_state->m_operationalRateSet[index];
1945}
1946
1948WifiRemoteStationManager::GetAddress(const WifiRemoteStation* station) const
1949{
1950 return station->m_state->m_address;
1951}
1952
1953uint16_t
1954WifiRemoteStationManager::GetChannelWidth(const WifiRemoteStation* station) const
1955{
1956 return station->m_state->m_channelWidth;
1957}
1958
1959bool
1960WifiRemoteStationManager::GetShortGuardIntervalSupported(const WifiRemoteStation* station) const
1961{
1962 Ptr<const HtCapabilities> htCapabilities = station->m_state->m_htCapabilities;
1963
1964 if (!htCapabilities)
1965 {
1966 return false;
1967 }
1968 return htCapabilities->GetShortGuardInterval20();
1969}
1970
1971uint16_t
1972WifiRemoteStationManager::GetGuardInterval(const WifiRemoteStation* station) const
1973{
1974 return station->m_state->m_guardInterval;
1975}
1976
1977bool
1978WifiRemoteStationManager::GetAggregation(const WifiRemoteStation* station) const
1979{
1980 return station->m_state->m_aggregation;
1981}
1982
1983uint8_t
1984WifiRemoteStationManager::GetNumberOfSupportedStreams(const WifiRemoteStation* station) const
1985{
1986 Ptr<const HtCapabilities> htCapabilities = station->m_state->m_htCapabilities;
1987
1988 if (!htCapabilities)
1989 {
1990 return 1;
1991 }
1992 return htCapabilities->GetRxHighestSupportedAntennas();
1993}
1994
1995uint8_t
1996WifiRemoteStationManager::GetNess(const WifiRemoteStation* station) const
1997{
1998 return station->m_state->m_ness;
1999}
2000
2002WifiRemoteStationManager::GetPhy() const
2003{
2004 return m_wifiPhy;
2005}
2006
2008WifiRemoteStationManager::GetMac() const
2009{
2010 return m_wifiMac;
2011}
2012
2013uint8_t
2014WifiRemoteStationManager::GetNSupported(const WifiRemoteStation* station) const
2015{
2016 return static_cast<uint8_t>(station->m_state->m_operationalRateSet.size());
2017}
2018
2019bool
2020WifiRemoteStationManager::GetQosSupported(const WifiRemoteStation* station) const
2021{
2022 return station->m_state->m_qosSupported;
2023}
2024
2025bool
2026WifiRemoteStationManager::GetHtSupported(const WifiRemoteStation* station) const
2027{
2028 return bool(station->m_state->m_htCapabilities);
2029}
2030
2031bool
2032WifiRemoteStationManager::GetVhtSupported(const WifiRemoteStation* station) const
2033{
2034 return bool(station->m_state->m_vhtCapabilities);
2035}
2036
2037bool
2038WifiRemoteStationManager::GetHeSupported(const WifiRemoteStation* station) const
2039{
2040 return bool(station->m_state->m_heCapabilities);
2041}
2042
2043bool
2044WifiRemoteStationManager::GetEhtSupported(const WifiRemoteStation* station) const
2045{
2046 return (bool)(station->m_state->m_ehtCapabilities);
2047}
2048
2049bool
2050WifiRemoteStationManager::GetEmlsrSupported(const WifiRemoteStation* station) const
2051{
2052 auto mleCommonInfo = station->m_state->m_mleCommonInfo;
2053 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2054 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2055}
2056
2057bool
2058WifiRemoteStationManager::GetEmlsrEnabled(const WifiRemoteStation* station) const
2059{
2060 return station->m_state->m_emlsrEnabled;
2061}
2062
2063uint8_t
2064WifiRemoteStationManager::GetNMcsSupported(const WifiRemoteStation* station) const
2065{
2066 return static_cast<uint8_t>(station->m_state->m_operationalMcsSet.size());
2067}
2068
2070WifiRemoteStationManager::GetNNonErpSupported(const WifiRemoteStation* station) const
2071{
2072 uint32_t size = 0;
2073 for (auto i = station->m_state->m_operationalRateSet.begin();
2074 i != station->m_state->m_operationalRateSet.end();
2075 i++)
2076 {
2077 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
2078 {
2079 continue;
2080 }
2081 size++;
2082 }
2083 return size;
2084}
2085
2086uint16_t
2087WifiRemoteStationManager::GetChannelWidthSupported(Mac48Address address) const
2088{
2089 return LookupState(address)->m_channelWidth;
2090}
2091
2092bool
2093WifiRemoteStationManager::GetShortGuardIntervalSupported(Mac48Address address) const
2094{
2095 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2096
2097 if (!htCapabilities)
2098 {
2099 return false;
2100 }
2101 return htCapabilities->GetShortGuardInterval20();
2102}
2103
2104uint8_t
2105WifiRemoteStationManager::GetNumberOfSupportedStreams(Mac48Address address) const
2106{
2107 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2108
2109 if (!htCapabilities)
2110 {
2111 return 1;
2112 }
2113 return htCapabilities->GetRxHighestSupportedAntennas();
2114}
2115
2116uint8_t
2117WifiRemoteStationManager::GetNMcsSupported(Mac48Address address) const
2118{
2119 return static_cast<uint8_t>(LookupState(address)->m_operationalMcsSet.size());
2120}
2121
2122bool
2123WifiRemoteStationManager::GetDsssSupported(const Mac48Address& address) const
2124{
2125 return (LookupState(address)->m_dsssSupported);
2126}
2127
2128bool
2129WifiRemoteStationManager::GetErpOfdmSupported(const Mac48Address& address) const
2130{
2131 return (LookupState(address)->m_erpOfdmSupported);
2132}
2133
2134bool
2135WifiRemoteStationManager::GetOfdmSupported(const Mac48Address& address) const
2136{
2137 return (LookupState(address)->m_ofdmSupported);
2138}
2139
2140bool
2141WifiRemoteStationManager::GetHtSupported(Mac48Address address) const
2142{
2143 return bool(LookupState(address)->m_htCapabilities);
2144}
2145
2146bool
2147WifiRemoteStationManager::GetVhtSupported(Mac48Address address) const
2148{
2149 return bool(LookupState(address)->m_vhtCapabilities);
2150}
2151
2152bool
2153WifiRemoteStationManager::GetHeSupported(Mac48Address address) const
2154{
2155 return bool(LookupState(address)->m_heCapabilities);
2156}
2157
2158bool
2159WifiRemoteStationManager::GetEhtSupported(Mac48Address address) const
2160{
2161 return (bool)(LookupState(address)->m_ehtCapabilities);
2162}
2163
2164bool
2165WifiRemoteStationManager::GetEmlsrSupported(const Mac48Address& address) const
2166{
2167 auto mleCommonInfo = LookupState(address)->m_mleCommonInfo;
2168 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2169 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2170}
2171
2172bool
2173WifiRemoteStationManager::GetEmlsrEnabled(const Mac48Address& address) const
2174{
2175 if (auto stateIt = m_states.find(address); stateIt != m_states.cend())
2176 {
2177 return stateIt->second->m_emlsrEnabled;
2178 }
2179 return false;
2180}
2181
2182void
2183WifiRemoteStationManager::SetDefaultTxPowerLevel(uint8_t txPower)
2184{
2185 m_defaultTxPowerLevel = txPower;
2186}
2187
2188uint8_t
2189WifiRemoteStationManager::GetNumberOfAntennas() const
2190{
2191 return m_wifiPhy->GetNumberOfAntennas();
2192}
2193
2194uint8_t
2195WifiRemoteStationManager::GetMaxNumberOfTransmitStreams() const
2196{
2197 return m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2198}
2199
2200bool
2201WifiRemoteStationManager::UseLdpcForDestination(Mac48Address dest) const
2202{
2203 return (GetLdpcSupported() && GetLdpcSupported(dest));
2204}
2205
2206} // namespace ns3
The IEEE 802.11be EHT Capabilities.
uint8_t GetHighestSupportedRxMcs(EhtMcsAndNssSet::EhtMcsMapType mapType)
Get the highest supported RX MCS for a given EHT-MCS map type.
Hold variables of type enum.
Definition: enum.h:62
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 IEEE 802.11ax HE Capabilities.
uint8_t GetHighestMcsSupported() const
Get highest MCS supported.
bool GetHeSuPpdu1xHeLtf800nsGi() const
Get 1xHE-LTF and 800ns GI in HE SU PPDU reception support.
uint8_t GetChannelWidthSet() const
Get channel width set.
The HT Capabilities Information Element.
uint8_t GetSupportedChannelWidth() const
Return the supported channel width.
bool IsSupportedMcs(uint8_t mcs) const
Return the is MCS supported flag.
an EUI-48 address
Definition: mac48-address.h:46
bool IsGroup() const
A base class which provides memory management and object aggregation.
Definition: object.h:89
static WifiMode GetOfdmRate(uint64_t rate, uint16_t bw=20)
Return a WifiMode for OFDM corresponding to the provided rate and the channel bandwidth (20,...
Definition: ofdm-phy.cc:414
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Hold an unsigned integer type.
Definition: uinteger.h:45
The IEEE 802.11ac VHT Capabilities.
bool IsSupportedMcs(uint8_t mcs, uint8_t nss) const
Get the is MCS supported.
uint8_t GetSupportedChannelWidthSet() const
Get the supported channel width set.
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
bool IsMgt() const
Return true if the Type is Management.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition: wifi-mac.cc:422
represent a single transmission mode
Definition: wifi-mode.h:51
bool IsHigherDataRate(WifiMode mode) const
Definition: wifi-mode.cc:208
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:185
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:122
uint8_t GetMcsValue() const
Definition: wifi-mode.cc:163
AttributeValue implementation for WifiMode.
Definition: wifi-mode.h:254
Ptr< VhtConfiguration > GetVhtConfiguration() const
Ptr< EhtConfiguration > GetEhtConfiguration() const
Ptr< HtConfiguration > GetHtConfiguration() const
Ptr< HeConfiguration > GetHeConfiguration() const
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:1073
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1043
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition: wifi-phy.cc:621
uint16_t GetTxBandwidth(WifiMode mode, uint16_t maxAllowedBandWidth=std::numeric_limits< uint16_t >::max()) const
Get the bandwidth for a transmission occurring on the current operating channel and using the given W...
Definition: wifi-phy.cc:1097
std::list< WifiMode > GetMcsList() const
The WifiPhy::GetMcsList() method is used (e.g., by a WifiRemoteStationManager) to determine the set o...
Definition: wifi-phy.cc:2035
std::list< WifiMode > GetModeList() const
The WifiPhy::GetModeList() method is used (e.g., by a WifiRemoteStationManager) to determine the set ...
Definition: wifi-phy.cc:1986
TID independent remote station statistics.
void NotifyTxSuccess(uint32_t retryCounter)
Updates average frame error rate when data or RTS was transmitted successfully.
void NotifyTxFailed()
Updates average frame error rate when final data or RTS has failed.
hold a list of per-remote-station state.
void ReportDataFailed(Ptr< const WifiMpdu > mpdu)
Should be invoked whenever the AckTimeout associated to a transmission attempt expires.
bool GetQosSupported(Mac48Address address) const
Return whether the given station is QoS capable.
WifiTxVector GetAckTxVector(Mac48Address to, const WifiTxVector &dataTxVector) const
Return a TXVECTOR for the Ack frame given the destination and the mode of the Data used by the sender...
virtual bool DoNeedFragmentation(WifiRemoteStation *station, Ptr< const Packet > packet, bool normally)
uint32_t m_fragmentationThreshold
Current threshold for fragmentation.
void SetShortSlotTimeEnabled(bool enable)
Enable or disable short slot time.
void SetPsMode(const Mac48Address &address, bool isInPsMode)
Register whether the STA is in Power Save mode or not.
void AddBasicMode(WifiMode mode)
Invoked in a STA upon association to store the set of rates which belong to the BSSBasicRateSet of th...
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
uint32_t GetNFragments(Ptr< const WifiMpdu > mpdu)
Return the number of fragments needed for the given packet.
uint16_t GetAssociationId(Mac48Address remoteAddress) const
Get the AID of a remote station.
ProtectionMode m_htProtectionMode
Protection mode for HT stations when non-HT stations are detected.
void AdjustTxVectorForIcf(WifiTxVector &txVector) const
Adjust the TXVECTOR for an initial Control frame to ensure that the modulation class is non-HT and th...
std::array< uint32_t, AC_BE_NQOS > m_slrc
long retry count per AC
WifiRemoteStation * Lookup(Mac48Address address) const
Return the station associated with the given address.
uint32_t GetFragmentationThreshold() const
Return the fragmentation threshold.
bool NeedRetransmission(Ptr< const WifiMpdu > mpdu)
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)
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.
bool GetShortSlotTimeEnabled() const
Return whether the device uses short slot time.
void DoDispose() override
Destructor implementation.
virtual void DoReportDataFailed(WifiRemoteStation *station)=0
This method is a pure virtual method that must be implemented by the sub-class.
bool NeedRts(const WifiMacHeader &header, uint32_t size)
bool IsLastFragment(Ptr< const WifiMpdu > mpdu, uint32_t fragmentNumber)
void ReportFinalDataFailed(Ptr< const WifiMpdu > mpdu)
Should be invoked after calling ReportDataFailed if NeedRetransmission returns false.
void SetUseNonErpProtection(bool enable)
Enable or disable protection for non-ERP stations.
bool m_useNonHtProtection
flag if protection for non-HT stations against HT transmissions is enabled
bool GetShortPreambleSupported(Mac48Address address) const
Return whether the station supports short PHY preamble or not.
void AddAllSupportedModes(Mac48Address address)
Invoked in a STA or AP to store all of the modes supported by a destination which is also supported l...
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...
void ReportRtsOk(const WifiMacHeader &header, double ctsSnr, WifiMode ctsMode, double rtsSnr)
Should be invoked whenever we receive the CTS associated to an RTS we just sent.
void AddSupportedMcs(Mac48Address address, WifiMode mcs)
Record the MCS index supported by the station.
WifiTxVector GetBlockAckTxVector(Mac48Address to, const WifiTxVector &dataTxVector) const
Return a TXVECTOR for the BlockAck frame given the destination and the mode of the Data used by the s...
void RemoveAllSupportedMcs(Mac48Address address)
Invoked in a STA or AP to delete all of the supported MCS by a destination.
uint32_t DoGetFragmentationThreshold() const
Return the current fragmentation threshold.
WifiModeList m_bssBasicMcsSet
basic MCS set
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
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.
virtual WifiTxVector DoGetDataTxVector(WifiRemoteStation *station, uint16_t allowedWidth)=0
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 ReportRxOk(Mac48Address address, RxSignalInfo rxSignalInfo, WifiTxVector txVector)
uint8_t m_defaultTxPowerLevel
Default transmission power level.
static TypeId GetTypeId()
Get the type ID.
WifiMode m_nonUnicastMode
Transmission mode for non-unicast Data frames.
void SetUseNonHtProtection(bool enable)
Enable or disable protection for non-HT stations.
uint16_t GetGuardInterval() const
Return the supported HE guard interval duration (in nanoseconds).
bool IsAssociated(Mac48Address address) const
Return whether the station associated.
bool NeedFragmentation(Ptr< const WifiMpdu > mpdu)
void ReportAmpduTxStatus(Mac48Address address, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus, double rxSnr, double dataSnr, WifiTxVector dataTxVector)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
uint32_t GetFragmentOffset(Ptr< const WifiMpdu > mpdu, uint32_t fragmentNumber)
WifiRemoteStationInfo GetInfo(Mac48Address address)
uint32_t GetFragmentSize(Ptr< const WifiMpdu > mpdu, uint32_t fragmentNumber)
WifiTxVector GetCtsToSelfTxVector()
Since CTS-to-self parameters are not dependent on the station, it is implemented in wifi remote stati...
uint8_t GetNBasicMcs() const
Return the number of basic MCS index.
bool GetHtSupported() const
Return whether the device has HT capability support enabled.
void RecordWaitAssocTxOk(Mac48Address address)
Records that we are waiting for an ACK for the association response we sent.
void SetFragmentationThreshold(uint32_t threshold)
Sets a fragmentation threshold.
Ptr< WifiMac > m_wifiMac
This is a pointer to the WifiMac associated with this WifiRemoteStationManager that is set on call to...
void RecordGotAssocTxOk(Mac48Address address)
Records that we got an ACK for the association response we sent.
bool GetLdpcSupported() const
Return whether the device has LDPC support enabled.
WifiTxVector GetRtsTxVector(Mac48Address address, uint16_t allowedWidth)
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::optional< double > GetMostRecentRssi(Mac48Address address) const
std::shared_ptr< WifiRemoteStationState > LookupState(Mac48Address address) const
Return the state of the station associated with the given address.
std::array< uint32_t, AC_BE_NQOS > m_ssrc
short retry count per AC
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 NeedRetransmission returns false.
StationStates m_states
States of known stations.
bool NeedCtsToSelf(WifiTxVector txVector)
Return if we need to do CTS-to-self before sending a DATA.
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.
void SetMaxSsrc(uint32_t maxSsrc)
Sets the maximum STA short retry count (SSRC).
WifiMode GetBasicMcs(uint8_t i) const
Return the MCS at the given list index.
TracedCallback< Mac48Address > m_macTxDataFailed
The trace source fired when the transmission of a single data packet has failed.
uint16_t GetStaId(Mac48Address address, const WifiTxVector &txVector) const
If the given TXVECTOR is used for a MU transmission, return the STAID of the station with the given a...
WifiMode GetBasicMode(uint8_t i) const
Return a basic mode from the set of basic modes.
void AddSupportedPhyPreamble(Mac48Address address, bool isShortPreambleSupported)
Record whether the short PHY preamble is supported by the station.
bool GetShortGuardIntervalSupported() const
Return whether the device has SGI support enabled.
virtual void SetupPhy(const Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
virtual void DoReportRtsFailed(WifiRemoteStation *station)=0
This method is a pure virtual method that must be implemented by the sub-class.
void RecordDisassociated(Mac48Address address)
Records that the STA was disassociated.
virtual WifiTxVector DoGetRtsTxVector(WifiRemoteStation *station)=0
uint16_t GetChannelWidthSupported(Mac48Address address) const
Return the channel width supported by the station.
uint32_t m_maxSlrc
Maximum STA long retry count (SLRC)
void Reset()
Reset the station, invoked in a STA upon dis-association or in an AP upon reboot.
bool GetUseNonErpProtection() const
Return whether the device supports protection of non-ERP stations.
bool IsAssocRefused(Mac48Address address) const
Return whether we refused an association request from the given station.
virtual void DoReportAmpduTxStatus(WifiRemoteStation *station, uint16_t nSuccessfulMpdus, uint16_t nFailedMpdus, double rxSnr, double dataSnr, uint16_t dataChannelWidth, uint8_t dataNss)
Typically called per A-MPDU, either when a Block ACK was successfully received or when a BlockAckTime...
bool GetVhtSupported() const
Return whether the device has VHT capability support enabled.
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.
virtual void DoReportDataOk(WifiRemoteStation *station, double ackSnr, WifiMode ackMode, double dataSnr, uint16_t dataChannelWidth, uint8_t dataNss)=0
This method is a pure virtual method that must be implemented by the sub-class.
WifiTxVector GetDataTxVector(const WifiMacHeader &header, uint16_t allowedWidth)
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.
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.
virtual bool DoNeedRetransmission(WifiRemoteStation *station, Ptr< const Packet > packet, bool normally)
WifiMode GetDefaultMode() const
Return the default transmission mode.
void RecordGotAssocTxFailed(Mac48Address address)
Records that we missed an ACK for the association response we sent.
std::optional< Mac48Address > GetMldAddress(const Mac48Address &address) const
Get the address of the MLD the given station is affiliated with, if any.
virtual void DoReportFinalRtsFailed(WifiRemoteStation *station)=0
This method is a pure virtual method that must be implemented by the sub-class.
virtual void SetupMac(const Ptr< WifiMac > mac)
Set up MAC associated with this device since it is the object that knows the full set of timing param...
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 mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetNess(uint8_t ness)
Sets the Ness number.
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
void SetLdpc(bool ldpc)
Sets if LDPC FEC coding is being used.
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t 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.
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.
void SetBssColor(uint8_t color)
Set the BSS color.
void SetNTx(uint8_t nTx)
Sets the number of TX antennas.
uint16_t GetChannelWidth() const
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:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
Ptr< const AttributeChecker > MakeWifiModeChecker()
Definition: wifi-mode.cc:263
Ptr< const AttributeAccessor > MakeWifiModeAccessor(T1 a1)
Definition: wifi-mode.h:254
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_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:261
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
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:134
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:73
@ STA
Definition: wifi-mac.h:65
@ AP
Definition: wifi-mac.h:66
@ 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.
Definition: wifi-phy-band.h:39
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ 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.
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octets of the IEEE 802.11 MAC FCS field.
bool IsAllowedControlAnswerModulationClass(WifiModulationClass modClassReq, WifiModulationClass modClassAnswer)
Return whether the modulation class of the selected mode for the control answer frame is allowed.
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:189
uint16_t ConvertGuardIntervalToNanoSeconds(WifiMode mode, const Ptr< WifiNetDevice > device)
Convert the guard interval to nanoseconds based on the WifiMode.
WifiPreamble GetPreambleForTransmission(WifiModulationClass modulation, bool useShortPreamble)
Return the preamble to be used for the transmission.
std::vector< WifiMode > WifiModeList
In various parts of the code, folk are interested in maintaining a list of transmission modes.
Definition: wifi-mode.h:262
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
EhtMcsMapType
The different EHT-MCS map types as defined in 9.4.2.313.4 Supported EHT-MCS And NSS Set field.
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
double rssi
RSSI in dBm.
Definition: phy-entity.h:71
double snr
SNR in linear scale.
Definition: phy-entity.h:70
hold per-remote-station state.
WifiRemoteStationState * m_state
Remote station state.
std::pair< double, Time > m_rssiAndUpdateTimePair
RSSI (in dBm) 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.
uint16_t m_channelWidth
Channel width (in MHz) 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
uint16_t m_guardInterval
HE Guard interval duration (in nanoseconds) supported by the remote station.
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
Ptr< const HeCapabilities > m_heCapabilities
remote station HE capabilities