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#include "wifi-tx-parameters.h"
30
31#include "ns3/boolean.h"
32#include "ns3/eht-configuration.h"
33#include "ns3/enum.h"
34#include "ns3/erp-ofdm-phy.h"
35#include "ns3/he-configuration.h"
36#include "ns3/ht-configuration.h"
37#include "ns3/ht-phy.h"
38#include "ns3/log.h"
39#include "ns3/simulator.h"
40#include "ns3/uinteger.h"
41#include "ns3/vht-configuration.h"
42
43namespace ns3
44{
45
46NS_LOG_COMPONENT_DEFINE("WifiRemoteStationManager");
47
48NS_OBJECT_ENSURE_REGISTERED(WifiRemoteStationManager);
49
50TypeId
52{
53 static TypeId tid =
54 TypeId("ns3::WifiRemoteStationManager")
56 .SetGroupName("Wifi")
57 .AddAttribute("MaxSsrc",
58 "The maximum number of retransmission attempts for any packet with size "
59 "<= RtsCtsThreshold. "
60 "This value will not have any effect on some rate control algorithms.",
63 MakeUintegerChecker<uint32_t>())
64 .AddAttribute("MaxSlrc",
65 "The maximum number of retransmission attempts for any packet with size "
66 "> RtsCtsThreshold. "
67 "This value will not have any effect on some rate control algorithms.",
70 MakeUintegerChecker<uint32_t>())
71 .AddAttribute("RtsCtsThreshold",
72 "If the size of the PSDU is bigger than this value, we use an RTS/CTS "
73 "handshake before sending the data frame."
74 "This value will not have any effect on some rate control algorithms.",
75 UintegerValue(4692480),
77 MakeUintegerChecker<uint32_t>(0, 4692480))
78 .AddAttribute("RtsCtsTxDurationThresh",
79 "If this threshold is a strictly positive value and the TX duration of "
80 "the PSDU is greater than or equal to this threshold, we use an RTS/CTS "
81 "handshake before sending the data frame.",
82 TimeValue(Time{0}),
85 .AddAttribute(
86 "FragmentationThreshold",
87 "If the size of the PSDU is bigger than this value, we fragment it such that the "
88 "size of the fragments are equal or smaller. "
89 "This value does not apply when it is carried in an A-MPDU. "
90 "This value will not have any effect on some rate control algorithms.",
91 UintegerValue(65535),
94 MakeUintegerChecker<uint32_t>())
95 .AddAttribute("NonUnicastMode",
96 "Wifi mode used for non-unicast transmissions.",
100 .AddAttribute("DefaultTxPowerLevel",
101 "Default power level to be used for transmissions. "
102 "This is the power level that is used by all those WifiManagers that do "
103 "not implement TX power control.",
104 UintegerValue(0),
106 MakeUintegerChecker<uint8_t>())
107 .AddAttribute("ErpProtectionMode",
108 "Protection mode used when non-ERP STAs are connected to an ERP AP: "
109 "Rts-Cts or Cts-To-Self",
111 MakeEnumAccessor<WifiRemoteStationManager::ProtectionMode>(
114 "Rts-Cts",
116 "Cts-To-Self"))
117 .AddAttribute("HtProtectionMode",
118 "Protection mode used when non-HT STAs are connected to a HT AP: Rts-Cts "
119 "or Cts-To-Self",
121 MakeEnumAccessor<WifiRemoteStationManager::ProtectionMode>(
124 "Rts-Cts",
126 "Cts-To-Self"))
127 .AddTraceSource("MacTxRtsFailed",
128 "The transmission of a RTS by the MAC layer has failed",
130 "ns3::Mac48Address::TracedCallback")
131 .AddTraceSource("MacTxDataFailed",
132 "The transmission of a data packet by the MAC layer has failed",
134 "ns3::Mac48Address::TracedCallback")
135 .AddTraceSource(
136 "MacTxFinalRtsFailed",
137 "The transmission of a RTS has exceeded the maximum number of attempts",
139 "ns3::Mac48Address::TracedCallback")
140 .AddTraceSource(
141 "MacTxFinalDataFailed",
142 "The transmission of a data packet has exceeded the maximum number of attempts",
144 "ns3::Mac48Address::TracedCallback");
145 return tid;
146}
147
149 : m_useNonErpProtection(false),
150 m_useNonHtProtection(false),
151 m_shortPreambleEnabled(false),
152 m_shortSlotTimeEnabled(false)
153{
154 NS_LOG_FUNCTION(this);
155 m_ssrc.fill(0);
156 m_slrc.fill(0);
157}
158
160{
161 NS_LOG_FUNCTION(this);
162}
163
164void
166{
167 NS_LOG_FUNCTION(this);
168 Reset();
169}
170
171void
173{
174 NS_LOG_FUNCTION(this << phy);
175 // We need to track our PHY because it is the object that knows the
176 // full set of transmit rates that are supported. We need to know
177 // this in order to find the relevant mandatory rates when choosing a
178 // transmit rate for automatic control responses like
179 // acknowledgments.
180 m_wifiPhy = phy;
181}
182
183void
185{
186 NS_LOG_FUNCTION(this << mac);
187 // We need to track our MAC because it is the object that knows the
188 // full set of interframe spaces.
189 m_wifiMac = mac;
190}
191
192int64_t
194{
195 NS_LOG_FUNCTION(this << stream);
196 return 0;
197}
198
199void
201{
202 NS_LOG_FUNCTION(this << maxSsrc);
203 m_maxSsrc = maxSsrc;
204}
205
206void
208{
209 NS_LOG_FUNCTION(this << maxSlrc);
210 m_maxSlrc = maxSlrc;
211}
212
213void
215{
216 NS_LOG_FUNCTION(this << threshold);
217 m_rtsCtsThreshold = threshold;
218}
219
220void
222{
223 NS_LOG_FUNCTION(this << threshold);
225}
226
227void
229{
230 NS_LOG_FUNCTION(this << enable);
231 m_shortPreambleEnabled = enable;
232}
233
234void
236{
237 NS_LOG_FUNCTION(this << enable);
238 m_shortSlotTimeEnabled = enable;
239}
240
241bool
243{
245}
246
247bool
249{
251}
252
253bool
255{
256 return bool(m_wifiPhy->GetDevice()->GetHtConfiguration());
257}
258
259bool
261{
264}
265
266bool
268{
269 return bool(m_wifiPhy->GetDevice()->GetHeConfiguration());
270}
271
272bool
274{
275 return bool(m_wifiPhy->GetDevice()->GetEhtConfiguration());
276}
277
278bool
280{
281 if (GetHtSupported())
282 {
284 NS_ASSERT(htConfiguration); // If HT is supported, we should have a HT configuration
285 // attached
286 return htConfiguration->GetLdpcSupported();
287 }
288 return false;
289}
290
291bool
293{
294 if (GetHtSupported())
295 {
297 NS_ASSERT(htConfiguration); // If HT is supported, we should have a HT configuration
298 // attached
299 if (htConfiguration->GetShortGuardIntervalSupported())
300 {
301 return true;
302 }
303 }
304 return false;
305}
306
307uint16_t
309{
310 uint16_t gi = 0;
311 if (GetHeSupported())
312 {
314 NS_ASSERT(heConfiguration); // If HE is supported, we should have a HE configuration
315 // attached
316 gi = static_cast<uint16_t>(heConfiguration->GetGuardInterval().GetNanoSeconds());
317 }
318 return gi;
319}
320
323{
325}
326
327void
329 bool isShortPreambleSupported)
330{
331 NS_LOG_FUNCTION(this << address << isShortPreambleSupported);
332 NS_ASSERT(!address.IsGroup());
333 LookupState(address)->m_shortPreamble = isShortPreambleSupported;
334}
335
336void
338 bool isShortSlotTimeSupported)
339{
340 NS_LOG_FUNCTION(this << address << isShortSlotTimeSupported);
341 NS_ASSERT(!address.IsGroup());
342 LookupState(address)->m_shortSlotTime = isShortSlotTimeSupported;
343}
344
345void
347{
348 NS_LOG_FUNCTION(this << address << mode);
349 NS_ASSERT(!address.IsGroup());
350 auto state = LookupState(address);
351 for (const auto& i : state->m_operationalRateSet)
352 {
353 if (i == mode)
354 {
355 return; // already in
356 }
357 }
358 if ((mode.GetModulationClass() == WIFI_MOD_CLASS_DSSS) ||
360 {
361 state->m_dsssSupported = true;
362 }
364 {
365 state->m_erpOfdmSupported = true;
366 }
367 else if (mode.GetModulationClass() == WIFI_MOD_CLASS_OFDM)
368 {
369 state->m_ofdmSupported = true;
370 }
371 state->m_operationalRateSet.push_back(mode);
372}
373
374void
376{
377 NS_LOG_FUNCTION(this << address);
378 NS_ASSERT(!address.IsGroup());
379 auto state = LookupState(address);
380 state->m_operationalRateSet.clear();
381 for (const auto& mode : m_wifiPhy->GetModeList())
382 {
383 state->m_operationalRateSet.push_back(mode);
384 if (mode.IsMandatory())
385 {
386 AddBasicMode(mode);
387 }
388 }
389}
390
391void
393{
394 NS_LOG_FUNCTION(this << address);
395 NS_ASSERT(!address.IsGroup());
396 auto state = LookupState(address);
397
398 const auto& mcsList = m_wifiPhy->GetMcsList();
399 state->m_operationalMcsSet = WifiModeList(mcsList.begin(), mcsList.end());
400}
401
402void
404{
405 NS_LOG_FUNCTION(this << address);
406 NS_ASSERT(!address.IsGroup());
407 LookupState(address)->m_operationalMcsSet.clear();
408}
409
410void
412{
413 NS_LOG_FUNCTION(this << address << mcs);
414 NS_ASSERT(!address.IsGroup());
415 auto state = LookupState(address);
416 for (const auto& i : state->m_operationalMcsSet)
417 {
418 if (i == mcs)
419 {
420 return; // already in
421 }
422 }
423 state->m_operationalMcsSet.push_back(mcs);
424}
425
426bool
428{
429 return LookupState(address)->m_shortPreamble;
430}
431
432bool
434{
435 return LookupState(address)->m_shortSlotTime;
436}
437
438bool
440{
441 return LookupState(address)->m_qosSupported;
442}
443
444bool
446{
447 if (address.IsGroup())
448 {
449 return false;
450 }
451 return LookupState(address)->m_state == WifiRemoteStationState::BRAND_NEW;
452}
453
454bool
456{
457 if (address.IsGroup())
458 {
459 return true;
460 }
461 return LookupState(address)->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK;
462}
463
464bool
466{
467 if (address.IsGroup())
468 {
469 return false;
470 }
471 return LookupState(address)->m_state == WifiRemoteStationState::WAIT_ASSOC_TX_OK;
472}
473
474void
476{
477 NS_ASSERT(!address.IsGroup());
479}
480
481void
483{
484 NS_ASSERT(!address.IsGroup());
486}
487
488void
490{
491 NS_ASSERT(!address.IsGroup());
493}
494
495void
497{
498 NS_ASSERT(!address.IsGroup());
500}
501
502bool
504{
505 if (address.IsGroup())
506 {
507 return false;
508 }
509 return LookupState(address)->m_state == WifiRemoteStationState::ASSOC_REFUSED;
510}
511
512void
514{
515 NS_ASSERT(!address.IsGroup());
517}
518
519uint16_t
521{
522 std::shared_ptr<WifiRemoteStationState> state;
523 if (!remoteAddress.IsGroup() &&
524 (state = LookupState(remoteAddress))->m_state == WifiRemoteStationState::GOT_ASSOC_TX_OK)
525 {
526 return state->m_aid;
527 }
528 return SU_STA_ID;
529}
530
531uint16_t
533{
534 NS_LOG_FUNCTION(this << address << txVector);
535
536 uint16_t staId = SU_STA_ID;
537
538 if (txVector.IsMu())
539 {
540 if (m_wifiMac->GetTypeOfStation() == AP)
541 {
542 staId = GetAssociationId(address);
543 }
544 else if (m_wifiMac->GetTypeOfStation() == STA)
545 {
546 Ptr<StaWifiMac> staMac = StaticCast<StaWifiMac>(m_wifiMac);
547 if (staMac->IsAssociated())
548 {
549 staId = staMac->GetAssociationId();
550 }
551 }
552 }
553
554 NS_LOG_DEBUG("Returning STAID = " << staId);
555 return staId;
556}
557
558bool
560{
561 return LookupState(address)->m_isInPsMode;
562}
563
564void
565WifiRemoteStationManager::SetPsMode(const Mac48Address& address, bool isInPsMode)
566{
567 LookupState(address)->m_isInPsMode = isInPsMode;
568}
569
570std::optional<Mac48Address>
572{
573 if (auto stateIt = m_states.find(address);
574 stateIt != m_states.end() && stateIt->second->m_mleCommonInfo)
575 {
576 return stateIt->second->m_mleCommonInfo->m_mldMacAddress;
577 }
578
579 return std::nullopt;
580}
581
582std::optional<Mac48Address>
584{
585 auto stateIt = m_states.find(mldAddress);
586
587 if (stateIt == m_states.end() || !stateIt->second->m_mleCommonInfo)
588 {
589 // MLD address not found
590 return std::nullopt;
591 }
592
593 NS_ASSERT(stateIt->second->m_mleCommonInfo->m_mldMacAddress == mldAddress);
594 return stateIt->second->m_address;
595}
596
598WifiRemoteStationManager::GetDataTxVector(const WifiMacHeader& header, uint16_t allowedWidth)
599{
600 NS_LOG_FUNCTION(this << header << allowedWidth);
601 Mac48Address address = header.GetAddr1();
602 if (!header.IsMgt() && address.IsGroup())
603 {
605 WifiTxVector v;
606 v.SetMode(mode);
610 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mode, allowedWidth));
613 v.SetNss(1);
614 v.SetNess(0);
615 return v;
616 }
617 WifiTxVector txVector;
618 if (header.IsMgt())
619 {
620 // Use the lowest basic rate for management frames
621 WifiMode mgtMode;
622 if (GetNBasicModes() > 0)
623 {
624 mgtMode = GetBasicMode(0);
625 }
626 else
627 {
628 mgtMode = GetDefaultMode();
629 }
630 txVector.SetMode(mgtMode);
631 txVector.SetPreambleType(
634 uint16_t channelWidth = allowedWidth;
635 if (!header.GetAddr1().IsGroup())
636 {
637 if (uint16_t rxWidth = GetChannelWidthSupported(header.GetAddr1());
638 rxWidth < channelWidth)
639 {
640 channelWidth = rxWidth;
641 }
642 }
643
644 txVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mgtMode, channelWidth));
645 txVector.SetGuardInterval(
647 }
648 else
649 {
650 txVector = DoGetDataTxVector(Lookup(address), allowedWidth);
652 ? false
653 : UseLdpcForDestination(address));
654 }
656 if (heConfiguration)
657 {
658 txVector.SetBssColor(heConfiguration->GetBssColor());
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((txVector.GetChannelWidth() % 20 != 0) || (allowedWidth % 20 != 0) ||
663 (txVector.GetChannelWidth() <= allowedWidth),
664 "TXVECTOR channel width (" << txVector.GetChannelWidth()
665 << " MHz) exceeds allowed width (" << allowedWidth
666 << " MHz)");
667 return txVector;
668}
669
672{
673 WifiMode defaultMode = GetDefaultMode();
674 WifiPreamble defaultPreamble;
675 if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_EHT)
676 {
677 defaultPreamble = WIFI_PREAMBLE_EHT_MU;
678 }
679 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HE)
680 {
681 defaultPreamble = WIFI_PREAMBLE_HE_SU;
682 }
683 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_VHT)
684 {
685 defaultPreamble = WIFI_PREAMBLE_VHT_SU;
686 }
687 else if (defaultMode.GetModulationClass() == WIFI_MOD_CLASS_HT)
688 {
689 defaultPreamble = WIFI_PREAMBLE_HT_MF;
690 }
691 else
692 {
693 defaultPreamble = WIFI_PREAMBLE_LONG;
694 }
695
696 return WifiTxVector(defaultMode,
698 defaultPreamble,
701 1,
702 0,
703 m_wifiPhy->GetTxBandwidth(defaultMode),
704 false);
705}
706
709{
710 NS_LOG_FUNCTION(this << address << allowedWidth);
711 WifiTxVector v;
712 if (address.IsGroup())
713 {
715 v.SetMode(mode);
722 v.SetNss(1);
723 v.SetNess(0);
724 }
725 else
726 {
727 v = DoGetRtsTxVector(Lookup(address));
728 }
729 auto modulation = v.GetModulationClass();
730
731 if (allowedWidth >= 40 &&
732 (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS))
733 {
734 // RTS must be sent in a non-HT duplicate PPDU because it must protect a frame being
735 // transmitted on at least 40 MHz. Change the modulation class to ERP-OFDM and the rate
736 // to 6 Mbps
738 modulation = v.GetModulationClass();
739 }
740 // do not set allowedWidth as the TX width if the modulation class is (HR-)DSSS (allowedWidth
741 // may be >= 40 MHz) or allowedWidth is 22 MHz (the selected modulation class may be OFDM)
742 if (modulation != WIFI_MOD_CLASS_DSSS && modulation != WIFI_MOD_CLASS_HR_DSSS &&
743 allowedWidth != 22)
744 {
745 v.SetChannelWidth(allowedWidth);
746 }
747
748 return v;
749}
750
753{
754 NS_ASSERT(!to.IsGroup());
755 WifiMode ctsMode = GetControlAnswerMode(rtsTxMode);
756 WifiTxVector v;
757 v.SetMode(ctsMode);
762 uint16_t ctsTxGuardInterval =
764 v.SetGuardInterval(ctsTxGuardInterval);
765 v.SetNss(1);
766 return v;
767}
768
769void
771{
772 NS_LOG_FUNCTION(this << txVector);
773
774 auto txMode = txVector.GetMode();
775 if (txMode.GetModulationClass() >= WIFI_MOD_CLASS_HT)
776 {
777 auto rate = txMode.GetDataRate(txVector);
778 if (rate >= 24e6)
779 {
780 rate = 24e6;
781 }
782 else if (rate >= 12e6)
783 {
784 rate = 12e6;
785 }
786 else
787 {
788 rate = 6e6;
789 }
792 {
793 txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(rate));
794 }
795 else
796 {
797 txVector.SetMode(OfdmPhy::GetOfdmRate(rate));
798 }
799 }
800}
801
804{
805 NS_ASSERT(!to.IsGroup());
806 WifiMode ackMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
807 WifiTxVector v;
808 v.SetMode(ackMode);
813 uint16_t ackTxGuardInterval =
815 v.SetGuardInterval(ackTxGuardInterval);
816 v.SetNss(1);
817 return v;
818}
819
822 const WifiTxVector& dataTxVector) const
823{
824 NS_ASSERT(!to.IsGroup());
825 WifiMode blockAckMode = GetControlAnswerMode(dataTxVector.GetMode(GetStaId(to, dataTxVector)));
826 WifiTxVector v;
827 v.SetMode(blockAckMode);
831 v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(blockAckMode));
832 uint16_t blockAckTxGuardInterval =
834 v.SetGuardInterval(blockAckTxGuardInterval);
835 v.SetNss(1);
836 return v;
837}
838
841{
842 /**
843 * The standard has relatively unambiguous rules for selecting a
844 * control response rate (the below is quoted from IEEE 802.11-2012,
845 * Section 9.7):
846 *
847 * To allow the transmitting STA to calculate the contents of the
848 * Duration/ID field, a STA responding to a received frame shall
849 * transmit its Control Response frame (either CTS or Ack), other
850 * than the BlockAck control frame, at the highest rate in the
851 * BSSBasicRateSet parameter that is less than or equal to the
852 * rate of the immediately previous frame in the frame exchange
853 * sequence (as defined in Annex G) and that is of the same
854 * modulation class (see Section 9.7.8) as the received frame...
855 */
856 NS_LOG_FUNCTION(this << reqMode);
857 WifiMode mode = GetDefaultMode();
858 bool found = false;
859 // First, search the BSS Basic Rate set
860 for (uint8_t i = 0; i < GetNBasicModes(); i++)
861 {
862 WifiMode testMode = GetBasicMode(i);
863 if ((!found || testMode.IsHigherDataRate(mode)) && (!testMode.IsHigherDataRate(reqMode)) &&
865 testMode.GetModulationClass())))
866 {
867 mode = testMode;
868 // We've found a potentially-suitable transmit rate, but we
869 // need to continue and consider all the basic rates before
870 // we can be sure we've got the right one.
871 found = true;
872 }
873 }
874 if (GetHtSupported())
875 {
876 if (!found)
877 {
878 mode = GetDefaultMcs();
879 for (uint8_t i = 0; i != GetNBasicMcs(); i++)
880 {
881 WifiMode testMode = GetBasicMcs(i);
882 if ((!found || testMode.IsHigherDataRate(mode)) &&
883 (!testMode.IsHigherDataRate(reqMode)) &&
884 (testMode.GetModulationClass() == reqMode.GetModulationClass()))
885 {
886 mode = testMode;
887 // We've found a potentially-suitable transmit rate, but we
888 // need to continue and consider all the basic rates before
889 // we can be sure we've got the right one.
890 found = true;
891 }
892 }
893 }
894 }
895 // If we found a suitable rate in the BSSBasicRateSet, then we are
896 // done and can return that mode.
897 if (found)
898 {
899 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
900 return mode;
901 }
902
903 /**
904 * If no suitable basic rate was found, we search the mandatory
905 * rates. The standard (IEEE 802.11-2007, Section 9.6) says:
906 *
907 * ...If no rate contained in the BSSBasicRateSet parameter meets
908 * these conditions, then the control frame sent in response to a
909 * received frame shall be transmitted at the highest mandatory
910 * rate of the PHY that is less than or equal to the rate of the
911 * received frame, and that is of the same modulation class as the
912 * received frame. In addition, the Control Response frame shall
913 * be sent using the same PHY options as the received frame,
914 * unless they conflict with the requirement to use the
915 * BSSBasicRateSet parameter.
916 *
917 * \todo Note that we're ignoring the last sentence for now, because
918 * there is not yet any manipulation here of PHY options.
919 */
920 for (const auto& thismode : m_wifiPhy->GetModeList())
921 {
922 /* If the rate:
923 *
924 * - is a mandatory rate for the PHY, and
925 * - is equal to or faster than our current best choice, and
926 * - is less than or equal to the rate of the received frame, and
927 * - is of the same modulation class as the received frame
928 *
929 * ...then it's our best choice so far.
930 */
931 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
932 (!thismode.IsHigherDataRate(reqMode)) &&
934 thismode.GetModulationClass())))
935 {
936 mode = thismode;
937 // As above; we've found a potentially-suitable transmit
938 // rate, but we need to continue and consider all the
939 // mandatory rates before we can be sure we've got the right one.
940 found = true;
941 }
942 }
943 if (GetHtSupported())
944 {
945 for (const auto& thismode : m_wifiPhy->GetMcsList())
946 {
947 if (thismode.IsMandatory() && (!found || thismode.IsHigherDataRate(mode)) &&
948 (!thismode.IsHigherCodeRate(reqMode)) &&
949 (thismode.GetModulationClass() == reqMode.GetModulationClass()))
950 {
951 mode = thismode;
952 // As above; we've found a potentially-suitable transmit
953 // rate, but we need to continue and consider all the
954 // mandatory rates before we can be sure we've got the right one.
955 found = true;
956 }
957 }
958 }
959
960 /**
961 * If we still haven't found a suitable rate for the response then
962 * someone has messed up the simulation configuration. This probably means
963 * that the WifiPhyStandard is not set correctly, or that a rate that
964 * is not supported by the PHY has been explicitly requested.
965 *
966 * Either way, it is serious - we can either disobey the standard or
967 * fail, and I have chosen to do the latter...
968 */
969 if (!found)
970 {
971 NS_FATAL_ERROR("Can't find response rate for " << reqMode);
972 }
973
974 NS_LOG_DEBUG("WifiRemoteStationManager::GetControlAnswerMode returning " << mode);
975 return mode;
976}
977
978void
980{
981 NS_LOG_FUNCTION(this << header);
982 NS_ASSERT(!header.GetAddr1().IsGroup());
983 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
984 m_ssrc[ac]++;
985 m_macTxRtsFailed(header.GetAddr1());
987}
988
989void
991{
992 NS_LOG_FUNCTION(this << *mpdu);
993 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
994 AcIndex ac =
995 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
996 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
997 if (longMpdu)
998 {
999 m_slrc[ac]++;
1000 }
1001 else
1002 {
1003 m_ssrc[ac]++;
1004 }
1005 m_macTxDataFailed(mpdu->GetHeader().GetAddr1());
1006 DoReportDataFailed(Lookup(mpdu->GetHeader().GetAddr1()));
1007}
1008
1009void
1011 double ctsSnr,
1012 WifiMode ctsMode,
1013 double rtsSnr)
1014{
1015 NS_LOG_FUNCTION(this << header << ctsSnr << ctsMode << rtsSnr);
1016 NS_ASSERT(!header.GetAddr1().IsGroup());
1017 WifiRemoteStation* station = Lookup(header.GetAddr1());
1018 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1019 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1020 m_ssrc[ac] = 0;
1021 DoReportRtsOk(station, ctsSnr, ctsMode, rtsSnr);
1022}
1023
1024void
1026 double ackSnr,
1027 WifiMode ackMode,
1028 double dataSnr,
1029 WifiTxVector dataTxVector)
1030{
1031 NS_LOG_FUNCTION(this << *mpdu << ackSnr << ackMode << dataSnr << dataTxVector);
1032 const WifiMacHeader& hdr = mpdu->GetHeader();
1033 NS_ASSERT(!hdr.GetAddr1().IsGroup());
1034 WifiRemoteStation* station = Lookup(hdr.GetAddr1());
1035 AcIndex ac = QosUtilsMapTidToAc((hdr.IsQosData()) ? hdr.GetQosTid() : 0);
1036 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1037 if (longMpdu)
1038 {
1039 station->m_state->m_info.NotifyTxSuccess(m_slrc[ac]);
1040 m_slrc[ac] = 0;
1041 }
1042 else
1043 {
1044 station->m_state->m_info.NotifyTxSuccess(m_ssrc[ac]);
1045 m_ssrc[ac] = 0;
1046 }
1047 DoReportDataOk(station,
1048 ackSnr,
1049 ackMode,
1050 dataSnr,
1051 dataTxVector.GetChannelWidth(),
1052 dataTxVector.GetNss(GetStaId(hdr.GetAddr1(), dataTxVector)));
1053}
1054
1055void
1057{
1058 NS_LOG_FUNCTION(this << header);
1059 NS_ASSERT(!header.GetAddr1().IsGroup());
1060 WifiRemoteStation* station = Lookup(header.GetAddr1());
1061 AcIndex ac = QosUtilsMapTidToAc((header.IsQosData()) ? header.GetQosTid() : 0);
1062 station->m_state->m_info.NotifyTxFailed();
1063 m_ssrc[ac] = 0;
1065 DoReportFinalRtsFailed(station);
1066}
1067
1068void
1070{
1071 NS_LOG_FUNCTION(this << *mpdu);
1072 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1073 WifiRemoteStation* station = Lookup(mpdu->GetHeader().GetAddr1());
1074 AcIndex ac =
1075 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1076 station->m_state->m_info.NotifyTxFailed();
1077 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1078 if (longMpdu)
1079 {
1080 m_slrc[ac] = 0;
1081 }
1082 else
1083 {
1084 m_ssrc[ac] = 0;
1085 }
1086 m_macTxFinalDataFailed(mpdu->GetHeader().GetAddr1());
1087 DoReportFinalDataFailed(station);
1088}
1089
1090void
1092 RxSignalInfo rxSignalInfo,
1093 WifiTxVector txVector)
1094{
1095 NS_LOG_FUNCTION(this << address << rxSignalInfo << txVector);
1096 if (address.IsGroup())
1097 {
1098 return;
1099 }
1100 WifiRemoteStation* station = Lookup(address);
1101 DoReportRxOk(station, rxSignalInfo.snr, txVector.GetMode(GetStaId(address, txVector)));
1102 station->m_rssiAndUpdateTimePair = std::make_pair(rxSignalInfo.rssi, Simulator::Now());
1103}
1104
1105void
1107 uint16_t nSuccessfulMpdus,
1108 uint16_t nFailedMpdus,
1109 double rxSnr,
1110 double dataSnr,
1111 WifiTxVector dataTxVector)
1112{
1113 NS_LOG_FUNCTION(this << address << nSuccessfulMpdus << nFailedMpdus << rxSnr << dataSnr
1114 << dataTxVector);
1115 NS_ASSERT(!address.IsGroup());
1116 for (uint16_t i = 0; i < nFailedMpdus; i++)
1117 {
1118 m_macTxDataFailed(address);
1119 }
1121 nSuccessfulMpdus,
1122 nFailedMpdus,
1123 rxSnr,
1124 dataSnr,
1125 dataTxVector.GetChannelWidth(),
1126 dataTxVector.GetNss(GetStaId(address, dataTxVector)));
1127}
1128
1129bool
1131{
1132 NS_LOG_FUNCTION(this << header << &txParams);
1133 auto address = header.GetAddr1();
1134 const auto modulationClass = txParams.m_txVector.GetModulationClass();
1135 if (address.IsGroup())
1136 {
1137 return false;
1138 }
1140 ((modulationClass == WIFI_MOD_CLASS_ERP_OFDM) || (modulationClass == WIFI_MOD_CLASS_HT) ||
1141 (modulationClass == WIFI_MOD_CLASS_VHT) || (modulationClass == WIFI_MOD_CLASS_HE) ||
1142 (modulationClass == WIFI_MOD_CLASS_EHT)) &&
1144 {
1146 "WifiRemoteStationManager::NeedRTS returning true to protect non-ERP stations");
1147 return true;
1148 }
1149 else if (m_htProtectionMode == RTS_CTS &&
1150 ((modulationClass == WIFI_MOD_CLASS_HT) || (modulationClass == WIFI_MOD_CLASS_VHT)) &&
1152 {
1153 NS_LOG_DEBUG("WifiRemoteStationManager::NeedRTS returning true to protect non-HT stations");
1154 return true;
1155 }
1156 NS_ASSERT(txParams.m_txDuration.has_value());
1157 auto size = txParams.GetSize(header.GetAddr1());
1158 bool normally =
1161 return DoNeedRts(Lookup(address), size, normally);
1162}
1163
1164bool
1166{
1167 WifiMode mode = txVector.GetMode();
1168 NS_LOG_FUNCTION(this << mode);
1176 {
1178 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-ERP stations");
1179 return true;
1180 }
1181 else if (m_htProtectionMode == CTS_TO_SELF &&
1185 {
1187 "WifiRemoteStationManager::NeedCtsToSelf returning true to protect non-HT stations");
1188 return true;
1189 }
1190 else if (!m_useNonErpProtection)
1191 {
1192 // search for the BSS Basic Rate set, if the used mode is in the basic set then there is no
1193 // need for CTS To Self
1194 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
1195 {
1196 if (mode == *i)
1197 {
1198 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1199 return false;
1200 }
1201 }
1202 if (GetHtSupported())
1203 {
1204 // search for the BSS Basic MCS set, if the used mode is in the basic set then there is
1205 // no need for CTS To Self
1206 for (auto i = m_bssBasicMcsSet.begin(); i != m_bssBasicMcsSet.end(); i++)
1207 {
1208 if (mode == *i)
1209 {
1210 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning false");
1211 return false;
1212 }
1213 }
1214 }
1215 NS_LOG_DEBUG("WifiRemoteStationManager::NeedCtsToSelf returning true");
1216 return true;
1217 }
1218 return false;
1219}
1220
1221void
1223{
1224 NS_LOG_FUNCTION(this << enable);
1225 m_useNonErpProtection = enable;
1226}
1227
1228bool
1230{
1231 return m_useNonErpProtection;
1232}
1233
1234void
1236{
1237 NS_LOG_FUNCTION(this << enable);
1238 m_useNonHtProtection = enable;
1239}
1240
1241bool
1243{
1244 return m_useNonHtProtection;
1245}
1246
1247bool
1249{
1250 NS_LOG_FUNCTION(this << *mpdu);
1251 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1252 AcIndex ac =
1253 QosUtilsMapTidToAc((mpdu->GetHeader().IsQosData()) ? mpdu->GetHeader().GetQosTid() : 0);
1254 bool longMpdu = (mpdu->GetSize() > m_rtsCtsThreshold);
1255 uint32_t retryCount;
1256 uint32_t maxRetryCount;
1257 if (longMpdu)
1258 {
1259 retryCount = m_slrc[ac];
1260 maxRetryCount = m_maxSlrc;
1261 }
1262 else
1263 {
1264 retryCount = m_ssrc[ac];
1265 maxRetryCount = m_maxSsrc;
1266 }
1267 bool normally = retryCount < maxRetryCount;
1268 NS_LOG_DEBUG("WifiRemoteStationManager::NeedRetransmission count: "
1269 << retryCount << " result: " << std::boolalpha << normally);
1270 return DoNeedRetransmission(Lookup(mpdu->GetHeader().GetAddr1()), mpdu->GetPacket(), normally);
1271}
1272
1273bool
1275{
1276 NS_LOG_FUNCTION(this << *mpdu);
1277 if (mpdu->GetHeader().GetAddr1().IsGroup())
1278 {
1279 return false;
1280 }
1281 bool normally = mpdu->GetSize() > GetFragmentationThreshold();
1282 NS_LOG_DEBUG("WifiRemoteStationManager::NeedFragmentation result: " << std::boolalpha
1283 << normally);
1284 return DoNeedFragmentation(Lookup(mpdu->GetHeader().GetAddr1()), mpdu->GetPacket(), normally);
1285}
1286
1287void
1289{
1290 NS_LOG_FUNCTION(this << threshold);
1291 if (threshold < 256)
1292 {
1293 /*
1294 * ASN.1 encoding of the MAC and PHY MIB (256 ... 8000)
1295 */
1296 NS_LOG_WARN("Fragmentation threshold should be larger than 256. Setting to 256.");
1298 }
1299 else
1300 {
1301 /*
1302 * The length of each fragment shall be an even number of octets, except for the last
1303 * fragment if an MSDU or MMPDU, which may be either an even or an odd number of octets.
1304 */
1305 if (threshold % 2 != 0)
1306 {
1307 NS_LOG_WARN("Fragmentation threshold should be an even number. Setting to "
1308 << threshold - 1);
1309 m_fragmentationThreshold = threshold - 1;
1310 }
1311 else
1312 {
1313 m_fragmentationThreshold = threshold;
1314 }
1315 }
1316}
1317
1320{
1322}
1323
1326{
1327 NS_LOG_FUNCTION(this << *mpdu);
1328 // The number of bytes a fragment can support is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS).
1329 uint32_t nFragments =
1330 (mpdu->GetPacket()->GetSize() /
1331 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH));
1332
1333 // If the size of the last fragment is not 0.
1334 if ((mpdu->GetPacket()->GetSize() %
1335 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH)) > 0)
1336 {
1337 nFragments++;
1338 }
1339 NS_LOG_DEBUG("WifiRemoteStationManager::GetNFragments returning " << nFragments);
1340 return nFragments;
1341}
1342
1345{
1346 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1347 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1348 uint32_t nFragment = GetNFragments(mpdu);
1349 if (fragmentNumber >= nFragment)
1350 {
1351 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning 0");
1352 return 0;
1353 }
1354 // Last fragment
1355 if (fragmentNumber == nFragment - 1)
1356 {
1357 uint32_t lastFragmentSize =
1358 mpdu->GetPacket()->GetSize() -
1359 (fragmentNumber *
1360 (GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH));
1361 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning " << lastFragmentSize);
1362 return lastFragmentSize;
1363 }
1364 // All fragments but the last, the number of bytes is (Threshold - WIFI_HEADER_SIZE - WIFI_FCS).
1365 else
1366 {
1367 uint32_t fragmentSize =
1368 GetFragmentationThreshold() - mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH;
1369 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentSize returning " << fragmentSize);
1370 return fragmentSize;
1371 }
1372}
1373
1376{
1377 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1378 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1379 NS_ASSERT(fragmentNumber < GetNFragments(mpdu));
1380 uint32_t fragmentOffset = fragmentNumber * (GetFragmentationThreshold() -
1381 mpdu->GetHeader().GetSize() - WIFI_MAC_FCS_LENGTH);
1382 NS_LOG_DEBUG("WifiRemoteStationManager::GetFragmentOffset returning " << fragmentOffset);
1383 return fragmentOffset;
1384}
1385
1386bool
1388{
1389 NS_LOG_FUNCTION(this << *mpdu << fragmentNumber);
1390 NS_ASSERT(!mpdu->GetHeader().GetAddr1().IsGroup());
1391 bool isLast = fragmentNumber == (GetNFragments(mpdu) - 1);
1392 NS_LOG_DEBUG("WifiRemoteStationManager::IsLastFragment returning " << std::boolalpha << isLast);
1393 return isLast;
1394}
1395
1396uint8_t
1398{
1399 return m_defaultTxPowerLevel;
1400}
1401
1404{
1405 return LookupState(address)->m_info;
1406}
1407
1408std::optional<double>
1410{
1411 auto station = Lookup(address);
1412 auto rssi = station->m_rssiAndUpdateTimePair.first;
1413 auto ts = station->m_rssiAndUpdateTimePair.second;
1414 if (ts.IsStrictlyPositive())
1415 {
1416 return rssi;
1417 }
1418 return std::nullopt;
1419}
1420
1421std::shared_ptr<WifiRemoteStationState>
1423{
1424 NS_LOG_FUNCTION(this << address);
1425 auto stateIt = m_states.find(address);
1426
1427 if (stateIt != m_states.end())
1428 {
1429 NS_LOG_DEBUG("WifiRemoteStationManager::LookupState returning existing state");
1430 return stateIt->second;
1431 }
1432
1433 auto state = std::make_shared<WifiRemoteStationState>();
1434 state->m_state = WifiRemoteStationState::BRAND_NEW;
1435 state->m_address = address;
1436 state->m_aid = 0;
1437 state->m_operationalRateSet.push_back(GetDefaultMode());
1438 state->m_operationalMcsSet.push_back(GetDefaultMcs());
1439 state->m_dsssSupported = false;
1440 state->m_erpOfdmSupported = false;
1441 state->m_ofdmSupported = false;
1442 state->m_htCapabilities = nullptr;
1443 state->m_vhtCapabilities = nullptr;
1444 state->m_heCapabilities = nullptr;
1445 state->m_ehtCapabilities = nullptr;
1446 state->m_mleCommonInfo = nullptr;
1447 state->m_emlsrEnabled = false;
1448 state->m_channelWidth = m_wifiPhy->GetChannelWidth();
1449 state->m_guardInterval = GetGuardInterval();
1450 state->m_ness = 0;
1451 state->m_aggregation = false;
1452 state->m_qosSupported = false;
1453 state->m_isInPsMode = false;
1454 const_cast<WifiRemoteStationManager*>(this)->m_states.insert({address, state});
1455 NS_LOG_DEBUG("WifiRemoteStationManager::LookupState returning new state");
1456 return state;
1457}
1458
1459WifiRemoteStation*
1460WifiRemoteStationManager::Lookup(Mac48Address address) const
1461{
1462 NS_LOG_FUNCTION(this << address);
1463 NS_ASSERT(!address.IsGroup());
1464 NS_ASSERT(address != m_wifiMac->GetAddress());
1465 auto stationIt = m_stations.find(address);
1466
1467 if (stationIt != m_stations.end())
1468 {
1469 return stationIt->second;
1470 }
1471
1472 WifiRemoteStation* station = DoCreateStation();
1473 station->m_state = LookupState(address).get();
1474 station->m_rssiAndUpdateTimePair = std::make_pair(0, Seconds(0));
1475 const_cast<WifiRemoteStationManager*>(this)->m_stations.insert({address, station});
1476 return station;
1477}
1478
1479void
1480WifiRemoteStationManager::SetAssociationId(Mac48Address remoteAddress, uint16_t aid)
1481{
1482 NS_LOG_FUNCTION(this << remoteAddress << aid);
1483 LookupState(remoteAddress)->m_aid = aid;
1484}
1485
1486void
1487WifiRemoteStationManager::SetQosSupport(Mac48Address from, bool qosSupported)
1488{
1489 NS_LOG_FUNCTION(this << from << qosSupported);
1490 LookupState(from)->m_qosSupported = qosSupported;
1491}
1492
1493void
1494WifiRemoteStationManager::SetEmlsrEnabled(const Mac48Address& from, bool emlsrEnabled)
1495{
1496 NS_LOG_FUNCTION(this << from << emlsrEnabled);
1497 LookupState(from)->m_emlsrEnabled = emlsrEnabled;
1498}
1499
1500void
1501WifiRemoteStationManager::AddStationHtCapabilities(Mac48Address from, HtCapabilities htCapabilities)
1502{
1503 // Used by all stations to record HT capabilities of remote stations
1504 NS_LOG_FUNCTION(this << from << htCapabilities);
1505 auto state = LookupState(from);
1506 if (htCapabilities.GetSupportedChannelWidth() == 1)
1507 {
1508 state->m_channelWidth = 40;
1509 }
1510 else
1511 {
1512 state->m_channelWidth = 20;
1513 }
1514 SetQosSupport(from, true);
1515 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_HT))
1516 {
1517 if (htCapabilities.IsSupportedMcs(mcs.GetMcsValue()))
1518 {
1519 AddSupportedMcs(from, mcs);
1520 }
1521 }
1522 state->m_htCapabilities = Create<const HtCapabilities>(htCapabilities);
1523}
1524
1525void
1526WifiRemoteStationManager::AddStationVhtCapabilities(Mac48Address from,
1527 VhtCapabilities vhtCapabilities)
1528{
1529 // Used by all stations to record VHT capabilities of remote stations
1530 NS_LOG_FUNCTION(this << from << vhtCapabilities);
1531 auto state = LookupState(from);
1532 if (vhtCapabilities.GetSupportedChannelWidthSet() == 1)
1533 {
1534 state->m_channelWidth = 160;
1535 }
1536 else
1537 {
1538 state->m_channelWidth = 80;
1539 }
1540 for (uint8_t i = 1; i <= m_wifiPhy->GetMaxSupportedTxSpatialStreams(); i++)
1541 {
1542 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_VHT))
1543 {
1544 if (vhtCapabilities.IsSupportedMcs(mcs.GetMcsValue(), i))
1545 {
1546 AddSupportedMcs(from, mcs);
1547 }
1548 }
1549 }
1550 state->m_vhtCapabilities = Create<const VhtCapabilities>(vhtCapabilities);
1551}
1552
1553void
1554WifiRemoteStationManager::AddStationHeCapabilities(Mac48Address from, HeCapabilities heCapabilities)
1555{
1556 // Used by all stations to record HE capabilities of remote stations
1557 NS_LOG_FUNCTION(this << from << heCapabilities);
1558 auto state = LookupState(from);
1559 if ((m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_5GHZ) ||
1560 (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_6GHZ))
1561 {
1562 if (heCapabilities.GetChannelWidthSet() & 0x04)
1563 {
1564 state->m_channelWidth = 160;
1565 }
1566 else if (heCapabilities.GetChannelWidthSet() & 0x02)
1567 {
1568 state->m_channelWidth = 80;
1569 }
1570 // For other cases at 5 GHz, the supported channel width is set by the VHT capabilities
1571 }
1572 else if (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
1573 {
1574 if (heCapabilities.GetChannelWidthSet() & 0x01)
1575 {
1576 state->m_channelWidth = 40;
1577 }
1578 else
1579 {
1580 state->m_channelWidth = 20;
1581 }
1582 }
1583 if (heCapabilities.GetHeSuPpdu1xHeLtf800nsGi())
1584 {
1585 state->m_guardInterval = 800;
1586 }
1587 else
1588 {
1589 // todo: Using 3200ns, default value for HeConfiguration::GuardInterval
1590 state->m_guardInterval = 3200;
1591 }
1592 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_HE))
1593 {
1594 if (heCapabilities.GetHighestMcsSupported() >= mcs.GetMcsValue())
1595 {
1596 AddSupportedMcs(from, mcs);
1597 }
1598 }
1599 state->m_heCapabilities = Create<const HeCapabilities>(heCapabilities);
1600 SetQosSupport(from, true);
1601}
1602
1603void
1604WifiRemoteStationManager::AddStationEhtCapabilities(Mac48Address from,
1605 EhtCapabilities ehtCapabilities)
1606{
1607 // Used by all stations to record EHT capabilities of remote stations
1608 NS_LOG_FUNCTION(this << from << ehtCapabilities);
1609 auto state = LookupState(from);
1610 for (const auto& mcs : m_wifiPhy->GetMcsList(WIFI_MOD_CLASS_EHT))
1611 {
1612 for (uint8_t mapType = 0; mapType < EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_MAX; ++mapType)
1613 {
1614 if (ehtCapabilities.GetHighestSupportedRxMcs(
1615 static_cast<EhtMcsAndNssSet::EhtMcsMapType>(mapType)) >= mcs.GetMcsValue())
1616 {
1617 AddSupportedMcs(from, mcs);
1618 }
1619 }
1620 }
1621 state->m_ehtCapabilities = Create<const EhtCapabilities>(ehtCapabilities);
1622 SetQosSupport(from, true);
1623}
1624
1625void
1626WifiRemoteStationManager::AddStationMleCommonInfo(
1627 Mac48Address from,
1628 const std::shared_ptr<CommonInfoBasicMle>& mleCommonInfo)
1629{
1630 NS_LOG_FUNCTION(this << from);
1631 auto state = LookupState(from);
1632 state->m_mleCommonInfo = mleCommonInfo;
1633 // insert another entry in m_states indexed by the MLD address and pointing to the same state
1634 const_cast<WifiRemoteStationManager*>(this)->m_states.insert(
1635 {mleCommonInfo->m_mldMacAddress, state});
1636}
1637
1638Ptr<const HtCapabilities>
1639WifiRemoteStationManager::GetStationHtCapabilities(Mac48Address from)
1640{
1641 return LookupState(from)->m_htCapabilities;
1642}
1643
1645WifiRemoteStationManager::GetStationVhtCapabilities(Mac48Address from)
1646{
1647 return LookupState(from)->m_vhtCapabilities;
1648}
1649
1651WifiRemoteStationManager::GetStationHeCapabilities(Mac48Address from)
1652{
1653 return LookupState(from)->m_heCapabilities;
1654}
1655
1657WifiRemoteStationManager::GetStationEhtCapabilities(Mac48Address from)
1658{
1659 return LookupState(from)->m_ehtCapabilities;
1660}
1661
1662std::optional<std::reference_wrapper<CommonInfoBasicMle::EmlCapabilities>>
1663WifiRemoteStationManager::GetStationEmlCapabilities(const Mac48Address& from)
1664{
1665 if (auto state = LookupState(from);
1666 state->m_mleCommonInfo && state->m_mleCommonInfo->m_emlCapabilities)
1667 {
1668 return state->m_mleCommonInfo->m_emlCapabilities.value();
1669 }
1670 return std::nullopt;
1671}
1672
1673std::optional<std::reference_wrapper<CommonInfoBasicMle::MldCapabilities>>
1674WifiRemoteStationManager::GetStationMldCapabilities(const Mac48Address& from)
1675{
1676 if (auto state = LookupState(from);
1677 state->m_mleCommonInfo && state->m_mleCommonInfo->m_mldCapabilities)
1678 {
1679 return state->m_mleCommonInfo->m_mldCapabilities.value();
1680 }
1681 return std::nullopt;
1682}
1683
1684bool
1685WifiRemoteStationManager::GetLdpcSupported(Mac48Address address) const
1686{
1687 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
1688 Ptr<const VhtCapabilities> vhtCapabilities = LookupState(address)->m_vhtCapabilities;
1689 Ptr<const HeCapabilities> heCapabilities = LookupState(address)->m_heCapabilities;
1690 bool supported = false;
1691 if (htCapabilities)
1692 {
1693 supported |= htCapabilities->GetLdpc();
1694 }
1695 if (vhtCapabilities)
1696 {
1697 supported |= vhtCapabilities->GetRxLdpc();
1698 }
1699 if (heCapabilities)
1700 {
1701 supported |= heCapabilities->GetLdpcCodingInPayload();
1702 }
1703 return supported;
1704}
1705
1707WifiRemoteStationManager::GetDefaultMode() const
1708{
1709 NS_ASSERT(m_wifiPhy);
1710 auto defaultTxMode = m_wifiPhy->GetDefaultMode();
1711 NS_ASSERT(defaultTxMode.IsMandatory());
1712 return defaultTxMode;
1713}
1714
1716WifiRemoteStationManager::GetDefaultMcs() const
1717{
1718 return HtPhy::GetHtMcs0();
1719}
1720
1722WifiRemoteStationManager::GetDefaultModeForSta(const WifiRemoteStation* st) const
1723{
1724 NS_LOG_FUNCTION(this << st);
1725
1726 if (!GetHtSupported() || !GetHtSupported(st))
1727 {
1728 return GetDefaultMode();
1729 }
1730
1731 // find the highest modulation class supported by both stations
1733 if (GetHeSupported() && GetHeSupported(st))
1734 {
1735 modClass = WIFI_MOD_CLASS_HE;
1736 }
1737 else if (GetVhtSupported() && GetVhtSupported(st))
1738 {
1739 modClass = WIFI_MOD_CLASS_VHT;
1740 }
1741
1742 // return the MCS with lowest index
1743 return *m_wifiPhy->GetPhyEntity(modClass)->begin();
1744}
1745
1746void
1747WifiRemoteStationManager::Reset()
1748{
1749 NS_LOG_FUNCTION(this);
1750 m_states.clear();
1751 for (auto& state : m_stations)
1752 {
1753 delete (state.second);
1754 }
1755 m_stations.clear();
1756 m_bssBasicRateSet.clear();
1757 m_bssBasicMcsSet.clear();
1758 m_ssrc.fill(0);
1759 m_slrc.fill(0);
1760}
1761
1762void
1763WifiRemoteStationManager::AddBasicMode(WifiMode mode)
1764{
1765 NS_LOG_FUNCTION(this << mode);
1767 {
1768 NS_FATAL_ERROR("It is not allowed to add a HT rate in the BSSBasicRateSet!");
1769 }
1770 for (uint8_t i = 0; i < GetNBasicModes(); i++)
1771 {
1772 if (GetBasicMode(i) == mode)
1773 {
1774 return;
1775 }
1776 }
1777 m_bssBasicRateSet.push_back(mode);
1778}
1779
1780uint8_t
1781WifiRemoteStationManager::GetNBasicModes() const
1782{
1783 return static_cast<uint8_t>(m_bssBasicRateSet.size());
1784}
1785
1787WifiRemoteStationManager::GetBasicMode(uint8_t i) const
1788{
1789 NS_ASSERT(i < GetNBasicModes());
1790 return m_bssBasicRateSet[i];
1791}
1792
1794WifiRemoteStationManager::GetNNonErpBasicModes() const
1795{
1796 uint32_t size = 0;
1797 for (auto i = m_bssBasicRateSet.begin(); i != m_bssBasicRateSet.end(); i++)
1798 {
1799 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
1800 {
1801 continue;
1802 }
1803 size++;
1804 }
1805 return size;
1806}
1807
1809WifiRemoteStationManager::GetNonErpBasicMode(uint8_t i) const
1810{
1811 NS_ASSERT(i < GetNNonErpBasicModes());
1812 uint32_t index = 0;
1813 bool found = false;
1814 for (auto j = m_bssBasicRateSet.begin(); j != m_bssBasicRateSet.end();)
1815 {
1816 if (i == index)
1817 {
1818 found = true;
1819 }
1820 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
1821 {
1822 if (found)
1823 {
1824 break;
1825 }
1826 }
1827 index++;
1828 j++;
1829 }
1830 return m_bssBasicRateSet[index];
1831}
1832
1833void
1834WifiRemoteStationManager::AddBasicMcs(WifiMode mcs)
1835{
1836 NS_LOG_FUNCTION(this << +mcs.GetMcsValue());
1837 for (uint8_t i = 0; i < GetNBasicMcs(); i++)
1838 {
1839 if (GetBasicMcs(i) == mcs)
1840 {
1841 return;
1842 }
1843 }
1844 m_bssBasicMcsSet.push_back(mcs);
1845}
1846
1847uint8_t
1848WifiRemoteStationManager::GetNBasicMcs() const
1849{
1850 return static_cast<uint8_t>(m_bssBasicMcsSet.size());
1851}
1852
1854WifiRemoteStationManager::GetBasicMcs(uint8_t i) const
1855{
1856 NS_ASSERT(i < GetNBasicMcs());
1857 return m_bssBasicMcsSet[i];
1858}
1859
1861WifiRemoteStationManager::GetNonUnicastMode() const
1862{
1863 if (m_nonUnicastMode == WifiMode())
1864 {
1865 if (GetNBasicModes() > 0)
1866 {
1867 return GetBasicMode(0);
1868 }
1869 else
1870 {
1871 return GetDefaultMode();
1872 }
1873 }
1874 else
1875 {
1876 return m_nonUnicastMode;
1877 }
1878}
1879
1880bool
1881WifiRemoteStationManager::DoNeedRts(WifiRemoteStation* station, uint32_t size, bool normally)
1882{
1883 return normally;
1884}
1885
1886bool
1887WifiRemoteStationManager::DoNeedRetransmission(WifiRemoteStation* station,
1888 Ptr<const Packet> packet,
1889 bool normally)
1890{
1891 return normally;
1892}
1893
1894bool
1895WifiRemoteStationManager::DoNeedFragmentation(WifiRemoteStation* station,
1896 Ptr<const Packet> packet,
1897 bool normally)
1898{
1899 return normally;
1900}
1901
1902void
1903WifiRemoteStationManager::DoReportAmpduTxStatus(WifiRemoteStation* station,
1904 uint16_t nSuccessfulMpdus,
1905 uint16_t nFailedMpdus,
1906 double rxSnr,
1907 double dataSnr,
1908 uint16_t dataChannelWidth,
1909 uint8_t dataNss)
1910{
1911 NS_LOG_DEBUG("DoReportAmpduTxStatus received but the manager does not handle A-MPDUs!");
1912}
1913
1915WifiRemoteStationManager::GetSupported(const WifiRemoteStation* station, uint8_t i) const
1916{
1917 NS_ASSERT(i < GetNSupported(station));
1918 return station->m_state->m_operationalRateSet[i];
1919}
1920
1922WifiRemoteStationManager::GetMcsSupported(const WifiRemoteStation* station, uint8_t i) const
1923{
1924 NS_ASSERT(i < GetNMcsSupported(station));
1925 return station->m_state->m_operationalMcsSet[i];
1926}
1927
1929WifiRemoteStationManager::GetNonErpSupported(const WifiRemoteStation* station, uint8_t i) const
1930{
1931 NS_ASSERT(i < GetNNonErpSupported(station));
1932 // IEEE 802.11g standard defines that if the protection mechanism is enabled, RTS, CTS and
1933 // CTS-To-Self frames should select a rate in the BSSBasicRateSet that corresponds to an 802.11b
1934 // basic rate. This is a implemented here to avoid changes in every RAA, but should maybe be
1935 // moved in case it breaks standard rules.
1936 uint32_t index = 0;
1937 bool found = false;
1938 for (auto j = station->m_state->m_operationalRateSet.begin();
1939 j != station->m_state->m_operationalRateSet.end();)
1940 {
1941 if (i == index)
1942 {
1943 found = true;
1944 }
1945 if (j->GetModulationClass() != WIFI_MOD_CLASS_ERP_OFDM)
1946 {
1947 if (found)
1948 {
1949 break;
1950 }
1951 }
1952 index++;
1953 j++;
1954 }
1955 return station->m_state->m_operationalRateSet[index];
1956}
1957
1959WifiRemoteStationManager::GetAddress(const WifiRemoteStation* station) const
1960{
1961 return station->m_state->m_address;
1962}
1963
1964uint16_t
1965WifiRemoteStationManager::GetChannelWidth(const WifiRemoteStation* station) const
1966{
1967 return station->m_state->m_channelWidth;
1968}
1969
1970bool
1971WifiRemoteStationManager::GetShortGuardIntervalSupported(const WifiRemoteStation* station) const
1972{
1973 Ptr<const HtCapabilities> htCapabilities = station->m_state->m_htCapabilities;
1974
1975 if (!htCapabilities)
1976 {
1977 return false;
1978 }
1979 return htCapabilities->GetShortGuardInterval20();
1980}
1981
1982uint16_t
1983WifiRemoteStationManager::GetGuardInterval(const WifiRemoteStation* station) const
1984{
1985 return station->m_state->m_guardInterval;
1986}
1987
1988bool
1989WifiRemoteStationManager::GetAggregation(const WifiRemoteStation* station) const
1990{
1991 return station->m_state->m_aggregation;
1992}
1993
1994uint8_t
1995WifiRemoteStationManager::GetNumberOfSupportedStreams(const WifiRemoteStation* station) const
1996{
1997 Ptr<const HtCapabilities> htCapabilities = station->m_state->m_htCapabilities;
1998
1999 if (!htCapabilities)
2000 {
2001 return 1;
2002 }
2003 return htCapabilities->GetRxHighestSupportedAntennas();
2004}
2005
2006uint8_t
2007WifiRemoteStationManager::GetNess(const WifiRemoteStation* station) const
2008{
2009 return station->m_state->m_ness;
2010}
2011
2013WifiRemoteStationManager::GetPhy() const
2014{
2015 return m_wifiPhy;
2016}
2017
2019WifiRemoteStationManager::GetMac() const
2020{
2021 return m_wifiMac;
2022}
2023
2024uint8_t
2025WifiRemoteStationManager::GetNSupported(const WifiRemoteStation* station) const
2026{
2027 return static_cast<uint8_t>(station->m_state->m_operationalRateSet.size());
2028}
2029
2030bool
2031WifiRemoteStationManager::GetQosSupported(const WifiRemoteStation* station) const
2032{
2033 return station->m_state->m_qosSupported;
2034}
2035
2036bool
2037WifiRemoteStationManager::GetHtSupported(const WifiRemoteStation* station) const
2038{
2039 return bool(station->m_state->m_htCapabilities);
2040}
2041
2042bool
2043WifiRemoteStationManager::GetVhtSupported(const WifiRemoteStation* station) const
2044{
2045 return bool(station->m_state->m_vhtCapabilities);
2046}
2047
2048bool
2049WifiRemoteStationManager::GetHeSupported(const WifiRemoteStation* station) const
2050{
2051 return bool(station->m_state->m_heCapabilities);
2052}
2053
2054bool
2055WifiRemoteStationManager::GetEhtSupported(const WifiRemoteStation* station) const
2056{
2057 return (bool)(station->m_state->m_ehtCapabilities);
2058}
2059
2060bool
2061WifiRemoteStationManager::GetEmlsrSupported(const WifiRemoteStation* station) const
2062{
2063 auto mleCommonInfo = station->m_state->m_mleCommonInfo;
2064 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2065 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2066}
2067
2068bool
2069WifiRemoteStationManager::GetEmlsrEnabled(const WifiRemoteStation* station) const
2070{
2071 return station->m_state->m_emlsrEnabled;
2072}
2073
2074uint8_t
2075WifiRemoteStationManager::GetNMcsSupported(const WifiRemoteStation* station) const
2076{
2077 return static_cast<uint8_t>(station->m_state->m_operationalMcsSet.size());
2078}
2079
2081WifiRemoteStationManager::GetNNonErpSupported(const WifiRemoteStation* station) const
2082{
2083 uint32_t size = 0;
2084 for (auto i = station->m_state->m_operationalRateSet.begin();
2085 i != station->m_state->m_operationalRateSet.end();
2086 i++)
2087 {
2088 if (i->GetModulationClass() == WIFI_MOD_CLASS_ERP_OFDM)
2089 {
2090 continue;
2091 }
2092 size++;
2093 }
2094 return size;
2095}
2096
2097uint16_t
2098WifiRemoteStationManager::GetChannelWidthSupported(Mac48Address address) const
2099{
2100 return LookupState(address)->m_channelWidth;
2101}
2102
2103bool
2104WifiRemoteStationManager::GetShortGuardIntervalSupported(Mac48Address address) const
2105{
2106 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2107
2108 if (!htCapabilities)
2109 {
2110 return false;
2111 }
2112 return htCapabilities->GetShortGuardInterval20();
2113}
2114
2115uint8_t
2116WifiRemoteStationManager::GetNumberOfSupportedStreams(Mac48Address address) const
2117{
2118 Ptr<const HtCapabilities> htCapabilities = LookupState(address)->m_htCapabilities;
2119
2120 if (!htCapabilities)
2121 {
2122 return 1;
2123 }
2124 return htCapabilities->GetRxHighestSupportedAntennas();
2125}
2126
2127uint8_t
2128WifiRemoteStationManager::GetNMcsSupported(Mac48Address address) const
2129{
2130 return static_cast<uint8_t>(LookupState(address)->m_operationalMcsSet.size());
2131}
2132
2133bool
2134WifiRemoteStationManager::GetDsssSupported(const Mac48Address& address) const
2135{
2136 return (LookupState(address)->m_dsssSupported);
2137}
2138
2139bool
2140WifiRemoteStationManager::GetErpOfdmSupported(const Mac48Address& address) const
2141{
2142 return (LookupState(address)->m_erpOfdmSupported);
2143}
2144
2145bool
2146WifiRemoteStationManager::GetOfdmSupported(const Mac48Address& address) const
2147{
2148 return (LookupState(address)->m_ofdmSupported);
2149}
2150
2151bool
2152WifiRemoteStationManager::GetHtSupported(Mac48Address address) const
2153{
2154 return bool(LookupState(address)->m_htCapabilities);
2155}
2156
2157bool
2158WifiRemoteStationManager::GetVhtSupported(Mac48Address address) const
2159{
2160 return bool(LookupState(address)->m_vhtCapabilities);
2161}
2162
2163bool
2164WifiRemoteStationManager::GetHeSupported(Mac48Address address) const
2165{
2166 return bool(LookupState(address)->m_heCapabilities);
2167}
2168
2169bool
2170WifiRemoteStationManager::GetEhtSupported(Mac48Address address) const
2171{
2172 return (bool)(LookupState(address)->m_ehtCapabilities);
2173}
2174
2175bool
2176WifiRemoteStationManager::GetEmlsrSupported(const Mac48Address& address) const
2177{
2178 auto mleCommonInfo = LookupState(address)->m_mleCommonInfo;
2179 return mleCommonInfo && mleCommonInfo->m_emlCapabilities &&
2180 mleCommonInfo->m_emlCapabilities->emlsrSupport == 1;
2181}
2182
2183bool
2184WifiRemoteStationManager::GetEmlsrEnabled(const Mac48Address& address) const
2185{
2186 if (auto stateIt = m_states.find(address); stateIt != m_states.cend())
2187 {
2188 return stateIt->second->m_emlsrEnabled;
2189 }
2190 return false;
2191}
2192
2193void
2194WifiRemoteStationManager::SetDefaultTxPowerLevel(uint8_t txPower)
2195{
2196 m_defaultTxPowerLevel = txPower;
2197}
2198
2199uint8_t
2200WifiRemoteStationManager::GetNumberOfAntennas() const
2201{
2202 return m_wifiPhy->GetNumberOfAntennas();
2203}
2204
2205uint8_t
2206WifiRemoteStationManager::GetMaxNumberOfTransmitStreams() const
2207{
2208 return m_wifiPhy->GetMaxSupportedTxSpatialStreams();
2209}
2210
2211bool
2212WifiRemoteStationManager::UseLdpcForDestination(Mac48Address dest) const
2213{
2214 return (GetLdpcSupported() && GetLdpcSupported(dest));
2215}
2216
2217} // 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
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:351
AttributeValue implementation for Time.
Definition: nstime.h:1406
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:436
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:1074
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1044
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition: wifi-phy.cc:622
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:1098
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:2036
std::list< WifiMode > GetModeList() const
The WifiPhy::GetModeList() method is used (e.g., by a WifiRemoteStationManager) to determine the set ...
Definition: wifi-phy.cc:1987
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.
Time m_rtsCtsTxDurationThresh
TX duration threshold for RTS/CTS.
bool GetShortSlotTimeEnabled() const
Return whether the device uses short slot time.
void DoDispose() override
Destructor implementation.
virtual void DoReportDataFailed(WifiRemoteStation *station)=0
This method is a pure virtual method that must be implemented by the sub-class.
bool IsLastFragment(Ptr< const WifiMpdu > mpdu, uint32_t fragmentNumber)
void ReportFinalDataFailed(Ptr< const WifiMpdu > mpdu)
Should be invoked after calling ReportDataFailed if 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...
bool NeedRts(const WifiMacHeader &header, const WifiTxParameters &txParams)
uint32_t m_rtsCtsThreshold
Threshold for RTS/CTS.
bool m_useNonErpProtection
flag if protection for non-ERP stations against ERP transmissions is enabled
WifiMode GetControlAnswerMode(WifiMode reqMode) const
Get control answer mode function.
bool m_shortSlotTimeEnabled
flag if short slot time is enabled
bool IsWaitAssocTxOk(Mac48Address address) const
Return whether we are waiting for an ACK for the association response we sent.
void SetMaxSlrc(uint32_t maxSlrc)
Sets the maximum STA long retry count (SLRC).
TracedCallback< Mac48Address > m_macTxFinalDataFailed
The trace source fired when the transmission of a data packet has exceeded the maximum number of atte...
bool GetUseNonHtProtection() const
Return whether the device supports protection of non-HT stations.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
std::optional< Time > m_txDuration
TX duration of the frame.
uint32_t GetSize(Mac48Address receiver) const
Get the size in bytes of the (A-)MPDU addressed to the given receiver.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetNess(uint8_t ness)
Sets the Ness number.
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
void SetLdpc(bool ldpc)
Sets if LDPC FEC coding is being used.
void 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 AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1427
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1407
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:1319
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:68
@ AP
Definition: wifi-mac.h:69
@ 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