A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ht-phy.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Orange Labs
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Rediet <getachew.redieteab@orange.com>
7 * Sébastien Deronne <sebastien.deronne@gmail.com> (for logic ported from wifi-phy)
8 */
9
10#include "ht-phy.h"
11
12#include "ht-ppdu.h"
13
14#include "ns3/assert.h"
15#include "ns3/interference-helper.h"
16#include "ns3/log.h"
17#include "ns3/wifi-phy.h"
18#include "ns3/wifi-psdu.h"
19#include "ns3/wifi-utils.h"
20
21#undef NS_LOG_APPEND_CONTEXT
22#define NS_LOG_APPEND_CONTEXT WIFI_PHY_NS_LOG_APPEND_CONTEXT(m_wifiPhy)
23
24namespace ns3
25{
26
28
29/*******************************************************
30 * HT PHY (IEEE 802.11-2016, clause 19)
31 *******************************************************/
32
33// clang-format off
34
38 WIFI_PPDU_FIELD_HT_SIG, // HT-SIG
39 WIFI_PPDU_FIELD_TRAINING, // HT-STF + HT-LTFs
41};
42
43/**
44 * \brief map a given secondary channel width to its channel list type
45 */
46const std::map<MHz_u, WifiChannelListType> htSecondaryChannels {
48};
49
50// clang-format on
51
52HtPhy::HtPhy(uint8_t maxNss /* = 1 */, bool buildModeList /* = true */)
53 : OfdmPhy(OFDM_PHY_DEFAULT, false) // don't add OFDM modes to list
54{
55 NS_LOG_FUNCTION(this << +maxNss << buildModeList);
56 m_maxSupportedNss = maxNss;
60 if (buildModeList)
61 {
62 NS_ABORT_MSG_IF(maxNss == 0 || maxNss > HT_MAX_NSS,
63 "Unsupported max Nss " << +maxNss << " for HT PHY");
65 }
66}
67
69{
70 NS_LOG_FUNCTION(this);
71}
72
73void
75{
76 NS_LOG_FUNCTION(this);
77 NS_ASSERT(m_modeList.empty());
79
80 uint8_t index = 0;
81 for (uint8_t nss = 1; nss <= m_maxSupportedNss; ++nss)
82 {
83 for (uint8_t i = 0; i <= m_maxSupportedMcsIndexPerSs; ++i)
84 {
85 NS_LOG_LOGIC("Add HtMcs" << +index << " to list");
86 m_modeList.emplace_back(CreateHtMcs(index));
87 ++index;
88 }
89 index = 8 * nss;
90 }
91}
92
94HtPhy::GetMcs(uint8_t index) const
95{
96 for (const auto& mcs : m_modeList)
97 {
98 if (mcs.GetMcsValue() == index)
99 {
100 return mcs;
101 }
102 }
103
104 // Should have returned if MCS found
105 NS_ABORT_MSG("Unsupported MCS index " << +index << " for this PHY entity");
106 return WifiMode();
107}
108
109bool
110HtPhy::IsMcsSupported(uint8_t index) const
111{
112 for (const auto& mcs : m_modeList)
113 {
114 if (mcs.GetMcsValue() == index)
115 {
116 return true;
117 }
118 }
119 return false;
120}
121
122bool
124{
125 return true;
126}
127
130{
131 return m_htPpduFormats;
132}
133
135HtPhy::GetSigMode(WifiPpduField field, const WifiTxVector& txVector) const
136{
137 switch (field)
138 {
139 case WIFI_PPDU_FIELD_PREAMBLE: // consider non-HT header mode for preamble (useful for
140 // InterferenceHelper)
142 return GetLSigMode();
143 case WIFI_PPDU_FIELD_TRAINING: // consider HT-SIG mode for training (useful for
144 // InterferenceHelper)
146 return GetHtSigMode();
147 default:
148 return OfdmPhy::GetSigMode(field, txVector);
149 }
150}
151
154{
155 return GetOfdmRate6Mbps();
156}
157
160{
161 return GetLSigMode(); // same number of data tones as OFDM (i.e. 48)
162}
163
164uint8_t
169
170void
172{
173 NS_LOG_FUNCTION(this << +maxIndex);
175 "Provided max MCS index " << +maxIndex
176 << " per SS greater than max standard-defined value "
178 if (maxIndex != m_maxSupportedMcsIndexPerSs)
179 {
180 NS_LOG_LOGIC("Rebuild mode list since max MCS index per spatial stream has changed");
182 m_modeList.clear();
184 }
185}
186
187uint8_t
192
193void
195{
196 NS_LOG_FUNCTION(this << +maxNss);
198 maxNss = std::min(HT_MAX_NSS, maxNss);
199 if (maxNss != m_maxSupportedNss)
200 {
201 NS_LOG_LOGIC("Rebuild mode list since max number of spatial streams has changed");
202 m_maxSupportedNss = maxNss;
203 m_modeList.clear();
205 }
206}
207
208Time
209HtPhy::GetDuration(WifiPpduField field, const WifiTxVector& txVector) const
210{
211 switch (field)
212 {
214 return MicroSeconds(16); // L-STF + L-LTF or HT-GF-STF + HT-LTF1
216 return GetLSigDuration(txVector.GetPreambleType());
218 // We suppose here that STBC = 0.
219 // If STBC > 0, we need a different mapping between Nss and Nltf
220 // (see IEEE 802.11-2016 , section 19.3.9.4.6 "HT-LTF definition").
221 uint8_t nDataLtf = 8;
222 uint8_t nss = txVector.GetNssMax(); // so as to cover also HE MU case (see
223 // section 27.3.10.10 of IEEE P802.11ax/D4.0)
224 if (nss < 3)
225 {
226 nDataLtf = nss;
227 }
228 else if (nss < 5)
229 {
230 nDataLtf = 4;
231 }
232 else if (nss < 7)
233 {
234 nDataLtf = 6;
235 }
236
237 uint8_t nExtensionLtf = (txVector.GetNess() < 3) ? txVector.GetNess() : 4;
238
239 return GetTrainingDuration(txVector, nDataLtf, nExtensionLtf);
240 }
242 return GetHtSigDuration();
243 default:
244 return OfdmPhy::GetDuration(field, txVector);
245 }
246}
247
248Time
250{
251 return MicroSeconds(4);
252}
253
254Time
256 uint8_t nDataLtf,
257 uint8_t nExtensionLtf /* = 0 */) const
258{
259 NS_ABORT_MSG_IF(nDataLtf == 0 || nDataLtf > 4 || nExtensionLtf > 4 ||
260 (nDataLtf + nExtensionLtf) > 5,
261 "Unsupported combination of data ("
262 << +nDataLtf << ") and extension (" << +nExtensionLtf
263 << ") LTFs numbers for HT"); // see IEEE 802.11-2016, section 19.3.9.4.6
264 // "HT-LTF definition"
265 return MicroSeconds(4) * (1 /* HT-STF */ + nDataLtf + nExtensionLtf);
266}
267
268Time
270{
271 return MicroSeconds(8); // HT-SIG
272}
273
274Time
276 const WifiTxVector& txVector,
277 WifiPhyBand band,
278 MpduType mpdutype,
279 bool incFlag,
280 uint32_t& totalAmpduSize,
281 double& totalAmpduNumSymbols,
282 uint16_t staId) const
283{
284 WifiMode payloadMode = txVector.GetMode(staId);
285 uint8_t stbc = txVector.IsStbc() ? 2 : 1; // corresponding to m_STBC in Nsym computation (see
286 // IEEE 802.11-2016, equations (19-32) and (21-62))
287 uint8_t nes = GetNumberBccEncoders(txVector);
288 // TODO: Update station managers to consider GI capabilities
289 Time symbolDuration = GetSymbolDuration(txVector);
290
291 double numDataBitsPerSymbol =
292 payloadMode.GetDataRate(txVector, staId) * symbolDuration.GetNanoSeconds() / 1e9;
293 uint8_t service = GetNumberServiceBits();
294
295 double numSymbols = 0;
296 switch (mpdutype)
297 {
299 // First packet in an A-MPDU
300 numSymbols = (stbc * (service + size * 8.0 + 6 * nes) / (stbc * numDataBitsPerSymbol));
301 if (incFlag)
302 {
303 totalAmpduSize += size;
304 totalAmpduNumSymbols += numSymbols;
305 }
306 break;
307 }
309 // consecutive packets in an A-MPDU
310 numSymbols = (stbc * size * 8.0) / (stbc * numDataBitsPerSymbol);
311 if (incFlag)
312 {
313 totalAmpduSize += size;
314 totalAmpduNumSymbols += numSymbols;
315 }
316 break;
317 }
319 // last packet in an A-MPDU
320 uint32_t totalSize = totalAmpduSize + size;
321 numSymbols =
322 stbc * ceil((service + totalSize * 8.0 + 6 * nes) / (stbc * numDataBitsPerSymbol));
323 NS_ASSERT(totalAmpduNumSymbols <= numSymbols);
324 numSymbols -= totalAmpduNumSymbols;
325 if (incFlag)
326 {
327 totalAmpduSize = 0;
328 totalAmpduNumSymbols = 0;
329 }
330 break;
331 }
332 case NORMAL_MPDU:
333 case SINGLE_MPDU: {
334 // Not an A-MPDU or single MPDU (i.e. the current payload contains both service and padding)
335 // The number of OFDM symbols in the data field when BCC encoding
336 // is used is given in equation 19-32 of the IEEE 802.11-2016 standard.
337 numSymbols =
338 stbc * ceil((service + size * 8.0 + 6.0 * nes) / (stbc * numDataBitsPerSymbol));
339 break;
340 }
341 default:
342 NS_FATAL_ERROR("Unknown MPDU type");
343 }
344
345 Time payloadDuration =
346 FemtoSeconds(static_cast<uint64_t>(numSymbols * symbolDuration.GetFemtoSeconds()));
347 if (mpdutype == NORMAL_MPDU || mpdutype == SINGLE_MPDU || mpdutype == LAST_MPDU_IN_AGGREGATE)
348 {
349 payloadDuration += GetSignalExtension(band);
350 }
351 return payloadDuration;
352}
353
354uint8_t
356{
357 /**
358 * Add an encoder when crossing maxRatePerCoder frontier.
359 *
360 * The value of 320 Mbps and 350 Mbps for normal GI and short GI (resp.)
361 * were obtained by observing the rates for which Nes was incremented in tables
362 * 19-27 to 19-41 of IEEE 802.11-2016.
363 */
364 double maxRatePerCoder = (txVector.GetGuardInterval().GetNanoSeconds() == 800) ? 320e6 : 350e6;
365 return ceil(txVector.GetMode().GetDataRate(txVector) / maxRatePerCoder);
366}
367
368Time
370{
371 const auto guardInterval = txVector.GetGuardInterval();
372 [[maybe_unused]] const auto gi = guardInterval.GetNanoSeconds();
373 NS_ASSERT(gi == 400 || gi == 800);
374 return GetSymbolDuration(guardInterval);
375}
376
378HtPhy::BuildPpdu(const WifiConstPsduMap& psdus, const WifiTxVector& txVector, Time ppduDuration)
379{
380 NS_LOG_FUNCTION(this << psdus << txVector << ppduDuration);
381 return Create<HtPpdu>(psdus.begin()->second,
382 txVector,
384 ppduDuration,
385 ObtainNextUid(txVector));
386}
387
390{
391 NS_LOG_FUNCTION(this << field << *event);
392 switch (field)
393 {
395 return EndReceiveHtSig(event);
397 return PhyFieldRxStatus(true); // always consider that training has been correctly received
399 // no break so as to go to OfdmPhy for processing
400 default:
401 return OfdmPhy::DoEndReceiveField(field, event);
402 }
403}
404
407{
408 NS_LOG_FUNCTION(this << *event);
409 NS_ASSERT(event->GetPpdu()->GetTxVector().GetPreambleType() == WIFI_PREAMBLE_HT_MF);
411 NS_LOG_DEBUG("HT-SIG: SNR(dB)=" << RatioToDb(snrPer.snr) << ", PER=" << snrPer.per);
412 PhyFieldRxStatus status(GetRandomValue() > snrPer.per);
413 if (status.isSuccess)
414 {
415 NS_LOG_DEBUG("Received HT-SIG");
416 if (!IsAllConfigSupported(WIFI_PPDU_FIELD_HT_SIG, event->GetPpdu()))
417 {
419 }
420 }
421 else
422 {
423 NS_LOG_DEBUG("Drop packet because HT-SIG reception failed");
424 status.reason = HT_SIG_FAILURE;
425 status.actionIfFailure = DROP;
426 }
427 return status;
428}
429
430bool
432{
434 {
435 return true; // wait till reception of HT-SIG (or SIG-A) to make decision
436 }
437 return OfdmPhy::IsAllConfigSupported(field, ppdu);
438}
439
440bool
442{
443 const auto& txVector = ppdu->GetTxVector();
444 if (txVector.GetNss() > m_wifiPhy->GetMaxSupportedRxSpatialStreams())
445 {
446 NS_LOG_DEBUG("Packet reception could not be started because not enough RX antennas");
447 return false;
448 }
449 if (!IsModeSupported(txVector.GetMode()))
450 {
451 NS_LOG_DEBUG("Drop packet because it was sent using an unsupported mode ("
452 << txVector.GetMode() << ")");
453 return false;
454 }
455 return true;
456}
457
460{
461 const auto& centerFrequencies = ppdu->GetTxCenterFreqs();
462 NS_ASSERT(centerFrequencies.size() == 1);
463 const auto& txVector = ppdu->GetTxVector();
464 const auto channelWidth = txVector.GetChannelWidth();
465 NS_LOG_FUNCTION(this << centerFrequencies.front() << channelWidth << txPower);
466 const auto& txMaskRejectionParams = GetTxMaskRejectionParams();
468 centerFrequencies,
469 channelWidth,
470 txPower,
471 GetGuardBandwidth(channelWidth),
472 std::get<0>(txMaskRejectionParams),
473 std::get<1>(txMaskRejectionParams),
474 std::get<2>(txMaskRejectionParams));
475 return v;
476}
477
478void
480{
481 for (uint8_t i = 0; i < 32; ++i)
482 {
483 GetHtMcs(i);
484 }
485}
486
488HtPhy::GetHtMcs(uint8_t index)
489{
490#define CASE(x) \
491 case x: \
492 return GetHtMcs##x();
493
494 switch (index)
495 {
496 CASE(0)
497 CASE(1)
498 CASE(2)
499 CASE(3)
500 CASE(4)
501 CASE(5)
502 CASE(6)
503 CASE(7)
504 CASE(8)
505 CASE(9)
506 CASE(10)
507 CASE(11)
508 CASE(12)
509 CASE(13)
510 CASE(14)
511 CASE(15)
512 CASE(16)
513 CASE(17)
514 CASE(18)
515 CASE(19)
516 CASE(20)
517 CASE(21)
518 CASE(22)
519 CASE(23)
520 CASE(24)
521 CASE(25)
522 CASE(26)
523 CASE(27)
524 CASE(28)
525 CASE(29)
526 CASE(30)
527 CASE(31)
528 default:
529 NS_ABORT_MSG("Inexistent (or not supported) index (" << +index << ") requested for HT");
530 return WifiMode();
531 }
532#undef CASE
533}
534
535#define GET_HT_MCS(x) \
536 WifiMode HtPhy::GetHtMcs##x() \
537 { \
538 static WifiMode mcs = CreateHtMcs(x); \
539 return mcs; \
540 }
541
542GET_HT_MCS(0)
543GET_HT_MCS(1)
544GET_HT_MCS(2)
545GET_HT_MCS(3)
546GET_HT_MCS(4)
547GET_HT_MCS(5)
548GET_HT_MCS(6)
549GET_HT_MCS(7)
550GET_HT_MCS(8)
551GET_HT_MCS(9)
552GET_HT_MCS(10)
553GET_HT_MCS(11)
554GET_HT_MCS(12)
555GET_HT_MCS(13)
556GET_HT_MCS(14)
557GET_HT_MCS(15)
558GET_HT_MCS(16)
559GET_HT_MCS(17)
560GET_HT_MCS(18)
561GET_HT_MCS(19)
562GET_HT_MCS(20)
563GET_HT_MCS(21)
564GET_HT_MCS(22)
565GET_HT_MCS(23)
566GET_HT_MCS(24)
567GET_HT_MCS(25)
568GET_HT_MCS(26)
569GET_HT_MCS(27)
570GET_HT_MCS(28)
571GET_HT_MCS(29)
572GET_HT_MCS(30)
573GET_HT_MCS(31)
574#undef GET_HT_MCS
575
576WifiMode
577HtPhy::CreateHtMcs(uint8_t index)
578{
579 NS_ASSERT_MSG(index <= 31, "HtMcs index must be <= 31!");
580 return WifiModeFactory::CreateWifiMcs("HtMcs" + std::to_string(index),
581 index,
583 false,
590}
591
593HtPhy::GetHtCodeRate(uint8_t mcsValue)
594{
595 return GetCodeRate(mcsValue % 8);
596}
597
599HtPhy::GetCodeRate(uint8_t mcsValue)
600{
601 switch (mcsValue)
602 {
603 case 0:
604 case 1:
605 case 3:
606 return WIFI_CODE_RATE_1_2;
607 case 2:
608 case 4:
609 case 6:
610 return WIFI_CODE_RATE_3_4;
611 case 5:
612 return WIFI_CODE_RATE_2_3;
613 case 7:
614 return WIFI_CODE_RATE_5_6;
615 default:
617 }
618}
619
620uint16_t
622{
623 return GetConstellationSize(mcsValue % 8);
624}
625
626uint16_t
628{
629 switch (mcsValue)
630 {
631 case 0:
632 return 2;
633 case 1:
634 case 2:
635 return 4;
636 case 3:
637 case 4:
638 return 16;
639 case 5:
640 case 6:
641 case 7:
642 return 64;
643 default:
644 return 0;
645 }
646}
647
648uint64_t
649HtPhy::GetPhyRate(uint8_t mcsValue, MHz_u channelWidth, Time guardInterval, uint8_t nss)
650{
651 const auto codeRate = GetHtCodeRate(mcsValue);
652 const auto dataRate = GetDataRate(mcsValue, channelWidth, guardInterval, nss);
653 return CalculatePhyRate(codeRate, dataRate);
654}
655
656uint64_t
657HtPhy::CalculatePhyRate(WifiCodeRate codeRate, uint64_t dataRate)
658{
659 return (dataRate / GetCodeRatio(codeRate));
660}
661
662uint64_t
663HtPhy::GetPhyRateFromTxVector(const WifiTxVector& txVector, uint16_t /* staId */)
664{
665 return GetPhyRate(txVector.GetMode().GetMcsValue(),
666 txVector.GetChannelWidth(),
667 txVector.GetGuardInterval(),
668 txVector.GetNss());
669}
670
671double
673{
674 switch (codeRate)
675 {
677 return (5.0 / 6.0);
678 default:
679 return OfdmPhy::GetCodeRatio(codeRate);
680 }
681}
682
683uint64_t
684HtPhy::GetDataRateFromTxVector(const WifiTxVector& txVector, uint16_t /* staId */)
685{
686 return GetDataRate(txVector.GetMode().GetMcsValue(),
687 txVector.GetChannelWidth(),
688 txVector.GetGuardInterval(),
689 txVector.GetNss());
690}
691
692uint64_t
693HtPhy::GetDataRate(uint8_t mcsValue, MHz_u channelWidth, Time guardInterval, uint8_t nss)
694{
695 [[maybe_unused]] const auto gi = guardInterval.GetNanoSeconds();
696 NS_ASSERT((gi == 800) || (gi == 400));
697 NS_ASSERT(nss <= 4);
698 return CalculateDataRate(GetSymbolDuration(guardInterval),
699 GetUsableSubcarriers(channelWidth),
700 static_cast<uint16_t>(log2(GetHtConstellationSize(mcsValue))),
701 GetCodeRatio(GetHtCodeRate(mcsValue)),
702 nss);
703}
704
705uint64_t
707 uint16_t usableSubCarriers,
708 uint16_t numberOfBitsPerSubcarrier,
709 double codingRate,
710 uint8_t nss)
711{
712 return nss * OfdmPhy::CalculateDataRate(symbolDuration,
713 usableSubCarriers,
714 numberOfBitsPerSubcarrier,
715 codingRate);
716}
717
718uint16_t
720{
721 return (channelWidth == MHz_u{40}) ? 108 : 52;
722}
723
724Time
726{
727 return NanoSeconds(3200) + guardInterval;
728}
729
730uint64_t
732{
733 const auto codeRate = GetHtCodeRate(mcsValue);
734 const auto constellationSize = GetHtConstellationSize(mcsValue);
735 return CalculateNonHtReferenceRate(codeRate, constellationSize);
736}
737
738uint64_t
739HtPhy::CalculateNonHtReferenceRate(WifiCodeRate codeRate, uint16_t constellationSize)
740{
741 uint64_t dataRate;
742 switch (constellationSize)
743 {
744 case 2:
745 if (codeRate == WIFI_CODE_RATE_1_2)
746 {
747 dataRate = 6000000;
748 }
749 else if (codeRate == WIFI_CODE_RATE_3_4)
750 {
751 dataRate = 9000000;
752 }
753 else
754 {
755 NS_FATAL_ERROR("Trying to get reference rate for a MCS with wrong combination of "
756 "coding rate and modulation");
757 }
758 break;
759 case 4:
760 if (codeRate == WIFI_CODE_RATE_1_2)
761 {
762 dataRate = 12000000;
763 }
764 else if (codeRate == WIFI_CODE_RATE_3_4)
765 {
766 dataRate = 18000000;
767 }
768 else
769 {
770 NS_FATAL_ERROR("Trying to get reference rate for a MCS with wrong combination of "
771 "coding rate and modulation");
772 }
773 break;
774 case 16:
775 if (codeRate == WIFI_CODE_RATE_1_2)
776 {
777 dataRate = 24000000;
778 }
779 else if (codeRate == WIFI_CODE_RATE_3_4)
780 {
781 dataRate = 36000000;
782 }
783 else
784 {
785 NS_FATAL_ERROR("Trying to get reference rate for a MCS with wrong combination of "
786 "coding rate and modulation");
787 }
788 break;
789 case 64:
790 if (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3)
791 {
792 dataRate = 48000000;
793 }
794 else if (codeRate == WIFI_CODE_RATE_3_4 || codeRate == WIFI_CODE_RATE_5_6)
795 {
796 dataRate = 54000000;
797 }
798 else
799 {
800 NS_FATAL_ERROR("Trying to get reference rate for a MCS with wrong combination of "
801 "coding rate and modulation");
802 }
803 break;
804 default:
805 NS_FATAL_ERROR("Wrong constellation size");
806 }
807 return dataRate;
808}
809
810bool
811HtPhy::IsAllowed(const WifiTxVector& /*txVector*/)
812{
813 return true;
814}
815
818{
819 return 65535;
820}
821
822const std::map<MHz_u, WifiChannelListType>&
827
828std::vector<MHz_u>
830{
831 std::vector<MHz_u> secondaryWidthsToCheck{};
832 if (ppdu)
833 {
834 for (const auto& secondaryChannel : GetCcaSecondaryChannels())
835 {
836 const auto secondaryWidth = secondaryChannel.first;
837 if (secondaryWidth >= m_wifiPhy->GetChannelWidth())
838 {
839 break;
840 }
841 const MHz_u secondaryMinFreq =
843 secondaryWidth) -
844 (secondaryWidth / 2);
845 const MHz_u secondaryMaxFreq =
847 secondaryWidth) +
848 (secondaryWidth / 2);
849 if (ppdu->DoesOverlapChannel(secondaryMinFreq, secondaryMaxFreq))
850 {
851 secondaryWidthsToCheck.push_back(secondaryWidth);
852 }
853 }
854 }
855 else
856 {
857 for (MHz_u secondaryWidth = 20; secondaryWidth < m_wifiPhy->GetChannelWidth();
858 secondaryWidth *= 2)
859 {
860 secondaryWidthsToCheck.push_back(secondaryWidth);
861 }
862 }
863 return secondaryWidthsToCheck;
864}
865
868{
869 const auto& secondaryChannels = GetCcaSecondaryChannels();
870 const auto secondaryWidthsToCheck = GetCcaSecondaryWidths(ppdu);
871 for (auto secondaryWidth : secondaryWidthsToCheck)
872 {
873 const auto channelType = secondaryChannels.at(secondaryWidth);
874
875 const auto ccaThreshold = GetCcaThreshold(ppdu, channelType);
876 const auto band = GetSecondaryBand(secondaryWidth);
877 if (const auto delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, band);
878 delayUntilCcaEnd.IsStrictlyPositive())
879 {
880 return std::make_pair(delayUntilCcaEnd, channelType);
881 }
882 }
883
884 return std::nullopt;
885}
886
889{
890 if (m_wifiPhy->GetChannelWidth() < MHz_u{40})
891 {
892 return OfdmPhy::GetCcaIndication(ppdu);
893 }
894
895 auto ccaThreshold = GetCcaThreshold(ppdu, WIFI_CHANLIST_PRIMARY);
896 auto delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, GetPrimaryBand(MHz_u{20}));
897 if (delayUntilCcaEnd.IsStrictlyPositive())
898 {
899 return std::make_pair(
900 delayUntilCcaEnd,
901 WIFI_CHANLIST_PRIMARY); // if Primary is busy, ignore CCA for Secondary
902 }
903
904 if (ppdu)
905 {
906 const MHz_u primaryWidth{20};
907 const MHz_u p20MinFreq =
909 (primaryWidth / 2);
910 const MHz_u p20MaxFreq =
912 (primaryWidth / 2);
913 if (ppdu->DoesOverlapChannel(p20MinFreq, p20MaxFreq))
914 {
915 /*
916 * PPDU occupies primary 20 MHz channel, hence we skip CCA sensitivity rules
917 * for signals not occupying the primary 20 MHz channel.
918 */
919 return std::nullopt;
920 }
921 }
922
923 return GetCcaIndicationOnSecondary(ppdu);
924}
925
926} // namespace ns3
927
928namespace
929{
930
931/**
932 * Constructor class for HT modes
933 */
935{
936 public:
943} g_constructor_ht; ///< the constructor for HT modes
944
945} // namespace
Constructor class for HT modes.
Definition ht-phy.cc:935
static uint64_t CalculatePhyRate(WifiCodeRate codeRate, uint64_t dataRate)
Return the PHY rate corresponding to the supplied code rate and data rate.
Definition ht-phy.cc:657
CcaIndication GetCcaIndication(const Ptr< const WifiPpdu > ppdu) override
Get CCA end time and its corresponding channel list type when a new signal has been received by the P...
Definition ht-phy.cc:888
static uint16_t GetConstellationSize(uint8_t mcsValue)
Return the constellation size corresponding to the supplied HT MCS index between 0 and 7,...
Definition ht-phy.cc:627
uint8_t m_bssMembershipSelector
the BSS membership selector
Definition ht-phy.h:570
PhyFieldRxStatus DoEndReceiveField(WifiPpduField field, Ptr< Event > event) override
End receiving a given field, perform amendment-specific actions, and provide the status of the recept...
Definition ht-phy.cc:389
Ptr< SpectrumValue > GetTxPowerSpectralDensity(Watt_u txPower, Ptr< const WifiPpdu > ppdu) const override
Definition ht-phy.cc:459
~HtPhy() override
Destructor for HT PHY.
Definition ht-phy.cc:68
static WifiMode GetLSigMode()
Definition ht-phy.cc:153
static uint16_t GetHtConstellationSize(uint8_t mcsValue)
Return the constellation size corresponding to the supplied HT MCS index.
Definition ht-phy.cc:621
uint8_t m_maxMcsIndexPerSs
the maximum MCS index per spatial stream as defined by the standard
Definition ht-phy.h:568
bool IsAllConfigSupported(WifiPpduField field, Ptr< const WifiPpdu > ppdu) const override
Checks if the signaled configuration (including bandwidth) is supported by the PHY.
Definition ht-phy.cc:431
HtPhy(uint8_t maxNss=1, bool buildModeList=true)
Constructor for HT PHY.
Definition ht-phy.cc:52
static uint64_t GetDataRateFromTxVector(const WifiTxVector &txVector, uint16_t staId)
Return the data rate corresponding to the supplied TXVECTOR.
Definition ht-phy.cc:684
static void InitializeModes()
Initialize all HT modes.
Definition ht-phy.cc:479
static WifiCodeRate GetHtCodeRate(uint8_t mcsValue)
Return the coding rate corresponding to the supplied HT MCS index.
Definition ht-phy.cc:593
static uint64_t CalculateNonHtReferenceRate(WifiCodeRate codeRate, uint16_t constellationSize)
Return the rate (in bps) of the non-HT Reference Rate which corresponds to the supplied code rate and...
Definition ht-phy.cc:739
virtual Time GetTrainingDuration(const WifiTxVector &txVector, uint8_t nDataLtf, uint8_t nExtensionLtf=0) const
Definition ht-phy.cc:255
bool IsMcsSupported(uint8_t index) const override
Check if the WifiMode corresponding to the given MCS index is supported.
Definition ht-phy.cc:110
Time GetDuration(WifiPpduField field, const WifiTxVector &txVector) const override
Get the duration of the PPDU field (or group of fields) used by this entity for the given transmissio...
Definition ht-phy.cc:209
Time GetPayloadDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, MpduType mpdutype, bool incFlag, uint32_t &totalAmpduSize, double &totalAmpduNumSymbols, uint16_t staId) const override
Definition ht-phy.cc:275
uint8_t GetBssMembershipSelector() const
Definition ht-phy.cc:165
static bool IsAllowed(const WifiTxVector &txVector)
Check whether the combination in TXVECTOR is allowed.
Definition ht-phy.cc:811
static uint64_t GetPhyRateFromTxVector(const WifiTxVector &txVector, uint16_t staId)
Return the PHY rate corresponding to the supplied TXVECTOR.
Definition ht-phy.cc:663
WifiMode GetMcs(uint8_t index) const override
Get the WifiMode corresponding to the given MCS index.
Definition ht-phy.cc:94
std::vector< MHz_u > GetCcaSecondaryWidths(const Ptr< const WifiPpdu > ppdu) const
Get the widths of the secondary channels to inspect for CCA indication.
Definition ht-phy.cc:829
virtual uint8_t GetNumberBccEncoders(const WifiTxVector &txVector) const
Definition ht-phy.cc:355
static uint64_t GetNonHtReferenceRate(uint8_t mcsValue)
Calculate the rate in bps of the non-HT Reference Rate corresponding to the supplied HT MCS index.
Definition ht-phy.cc:731
virtual Time GetLSigDuration(WifiPreamble preamble) const
Definition ht-phy.cc:249
static uint64_t GetPhyRate(uint8_t mcsValue, MHz_u channelWidth, Time guardInterval, uint8_t nss)
Return the PHY rate corresponding to the supplied HT MCS index, channel width, guard interval,...
Definition ht-phy.cc:649
virtual const std::map< MHz_u, WifiChannelListType > & GetCcaSecondaryChannels() const
Get the secondary channel widths and their corresponding channel list types that are supported by the...
Definition ht-phy.cc:823
void SetMaxSupportedMcsIndexPerSs(uint8_t maxIndex)
Set the maximum supported MCS index per spatial stream.
Definition ht-phy.cc:171
static WifiMode GetHtMcs(uint8_t index)
Return the HT MCS corresponding to the provided index.
Definition ht-phy.cc:488
static WifiMode CreateHtMcs(uint8_t index)
Return the HT MCS corresponding to the provided index.
Definition ht-phy.cc:577
uint32_t GetMaxPsduSize() const override
Get the maximum PSDU size in bytes.
Definition ht-phy.cc:817
static WifiCodeRate GetCodeRate(uint8_t mcsValue)
Return the coding rate corresponding to the supplied HT MCS index between 0 and 7,...
Definition ht-phy.cc:599
virtual WifiMode GetHtSigMode() const
Definition ht-phy.cc:159
WifiMode GetSigMode(WifiPpduField field, const WifiTxVector &txVector) const override
Get the WifiMode for the SIG field specified by the PPDU field.
Definition ht-phy.cc:135
static uint64_t CalculateDataRate(Time symbolDuration, uint16_t usableSubCarriers, uint16_t numberOfBitsPerSubcarrier, double codingRate, uint8_t nss)
Calculates data rate from the supplied parameters.
Definition ht-phy.cc:706
uint8_t GetMaxSupportedMcsIndexPerSs() const
Set the maximum supported MCS index per spatial stream.
Definition ht-phy.cc:188
bool IsConfigSupported(Ptr< const WifiPpdu > ppdu) const override
Checks if the signaled configuration (excluding bandwidth) is supported by the PHY.
Definition ht-phy.cc:441
Ptr< WifiPpdu > BuildPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, Time ppduDuration) override
Build amendment-specific PPDU.
Definition ht-phy.cc:378
uint8_t m_maxSupportedNss
Maximum supported number of spatial streams (used to build HT MCS indices)
Definition ht-phy.h:592
virtual void BuildModeList()
Build mode list.
Definition ht-phy.cc:74
static double GetCodeRatio(WifiCodeRate codeRate)
Convert WifiCodeRate to a ratio, e.g., code ratio of WIFI_CODE_RATE_1_2 is 0.5.
Definition ht-phy.cc:672
bool HandlesMcsModes() const override
Check if the WifiModes handled by this PHY are MCSs.
Definition ht-phy.cc:123
static const PpduFormats m_htPpduFormats
HT PPDU formats.
Definition ht-phy.h:595
void SetMaxSupportedNss(uint8_t maxNss)
Configure the maximum number of spatial streams supported by this HT PHY.
Definition ht-phy.cc:194
PhyFieldRxStatus EndReceiveHtSig(Ptr< Event > event)
End receiving the HT-SIG, perform HT-specific actions, and provide the status of the reception.
Definition ht-phy.cc:406
virtual Time GetHtSigDuration() const
Definition ht-phy.cc:269
uint8_t m_maxSupportedMcsIndexPerSs
the maximum supported MCS index per spatial stream
Definition ht-phy.h:569
const PpduFormats & GetPpduFormats() const override
Return the PPDU formats of the PHY.
Definition ht-phy.cc:129
virtual Time GetSymbolDuration(const WifiTxVector &txVector) const
Definition ht-phy.cc:369
virtual PhyEntity::CcaIndication GetCcaIndicationOnSecondary(const Ptr< const WifiPpdu > ppdu)
Get CCA end time and its corresponding channel list type when a new signal not occupying the primary ...
Definition ht-phy.cc:867
static uint64_t GetDataRate(uint8_t mcsValue, MHz_u channelWidth, Time guardInterval, uint8_t nss)
Return the data rate corresponding to the supplied HT MCS index, channel width, guard interval,...
Definition ht-phy.cc:693
PHY entity for OFDM (11a)
Definition ofdm-phy.h:50
static WifiMode GetOfdmRate6Mbps()
Return a WifiMode for OFDM at 6 Mbps.
dBm_u GetCcaThreshold(const Ptr< const WifiPpdu > ppdu, WifiChannelListType channelType) const override
Return the CCA threshold for a given channel type.
Definition ofdm-phy.cc:667
uint8_t GetNumberServiceBits() const
Definition ofdm-phy.cc:272
virtual bool IsAllConfigSupported(WifiPpduField field, Ptr< const WifiPpdu > ppdu) const
Checks if the signaled configuration (including bandwidth) is supported by the PHY.
Definition ofdm-phy.cc:346
static uint16_t GetUsableSubcarriers()
Definition ofdm-phy.cc:623
Time GetDuration(WifiPpduField field, const WifiTxVector &txVector) const override
Get the duration of the PPDU field (or group of fields) used by this entity for the given transmissio...
Definition ofdm-phy.cc:183
PhyFieldRxStatus DoEndReceiveField(WifiPpduField field, Ptr< Event > event) override
End receiving a given field, perform amendment-specific actions, and provide the status of the recept...
Definition ofdm-phy.cc:298
static uint64_t CalculateDataRate(WifiCodeRate codeRate, uint16_t constellationSize, MHz_u channelWidth)
Calculates data rate from the supplied parameters.
Definition ofdm-phy.cc:604
WifiMode GetSigMode(WifiPpduField field, const WifiTxVector &txVector) const override
Get the WifiMode for the SIG field specified by the PPDU field.
Definition ofdm-phy.cc:144
static double GetCodeRatio(WifiCodeRate codeRate)
Convert WifiCodeRate to a ratio, e.g., code ratio of WIFI_CODE_RATE_1_2 is 0.5.
Definition ofdm-phy.cc:572
Time GetSignalExtension(WifiPhyBand band) const
Definition ofdm-phy.cc:278
MHz_u GetGuardBandwidth(MHz_u currentChannelWidth) const
virtual uint64_t ObtainNextUid(const WifiTxVector &txVector)
Obtain the next UID for the PPDU to transmit.
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition phy-entity.h:941
std::optional< std::pair< Time, WifiChannelListType > > CcaIndication
CCA end time and its corresponding channel list type (can be std::nullopt if IDLE)
Definition phy-entity.h:926
std::map< WifiPreamble, std::vector< WifiPpduField > > PpduFormats
A map of PPDU field elements per preamble type.
Definition phy-entity.h:531
WifiSpectrumBandInfo GetPrimaryBand(MHz_u bandWidth) const
If the operating channel width is a multiple of 20 MHz, return the info corresponding to the primary ...
Time GetDelayUntilCcaEnd(dBm_u threshold, const WifiSpectrumBandInfo &band)
Return the delay until CCA busy is ended for a given sensitivity threshold and a given band.
virtual bool IsModeSupported(WifiMode mode) const
Check if the WifiMode is supported.
Definition phy-entity.cc:90
virtual CcaIndication GetCcaIndication(const Ptr< const WifiPpdu > ppdu)
Get CCA end time and its corresponding channel list type when a new signal has been received by the P...
std::list< WifiMode > m_modeList
the list of supported modes
Definition phy-entity.h:945
double GetRandomValue() const
Obtain a random value from the WifiPhy's generator.
SnrPer GetPhyHeaderSnrPer(WifiPpduField field, Ptr< Event > event) const
Obtain the SNR and PER of the PPDU field from the WifiPhy's InterferenceHelper class.
std::tuple< dBr_u, dBr_u, dBr_u > GetTxMaskRejectionParams() const
@ DROP
drop PPDU and set CCA_BUSY
Definition phy-entity.h:71
WifiSpectrumBandInfo GetSecondaryBand(MHz_u bandWidth) const
If the channel bonding is used, return the info corresponding to the secondary channel of the given b...
Smart pointer class similar to boost::intrusive_ptr.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:407
int64_t GetFemtoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:417
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition nstime.h:340
static WifiMode CreateWifiMcs(std::string uniqueName, uint8_t mcsValue, WifiModulationClass modClass, bool isMandatory, CodeRateCallback codeRateCallback, ConstellationSizeCallback constellationSizeCallback, PhyRateCallback phyRateCallback, DataRateCallback dataRateCallback, NonHtReferenceRateCallback nonHtReferenceRateCallback, AllowedCallback isAllowedCallback)
Definition wifi-mode.cc:305
represent a single transmission mode
Definition wifi-mode.h:38
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:110
uint8_t GetMcsValue() const
Definition wifi-mode.cc:151
uint8_t GetMaxSupportedRxSpatialStreams() const
Definition wifi-phy.cc:1372
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:810
MHz_u GetChannelWidth() const
Definition wifi-phy.cc:1087
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition wifi-phy.cc:1069
MHz_u GetSecondaryChannelCenterFrequency(MHz_u secondaryChannelWidth) const
Get the center frequency of the secondary channel of the given width.
MHz_u GetPrimaryChannelCenterFrequency(MHz_u primaryChannelWidth) const
Get the center frequency of the primary channel of the given width.
static Ptr< SpectrumValue > CreateHtOfdmTxPowerSpectralDensity(const std::vector< MHz_u > &centerFrequencies, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, dBr_u minInnerBand=dBr_u{-20}, dBr_u minOuterband=dBr_u{-28}, dBr_u lowestPoint=dBr_u{-40})
Create a transmit power spectral density corresponding to OFDM High Throughput (HT/VHT) (802....
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
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.
bool IsStbc() const
Check if STBC is used or not.
WifiPreamble GetPreambleType() const
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
MHz_u GetChannelWidth() const
Time GetGuardInterval() const
uint8_t GetNess() const
#define CASE(x)
#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
#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_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_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition callback.h:745
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:1369
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Time FemtoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1405
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiPhyBand
Identifies the PHY band.
WifiPpduField
The type of PPDU field (grouped for convenience)
MpduType
The type of an MPDU.
Definition wifi-types.h:48
@ UNSUPPORTED_SETTINGS
@ HT_SIG_FAILURE
@ WIFI_PREAMBLE_HT_MF
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ OFDM_PHY_DEFAULT
Definition ofdm-phy.h:34
@ WIFI_CHANLIST_PRIMARY
@ WIFI_CHANLIST_SECONDARY
@ WIFI_PPDU_FIELD_TRAINING
STF + LTF fields (excluding those in preamble for HT-GF)
@ WIFI_PPDU_FIELD_NON_HT_HEADER
PHY header field for DSSS or ERP, short PHY header field for HR/DSSS or ERP, field not present for HT...
@ WIFI_PPDU_FIELD_HT_SIG
HT-SIG field.
@ WIFI_PPDU_FIELD_PREAMBLE
SYNC + SFD fields for DSSS or ERP, shortSYNC + shortSFD fields for HR/DSSS or ERP,...
@ WIFI_PPDU_FIELD_DATA
data field
@ LAST_MPDU_IN_AGGREGATE
The MPDU is the last aggregate in an A-MPDU with multiple MPDUs.
Definition wifi-types.h:60
@ NORMAL_MPDU
The MPDU is not part of an A-MPDU.
Definition wifi-types.h:50
@ 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:55
@ SINGLE_MPDU
The MPDU is a single MPDU.
Definition wifi-types.h:52
@ 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:58
#define GET_HT_MCS(x)
Definition ht-phy.cc:535
Declaration of ns3::HtPhy class.
#define HT_PHY
This defines the BSS membership value for HT PHY.
Definition ht-phy.h:27
Declaration of ns3::HtPpdu class.
class anonymous_namespace{ht-phy.cc}::ConstructorHt g_constructor_ht
the constructor for HT modes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
dB_u RatioToDb(double ratio)
Convert from ratio to dB.
Definition wifi-utils.cc:45
const std::map< MHz_u, WifiChannelListType > htSecondaryChannels
map a given secondary channel width to its channel list type
Definition ht-phy.cc:46
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
constexpr uint8_t HT_MAX_NSS
Maximum number of supported NSS by HT PHY.
Definition ht-phy.h:30
WifiCodeRate
These constants define the various convolutional coding rates used for the OFDM transmission modes in...
@ WIFI_CODE_RATE_2_3
2/3 coding rate
@ WIFI_CODE_RATE_1_2
1/2 coding rate
@ WIFI_CODE_RATE_3_4
3/4 coding rate
@ WIFI_CODE_RATE_UNDEFINED
undefined coding rate
@ WIFI_CODE_RATE_5_6
5/6 coding rate
Status of the reception of the PPDU field.
Definition phy-entity.h:80
WifiPhyRxfailureReason reason
failure reason
Definition phy-entity.h:82
PhyRxFailureAction actionIfFailure
action to perform in case of failure
Definition phy-entity.h:83
bool isSuccess
outcome (true if success) of the reception
Definition phy-entity.h:81
A struct for both SNR and PER.
Definition phy-entity.h:115
double snr
SNR in linear scale.
Definition phy-entity.h:116