A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-phy.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 * Sébastien Deronne <sebastien.deronne@gmail.com>
8 */
9
10#include "wifi-phy.h"
11
12#include "error-rate-model.h"
13#include "frame-capture-model.h"
14#include "interference-helper.h"
16#include "wifi-net-device.h"
17#include "wifi-ppdu.h"
18#include "wifi-psdu.h"
20#include "wifi-utils.h"
21
22#include "ns3/attribute-container.h"
23#include "ns3/channel.h"
24#include "ns3/dsss-phy.h"
25#include "ns3/eht-phy.h" //also includes OFDM, HT, VHT and HE
26#include "ns3/erp-ofdm-phy.h"
27#include "ns3/error-model.h"
28#include "ns3/ht-configuration.h"
29#include "ns3/log.h"
30#include "ns3/mobility-model.h"
31#include "ns3/pointer.h"
32#include "ns3/random-variable-stream.h"
33#include "ns3/simulator.h"
34#include "ns3/string.h"
35#include "ns3/tuple.h"
36#include "ns3/vht-configuration.h"
37
38#include <algorithm>
39#include <numeric>
40
41#undef NS_LOG_APPEND_CONTEXT
42#define NS_LOG_APPEND_CONTEXT \
43 WIFI_PHY_NS_LOG_APPEND_CONTEXT( \
44 (m_device && (m_device->GetNPhys() > m_phyId) && m_device->GetPhy(m_phyId) \
45 ? m_device->GetPhy(m_phyId) \
46 : nullptr))
47
48namespace ns3
49{
50
52
53/****************************************************************
54 * The actual WifiPhy class
55 ****************************************************************/
56
58
59TypeId
61{
62 static TypeId tid =
63 TypeId("ns3::WifiPhy")
65 .SetGroupName("Wifi")
66 .AddAttribute("Channel",
67 "The channel attached to this PHY",
72 .AddAttribute(
73 "ChannelSettings",
74 "A vector of tuple {channel number, channel width (MHz), PHY band, primary20 "
75 "index} "
76 "describing the settings of the operating channel for each segment. "
77 "The primary20 index (only the value set for the first segment is used) "
78 "is the index of the primary 20 MHz channel within the operating channel "
79 "(0 indicates the 20 MHz subchannel with the lowest center frequency) and "
80 "is only valid if the width of the operating channel is a multiple of 20 MHz. "
81 "If the standard for this object has not been set yet, the value of this "
82 "attribute is saved and will be used to set the operating channel when the "
83 "standard is configured. If the PHY band is left unspecified, the default "
84 "band for the configured standard is used. If the channel width and the "
85 "channel number are both 0, the default channel width for the configured "
86 "standard and band are used. If the channel number is 0, the default "
87 "channel number for the configured standard, band and channel width is used. "
88 "Note that the channel width can be left unspecified (0) if the channel "
89 "number uniquely identify a frequency channel for the given standard and band.",
90 StringValue("{0, 0, BAND_UNSPECIFIED, 0}"),
93 ';'>((void(WifiPhy::*)(const ChannelSegments&)) & WifiPhy::SetOperatingChannel),
103 "BAND_2_4GHZ",
105 "BAND_5GHZ",
107 "BAND_6GHZ",
109 "BAND_UNSPECIFIED"),
111 .AddAttribute("Frequency",
112 "The center frequency (MHz) of the current operating channel.",
114 UintegerValue(0),
117 .AddAttribute("ChannelNumber",
118 "The channel number of the current operating channel.",
120 UintegerValue(0),
123 .AddAttribute(
124 "ChannelWidth",
125 "The width in MHz of the current operating channel (5, 10, 20, 22, 40, 80 or 160). "
126 "If 80+80MHz is used, this corresponds to the total channel width, hence 160 MHz.",
128 UintegerValue(0),
131 .AddAttribute(
132 "Primary20MHzIndex",
133 "The index of the primary 20 MHz channel within the current operating channel "
134 "(0 indicates the 20 MHz subchannel with the lowest center frequency).",
135 UintegerValue(0),
138 .AddAttribute("FixedPhyBand",
139 "If set to true, changing PHY band is prohibited after initialization.",
140 BooleanValue(false),
143 .AddAttribute(
144 "RxSensitivity",
145 "The energy of a received signal should be higher than "
146 "this threshold (dBm) for the PHY to detect the signal. "
147 "This threshold refers to a width of 20 MHz and will be "
148 "scaled to match the width of the received signal.",
149 DoubleValue(-101.0),
152 .AddAttribute(
153 "CcaEdThreshold",
154 "The energy of all received signals should be higher than "
155 "this threshold (dBm) in the primary channel to allow the PHY layer "
156 "to declare CCA BUSY state.",
157 DoubleValue(-62.0),
160 .AddAttribute("CcaSensitivity",
161 "The energy of a received wifi signal should be higher than "
162 "this threshold (dBm) in the primary channel to allow the PHY layer "
163 "to declare CCA BUSY state.",
164 DoubleValue(-82.0),
168 .AddAttribute("TxGain",
169 "Transmission gain (dB).",
170 DoubleValue(0.0),
173 .AddAttribute("RxGain",
174 "Reception gain (dB).",
175 DoubleValue(0.0),
178 .AddAttribute("TxPowerLevels",
179 "Number of transmission power levels available between "
180 "TxPowerStart and TxPowerEnd included.",
181 UintegerValue(1),
184 .AddAttribute("TxPowerEnd",
185 "Maximum available transmission level (dBm).",
186 DoubleValue(16.0206),
189 .AddAttribute("TxPowerStart",
190 "Minimum available transmission level (dBm).",
191 DoubleValue(16.0206),
194 .AddAttribute(
195 "RxNoiseFigure",
196 "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
197 " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
198 "\"the difference in decibels (dB) between"
199 " the noise output of the actual receiver to the noise output of an "
200 " ideal receiver with the same overall gain and bandwidth when the receivers "
201 " are connected to sources at the standard noise temperature T0 (usually 290 K)\".",
202 DoubleValue(7),
205 .AddAttribute("State",
206 "The state of the PHY layer.",
207 PointerValue(),
210 .AddAttribute("ChannelSwitchDelay",
211 "Delay between two short frames transmitted on different frequencies.",
215 .AddAttribute(
216 "Antennas",
217 "The number of antennas on the device.",
218 UintegerValue(1),
221 .AddAttribute("MaxSupportedTxSpatialStreams",
222 "The maximum number of supported TX spatial streams."
223 "This parameter is only valuable for 802.11n/ac/ax STAs and APs.",
224 UintegerValue(1),
228 .AddAttribute("MaxSupportedRxSpatialStreams",
229 "The maximum number of supported RX spatial streams."
230 "This parameter is only valuable for 802.11n/ac/ax STAs and APs.",
231 UintegerValue(1),
235 .AddAttribute("ShortPlcpPreambleSupported",
236 "Whether or not short PHY preamble is supported."
237 "This parameter is only valuable for 802.11b STAs and APs."
238 "Note: 802.11g APs and STAs always support short PHY preamble.",
239 BooleanValue(false),
243 .AddAttribute("FrameCaptureModel",
244 "Ptr to an object that implements the frame capture model",
245 PointerValue(),
248 .AddAttribute("PreambleDetectionModel",
249 "Ptr to an object that implements the preamble detection model",
250 PointerValue(),
253 .AddAttribute("PostReceptionErrorModel",
254 "An optional packet error model can be added to the receive "
255 "packet process after any propagation-based (SNR-based) error "
256 "models have been applied. Typically this is used to force "
257 "specific packet drops, for testing purposes.",
258 PointerValue(),
261 .AddAttribute("InterferenceHelper",
262 "Ptr to an object that implements the interference helper",
263 PointerValue(),
266 .AddAttribute("Sifs",
267 "The duration of the Short Interframe Space. "
268 "NOTE that the default value is overwritten by the value defined "
269 "by the standard; if you want to set this attribute, you have to "
270 "do it after that the PHY object is initialized.",
274 .AddAttribute("Slot",
275 "The duration of a slot. "
276 "NOTE that the default value is overwritten by the value defined "
277 "by the standard; if you want to set this attribute, you have to "
278 "do it after that the PHY object is initialized.",
282 .AddAttribute("Pifs",
283 "The duration of the PCF Interframe Space. "
284 "NOTE that the default value is overwritten by the value defined "
285 "by the standard; if you want to set this attribute, you have to "
286 "do it after that the PHY object is initialized.",
290 .AddAttribute("PowerDensityLimit",
291 "The mean equivalent isotropically radiated power density"
292 "limit (in dBm/MHz) set by regulators.",
293 DoubleValue(100.0), // set to a high value so as to have no effect
296 .AddAttribute("NotifyMacHdrRxEnd",
297 "Whether the PHY is capable of notifying the MAC about the end of "
298 "the reception of the MAC header of every MPDU.",
299 BooleanValue(false),
302 .AddTraceSource("PhyTxBegin",
303 "Trace source indicating a packet "
304 "has begun transmitting over the channel medium",
306 "ns3::WifiPhy::PhyTxBeginTracedCallback")
307 .AddTraceSource("PhyTxPsduBegin",
308 "Trace source indicating a PSDU "
309 "has begun transmitting over the channel medium",
311 "ns3::WifiPhy::PsduTxBeginCallback")
312 .AddTraceSource("PhyTxEnd",
313 "Trace source indicating a packet "
314 "has been completely transmitted over the channel.",
316 "ns3::Packet::TracedCallback")
317 .AddTraceSource("PhyTxDrop",
318 "Trace source indicating a packet "
319 "has been dropped by the device during transmission",
321 "ns3::Packet::TracedCallback")
322 .AddTraceSource("PhyRxBegin",
323 "Trace source indicating a packet "
324 "has begun being received from the channel medium "
325 "by the device",
327 "ns3::WifiPhy::PhyRxBeginTracedCallback")
328 .AddTraceSource("PhyRxPayloadBegin",
329 "Trace source indicating the reception of the "
330 "payload of a PPDU has begun",
332 "ns3::WifiPhy::PhyRxPayloadBeginTracedCallback")
333 .AddTraceSource("PhyRxMacHeaderEnd",
334 "Trace source indicating the MAC header of an MPDU has been "
335 "completely received.",
337 "ns3::WifiPhy::PhyRxMacHeaderEndTracedCallback")
338 .AddTraceSource("PhyRxEnd",
339 "Trace source indicating a packet "
340 "has been completely received from the channel medium "
341 "by the device",
343 "ns3::Packet::TracedCallback")
344 .AddTraceSource("PhyRxDrop",
345 "Trace source indicating a packet "
346 "has been dropped by the device during reception",
348 "ns3::Packet::TracedCallback")
349 .AddTraceSource("PhyRxPpduDrop",
350 "Trace source indicating a ppdu "
351 "has been dropped by the device during reception",
353 "ns3::WifiPhy::PhyRxPpduDropTracedCallback")
354 .AddTraceSource("MonitorSnifferRx",
355 "Trace source simulating a wifi device in monitor mode "
356 "sniffing all received frames",
358 "ns3::WifiPhy::MonitorSnifferRxTracedCallback")
359 .AddTraceSource("MonitorSnifferTx",
360 "Trace source simulating the capability of a wifi device "
361 "in monitor mode to sniff all frames being transmitted",
363 "ns3::WifiPhy::MonitorSnifferTxTracedCallback")
364 .AddTraceSource("SignalTransmission",
365 "Trace start of signal transmission",
367 "ns3::SpectrumWifiPhy::SignalTransmissionCallback");
368 return tid;
369}
370
372 : m_phyId(0),
373 m_txMpduReferenceNumber(0xffffffff),
374 m_rxMpduReferenceNumber(0xffffffff),
375 m_endPhyRxEvent(),
376 m_endTxEvent(),
377 m_currentEvent(nullptr),
378 m_previouslyRxPpduUid(UINT64_MAX),
379 m_standard(WIFI_STANDARD_UNSPECIFIED),
380 m_maxModClassSupported(WIFI_MOD_CLASS_UNKNOWN),
382 m_sifs(Seconds(0)),
383 m_slot(Seconds(0)),
384 m_pifs(Seconds(0)),
385 m_ackTxTime(Seconds(0)),
386 m_blockAckTxTime(Seconds(0)),
387 m_powerRestricted(false),
388 m_channelAccessRequested(false),
389 m_txSpatialStreams(1),
390 m_rxSpatialStreams(1),
391 m_wifiRadioEnergyModel(nullptr),
392 m_timeLastPreambleDetected(Seconds(0))
393{
394 NS_LOG_FUNCTION(this);
397}
398
400{
401 NS_LOG_FUNCTION(this);
402}
403
404void
406{
407 NS_LOG_FUNCTION(this);
408
409 // This method ensures that the local mobility model pointer holds
410 // a pointer to the Node's aggregated mobility model (if one exists)
411 // in the case that the user has not directly called SetMobility()
412 // on this WifiPhy during simulation setup. If the mobility model
413 // needs to be added or changed during simulation runtime, users must
414 // call SetMobility() on this object.
415
416 if (!m_mobility)
417 {
419 "Either install a MobilityModel on this object or ensure that this "
420 "object is part of a Node and NetDevice");
421 m_mobility = m_device->GetNode()->GetObject<MobilityModel>();
422 if (!m_mobility)
423 {
424 NS_LOG_WARN("Mobility not found, propagation models might not work properly");
425 }
426 }
427}
428
429void
431{
432 NS_LOG_FUNCTION(this);
433
434 m_device = nullptr;
435 m_mobility = nullptr;
436 m_frameCaptureModel = nullptr;
437 m_preambleDetectionModel = nullptr;
438 m_wifiRadioEnergyModel = nullptr;
440 if (m_interference)
441 {
442 m_interference->Dispose();
443 }
444 m_interference = nullptr;
445 m_random = nullptr;
446 m_state = nullptr;
447
448 Reset();
449
450 // this should be done after calling the Reset function
451 for (auto& phyEntity : m_phyEntities)
452 {
453 phyEntity.second = nullptr;
454 }
455 m_phyEntities.clear();
456}
457
458std::map<WifiModulationClass, Ptr<PhyEntity>>&
460{
461 static std::map<WifiModulationClass, Ptr<PhyEntity>> g_staticPhyEntities;
462 return g_staticPhyEntities;
463}
464
467{
468 return m_state;
469}
470
471void
473{
474 m_state->SetReceiveOkCallback(callback);
475}
476
477void
479{
480 m_state->SetReceiveErrorCallback(callback);
481}
482
483void
484WifiPhy::RegisterListener(const std::shared_ptr<WifiPhyListener>& listener)
485{
486 m_state->RegisterListener(listener);
487 if (IsInitialized())
488 {
489 // provide CCA busy information upon registering a PHY listener
490 SwitchMaybeToCcaBusy(nullptr);
491 }
492}
493
494void
495WifiPhy::UnregisterListener(const std::shared_ptr<WifiPhyListener>& listener)
496{
497 m_state->UnregisterListener(listener);
498}
499
500void
505
506void
508{
509 NS_LOG_FUNCTION(this << threshold);
510 m_rxSensitivity = threshold;
511}
512
513dBm_u
515{
516 return m_rxSensitivity;
517}
518
519void
521{
522 NS_LOG_FUNCTION(this << threshold);
523 m_ccaEdThreshold = threshold;
524}
525
526dBm_u
528{
529 return m_ccaEdThreshold;
530}
531
532void
534{
535 NS_LOG_FUNCTION(this << threshold);
536 m_ccaSensitivityThreshold = threshold;
537}
538
539dBm_u
544
545void
547{
548 NS_LOG_FUNCTION(this << noiseFigure);
549 if (m_interference)
550 {
551 m_interference->SetNoiseFigure(DbToRatio(noiseFigure));
552 }
553 m_noiseFigure = noiseFigure;
554}
555
556void
558{
559 NS_LOG_FUNCTION(this << start);
560 m_txPowerBase = start;
561}
562
563dBm_u
565{
566 return m_txPowerBase;
567}
568
569void
571{
572 NS_LOG_FUNCTION(this << end);
573 m_txPowerEnd = end;
574}
575
576dBm_u
578{
579 return m_txPowerEnd;
580}
581
582void
584{
585 NS_LOG_FUNCTION(this << +n);
586 m_nTxPower = n;
587}
588
589uint8_t
591{
592 return m_nTxPower;
593}
594
595void
597{
598 NS_LOG_FUNCTION(this << gain);
599 m_txGain = gain;
600}
601
602dB_u
604{
605 return m_txGain;
606}
607
608void
610{
611 NS_LOG_FUNCTION(this << gain);
612 m_rxGain = gain;
613}
614
615dB_u
617{
618 return m_rxGain;
619}
620
621void
623{
624 NS_LOG_FUNCTION(this << enable);
625 m_shortPreamble = enable;
626}
627
628bool
633
634void
636{
637 m_device = device;
638}
639
642{
643 return m_device;
644}
645
646void
648{
649 m_mobility = mobility;
650}
651
654{
655 return m_mobility;
656}
657
658void
659WifiPhy::SetPhyId(uint8_t phyId)
660{
661 NS_LOG_FUNCTION(this << phyId);
662 m_phyId = phyId;
663}
664
665uint8_t
667{
668 return m_phyId;
669}
670
671void
673{
674 NS_LOG_FUNCTION(this << helper);
675 m_interference = helper;
676 m_interference->SetNoiseFigure(DbToRatio(m_noiseFigure));
677 m_interference->SetNumberOfReceiveAntennas(m_numberOfAntennas);
678}
679
680void
682{
683 NS_LOG_FUNCTION(this << model);
685 m_interference->SetErrorRateModel(model);
686}
687
688void
694
695void
700
701void
706
707void
709{
710 m_wifiRadioEnergyModel = wifiRadioEnergyModel;
711}
712
713dBm_u
714WifiPhy::GetPower(uint8_t powerLevel) const
715{
718 dBm_u dbm;
719 if (m_nTxPower > 1)
720 {
721 dbm = m_txPowerBase + powerLevel * (m_txPowerEnd - m_txPowerBase) / (m_nTxPower - 1);
722 }
723 else
724 {
726 "cannot have TxPowerEnd != TxPowerStart with TxPowerLevels == 1");
727 dbm = m_txPowerBase;
728 }
729 return dbm;
730}
731
732Time
737
738double
739WifiPhy::CalculateSnr(const WifiTxVector& txVector, double ber) const
740{
741 return m_interference->GetErrorRateModel()->CalculateSnr(txVector, ber);
742}
743
746{
747 const auto it = GetStaticPhyEntities().find(modulation);
749 "Unimplemented Wi-Fi modulation class " << modulation);
750 return it->second;
751}
752
755{
756 const auto it = m_phyEntities.find(modulation);
757 NS_ABORT_MSG_IF(it == m_phyEntities.cend(),
758 "Unsupported Wi-Fi modulation class " << modulation);
759 return it->second;
760}
761
764{
766}
767
773
776{
777 NS_ABORT_IF(!ppdu);
778 const auto modulation = ppdu->GetModulation();
779 if (modulation > m_phyEntities.rbegin()->first)
780 {
781 // unsupported modulation: start reception process with latest PHY entity
782 return GetLatestPhyEntity();
783 }
784 if (modulation < WIFI_MOD_CLASS_HT)
785 {
786 // for non-HT (duplicate), call the latest PHY entity since some extra processing can be
787 // done in PHYs implemented in HT and later (e.g. channel width selection for non-HT
788 // duplicates)
789 return GetLatestPhyEntity();
790 }
791 return GetPhyEntity(modulation);
792}
793
794void
796{
797 NS_ASSERT_MSG(!GetStaticPhyEntities().contains(modulation),
798 "The PHY entity has already been added. The setting should only be done once per "
799 "modulation class");
800 GetStaticPhyEntities()[modulation] = phyEntity;
801}
802
803void
805{
806 NS_LOG_FUNCTION(this << modulation);
807 NS_ABORT_MSG_IF(!GetStaticPhyEntities().contains(modulation),
808 "Cannot add an unimplemented PHY to supported list. Update the former first.");
809 NS_ASSERT_MSG(m_phyEntities.find(modulation) == m_phyEntities.end(),
810 "The PHY entity has already been added. The setting should only be done once per "
811 "modulation class");
812 phyEntity->SetOwner(this);
813 m_phyEntities[modulation] = phyEntity;
814}
815
816void
818{
819 m_sifs = sifs;
820}
821
822Time
824{
825 return m_sifs;
826}
827
828void
830{
831 m_slot = slot;
832}
833
834Time
836{
837 return m_slot;
838}
839
840void
842{
843 m_pifs = pifs;
844}
845
846Time
848{
849 return m_pifs;
850}
851
852Time
854{
855 return m_ackTxTime;
856}
857
858Time
860{
861 return m_blockAckTxTime;
862}
863
864void
866{
867 NS_LOG_FUNCTION(this);
869
870 // See Table 17-21 "OFDM PHY characteristics" of 802.11-2016
873 SetPifs(GetSifs() + GetSlot());
874 // See Table 10-5 "Determination of the EstimatedAckTxTime based on properties
875 // of the PPDU causing the EIFS" of 802.11-2016
877}
878
879void
881{
882 NS_LOG_FUNCTION(this);
883 Ptr<DsssPhy> phyEntity = Create<DsssPhy>();
885 AddPhyEntity(WIFI_MOD_CLASS_DSSS, phyEntity); // when plain DSSS modes are used
886
887 // See Table 16-4 "HR/DSSS PHY characteristics" of 802.11-2016
890 SetPifs(GetSifs() + GetSlot());
891 // See Table 10-5 "Determination of the EstimatedAckTxTime based on properties
892 // of the PPDU causing the EIFS" of 802.11-2016
894}
895
896void
898{
899 NS_LOG_FUNCTION(this);
900 // See Table 18-5 "ERP characteristics" of 802.11-2016
901 // Slot time defaults to the "long slot time" of 20 us in the standard
902 // according to mixed 802.11b/g deployments. Short slot time is enabled
903 // if the user sets the ShortSlotTimeSupported flag to true and when the BSS
904 // consists of only ERP STAs capable of supporting this option.
907}
908
909void
911{
912 NS_LOG_FUNCTION(this);
913 if (GetChannelWidth() == 10)
914 {
916
917 // See Table 17-21 "OFDM PHY characteristics" of 802.11-2016
920 SetPifs(GetSifs() + GetSlot());
922 }
923 else if (GetChannelWidth() == 5)
924 {
926
927 // See Table 17-21 "OFDM PHY characteristics" of 802.11-2016
930 SetPifs(GetSifs() + GetSlot());
932 }
933 else
934 {
935 NS_FATAL_ERROR("802.11p configured with a wrong channel width!");
936 }
937}
938
939void
941{
942 NS_LOG_FUNCTION(this);
944 {
946 }
947 else
948 {
950 }
952
953 // See Table 10-5 "Determination of the EstimatedAckTxTime based on properties
954 // of the PPDU causing the EIFS" of 802.11-2016
956}
957
958void
965
966void
968{
969 NS_LOG_FUNCTION(this);
971 {
973 }
974 else
975 {
977 }
979}
980
981void
988
989void
995
1001
1002void
1004{
1005 NS_LOG_FUNCTION(this << standard);
1006
1008 "Cannot change standard");
1009
1010 m_standard = standard;
1011
1013 {
1015 }
1016
1018 {
1019 NS_LOG_DEBUG("Setting the operating channel first");
1021 // return because we are called back by SetOperatingChannel
1022 return;
1023 }
1024
1025 // this function is called when changing PHY band, hence we have to delete
1026 // the previous PHY entities
1027 m_phyEntities.clear();
1028
1029 switch (standard)
1030 {
1033 break;
1036 break;
1039 break;
1042 break;
1045 break;
1048 break;
1051 break;
1054 break;
1056 default:
1057 NS_ASSERT_MSG(false, "Unsupported standard");
1058 break;
1059 }
1060}
1061
1064{
1065 return m_band;
1066}
1067
1070{
1071 return m_standard;
1072}
1073
1076{
1077 return m_operatingChannel;
1078}
1079
1080MHz_u
1082{
1084}
1085
1086uint8_t
1088{
1090}
1091
1092MHz_u
1097
1098uint8_t
1103
1104void
1106{
1107 m_fixedPhyBand = enable;
1108}
1109
1110bool
1112{
1113 return m_fixedPhyBand;
1114}
1115
1116MHz_u
1117WifiPhy::GetTxBandwidth(WifiMode mode, MHz_u maxAllowedWidth) const
1118{
1119 auto modulation = mode.GetModulationClass();
1120 if (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)
1121 {
1122 return 22;
1123 }
1124
1125 return std::min({GetChannelWidth(), GetMaximumChannelWidth(modulation), maxAllowedWidth});
1126}
1127
1128void
1130{
1131 NS_LOG_FUNCTION(this << channel);
1132 ChannelSegments segments{};
1133 for (std::size_t segmentId = 0; segmentId < channel.GetNSegments(); ++segmentId)
1134 {
1135 segments.emplace_back(channel.GetNumber(segmentId),
1136 channel.GetWidth(segmentId),
1137 channel.GetPhyBand(),
1138 channel.GetPrimaryChannelIndex(20));
1139 }
1140 SetOperatingChannel(segments);
1141}
1142
1143void
1148
1149void
1151{
1152 NS_LOG_FUNCTION(this << +std::get<0>(channelSegments.front())
1153 << std::get<1>(channelSegments.front())
1154 << static_cast<WifiPhyBand>(std::get<2>(channelSegments.front()))
1155 << +std::get<3>(channelSegments.front()));
1156
1157 m_channelSettings = channelSegments;
1158
1160 {
1161 NS_LOG_DEBUG("Channel information will be applied when a standard is configured");
1162 return;
1163 }
1164
1165 if (IsInitialized())
1166 {
1167 const auto delay = GetDelayUntilChannelSwitch();
1168 if (!delay.has_value())
1169 {
1170 // switching channel is not possible now
1171 return;
1172 }
1173 if (delay.value().IsStrictlyPositive())
1174 {
1175 // switching channel has been postponed
1177 Simulator::Schedule(delay.value(), fp, this, channelSegments);
1178 return;
1179 }
1180 }
1181
1182 // channel can be switched now.
1184}
1185
1186std::optional<Time>
1188{
1189 if (!IsInitialized())
1190 {
1191 // this is not channel switch, this is initialization
1192 NS_LOG_DEBUG("Before initialization, nothing to do");
1193 return Seconds(0);
1194 }
1195
1196 std::optional<Time> delay;
1197 switch (m_state->GetState())
1198 {
1199 case WifiPhyState::RX:
1200 NS_LOG_DEBUG("drop packet because of channel switching while reception");
1202 delay = Seconds(0);
1203 break;
1204 case WifiPhyState::TX:
1205 NS_LOG_DEBUG("channel switching postponed until end of current transmission");
1206 delay = GetDelayUntilIdle();
1207 break;
1209 case WifiPhyState::IDLE:
1210 Reset();
1211 delay = Seconds(0);
1212 break;
1214 delay = Seconds(0);
1215 break;
1217 NS_LOG_DEBUG("channel switching ignored in sleep mode");
1218 break;
1219 default:
1220 NS_ASSERT(false);
1221 break;
1222 }
1223
1224 return delay;
1225}
1226
1227void
1229{
1230 NS_LOG_FUNCTION(this);
1231
1232 m_powerRestricted = false;
1234
1235 // Update unspecified parameters with default values
1236 std::optional<uint8_t> prevChannelNumber{};
1237 for (auto& [number, width, band, primary20] : m_channelSettings)
1238 {
1239 if (band == WIFI_PHY_BAND_UNSPECIFIED)
1240 {
1242 }
1243 if (width == 0 && number == 0)
1244 {
1245 width = GetDefaultChannelWidth(m_standard, static_cast<WifiPhyBand>(band));
1246 }
1247 if (number == 0)
1248 {
1249 number =
1251 m_standard,
1252 static_cast<WifiPhyBand>(band),
1253 prevChannelNumber);
1254 }
1255 prevChannelNumber = number;
1256 }
1257
1258 // We need to call SetStandard if this is the first time we set a channel or we
1259 // are changing PHY band. Checking if the new PHY band is different than the
1260 // previous one covers both cases because initially the PHY band is unspecified
1261 bool changingPhyBand =
1262 (static_cast<WifiPhyBand>(std::get<2>(m_channelSettings.front())) != m_band);
1263
1264 NS_ABORT_MSG_IF(IsInitialized() && m_fixedPhyBand && changingPhyBand,
1265 "Trying to change PHY band while prohibited.");
1266
1267 m_band = static_cast<WifiPhyBand>(std::get<2>(m_channelSettings.front()));
1268
1269 NS_LOG_DEBUG("switching channel");
1270 std::vector<FrequencyChannelInfo> segments{};
1271 std::transform(m_channelSettings.cbegin(),
1272 m_channelSettings.cend(),
1273 std::back_inserter(segments),
1274 [this](const auto& channelTuple) {
1275 return FrequencyChannelInfo{std::get<0>(channelTuple),
1276 0,
1277 std::get<1>(channelTuple),
1278 m_band};
1279 });
1280 m_operatingChannel.Set(segments, m_standard);
1281 m_operatingChannel.SetPrimary20Index(std::get<3>(m_channelSettings.front()));
1282
1283 // check that the channel width is supported
1284 const auto chWidth = GetChannelWidth();
1285
1286 if (m_device)
1287 {
1288 if (auto htConfig = m_device->GetHtConfiguration();
1289 htConfig && !htConfig->Get40MHzOperationSupported() && chWidth > 20)
1290 {
1291 NS_ABORT_MSG("Attempting to set a " << chWidth
1292 << " MHz channel on"
1293 "a station only supporting 20 MHz operation");
1294 }
1295
1296 if (auto vhtConfig = m_device->GetVhtConfiguration();
1297 vhtConfig && !vhtConfig->Get160MHzOperationSupported() && chWidth > 80)
1298 {
1299 NS_ABORT_MSG("Attempting to set a " << chWidth
1300 << " MHz channel on"
1301 "a station supporting up to 80 MHz operation");
1302 }
1303 }
1304
1305 if (changingPhyBand)
1306 {
1307 ConfigureStandard(m_standard);
1308 }
1309
1310 FinalizeChannelSwitch();
1311
1312 if (IsInitialized())
1313 {
1314 // notify channel switching
1315 m_state->SwitchToChannelSwitching(GetChannelSwitchDelay());
1316 /*
1317 * Needed here to be able to correctly sensed the medium for the first
1318 * time after the switching. The actual switching is not performed until
1319 * after m_channelSwitchDelay. Packets received during the switching
1320 * state are added to the event list and are employed later to figure
1321 * out the state of the medium after the switching.
1322 */
1323 SwitchMaybeToCcaBusy(nullptr);
1324 }
1325}
1326
1327void
1328WifiPhy::SetNumberOfAntennas(uint8_t antennas)
1329{
1330 NS_LOG_FUNCTION(this << +antennas);
1331 NS_ASSERT_MSG(antennas > 0 && antennas <= 8, "unsupported number of antennas");
1332 m_numberOfAntennas = antennas;
1333 if (m_interference)
1334 {
1335 m_interference->SetNumberOfReceiveAntennas(antennas);
1336 }
1337}
1338
1339uint8_t
1340WifiPhy::GetNumberOfAntennas() const
1341{
1342 return m_numberOfAntennas;
1343}
1344
1345void
1346WifiPhy::SetMaxSupportedTxSpatialStreams(uint8_t streams)
1347{
1348 NS_ASSERT(streams <= GetNumberOfAntennas());
1349 bool changed = (m_txSpatialStreams != streams);
1350 m_txSpatialStreams = streams;
1351 if (changed)
1352 {
1353 auto phyEntity = m_phyEntities.find(WIFI_MOD_CLASS_HT);
1354 if (phyEntity != m_phyEntities.end())
1355 {
1356 Ptr<HtPhy> htPhy = DynamicCast<HtPhy>(phyEntity->second);
1357 if (htPhy)
1358 {
1359 htPhy->SetMaxSupportedNss(
1360 m_txSpatialStreams); // this is essential to have the right MCSs configured
1361 }
1362
1363 if (!m_capabilitiesChangedCallback.IsNull())
1364 {
1365 m_capabilitiesChangedCallback();
1366 }
1367 }
1368 }
1369}
1370
1371uint8_t
1372WifiPhy::GetMaxSupportedTxSpatialStreams() const
1373{
1374 return m_txSpatialStreams;
1375}
1376
1377void
1378WifiPhy::SetMaxSupportedRxSpatialStreams(uint8_t streams)
1379{
1380 NS_ASSERT(streams <= GetNumberOfAntennas());
1381 bool changed = (m_rxSpatialStreams != streams);
1382 m_rxSpatialStreams = streams;
1383 if (changed && !m_capabilitiesChangedCallback.IsNull())
1384 {
1385 m_capabilitiesChangedCallback();
1386 }
1387}
1388
1389uint8_t
1390WifiPhy::GetMaxSupportedRxSpatialStreams() const
1391{
1392 return m_rxSpatialStreams;
1393}
1394
1395std::list<uint8_t>
1396WifiPhy::GetBssMembershipSelectorList() const
1397{
1398 std::list<uint8_t> list;
1399 for (const auto& phyEntity : m_phyEntities)
1400 {
1401 Ptr<HtPhy> htPhy = DynamicCast<HtPhy>(phyEntity.second);
1402 if (htPhy)
1403 {
1404 list.emplace_back(htPhy->GetBssMembershipSelector());
1405 }
1406 }
1407 return list;
1408}
1409
1410void
1411WifiPhy::SetSleepMode()
1412{
1413 NS_LOG_FUNCTION(this);
1414 m_powerRestricted = false;
1415 m_channelAccessRequested = false;
1416 switch (m_state->GetState())
1417 {
1418 case WifiPhyState::TX:
1419 NS_LOG_DEBUG("setting sleep mode postponed until end of current transmission");
1420 Simulator::Schedule(GetDelayUntilIdle(), &WifiPhy::SetSleepMode, this);
1421 break;
1422 case WifiPhyState::RX:
1423 NS_LOG_DEBUG("setting sleep mode postponed until end of current reception");
1424 Simulator::Schedule(GetDelayUntilIdle(), &WifiPhy::SetSleepMode, this);
1425 break;
1426 case WifiPhyState::SWITCHING:
1427 NS_LOG_DEBUG("setting sleep mode postponed until end of channel switching");
1428 Simulator::Schedule(GetDelayUntilIdle(), &WifiPhy::SetSleepMode, this);
1429 break;
1430 case WifiPhyState::CCA_BUSY:
1431 case WifiPhyState::IDLE:
1432 NS_LOG_DEBUG("setting sleep mode");
1433 // The PHY object may be in CCA_BUSY state because it is receiving a preamble. Cancel
1434 // preamble events before switching to sleep state
1435 Reset();
1436 m_state->SwitchToSleep();
1437 break;
1438 case WifiPhyState::SLEEP:
1439 NS_LOG_DEBUG("already in sleep mode");
1440 break;
1441 default:
1442 NS_ASSERT(false);
1443 break;
1444 }
1445}
1446
1447void
1448WifiPhy::SetOffMode()
1449{
1450 NS_LOG_FUNCTION(this);
1451 m_powerRestricted = false;
1452 m_channelAccessRequested = false;
1453 Reset();
1454 m_state->SwitchToOff();
1455}
1456
1457void
1458WifiPhy::ResumeFromSleep()
1459{
1460 NS_LOG_FUNCTION(this);
1461 switch (m_state->GetState())
1462 {
1463 case WifiPhyState::TX:
1464 case WifiPhyState::RX:
1465 case WifiPhyState::IDLE:
1466 case WifiPhyState::CCA_BUSY:
1467 case WifiPhyState::SWITCHING: {
1468 NS_LOG_DEBUG("not in sleep mode, there is nothing to resume");
1469 break;
1470 }
1471 case WifiPhyState::SLEEP: {
1472 NS_LOG_DEBUG("resuming from sleep mode");
1473 m_state->SwitchFromSleep();
1474 SwitchMaybeToCcaBusy();
1475 break;
1476 }
1477 default: {
1478 NS_ASSERT(false);
1479 break;
1480 }
1481 }
1482}
1483
1484void
1485WifiPhy::ResumeFromOff()
1486{
1487 NS_LOG_FUNCTION(this);
1488 switch (m_state->GetState())
1489 {
1490 case WifiPhyState::TX:
1491 case WifiPhyState::RX:
1492 case WifiPhyState::IDLE:
1493 case WifiPhyState::CCA_BUSY:
1494 case WifiPhyState::SWITCHING:
1495 case WifiPhyState::SLEEP: {
1496 NS_LOG_DEBUG("not in off mode, there is nothing to resume");
1497 break;
1498 }
1499 case WifiPhyState::OFF: {
1500 NS_LOG_DEBUG("resuming from off mode");
1501 m_state->SwitchFromOff();
1502 SwitchMaybeToCcaBusy();
1503 break;
1504 }
1505 default: {
1506 NS_ASSERT(false);
1507 break;
1508 }
1509 }
1510}
1511
1512Time
1513WifiPhy::GetPreambleDetectionDuration()
1514{
1515 return MicroSeconds(4);
1516}
1517
1518Time
1519WifiPhy::GetStartOfPacketDuration(const WifiTxVector& txVector)
1520{
1521 return MicroSeconds(4);
1522}
1523
1524Time
1525WifiPhy::GetPayloadDuration(uint32_t size,
1526 const WifiTxVector& txVector,
1527 WifiPhyBand band,
1528 MpduType mpdutype,
1529 uint16_t staId)
1530{
1531 uint32_t totalAmpduSize;
1532 double totalAmpduNumSymbols;
1533 return GetPayloadDuration(size,
1534 txVector,
1535 band,
1536 mpdutype,
1537 false,
1538 totalAmpduSize,
1539 totalAmpduNumSymbols,
1540 staId);
1541}
1542
1543Time
1544WifiPhy::GetPayloadDuration(uint32_t size,
1545 const WifiTxVector& txVector,
1546 WifiPhyBand band,
1547 MpduType mpdutype,
1548 bool incFlag,
1549 uint32_t& totalAmpduSize,
1550 double& totalAmpduNumSymbols,
1551 uint16_t staId)
1552{
1553 return GetStaticPhyEntity(txVector.GetModulationClass())
1554 ->GetPayloadDuration(size,
1555 txVector,
1556 band,
1557 mpdutype,
1558 incFlag,
1559 totalAmpduSize,
1560 totalAmpduNumSymbols,
1561 staId);
1562}
1563
1564Time
1565WifiPhy::CalculatePhyPreambleAndHeaderDuration(const WifiTxVector& txVector)
1566{
1567 return GetStaticPhyEntity(txVector.GetModulationClass())
1568 ->CalculatePhyPreambleAndHeaderDuration(txVector);
1569}
1570
1571Time
1572WifiPhy::CalculateTxDuration(uint32_t size,
1573 const WifiTxVector& txVector,
1574 WifiPhyBand band,
1575 uint16_t staId)
1576{
1577 Time duration = CalculatePhyPreambleAndHeaderDuration(txVector) +
1578 GetPayloadDuration(size, txVector, band, NORMAL_MPDU, staId);
1579 NS_ASSERT(duration.IsStrictlyPositive());
1580 return duration;
1581}
1582
1583Time
1584WifiPhy::CalculateTxDuration(Ptr<const WifiPsdu> psdu,
1585 const WifiTxVector& txVector,
1586 WifiPhyBand band)
1587{
1588 return CalculateTxDuration(GetWifiConstPsduMap(psdu, txVector), txVector, band);
1589}
1590
1591Time
1592WifiPhy::CalculateTxDuration(const WifiConstPsduMap& psduMap,
1593 const WifiTxVector& txVector,
1594 WifiPhyBand band)
1595{
1596 return GetStaticPhyEntity(txVector.GetModulationClass())
1597 ->CalculateTxDuration(psduMap, txVector, band);
1598}
1599
1601WifiPhy::GetMaxPsduSize(WifiModulationClass modulation)
1602{
1603 return GetStaticPhyEntity(modulation)->GetMaxPsduSize();
1604}
1605
1606void
1607WifiPhy::NotifyTxBegin(const WifiConstPsduMap& psdus, Watt_u txPower)
1608{
1609 if (!m_phyTxBeginTrace.IsEmpty())
1610 {
1611 for (const auto& psdu : psdus)
1612 {
1613 for (auto& mpdu : *PeekPointer(psdu.second))
1614 {
1615 m_phyTxBeginTrace(mpdu->GetProtocolDataUnit(), txPower);
1616 }
1617 }
1618 }
1619}
1620
1621void
1622WifiPhy::NotifyTxEnd(const WifiConstPsduMap& psdus)
1623{
1624 if (!m_phyTxEndTrace.IsEmpty())
1625 {
1626 for (const auto& psdu : psdus)
1627 {
1628 for (auto& mpdu : *PeekPointer(psdu.second))
1629 {
1630 m_phyTxEndTrace(mpdu->GetProtocolDataUnit());
1631 }
1632 }
1633 }
1634}
1635
1636void
1637WifiPhy::NotifyTxDrop(Ptr<const WifiPsdu> psdu)
1638{
1639 if (!m_phyTxDropTrace.IsEmpty())
1640 {
1641 for (auto& mpdu : *PeekPointer(psdu))
1642 {
1643 m_phyTxDropTrace(mpdu->GetProtocolDataUnit());
1644 }
1645 }
1646}
1647
1648void
1649WifiPhy::NotifyRxBegin(Ptr<const WifiPsdu> psdu, const RxPowerWattPerChannelBand& rxPowersW)
1650{
1651 if (psdu && !m_phyRxBeginTrace.IsEmpty())
1652 {
1653 for (auto& mpdu : *PeekPointer(psdu))
1654 {
1655 m_phyRxBeginTrace(mpdu->GetProtocolDataUnit(), rxPowersW);
1656 }
1657 }
1658}
1659
1660void
1661WifiPhy::NotifyRxEnd(Ptr<const WifiPsdu> psdu)
1662{
1663 if (psdu && !m_phyRxEndTrace.IsEmpty())
1664 {
1665 for (auto& mpdu : *PeekPointer(psdu))
1666 {
1667 m_phyRxEndTrace(mpdu->GetProtocolDataUnit());
1668 }
1669 }
1670}
1671
1672void
1673WifiPhy::NotifyRxDrop(Ptr<const WifiPsdu> psdu, WifiPhyRxfailureReason reason)
1674{
1675 if (psdu && !m_phyRxDropTrace.IsEmpty())
1676 {
1677 for (auto& mpdu : *PeekPointer(psdu))
1678 {
1679 m_phyRxDropTrace(mpdu->GetProtocolDataUnit(), reason);
1680 }
1681 }
1682}
1683
1684void
1685WifiPhy::NotifyRxPpduDrop(Ptr<const WifiPpdu> ppdu, WifiPhyRxfailureReason reason)
1686{
1687 NotifyRxDrop(GetAddressedPsduInPpdu(ppdu), reason);
1688 m_phyRxPpduDropTrace(ppdu, reason);
1689}
1690
1691void
1692WifiPhy::NotifyMonitorSniffRx(Ptr<const WifiPsdu> psdu,
1693 MHz_u channelFreq,
1694 WifiTxVector txVector,
1695 SignalNoiseDbm signalNoise,
1696 std::vector<bool> statusPerMpdu,
1697 uint16_t staId)
1698{
1699 MpduInfo aMpdu;
1700 if (psdu->IsAggregate())
1701 {
1702 // Expand A-MPDU
1703 NS_ASSERT_MSG(txVector.IsAggregation(),
1704 "TxVector with aggregate flag expected here according to PSDU");
1705 aMpdu.mpduRefNumber = ++m_rxMpduReferenceNumber;
1706 size_t nMpdus = psdu->GetNMpdus();
1707 NS_ASSERT_MSG(statusPerMpdu.size() == nMpdus, "Should have one reception status per MPDU");
1708 if (!m_phyMonitorSniffRxTrace.IsEmpty())
1709 {
1710 aMpdu.type = (psdu->IsSingle()) ? SINGLE_MPDU : FIRST_MPDU_IN_AGGREGATE;
1711 for (size_t i = 0; i < nMpdus;)
1712 {
1713 if (statusPerMpdu.at(i)) // packet received without error, hand over to sniffer
1714 {
1715 m_phyMonitorSniffRxTrace(psdu->GetAmpduSubframe(i),
1716 static_cast<uint16_t>(channelFreq),
1717 txVector,
1718 aMpdu,
1719 signalNoise,
1720 staId);
1721 }
1722 ++i;
1723 aMpdu.type =
1724 (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE;
1725 }
1726 }
1727 }
1728 else
1729 {
1730 NS_ASSERT_MSG(statusPerMpdu.size() == 1,
1731 "Should have one reception status for normal MPDU");
1732 if (!m_phyMonitorSniffRxTrace.IsEmpty())
1733 {
1734 aMpdu.type = NORMAL_MPDU;
1735 m_phyMonitorSniffRxTrace(psdu->GetPacket(),
1736 static_cast<uint16_t>(channelFreq),
1737 txVector,
1738 aMpdu,
1739 signalNoise,
1740 staId);
1741 }
1742 }
1743}
1744
1745void
1746WifiPhy::NotifyMonitorSniffTx(Ptr<const WifiPsdu> psdu,
1747 MHz_u channelFreq,
1748 WifiTxVector txVector,
1749 uint16_t staId)
1750{
1751 MpduInfo aMpdu;
1752 if (psdu->IsAggregate())
1753 {
1754 // Expand A-MPDU
1755 NS_ASSERT_MSG(txVector.IsAggregation(),
1756 "TxVector with aggregate flag expected here according to PSDU");
1757 aMpdu.mpduRefNumber = ++m_rxMpduReferenceNumber;
1758 if (!m_phyMonitorSniffTxTrace.IsEmpty())
1759 {
1760 size_t nMpdus = psdu->GetNMpdus();
1761 aMpdu.type = (psdu->IsSingle()) ? SINGLE_MPDU : FIRST_MPDU_IN_AGGREGATE;
1762 for (size_t i = 0; i < nMpdus;)
1763 {
1764 m_phyMonitorSniffTxTrace(psdu->GetAmpduSubframe(i),
1765 channelFreq,
1766 txVector,
1767 aMpdu,
1768 staId);
1769 ++i;
1770 aMpdu.type =
1771 (i == (nMpdus - 1)) ? LAST_MPDU_IN_AGGREGATE : MIDDLE_MPDU_IN_AGGREGATE;
1772 }
1773 }
1774 }
1775 else
1776 {
1777 if (!m_phyMonitorSniffTxTrace.IsEmpty())
1778 {
1779 aMpdu.type = NORMAL_MPDU;
1780 m_phyMonitorSniffTxTrace(psdu->GetPacket(), channelFreq, txVector, aMpdu, staId);
1781 }
1782 }
1783}
1784
1786WifiPhy::GetWifiConstPsduMap(Ptr<const WifiPsdu> psdu, const WifiTxVector& txVector)
1787{
1788 return GetStaticPhyEntity(txVector.GetModulationClass())->GetWifiConstPsduMap(psdu, txVector);
1789}
1790
1791void
1792WifiPhy::Send(Ptr<const WifiPsdu> psdu, const WifiTxVector& txVector)
1793{
1794 NS_LOG_FUNCTION(this << *psdu << txVector);
1795 Send(GetWifiConstPsduMap(psdu, txVector), txVector);
1796}
1797
1798void
1799WifiPhy::Send(const WifiConstPsduMap& psdus, const WifiTxVector& txVector)
1800{
1801 NS_LOG_FUNCTION(this << psdus << txVector);
1802 /* Transmission can happen if:
1803 * - we are syncing on a packet. It is the responsibility of the
1804 * MAC layer to avoid doing this but the PHY does nothing to
1805 * prevent it.
1806 * - we are idle
1807 */
1808 NS_ASSERT(!m_state->IsStateTx() && !m_state->IsStateSwitching());
1809 NS_ASSERT(m_endTxEvent.IsExpired());
1810
1811 if (!txVector.IsValid(m_band))
1812 {
1813 NS_FATAL_ERROR("TX-VECTOR is invalid!");
1814 }
1815
1816 uint8_t nss = 0;
1817 if (txVector.IsMu())
1818 {
1819 // We do not support mixed OFDMA and MU-MIMO
1820 if (txVector.IsDlMuMimo())
1821 {
1822 nss = txVector.GetNssTotal();
1823 }
1824 else
1825 {
1826 nss = txVector.GetNssMax();
1827 }
1828 }
1829 else
1830 {
1831 nss = txVector.GetNss();
1832 }
1833
1834 if (nss > GetMaxSupportedTxSpatialStreams())
1835 {
1836 NS_FATAL_ERROR("Unsupported number of spatial streams!");
1837 }
1838
1839 if (m_state->IsStateSleep())
1840 {
1841 NS_LOG_DEBUG("Dropping packet because in sleep mode");
1842 for (const auto& psdu : psdus)
1843 {
1844 NotifyTxDrop(psdu.second);
1845 }
1846 return;
1847 }
1848
1849 const auto txDuration = CalculateTxDuration(psdus, txVector, GetPhyBand());
1850
1851 auto noEndPreambleDetectionEvent = true;
1852 for (const auto& [mc, entity] : m_phyEntities)
1853 {
1854 noEndPreambleDetectionEvent =
1855 noEndPreambleDetectionEvent && entity->NoEndPreambleDetectionEvents();
1856 }
1857 if (!noEndPreambleDetectionEvent && !m_currentEvent)
1858 {
1859 // PHY is in the initial few microseconds during which the
1860 // start of RX has occurred but the preamble detection period
1861 // has not elapsed
1862 AbortCurrentReception(SIGNAL_DETECTION_ABORTED_BY_TX);
1863 }
1864 else if (!noEndPreambleDetectionEvent || m_currentEvent)
1865 {
1866 AbortCurrentReception(RECEPTION_ABORTED_BY_TX);
1867 }
1868
1869 if (m_powerRestricted)
1870 {
1871 NS_LOG_DEBUG("Transmitting with power restriction for " << txDuration.As(Time::NS));
1872 }
1873 else
1874 {
1875 NS_LOG_DEBUG("Transmitting without power restriction for " << txDuration.As(Time::NS));
1876 }
1877
1878 if (m_state->GetState() == WifiPhyState::OFF)
1879 {
1880 NS_LOG_DEBUG("Transmission canceled because device is OFF");
1881 return;
1882 }
1883
1884 auto ppdu = GetPhyEntity(txVector.GetModulationClass())->BuildPpdu(psdus, txVector, txDuration);
1885 m_previouslyRxPpduUid = UINT64_MAX; // reset (after creation of PPDU) to use it only once
1886
1887 const auto txPower = DbmToW(GetTxPowerForTransmission(ppdu) + GetTxGain());
1888 NotifyTxBegin(psdus, txPower);
1889 if (!m_phyTxPsduBeginTrace.IsEmpty())
1890 {
1891 m_phyTxPsduBeginTrace(psdus, txVector, txPower);
1892 }
1893 for (const auto& psdu : psdus)
1894 {
1895 NotifyMonitorSniffTx(psdu.second, GetFrequency(), txVector, psdu.first);
1896 }
1897 m_state->SwitchToTx(txDuration, psdus, GetPower(txVector.GetTxPowerLevel()), txVector);
1898
1899 if (m_wifiRadioEnergyModel &&
1900 m_wifiRadioEnergyModel->GetMaximumTimeInState(WifiPhyState::TX) < txDuration)
1901 {
1902 ppdu->SetTruncatedTx();
1903 }
1904
1905 m_endTxEvent =
1906 Simulator::Schedule(txDuration, &WifiPhy::TxDone, this, psdus); // TODO: fix for MU
1907
1908 StartTx(ppdu);
1909 ppdu->ResetTxVector();
1910
1911 m_channelAccessRequested = false;
1912 m_powerRestricted = false;
1913}
1914
1915void
1916WifiPhy::TxDone(const WifiConstPsduMap& psdus)
1917{
1918 NS_LOG_FUNCTION(this << psdus);
1919 NotifyTxEnd(psdus);
1920 Reset();
1921 // we might have received signals during TX
1922 SwitchMaybeToCcaBusy();
1923}
1924
1925uint64_t
1926WifiPhy::GetPreviouslyRxPpduUid() const
1927{
1928 return m_previouslyRxPpduUid;
1929}
1930
1931void
1932WifiPhy::SetPreviouslyRxPpduUid(uint64_t uid)
1933{
1934 NS_ASSERT(m_standard >= WIFI_STANDARD_80211be);
1935 m_previouslyRxPpduUid = uid;
1936}
1937
1938void
1939WifiPhy::Reset()
1940{
1941 NS_LOG_FUNCTION(this);
1942 m_currentPreambleEvents.clear();
1943 bool noEndPreambleDetectionEvent = true;
1944 for (const auto& [mc, entity] : m_phyEntities)
1945 {
1946 noEndPreambleDetectionEvent =
1947 noEndPreambleDetectionEvent && entity->NoEndPreambleDetectionEvents();
1948 }
1949 if (m_interference && (m_currentEvent || !noEndPreambleDetectionEvent))
1950 {
1951 m_interference->NotifyRxEnd(Simulator::Now(), GetCurrentFrequencyRange());
1952 }
1953 m_currentEvent = nullptr;
1954 for (auto& phyEntity : m_phyEntities)
1955 {
1956 phyEntity.second->CancelAllEvents();
1957 }
1958 m_endPhyRxEvent.Cancel();
1959 m_endTxEvent.Cancel();
1960}
1961
1962void
1963WifiPhy::StartReceivePreamble(Ptr<const WifiPpdu> ppdu,
1964 RxPowerWattPerChannelBand& rxPowersW,
1965 Time rxDuration)
1966{
1967 NS_LOG_FUNCTION(this << ppdu << rxDuration);
1968 WifiModulationClass modulation = ppdu->GetModulation();
1969 NS_ASSERT(m_maxModClassSupported != WIFI_MOD_CLASS_UNKNOWN);
1970 if (auto it = m_phyEntities.find(modulation);
1971 it != m_phyEntities.end() && modulation <= m_maxModClassSupported)
1972 {
1973 it->second->StartReceivePreamble(ppdu, rxPowersW, rxDuration);
1974 }
1975 else
1976 {
1977 // TODO find a fallback PHY for receiving the PPDU (e.g. 11a for 11ax due to preamble
1978 // structure)
1979 NS_LOG_DEBUG("Unsupported modulation received (" << modulation << "), consider as noise");
1980 m_interference->Add(ppdu, rxDuration, rxPowersW, GetCurrentFrequencyRange());
1981 SwitchMaybeToCcaBusy();
1982 }
1983}
1984
1985bool
1986WifiPhy::IsReceivingPhyHeader() const
1987{
1988 return m_endPhyRxEvent.IsPending();
1989}
1990
1991void
1992WifiPhy::EndReceiveInterBss()
1993{
1994 NS_LOG_FUNCTION(this);
1995 if (!m_channelAccessRequested)
1996 {
1997 m_powerRestricted = false;
1998 }
1999}
2000
2001void
2002WifiPhy::NotifyChannelAccessRequested()
2003{
2004 NS_LOG_FUNCTION(this);
2005 m_channelAccessRequested = true;
2006}
2007
2008bool
2009WifiPhy::IsModeSupported(WifiMode mode) const
2010{
2011 for (const auto& phyEntity : m_phyEntities)
2012 {
2013 if (phyEntity.second->IsModeSupported(mode))
2014 {
2015 return true;
2016 }
2017 }
2018 return false;
2019}
2020
2022WifiPhy::GetDefaultMode() const
2023{
2024 // Start from oldest standards and move up (guaranteed by fact that WifModulationClass is
2025 // ordered)
2026 for (const auto& phyEntity : m_phyEntities)
2027 {
2028 for (const auto& mode : *(phyEntity.second))
2029 {
2030 return mode;
2031 }
2032 }
2033 NS_ASSERT_MSG(false, "Should have found at least one default mode");
2034 return WifiMode();
2035}
2036
2037bool
2038WifiPhy::IsMcsSupported(WifiModulationClass modulation, uint8_t mcs) const
2039{
2040 const auto phyEntity = m_phyEntities.find(modulation);
2041 if (phyEntity == m_phyEntities.end())
2042 {
2043 return false;
2044 }
2045 return phyEntity->second->IsMcsSupported(mcs);
2046}
2047
2048std::list<WifiMode>
2049WifiPhy::GetModeList() const
2050{
2051 std::list<WifiMode> list;
2052 for (const auto& phyEntity : m_phyEntities)
2053 {
2054 if (!phyEntity.second->HandlesMcsModes()) // to exclude MCSs from search
2055 {
2056 for (const auto& mode : *(phyEntity.second))
2057 {
2058 list.emplace_back(mode);
2059 }
2060 }
2061 }
2062 return list;
2063}
2064
2065std::list<WifiMode>
2066WifiPhy::GetModeList(WifiModulationClass modulation) const
2067{
2068 std::list<WifiMode> list;
2069 const auto phyEntity = m_phyEntities.find(modulation);
2070 if (phyEntity != m_phyEntities.end())
2071 {
2072 if (!phyEntity->second->HandlesMcsModes()) // to exclude MCSs from search
2073 {
2074 for (const auto& mode : *(phyEntity->second))
2075 {
2076 list.emplace_back(mode);
2077 }
2078 }
2079 }
2080 return list;
2081}
2082
2083uint16_t
2084WifiPhy::GetNMcs() const
2085{
2086 uint16_t numMcs = 0;
2087 for (const auto& phyEntity : m_phyEntities)
2088 {
2089 if (phyEntity.second->HandlesMcsModes()) // to exclude non-MCS modes from search
2090 {
2091 numMcs += phyEntity.second->GetNumModes();
2092 }
2093 }
2094 return numMcs;
2095}
2096
2097std::list<WifiMode>
2098WifiPhy::GetMcsList() const
2099{
2100 std::list<WifiMode> list;
2101 for (const auto& phyEntity : m_phyEntities)
2102 {
2103 if (phyEntity.second->HandlesMcsModes()) // to exclude non-MCS modes from search
2104 {
2105 for (const auto& mode : *(phyEntity.second))
2106 {
2107 list.emplace_back(mode);
2108 }
2109 }
2110 }
2111 return list;
2112}
2113
2114std::list<WifiMode>
2115WifiPhy::GetMcsList(WifiModulationClass modulation) const
2116{
2117 std::list<WifiMode> list;
2118 auto phyEntity = m_phyEntities.find(modulation);
2119 if (phyEntity != m_phyEntities.end())
2120 {
2121 if (phyEntity->second->HandlesMcsModes()) // to exclude non-MCS modes from search
2122 {
2123 for (const auto& mode : *(phyEntity->second))
2124 {
2125 list.emplace_back(mode);
2126 }
2127 }
2128 }
2129 return list;
2130}
2131
2133WifiPhy::GetMcs(WifiModulationClass modulation, uint8_t mcs) const
2134{
2135 NS_ASSERT_MSG(IsMcsSupported(modulation, mcs), "Unsupported MCS");
2136 return m_phyEntities.at(modulation)->GetMcs(mcs);
2137}
2138
2139bool
2140WifiPhy::IsStateCcaBusy() const
2141{
2142 return m_state->IsStateCcaBusy();
2143}
2144
2145bool
2146WifiPhy::IsStateIdle() const
2147{
2148 return m_state->IsStateIdle();
2149}
2150
2151bool
2152WifiPhy::IsStateRx() const
2153{
2154 return m_state->IsStateRx();
2155}
2156
2157bool
2158WifiPhy::IsStateTx() const
2159{
2160 return m_state->IsStateTx();
2161}
2162
2163bool
2164WifiPhy::IsStateSwitching() const
2165{
2166 return m_state->IsStateSwitching();
2167}
2168
2169bool
2170WifiPhy::IsStateSleep() const
2171{
2172 return m_state->IsStateSleep();
2173}
2174
2175bool
2176WifiPhy::IsStateOff() const
2177{
2178 return m_state->IsStateOff();
2179}
2180
2181Time
2182WifiPhy::GetDelayUntilIdle()
2183{
2184 return m_state->GetDelayUntilIdle();
2185}
2186
2187Time
2188WifiPhy::GetLastRxStartTime() const
2189{
2190 return m_state->GetLastRxStartTime();
2191}
2192
2193Time
2194WifiPhy::GetLastRxEndTime() const
2195{
2196 return m_state->GetLastRxEndTime();
2197}
2198
2199void
2200WifiPhy::SwitchMaybeToCcaBusy(const Ptr<const WifiPpdu> ppdu /* = nullptr */)
2201{
2202 NS_LOG_FUNCTION(this);
2203 GetLatestPhyEntity()->SwitchMaybeToCcaBusy(ppdu);
2204}
2205
2206void
2207WifiPhy::NotifyCcaBusy(const Ptr<const WifiPpdu> ppdu, Time duration)
2208{
2209 NS_LOG_FUNCTION(this << duration);
2210 GetLatestPhyEntity()->NotifyCcaBusy(ppdu, duration, WIFI_CHANLIST_PRIMARY);
2211}
2212
2213void
2214WifiPhy::AbortCurrentReception(WifiPhyRxfailureReason reason)
2215{
2216 NS_LOG_FUNCTION(this << reason);
2217 if (reason != OBSS_PD_CCA_RESET ||
2218 m_currentEvent) // Otherwise abort has already been called previously
2219 {
2220 if (reason == SIGNAL_DETECTION_ABORTED_BY_TX)
2221 {
2222 for (auto signalDetectEvent : m_currentPreambleEvents)
2223 {
2224 NotifyRxPpduDrop(signalDetectEvent.second->GetPpdu(),
2226 }
2227 }
2228 for (auto& phyEntity : m_phyEntities)
2229 {
2230 phyEntity.second->CancelAllEvents();
2231 }
2232 m_endPhyRxEvent.Cancel();
2233 m_interference->NotifyRxEnd(Simulator::Now(), GetCurrentFrequencyRange());
2234 if (!m_currentEvent)
2235 {
2236 return;
2237 }
2238 NotifyRxPpduDrop(m_currentEvent->GetPpdu(), reason);
2239 if (reason == OBSS_PD_CCA_RESET)
2240 {
2241 m_state->SwitchFromRxAbort(GetChannelWidth());
2242 }
2243 if (reason == RECEPTION_ABORTED_BY_TX)
2244 {
2245 Reset();
2246 }
2247 else
2248 {
2249 for (auto it = m_currentPreambleEvents.begin(); it != m_currentPreambleEvents.end();
2250 ++it)
2251 {
2252 if (it->second == m_currentEvent)
2253 {
2254 it = m_currentPreambleEvents.erase(it);
2255 break;
2256 }
2257 }
2258 m_currentEvent = nullptr;
2259 }
2260 }
2261}
2262
2263void
2264WifiPhy::ResetCca(bool powerRestricted, dBm_u txPowerMaxSiso, dBm_u txPowerMaxMimo)
2265{
2266 NS_LOG_FUNCTION(this << powerRestricted << txPowerMaxSiso << txPowerMaxMimo);
2267 // This method might be called multiple times when receiving TB PPDUs with a BSS color
2268 // different than the one of the receiver. The first time this method is called, the call
2269 // to AbortCurrentReception sets m_currentEvent to 0. Therefore, we need to check whether
2270 // m_currentEvent is not 0 before executing the instructions below.
2271 if (m_currentEvent)
2272 {
2273 m_powerRestricted = powerRestricted;
2274 m_txPowerMaxSiso = txPowerMaxSiso;
2275 m_txPowerMaxMimo = txPowerMaxMimo;
2276 NS_ASSERT((m_currentEvent->GetEndTime() - Simulator::Now()).IsPositive());
2277 Simulator::Schedule(m_currentEvent->GetEndTime() - Simulator::Now(),
2278 &WifiPhy::EndReceiveInterBss,
2279 this);
2280 Simulator::ScheduleNow(&WifiPhy::AbortCurrentReception,
2281 this,
2282 OBSS_PD_CCA_RESET); // finish processing field first
2283 }
2284}
2285
2286dBm_u
2287WifiPhy::GetTxPowerForTransmission(Ptr<const WifiPpdu> ppdu) const
2288{
2289 NS_LOG_FUNCTION(this << m_powerRestricted << ppdu);
2290 const auto& txVector = ppdu->GetTxVector();
2291 // Get transmit power before antenna gain
2292 dBm_u txPower;
2293 if (!m_powerRestricted)
2294 {
2295 txPower = GetPower(txVector.GetTxPowerLevel());
2296 }
2297 else
2298 {
2299 if (txVector.GetNssMax() > 1 || txVector.GetNssTotal() > 1)
2300 {
2301 txPower = std::min(m_txPowerMaxMimo, GetPower(txVector.GetTxPowerLevel()));
2302 }
2303 else
2304 {
2305 txPower = std::min(m_txPowerMaxSiso, GetPower(txVector.GetTxPowerLevel()));
2306 }
2307 }
2308
2309 // Apply power density constraint on EIRP
2310 const auto channelWidth = ppdu->GetTxChannelWidth();
2311 dBm_per_MHz_u txPowerDbmPerMhz =
2312 (txPower + GetTxGain()) - RatioToDb(channelWidth); // account for antenna gain since EIRP
2313 NS_LOG_INFO("txPower=" << txPower << "dBm with txPowerDbmPerMhz=" << txPowerDbmPerMhz
2314 << " over " << channelWidth << " MHz");
2315 txPower = std::min(txPowerDbmPerMhz, m_powerDensityLimit) + RatioToDb(channelWidth);
2316 txPower -= GetTxGain(); // remove antenna gain since will be added right afterwards
2317 NS_LOG_INFO("txPower=" << txPower
2318 << "dBm after applying m_powerDensityLimit=" << m_powerDensityLimit);
2319 return txPower;
2320}
2321
2323WifiPhy::GetAddressedPsduInPpdu(Ptr<const WifiPpdu> ppdu) const
2324{
2325 // TODO: wrapper. See if still needed
2326 return GetPhyEntityForPpdu(ppdu)->GetAddressedPsduInPpdu(ppdu);
2327}
2328
2329int64_t
2330WifiPhy::AssignStreams(int64_t stream)
2331{
2332 NS_LOG_FUNCTION(this << stream);
2333 int64_t currentStream = stream;
2334 m_random->SetStream(currentStream++);
2335 currentStream += m_interference->GetErrorRateModel()->AssignStreams(currentStream);
2336 return (currentStream - stream);
2337}
2338
2339std::ostream&
2340operator<<(std::ostream& os, RxSignalInfo rxSignalInfo)
2341{
2342 os << "SNR:" << RatioToDb(rxSignalInfo.snr) << " dB"
2343 << ", RSSI:" << rxSignalInfo.rssi << " dBm";
2344 return os;
2345}
2346
2347uint8_t
2348WifiPhy::GetPrimaryChannelNumber(MHz_u primaryChannelWidth) const
2349{
2350 return m_operatingChannel.GetPrimaryChannelNumber(primaryChannelWidth, m_standard);
2351}
2352
2353Hz_u
2354WifiPhy::GetSubcarrierSpacing() const
2355{
2356 Hz_u subcarrierSpacing = 0;
2357 switch (GetStandard())
2358 {
2364 subcarrierSpacing = 312500;
2365 break;
2367 if (GetChannelWidth() == 5)
2368 {
2369 subcarrierSpacing = 78125;
2370 }
2371 else
2372 {
2373 subcarrierSpacing = 156250;
2374 }
2375 break;
2378 subcarrierSpacing = 78125;
2379 break;
2380 default:
2381 NS_FATAL_ERROR("Standard unknown: " << GetStandard());
2382 break;
2383 }
2384 return subcarrierSpacing;
2385}
2386
2387} // namespace ns3
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
Hold variables of type enum.
Definition enum.h:52
Keep track of the current position and velocity of an object.
A base class which provides memory management and object aggregation.
Definition object.h:78
bool IsInitialized() const
Check if the object has been initialized.
Definition object.cc:240
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:340
AttributeValue implementation for Tuple.
Definition tuple.h:67
a unique identifier for an interface.
Definition type-id.h:48
@ ATTR_GET
The attribute can be read.
Definition type-id.h:53
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
represent a single transmission mode
Definition wifi-mode.h:40
WifiModulationClass GetModulationClass() const
Definition wifi-mode.cc:174
802.11 PHY layer model
Definition wifi-phy.h:55
static TypeId GetTypeId()
Get the type ID.
Definition wifi-phy.cc:60
void SetNumberOfAntennas(uint8_t antennas)
Definition wifi-phy.cc:1328
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper.
Definition wifi-phy.h:1325
Time GetBlockAckTxTime() const
Return the estimated BlockAck TX time for this PHY.
Definition wifi-phy.cc:859
Ptr< MobilityModel > m_mobility
Pointer to the mobility model.
Definition wifi-phy.h:1624
dBm_u m_ccaEdThreshold
Clear channel assessment (CCA) energy detection (ED) threshold.
Definition wifi-phy.h:1597
dBm_u GetTxPowerStart() const
Return the minimum available transmission power level.
Definition wifi-phy.cc:564
WifiModulationClass GetMaxModulationClassSupported() const
Definition wifi-phy.cc:997
void SetRxGain(dB_u gain)
Sets the reception gain.
Definition wifi-phy.cc:609
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition wifi-phy.cc:672
uint8_t m_txSpatialStreams
Number of supported TX spatial streams.
Definition wifi-phy.h:1616
Ptr< UniformRandomVariable > m_random
Provides uniform random variables.
Definition wifi-phy.h:1324
Ptr< WifiRadioEnergyModel > m_wifiRadioEnergyModel
Wifi radio energy model.
Definition wifi-phy.h:1628
void SetRxNoiseFigure(dB_u noiseFigure)
Sets the RX loss in the Signal-to-Noise-Ratio due to non-idealities in the receiver.
Definition wifi-phy.cc:546
void Configure80211ax()
Configure WifiPhy with appropriate channel frequency and supported rates for 802.11ax standard.
Definition wifi-phy.cc:967
void SetRxSensitivity(dBm_u threshold)
Sets the receive sensitivity threshold.
Definition wifi-phy.cc:507
Time m_channelSwitchDelay
Time required to switch between channel.
Definition wifi-phy.h:1621
dB_u GetTxGain() const
Return the transmission gain.
Definition wifi-phy.cc:603
void SetTxPowerEnd(dBm_u end)
Sets the maximum available transmission power level.
Definition wifi-phy.cc:570
dBm_per_MHz_u m_powerDensityLimit
the power density limit
Definition wifi-phy.h:1606
WifiPhyOperatingChannel m_operatingChannel
Operating channel.
Definition wifi-phy.h:1587
TracedCallback< Ptr< const Packet > > m_phyTxDropTrace
The trace source fired when the PHY layer drops a packet as it tries to transmit it.
Definition wifi-phy.h:1478
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition wifi-phy.cc:681
bool m_channelAccessRequested
Flag if channels access has been requested (used for OBSS_PD SR)
Definition wifi-phy.h:1611
Time GetSlot() const
Return the slot duration for this PHY.
Definition wifi-phy.cc:835
void SetMaxSupportedRxSpatialStreams(uint8_t streams)
Definition wifi-phy.cc:1378
void Configure80211g()
Configure WifiPhy with appropriate channel frequency and supported rates for 802.11g standard.
Definition wifi-phy.cc:897
uint8_t GetPrimary20Index() const
Definition wifi-phy.cc:1099
dBm_u m_rxSensitivity
Receive sensitivity threshold.
Definition wifi-phy.h:1596
uint8_t GetNumberOfAntennas() const
Definition wifi-phy.cc:1340
Time m_slot
Slot duration.
Definition wifi-phy.h:1591
dBm_u GetRxSensitivity() const
Return the receive sensitivity threshold.
Definition wifi-phy.cc:514
Time GetDelayUntilIdle()
Definition wifi-phy.cc:2182
bool GetShortPhyPreambleSupported() const
Return whether short PHY preamble is supported.
Definition wifi-phy.cc:629
void SetSifs(Time sifs)
Set the Short Interframe Space (SIFS) for this PHY.
Definition wifi-phy.cc:817
void Configure80211n()
Configure WifiPhy with appropriate channel frequency and supported rates for 802.11n standard.
Definition wifi-phy.cc:940
dBm_u m_ccaSensitivityThreshold
Clear channel assessment (CCA) modulation and coding rate sensitivity threshold.
Definition wifi-phy.h:1598
void Configure80211be()
Configure WifiPhy with appropriate channel frequency and supported rates for 802.11be standard.
Definition wifi-phy.cc:982
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition wifi-phy.cc:823
bool m_notifyRxMacHeaderEnd
whether the PHY is capable of notifying MAC header RX end
Definition wifi-phy.h:1631
std::tuple< uint8_t, MHz_u, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying a segment of an operating channel.
Definition wifi-phy.h:919
MHz_u GetFrequency() const
Definition wifi-phy.cc:1081
Ptr< MobilityModel > GetMobility() const
Return the mobility model this PHY is associated with.
Definition wifi-phy.cc:653
Time m_blockAckTxTime
estimated BlockAck TX time
Definition wifi-phy.h:1594
void SetTxPowerStart(dBm_u start)
Sets the minimum available transmission power level.
Definition wifi-phy.cc:557
void Configure80211p()
Configure WifiPhy with appropriate channel frequency and supported rates for 802.11p standard.
Definition wifi-phy.cc:910
dBm_u m_txPowerEnd
Maximum transmission power.
Definition wifi-phy.h:1604
void AbortCurrentReception(WifiPhyRxfailureReason reason)
Due to newly arrived signal, the current reception cannot be continued and has to be aborted.
Definition wifi-phy.cc:2214
Ptr< FrameCaptureModel > m_frameCaptureModel
Frame capture model.
Definition wifi-phy.h:1626
TracedCallback< Ptr< const Packet > > m_phyRxEndTrace
The trace source fired when a packet ends the reception process from the medium.
Definition wifi-phy.h:1521
Time GetChannelSwitchDelay() const
Definition wifi-phy.cc:733
void SetTxGain(dB_u gain)
Sets the transmission gain.
Definition wifi-phy.cc:596
void SetMaxSupportedTxSpatialStreams(uint8_t streams)
Definition wifi-phy.cc:1346
Time m_sifs
Short Interframe Space (SIFS) duration.
Definition wifi-phy.h:1590
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition wifi-phy.cc:478
TracedCallback< Ptr< const WifiPpdu >, const WifiTxVector & > m_signalTransmissionCb
Signal Transmission callback.
Definition wifi-phy.h:1363
dBm_u GetTxPowerEnd() const
Return the maximum available transmission power level.
Definition wifi-phy.cc:577
uint8_t GetMaxSupportedRxSpatialStreams() const
Definition wifi-phy.cc:1390
MHz_u GetTxBandwidth(WifiMode mode, MHz_u maxAllowedBandWidth=std::numeric_limits< MHz_u >::max()) const
Get the bandwidth for a transmission occurring on the current operating channel and using the given W...
Definition wifi-phy.cc:1117
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition wifi-phy.cc:1003
void SetPostReceptionErrorModel(const Ptr< ErrorModel > em)
Attach a receive ErrorModel to the WifiPhy.
Definition wifi-phy.cc:689
uint8_t m_numberOfAntennas
Number of transmitters.
Definition wifi-phy.h:1615
TracedCallback< Ptr< const WifiPpdu >, WifiPhyRxfailureReason > m_phyRxPpduDropTrace
The trace source fired when the PHY layer drops a packet it has received.
Definition wifi-phy.h:1533
dBm_u GetCcaEdThreshold() const
Return the CCA energy detection threshold.
Definition wifi-phy.cc:527
Ptr< WifiPhyStateHelper > GetState() const
Return the WifiPhyStateHelper of this PHY.
Definition wifi-phy.cc:466
dBm_u m_txPowerBase
Minimum transmission power.
Definition wifi-phy.h:1603
virtual Ptr< Channel > GetChannel() const =0
Return the Channel this WifiPhy is connected to.
void SetShortPhyPreambleSupported(bool preamble)
Enable or disable short PHY preamble.
Definition wifi-phy.cc:622
void SetNTxPower(uint8_t n)
Sets the number of transmission power levels available between the minimum level and the maximum leve...
Definition wifi-phy.cc:583
void SetCcaSensitivityThreshold(dBm_u threshold)
Sets the CCA sensitivity threshold.
Definition wifi-phy.cc:533
WifiPhyBand m_band
WifiPhyBand.
Definition wifi-phy.h:1585
static const Ptr< const PhyEntity > GetStaticPhyEntity(WifiModulationClass modulation)
Get the implemented PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:745
TracedCallback< Ptr< const Packet >, uint16_t, WifiTxVector, MpduInfo, uint16_t > m_phyMonitorSniffTxTrace
A trace source that emulates a Wi-Fi device in monitor mode sniffing a packet being transmitted.
Definition wifi-phy.h:1572
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition wifi-phy.h:1360
void SetMaxModulationClassSupported(WifiModulationClass modClass)
Set the maximum modulation class that has to be supported by this PHY object.
Definition wifi-phy.cc:990
void AddPhyEntity(WifiModulationClass modulation, Ptr< PhyEntity > phyEntity)
Add the PHY entity to the map of supported PHY entities for the given modulation class for the WifiPh...
Definition wifi-phy.cc:804
TracedCallback< Ptr< const Packet >, uint16_t, WifiTxVector, MpduInfo, SignalNoiseDbm, uint16_t > m_phyMonitorSniffRxTrace
A trace source that emulates a Wi-Fi device in monitor mode sniffing a packet being received.
Definition wifi-phy.h:1553
Ptr< ErrorModel > m_postReceptionErrorModel
Error model for receive packet events.
Definition wifi-phy.h:1629
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition wifi-phy.cc:484
static std::map< WifiModulationClass, Ptr< PhyEntity > > & GetStaticPhyEntities()
Definition wifi-phy.cc:459
void SetSlot(Time slot)
Set the slot duration for this PHY.
Definition wifi-phy.cc:829
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition wifi-phy.cc:1063
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:754
uint8_t GetChannelNumber() const
Return current channel number.
Definition wifi-phy.cc:1087
TracedCallback< Ptr< const Packet > > m_phyTxEndTrace
The trace source fired when a packet ends the transmission process on the medium.
Definition wifi-phy.h:1470
std::optional< Time > GetDelayUntilChannelSwitch()
Perform any actions necessary when user changes operating channel after initialization.
Definition wifi-phy.cc:1187
void SetWifiRadioEnergyModel(const Ptr< WifiRadioEnergyModel > wifiRadioEnergyModel)
Sets the wifi radio energy model.
Definition wifi-phy.cc:708
TracedCallback< Ptr< const Packet >, double > m_phyTxBeginTrace
The trace source fired when a packet begins the transmission process on the medium.
Definition wifi-phy.h:1455
virtual void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition wifi-phy.cc:635
Ptr< PreambleDetectionModel > m_preambleDetectionModel
Preamble detection model.
Definition wifi-phy.h:1627
Time GetPifs() const
Return the PCF Interframe Space (PIFS) for this PHY.
Definition wifi-phy.cc:847
static void AddStaticPhyEntity(WifiModulationClass modulation, Ptr< PhyEntity > phyEntity)
Add the PHY entity to the map of implemented PHY entities for the given modulation class.
Definition wifi-phy.cc:795
TracedCallback< WifiConstPsduMap, WifiTxVector, double > m_phyTxPsduBeginTrace
The trace source fired when a PSDU map begins the transmission process on the medium.
Definition wifi-phy.h:1462
std::vector< ChannelTuple > ChannelSegments
segments identifying an operating channel
Definition wifi-phy.h:925
dB_u m_txGain
Transmission gain.
Definition wifi-phy.h:1601
MHz_u GetChannelWidth() const
Definition wifi-phy.cc:1093
void SetOperatingChannel(const WifiPhyOperatingChannel &channel)
If the standard for this object has not been set yet, store the channel settings corresponding to the...
Definition wifi-phy.cc:1129
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition wifi-phy.cc:641
WifiStandard m_standard
WifiStandard.
Definition wifi-phy.h:1583
uint8_t m_nTxPower
Number of available transmission power levels.
Definition wifi-phy.h:1605
void DoDispose() override
Destructor implementation.
Definition wifi-phy.cc:430
dB_u GetRxGain() const
Return the reception gain.
Definition wifi-phy.cc:616
void SetPhyId(uint8_t phyId)
Set the index allocated to this PHY.
Definition wifi-phy.cc:659
virtual void DoChannelSwitch()
Actually switch channel based on the stored channel settings.
Definition wifi-phy.cc:1228
TracedCallback< Ptr< const Packet >, WifiPhyRxfailureReason > m_phyRxDropTrace
The trace source fired when the PHY layer drops a packet it has received.
Definition wifi-phy.h:1528
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition wifi-phy.cc:702
uint8_t m_phyId
the index of the PHY in the vector of PHYs held by the WifiNetDevice
Definition wifi-phy.h:1319
void SetPifs(Time pifs)
Set the PCF Interframe Space (PIFS) for this PHY.
Definition wifi-phy.cc:841
void Configure80211b()
Configure WifiPhy with appropriate channel frequency and supported rates for 802.11b standard.
Definition wifi-phy.cc:880
void SetCcaEdThreshold(dBm_u threshold)
Sets the CCA energy detection threshold.
Definition wifi-phy.cc:520
dB_u m_noiseFigure
The noise figure.
Definition wifi-phy.h:1619
void SwitchMaybeToCcaBusy(const Ptr< const WifiPpdu > ppdu=nullptr)
Check if PHY state should move to CCA busy state based on current state of interference tracker.
Definition wifi-phy.cc:2200
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition wifi-phy.cc:647
dB_u m_rxGain
Reception gain.
Definition wifi-phy.h:1602
double CalculateSnr(const WifiTxVector &txVector, double ber) const
Definition wifi-phy.cc:739
void SetFixedPhyBand(bool enable)
Configure whether it is prohibited to change PHY band after initialization.
Definition wifi-phy.cc:1105
~WifiPhy() override
Definition wifi-phy.cc:399
void Configure80211ac()
Configure WifiPhy with appropriate channel frequency and supported rates for 802.11ac standard.
Definition wifi-phy.cc:959
bool HasFixedPhyBand() const
Definition wifi-phy.cc:1111
TracedCallback< Ptr< const Packet >, RxPowerWattPerChannelBand > m_phyRxBeginTrace
The trace source fired when a packet begins the reception process from the medium.
Definition wifi-phy.h:1486
Ptr< WifiNetDevice > m_device
Pointer to the device.
Definition wifi-phy.h:1623
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition wifi-phy.h:1322
void DoInitialize() override
Initialize() implementation.
Definition wifi-phy.cc:405
bool m_shortPreamble
Flag if short PHY preamble is supported.
Definition wifi-phy.h:1614
uint8_t GetPhyId() const
Get the index allocated to this PHY.
Definition wifi-phy.cc:666
Time m_pifs
PCF Interframe Space (PIFS) duration.
Definition wifi-phy.h:1592
WifiModulationClass m_maxModClassSupported
max modulation class supported
Definition wifi-phy.h:1584
WifiStandard GetStandard() const
Get the configured Wi-Fi standard.
Definition wifi-phy.cc:1069
void SetCapabilitiesChangedCallback(Callback< void > callback)
Definition wifi-phy.cc:501
void SetReceiveOkCallback(RxOkCallback callback)
Definition wifi-phy.cc:472
void SetFrameCaptureModel(const Ptr< FrameCaptureModel > frameCaptureModel)
Sets the frame capture model.
Definition wifi-phy.cc:696
bool m_powerRestricted
Flag whether transmit power is restricted by OBSS PD SR.
Definition wifi-phy.h:1608
Callback< void > m_capabilitiesChangedCallback
Callback when PHY capabilities changed.
Definition wifi-phy.h:1633
Ptr< PhyEntity > GetPhyEntityForPpdu(const Ptr< const WifiPpdu > ppdu) const
Get the supported PHY entity to use for a received PPDU.
Definition wifi-phy.cc:775
Time GetAckTxTime() const
Return the estimated Ack TX time for this PHY.
Definition wifi-phy.cc:853
void Reset()
Reset data upon end of TX or RX.
Definition wifi-phy.cc:1939
TracedCallback< WifiTxVector, Time > m_phyRxPayloadBeginTrace
The trace source fired when the reception of the PHY payload (PSDU) begins.
Definition wifi-phy.h:1502
TracedCallback< const WifiMacHeader &, const WifiTxVector &, Time > m_phyRxMacHeaderEndTrace
The trace source fired when the reception of a MAC header ends.
Definition wifi-phy.h:1513
uint8_t GetMaxSupportedTxSpatialStreams() const
Definition wifi-phy.cc:1372
void Configure80211a()
Configure WifiPhy with appropriate channel frequency and supported rates for 802.11a standard.
Definition wifi-phy.cc:865
ChannelSegments m_channelSettings
Store operating channel settings until initialization.
Definition wifi-phy.h:1586
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition wifi-phy.cc:1075
dBm_u GetPower(uint8_t powerLevel) const
Get the power of the given power level.
Definition wifi-phy.cc:714
bool m_fixedPhyBand
True to prohibit changing PHY band after initialization.
Definition wifi-phy.h:1588
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition wifi-phy.cc:769
uint8_t GetNTxPower() const
Return the number of available transmission power levels.
Definition wifi-phy.cc:590
Time m_ackTxTime
estimated Ack TX time
Definition wifi-phy.h:1593
void UnregisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition wifi-phy.cc:495
dBm_u GetCcaSensitivityThreshold() const
Return the CCA sensitivity threshold.
Definition wifi-phy.cc:540
Class that keeps track of all information about the current PHY operating channel.
MHz_u GetTotalWidth() const
Return the width of the whole operating channel.
bool IsSet() const
Return true if a valid channel has been set, false otherwise.
uint8_t GetNumber(std::size_t segment=0) const
Return the channel number for a given frequency segment.
static uint8_t GetDefaultChannelNumber(MHz_u width, WifiStandard standard, WifiPhyBand band, std::optional< uint8_t > previousChannelNumber=std::nullopt)
Get the default channel number for a given segment of the given width and for the given standard and ...
uint8_t GetPrimaryChannelIndex(MHz_u primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
MHz_u GetFrequency(std::size_t segment=0) const
Return the center frequency for a given frequency segment.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
bool IsValid(WifiPhyBand band=WIFI_PHY_BAND_UNSPECIFIED) const
The standard disallows certain combinations of WifiMode, number of spatial streams,...
uint8_t GetNssTotal() const
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.
uint8_t GetNssMax() const
uint8_t GetTxPowerLevel() const
bool IsAggregation() const
Checks whether the PSDU contains A-MPDU.
bool IsDlMuMimo() const
Return true if this TX vector is used for a downlink multi-user transmission using MU-MIMO.
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< AttributeChecker > MakeAttributeContainerChecker()
Make uninitialized AttributeContainerChecker using explicit types.
Ptr< const AttributeAccessor > MakeAttributeContainerAccessor(T1 a1)
Make AttributeContainerAccessor using explicit types.
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
Ptr< const AttributeChecker > MakeTupleChecker(Ts... checkers)
Create a TupleChecker from AttributeCheckers associated with TupleValue elements.
Definition tuple.h:529
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition abort.h:133
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1332
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPhyBand
Identifies the PHY band.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
MpduType
The type of an MPDU.
Definition wifi-types.h:41
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211p
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211g
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_UNSPECIFIED
@ WIFI_STANDARD_80211ac
@ WIFI_STANDARD_80211b
@ OBSS_PD_CCA_RESET
@ SIGNAL_DETECTION_ABORTED_BY_TX
@ RECEPTION_ABORTED_BY_TX
@ CHANNEL_SWITCHING
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_MOD_CLASS_OFDM
OFDM (Clause 17)
@ WIFI_MOD_CLASS_HR_DSSS
HR/DSSS (Clause 16)
@ WIFI_MOD_CLASS_UNKNOWN
Modulation class unknown or unspecified.
@ 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)
@ OFDM_PHY_10_MHZ
Definition ofdm-phy.h:35
@ OFDM_PHY_5_MHZ
Definition ofdm-phy.h:36
@ WIFI_CHANLIST_PRIMARY
@ LAST_MPDU_IN_AGGREGATE
The MPDU is the last aggregate in an A-MPDU with multiple MPDUs.
Definition wifi-types.h:53
@ NORMAL_MPDU
The MPDU is not part of an A-MPDU.
Definition wifi-types.h:43
@ FIRST_MPDU_IN_AGGREGATE
The MPDU is the first aggregate in an A-MPDU with multiple MPDUs, but is not the last aggregate.
Definition wifi-types.h:48
@ SINGLE_MPDU
The MPDU is a single MPDU.
Definition wifi-types.h:45
@ MIDDLE_MPDU_IN_AGGREGATE
The MPDU is part of an A-MPDU with multiple MPDUs, but is neither the first nor the last aggregate.
Definition wifi-types.h:51
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:443
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
@ SWITCHING
The PHY layer is switching to other channel.
@ TX
The PHY layer is sending a packet.
@ IDLE
The PHY layer is IDLE.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ SLEEP
The PHY layer is sleeping.
@ RX
The PHY layer is receiving a packet.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition nstime.h:1396
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
double Hz_u
Hz weak type.
Definition wifi-units.h:30
double MHz_u
MHz weak type.
Definition wifi-units.h:31
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition enum.h:179
MHz_u GetDefaultChannelWidth(WifiStandard standard, WifiPhyBand band)
Get the default channel width for the given PHY standard and band.
std::map< WifiSpectrumBandInfo, Watt_u > RxPowerWattPerChannelBand
A map of the received power for each band.
Definition phy-entity.h:45
MHz_u GetMaximumChannelWidth(WifiModulationClass modulation)
Get the maximum channel width allowed for the given modulation class.
double dBm_u
dBm weak type
Definition wifi-units.h:27
double DbToRatio(dB_u val)
Convert from dB to ratio.
Definition wifi-utils.cc:25
WifiPhyBand GetDefaultPhyBand(WifiStandard standard)
Get the default PHY band for the given standard.
WifiModulationClass GetModulationClassForStandard(WifiStandard standard)
Return the modulation class corresponding to a given standard.
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition boolean.h:70
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition double.h:32
double dB_u
dB weak type
Definition wifi-units.h:28
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1416
#define list
std::ostream & operator<<(std::ostream &os, const PairObject &obj)
Stream insertion operator.
MpduInfo structure.
Definition wifi-types.h:65
MpduType type
type of MPDU
Definition wifi-types.h:66
uint32_t mpduRefNumber
MPDU ref number.
Definition wifi-types.h:67
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:72
double snr
SNR in linear scale.
Definition wifi-types.h:73
dBm_u rssi
RSSI.
Definition wifi-types.h:74
SignalNoiseDbm structure.
Definition wifi-types.h:58
Declaration of ns3::WifiPpdu class and ns3::WifiConstPsduMap.