A Discrete-Event Network Simulator
API
ht-phy.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Orange Labs
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Authors: Rediet <getachew.redieteab@orange.com>
18  * Sébastien Deronne <sebastien.deronne@gmail.com> (for logic ported from wifi-phy)
19  */
20 
21 #include "ht-phy.h"
22 
23 #include "ht-ppdu.h"
24 
25 #include "ns3/assert.h"
26 #include "ns3/interference-helper.h"
27 #include "ns3/log.h"
28 #include "ns3/wifi-phy.h"
29 #include "ns3/wifi-psdu.h"
30 #include "ns3/wifi-utils.h"
31 
32 namespace ns3
33 {
34 
36 
37 /*******************************************************
38  * HT PHY (IEEE 802.11-2016, clause 19)
39  *******************************************************/
40 
41 // clang-format off
42 
44  { WIFI_PREAMBLE_HT_MF, { WIFI_PPDU_FIELD_PREAMBLE, // L-STF + L-LTF
46  WIFI_PPDU_FIELD_HT_SIG, // HT-SIG
47  WIFI_PPDU_FIELD_TRAINING, // HT-STF + HT-LTFs
49 };
50 
51 // clang-format on
52 
53 HtPhy::HtPhy(uint8_t maxNss /* = 1 */, bool buildModeList /* = true */)
54  : OfdmPhy(OFDM_PHY_DEFAULT, false) // don't add OFDM modes to list
55 {
56  NS_LOG_FUNCTION(this << +maxNss << buildModeList);
57  m_maxSupportedNss = maxNss;
61  if (buildModeList)
62  {
63  NS_ABORT_MSG_IF(maxNss == 0 || maxNss > HT_MAX_NSS,
64  "Unsupported max Nss " << +maxNss << " for HT PHY");
65  BuildModeList();
66  }
67 }
68 
70 {
71  NS_LOG_FUNCTION(this);
72 }
73 
74 void
76 {
77  NS_LOG_FUNCTION(this);
78  NS_ASSERT(m_modeList.empty());
80 
81  uint8_t index = 0;
82  for (uint8_t nss = 1; nss <= m_maxSupportedNss; ++nss)
83  {
84  for (uint8_t i = 0; i <= m_maxSupportedMcsIndexPerSs; ++i)
85  {
86  NS_LOG_LOGIC("Add HtMcs" << +index << " to list");
87  m_modeList.emplace_back(CreateHtMcs(index));
88  ++index;
89  }
90  index = 8 * nss;
91  }
92 }
93 
95 HtPhy::GetMcs(uint8_t index) const
96 {
97  for (const auto& mcs : m_modeList)
98  {
99  if (mcs.GetMcsValue() == index)
100  {
101  return mcs;
102  }
103  }
104 
105  // Should have returned if MCS found
106  NS_ABORT_MSG("Unsupported MCS index " << +index << " for this PHY entity");
107  return WifiMode();
108 }
109 
110 bool
111 HtPhy::IsMcsSupported(uint8_t index) const
112 {
113  for (const auto& mcs : m_modeList)
114  {
115  if (mcs.GetMcsValue() == index)
116  {
117  return true;
118  }
119  }
120  return false;
121 }
122 
123 bool
125 {
126  return true;
127 }
128 
131 {
132  return m_htPpduFormats;
133 }
134 
135 WifiMode
136 HtPhy::GetSigMode(WifiPpduField field, const WifiTxVector& txVector) const
137 {
138  switch (field)
139  {
140  case WIFI_PPDU_FIELD_PREAMBLE: // consider non-HT header mode for preamble (useful for
141  // InterferenceHelper)
143  return GetLSigMode();
144  case WIFI_PPDU_FIELD_TRAINING: // consider HT-SIG mode for training (useful for
145  // InterferenceHelper)
147  return GetHtSigMode();
148  default:
149  return OfdmPhy::GetSigMode(field, txVector);
150  }
151 }
152 
153 WifiMode
155 {
156  return GetOfdmRate6Mbps();
157 }
158 
159 WifiMode
161 {
162  return GetLSigMode(); // same number of data tones as OFDM (i.e. 48)
163 }
164 
165 uint8_t
167 {
169 }
170 
171 void
173 {
174  NS_LOG_FUNCTION(this << +maxIndex);
176  "Provided max MCS index " << +maxIndex
177  << " per SS greater than max standard-defined value "
178  << +m_maxMcsIndexPerSs);
179  if (maxIndex != m_maxSupportedMcsIndexPerSs)
180  {
181  NS_LOG_LOGIC("Rebuild mode list since max MCS index per spatial stream has changed");
182  m_maxSupportedMcsIndexPerSs = maxIndex;
183  m_modeList.clear();
184  BuildModeList();
185  }
186 }
187 
188 uint8_t
190 {
192 }
193 
194 void
196 {
197  NS_LOG_FUNCTION(this << +maxNss);
199  maxNss = std::min(HT_MAX_NSS, maxNss);
200  if (maxNss != m_maxSupportedNss)
201  {
202  NS_LOG_LOGIC("Rebuild mode list since max number of spatial streams has changed");
203  m_maxSupportedNss = maxNss;
204  m_modeList.clear();
205  BuildModeList();
206  }
207 }
208 
209 Time
210 HtPhy::GetDuration(WifiPpduField field, const WifiTxVector& txVector) const
211 {
212  switch (field)
213  {
215  return MicroSeconds(16); // L-STF + L-LTF or HT-GF-STF + HT-LTF1
217  return GetLSigDuration(txVector.GetPreambleType());
219  // We suppose here that STBC = 0.
220  // If STBC > 0, we need a different mapping between Nss and Nltf
221  // (see IEEE 802.11-2016 , section 19.3.9.4.6 "HT-LTF definition").
222  uint8_t nDataLtf = 8;
223  uint8_t nss = txVector.GetNssMax(); // so as to cover also HE MU case (see
224  // section 27.3.10.10 of IEEE P802.11ax/D4.0)
225  if (nss < 3)
226  {
227  nDataLtf = nss;
228  }
229  else if (nss < 5)
230  {
231  nDataLtf = 4;
232  }
233  else if (nss < 7)
234  {
235  nDataLtf = 6;
236  }
237 
238  uint8_t nExtensionLtf = (txVector.GetNess() < 3) ? txVector.GetNess() : 4;
239 
240  return GetTrainingDuration(txVector, nDataLtf, nExtensionLtf);
241  }
243  return GetHtSigDuration();
244  default:
245  return OfdmPhy::GetDuration(field, txVector);
246  }
247 }
248 
249 Time
251 {
252  return MicroSeconds(4);
253 }
254 
255 Time
257  uint8_t nDataLtf,
258  uint8_t nExtensionLtf /* = 0 */) const
259 {
260  NS_ABORT_MSG_IF(nDataLtf == 0 || nDataLtf > 4 || nExtensionLtf > 4 ||
261  (nDataLtf + nExtensionLtf) > 5,
262  "Unsupported combination of data ("
263  << +nDataLtf << ") and extension (" << +nExtensionLtf
264  << ") LTFs numbers for HT"); // see IEEE 802.11-2016, section 19.3.9.4.6
265  // "HT-LTF definition"
266  Time duration = MicroSeconds(4) * (nDataLtf + nExtensionLtf);
267  return MicroSeconds(4) * (1 /* HT-STF */ + nDataLtf + nExtensionLtf);
268 }
269 
270 Time
272 {
273  return MicroSeconds(8); // HT-SIG
274 }
275 
276 Time
278  const WifiTxVector& txVector,
279  WifiPhyBand band,
280  MpduType mpdutype,
281  bool incFlag,
282  uint32_t& totalAmpduSize,
283  double& totalAmpduNumSymbols,
284  uint16_t staId) const
285 {
286  WifiMode payloadMode = txVector.GetMode(staId);
287  uint8_t stbc = txVector.IsStbc() ? 2 : 1; // corresponding to m_STBC in Nsym computation (see
288  // IEEE 802.11-2016, equations (19-32) and (21-62))
289  uint8_t nes = GetNumberBccEncoders(txVector);
290  // TODO: Update station managers to consider GI capabilities
291  Time symbolDuration = GetSymbolDuration(txVector);
292 
293  double numDataBitsPerSymbol =
294  payloadMode.GetDataRate(txVector, staId) * symbolDuration.GetNanoSeconds() / 1e9;
295  uint8_t service = GetNumberServiceBits();
296 
297  double numSymbols = 0;
298  switch (mpdutype)
299  {
301  // First packet in an A-MPDU
302  numSymbols = (stbc * (service + size * 8.0 + 6 * nes) / (stbc * numDataBitsPerSymbol));
303  if (incFlag)
304  {
305  totalAmpduSize += size;
306  totalAmpduNumSymbols += numSymbols;
307  }
308  break;
309  }
311  // consecutive packets in an A-MPDU
312  numSymbols = (stbc * size * 8.0) / (stbc * numDataBitsPerSymbol);
313  if (incFlag)
314  {
315  totalAmpduSize += size;
316  totalAmpduNumSymbols += numSymbols;
317  }
318  break;
319  }
320  case LAST_MPDU_IN_AGGREGATE: {
321  // last packet in an A-MPDU
322  uint32_t totalSize = totalAmpduSize + size;
323  numSymbols = lrint(
324  stbc * ceil((service + totalSize * 8.0 + 6 * nes) / (stbc * numDataBitsPerSymbol)));
325  NS_ASSERT(totalAmpduNumSymbols <= numSymbols);
326  numSymbols -= totalAmpduNumSymbols;
327  if (incFlag)
328  {
329  totalAmpduSize = 0;
330  totalAmpduNumSymbols = 0;
331  }
332  break;
333  }
334  case NORMAL_MPDU:
335  case SINGLE_MPDU: {
336  // Not an A-MPDU or single MPDU (i.e. the current payload contains both service and padding)
337  // The number of OFDM symbols in the data field when BCC encoding
338  // is used is given in equation 19-32 of the IEEE 802.11-2016 standard.
339  numSymbols =
340  lrint(stbc * ceil((service + size * 8.0 + 6.0 * nes) / (stbc * numDataBitsPerSymbol)));
341  break;
342  }
343  default:
344  NS_FATAL_ERROR("Unknown MPDU type");
345  }
346 
347  Time payloadDuration =
348  FemtoSeconds(static_cast<uint64_t>(numSymbols * symbolDuration.GetFemtoSeconds()));
349  if (mpdutype == NORMAL_MPDU || mpdutype == SINGLE_MPDU || mpdutype == LAST_MPDU_IN_AGGREGATE)
350  {
351  payloadDuration += GetSignalExtension(band);
352  }
353  return payloadDuration;
354 }
355 
356 uint8_t
358 {
366  double maxRatePerCoder = (txVector.GetGuardInterval() == 800) ? 320e6 : 350e6;
367  return ceil(txVector.GetMode().GetDataRate(txVector) / maxRatePerCoder);
368 }
369 
370 Time
372 {
373  uint16_t gi = txVector.GetGuardInterval();
374  NS_ASSERT(gi == 400 || gi == 800);
375  return NanoSeconds(3200 + gi);
376 }
377 
379 HtPhy::BuildPpdu(const WifiConstPsduMap& psdus, const WifiTxVector& txVector, Time ppduDuration)
380 {
381  NS_LOG_FUNCTION(this << psdus << txVector << ppduDuration);
382  return Create<HtPpdu>(psdus.begin()->second,
383  txVector,
385  ppduDuration,
386  ObtainNextUid(txVector));
387 }
388 
391 {
392  NS_LOG_FUNCTION(this << field << *event);
393  switch (field)
394  {
396  return EndReceiveHtSig(event);
398  return PhyFieldRxStatus(true); // always consider that training has been correctly received
400  // no break so as to go to OfdmPhy for processing
401  default:
402  return OfdmPhy::DoEndReceiveField(field, event);
403  }
404 }
405 
408 {
409  NS_LOG_FUNCTION(this << *event);
410  NS_ASSERT(event->GetPpdu()->GetTxVector().GetPreambleType() == WIFI_PREAMBLE_HT_MF);
412  NS_LOG_DEBUG("HT-SIG: SNR(dB)=" << RatioToDb(snrPer.snr) << ", PER=" << snrPer.per);
413  PhyFieldRxStatus status(GetRandomValue() > snrPer.per);
414  if (status.isSuccess)
415  {
416  NS_LOG_DEBUG("Received HT-SIG");
417  if (!IsAllConfigSupported(WIFI_PPDU_FIELD_HT_SIG, event->GetPpdu()))
418  {
419  status = PhyFieldRxStatus(false, UNSUPPORTED_SETTINGS, DROP);
420  }
421  }
422  else
423  {
424  NS_LOG_DEBUG("Drop packet because HT-SIG reception failed");
425  status.reason = HT_SIG_FAILURE;
426  status.actionIfFailure = DROP;
427  }
428  return status;
429 }
430 
431 bool
433 {
434  if (field == WIFI_PPDU_FIELD_NON_HT_HEADER)
435  {
436  return true; // wait till reception of HT-SIG (or SIG-A) to make decision
437  }
438  return OfdmPhy::IsAllConfigSupported(field, ppdu);
439 }
440 
441 bool
443 {
444  const auto& txVector = ppdu->GetTxVector();
445  if (txVector.GetNss() > m_wifiPhy->GetMaxSupportedRxSpatialStreams())
446  {
447  NS_LOG_DEBUG("Packet reception could not be started because not enough RX antennas");
448  return false;
449  }
450  if (!IsModeSupported(txVector.GetMode()))
451  {
452  NS_LOG_DEBUG("Drop packet because it was sent using an unsupported mode ("
453  << txVector.GetMode() << ")");
454  return false;
455  }
456  return true;
457 }
458 
461 {
462  const auto& txVector = ppdu->GetTxVector();
463  uint16_t centerFrequency = GetCenterFrequencyForChannelWidth(txVector);
464  uint16_t channelWidth = txVector.GetChannelWidth();
465  NS_LOG_FUNCTION(this << centerFrequency << channelWidth << txPowerW);
466  const auto& txMaskRejectionParams = GetTxMaskRejectionParams();
468  centerFrequency,
469  channelWidth,
470  txPowerW,
471  GetGuardBandwidth(channelWidth),
472  std::get<0>(txMaskRejectionParams),
473  std::get<1>(txMaskRejectionParams),
474  std::get<2>(txMaskRejectionParams));
475  return v;
476 }
477 
478 void
480 {
481  for (uint8_t i = 0; i < 32; ++i)
482  {
483  GetHtMcs(i);
484  }
485 }
486 
487 WifiMode
488 HtPhy::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 
542 GET_HT_MCS(0)
543 GET_HT_MCS(1)
544 GET_HT_MCS(2)
545 GET_HT_MCS(3)
546 GET_HT_MCS(4)
547 GET_HT_MCS(5)
548 GET_HT_MCS(6)
549 GET_HT_MCS(7)
550 GET_HT_MCS(8)
551 GET_HT_MCS(9)
552 GET_HT_MCS(10)
553 GET_HT_MCS(11)
554 GET_HT_MCS(12)
555 GET_HT_MCS(13)
556 GET_HT_MCS(14)
557 GET_HT_MCS(15)
558 GET_HT_MCS(16)
559 GET_HT_MCS(17)
560 GET_HT_MCS(18)
561 GET_HT_MCS(19)
562 GET_HT_MCS(20)
563 GET_HT_MCS(21)
564 GET_HT_MCS(22)
565 GET_HT_MCS(23)
566 GET_HT_MCS(24)
567 GET_HT_MCS(25)
568 GET_HT_MCS(26)
569 GET_HT_MCS(27)
570 GET_HT_MCS(28)
571 GET_HT_MCS(29)
572 GET_HT_MCS(30)
573 GET_HT_MCS(31)
574 #undef GET_HT_MCS
575 
576 WifiMode
577 HtPhy::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 
593 HtPhy::GetHtCodeRate(uint8_t mcsValue)
594 {
595  return GetCodeRate(mcsValue % 8);
596 }
597 
599 HtPhy::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 
620 uint16_t
622 {
623  return GetConstellationSize(mcsValue % 8);
624 }
625 
626 uint16_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 
648 uint64_t
649 HtPhy::GetPhyRate(uint8_t mcsValue, uint16_t channelWidth, uint16_t guardInterval, uint8_t nss)
650 {
651  WifiCodeRate codeRate = GetHtCodeRate(mcsValue);
652  uint64_t dataRate = GetDataRate(mcsValue, channelWidth, guardInterval, nss);
653  return CalculatePhyRate(codeRate, dataRate);
654 }
655 
656 uint64_t
657 HtPhy::CalculatePhyRate(WifiCodeRate codeRate, uint64_t dataRate)
658 {
659  return (dataRate / GetCodeRatio(codeRate));
660 }
661 
662 uint64_t
663 HtPhy::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 
671 double
673 {
674  switch (codeRate)
675  {
676  case WIFI_CODE_RATE_5_6:
677  return (5.0 / 6.0);
678  default:
679  return OfdmPhy::GetCodeRatio(codeRate);
680  }
681 }
682 
683 uint64_t
684 HtPhy::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 
692 uint64_t
693 HtPhy::GetDataRate(uint8_t mcsValue, uint16_t channelWidth, uint16_t guardInterval, uint8_t nss)
694 {
695  NS_ASSERT(guardInterval == 800 || guardInterval == 400);
696  NS_ASSERT(nss <= 4);
697  return CalculateDataRate(GetSymbolDuration(NanoSeconds(guardInterval)),
698  GetUsableSubcarriers(channelWidth),
699  static_cast<uint16_t>(log2(GetHtConstellationSize(mcsValue))),
700  GetCodeRatio(GetHtCodeRate(mcsValue)),
701  nss);
702 }
703 
704 uint64_t
706  uint16_t usableSubCarriers,
707  uint16_t numberOfBitsPerSubcarrier,
708  double codingRate,
709  uint8_t nss)
710 {
711  return nss * OfdmPhy::CalculateDataRate(symbolDuration,
712  usableSubCarriers,
713  numberOfBitsPerSubcarrier,
714  codingRate);
715 }
716 
717 uint16_t
718 HtPhy::GetUsableSubcarriers(uint16_t channelWidth)
719 {
720  return (channelWidth == 40) ? 108 : 52;
721 }
722 
723 Time
725 {
726  return NanoSeconds(3200) + guardInterval;
727 }
728 
729 uint64_t
731 {
732  WifiCodeRate codeRate = GetHtCodeRate(mcsValue);
733  uint16_t constellationSize = GetHtConstellationSize(mcsValue);
734  return CalculateNonHtReferenceRate(codeRate, constellationSize);
735 }
736 
737 uint64_t
738 HtPhy::CalculateNonHtReferenceRate(WifiCodeRate codeRate, uint16_t constellationSize)
739 {
740  uint64_t dataRate;
741  switch (constellationSize)
742  {
743  case 2:
744  if (codeRate == WIFI_CODE_RATE_1_2)
745  {
746  dataRate = 6000000;
747  }
748  else if (codeRate == WIFI_CODE_RATE_3_4)
749  {
750  dataRate = 9000000;
751  }
752  else
753  {
754  NS_FATAL_ERROR("Trying to get reference rate for a MCS with wrong combination of "
755  "coding rate and modulation");
756  }
757  break;
758  case 4:
759  if (codeRate == WIFI_CODE_RATE_1_2)
760  {
761  dataRate = 12000000;
762  }
763  else if (codeRate == WIFI_CODE_RATE_3_4)
764  {
765  dataRate = 18000000;
766  }
767  else
768  {
769  NS_FATAL_ERROR("Trying to get reference rate for a MCS with wrong combination of "
770  "coding rate and modulation");
771  }
772  break;
773  case 16:
774  if (codeRate == WIFI_CODE_RATE_1_2)
775  {
776  dataRate = 24000000;
777  }
778  else if (codeRate == WIFI_CODE_RATE_3_4)
779  {
780  dataRate = 36000000;
781  }
782  else
783  {
784  NS_FATAL_ERROR("Trying to get reference rate for a MCS with wrong combination of "
785  "coding rate and modulation");
786  }
787  break;
788  case 64:
789  if (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3)
790  {
791  dataRate = 48000000;
792  }
793  else if (codeRate == WIFI_CODE_RATE_3_4 || codeRate == WIFI_CODE_RATE_5_6)
794  {
795  dataRate = 54000000;
796  }
797  else
798  {
799  NS_FATAL_ERROR("Trying to get reference rate for a MCS with wrong combination of "
800  "coding rate and modulation");
801  }
802  break;
803  default:
804  NS_FATAL_ERROR("Wrong constellation size");
805  }
806  return dataRate;
807 }
808 
809 bool
810 HtPhy::IsAllowed(const WifiTxVector& /*txVector*/)
811 {
812  return true;
813 }
814 
815 uint32_t
817 {
818  return 65535;
819 }
820 
823 {
824  NS_LOG_FUNCTION(this);
825  if (m_wifiPhy->GetChannelWidth() < 40)
826  {
827  return OfdmPhy::GetCcaIndication(ppdu);
828  }
829  double ccaThresholdDbm = GetCcaThreshold(ppdu, WIFI_CHANLIST_PRIMARY);
830  Time delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThresholdDbm, GetPrimaryBand(20));
831  if (delayUntilCcaEnd.IsStrictlyPositive())
832  {
833  return std::make_pair(
834  delayUntilCcaEnd,
835  WIFI_CHANLIST_PRIMARY); // if Primary is busy, ignore CCA for Secondary
836  }
837  if (ppdu)
838  {
839  const uint16_t primaryWidth = 20;
840  uint16_t p20MinFreq =
842  (primaryWidth / 2);
843  uint16_t p20MaxFreq =
845  (primaryWidth / 2);
846  if (ppdu->DoesOverlapChannel(p20MinFreq, p20MaxFreq))
847  {
848  /*
849  * PPDU occupies primary 20 MHz channel, hence we skip CCA sensitivity rules
850  * for signals not occupying the primary 20 MHz channel.
851  */
852  return std::nullopt;
853  }
854  }
855 
856  const uint16_t secondaryWidth = 20;
857  uint16_t s20MinFreq =
859  (secondaryWidth / 2);
860  uint16_t s20MaxFreq =
862  (secondaryWidth / 2);
863  if (!ppdu || ppdu->DoesOverlapChannel(s20MinFreq, s20MaxFreq))
864  {
865  ccaThresholdDbm = GetCcaThreshold(ppdu, WIFI_CHANLIST_SECONDARY);
866  delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThresholdDbm, GetSecondaryBand(20));
867  if (delayUntilCcaEnd.IsStrictlyPositive())
868  {
869  return std::make_pair(delayUntilCcaEnd, WIFI_CHANLIST_SECONDARY);
870  }
871  }
872 
873  return std::nullopt;
874 }
875 
876 } // namespace ns3
877 
878 namespace
879 {
880 
885 {
886  public:
888  {
891  ns3::Create<ns3::HtPhy>()); // dummy Nss
892  }
894 
895 } // namespace
#define min(a, b)
Definition: 80211b.c:41
Constructor class for HT modes.
Definition: ht-phy.cc:885
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:822
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:561
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:390
~HtPhy() override
Destructor for HT PHY.
Definition: ht-phy.cc:69
static WifiMode GetLSigMode()
Definition: ht-phy.cc:154
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:559
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:432
HtPhy(uint8_t maxNss=1, bool buildModeList=true)
Constructor for HT PHY.
Definition: ht-phy.cc:53
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 uint64_t GetDataRate(uint8_t mcsValue, uint16_t channelWidth, uint16_t guardInterval, uint8_t nss)
Return the data rate corresponding to the supplied HT MCS index, channel width, guard interval,...
Definition: ht-phy.cc:693
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:738
virtual Time GetTrainingDuration(const WifiTxVector &txVector, uint8_t nDataLtf, uint8_t nExtensionLtf=0) const
Definition: ht-phy.cc:256
bool IsMcsSupported(uint8_t index) const override
Check if the WifiMode corresponding to the given MCS index is supported.
Definition: ht-phy.cc:111
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:210
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:277
uint8_t GetBssMembershipSelector() const
Definition: ht-phy.cc:166
static bool IsAllowed(const WifiTxVector &txVector)
Check whether the combination in TXVECTOR is allowed.
Definition: ht-phy.cc:810
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:95
virtual uint8_t GetNumberBccEncoders(const WifiTxVector &txVector) const
Definition: ht-phy.cc:357
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:730
virtual Time GetLSigDuration(WifiPreamble preamble) const
Definition: ht-phy.cc:250
static uint64_t GetPhyRate(uint8_t mcsValue, uint16_t channelWidth, uint16_t guardInterval, uint8_t nss)
Return the PHY rate corresponding to the supplied HT MCS index, channel width, guard interval,...
Definition: ht-phy.cc:649
void SetMaxSupportedMcsIndexPerSs(uint8_t maxIndex)
Set the maximum supported MCS index per spatial stream.
Definition: ht-phy.cc:172
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:816
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:160
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:136
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:705
uint8_t GetMaxSupportedMcsIndexPerSs() const
Set the maximum supported MCS index per spatial stream.
Definition: ht-phy.cc:189
Ptr< SpectrumValue > GetTxPowerSpectralDensity(double txPowerW, Ptr< const WifiPpdu > ppdu) const override
Definition: ht-phy.cc:460
bool IsConfigSupported(Ptr< const WifiPpdu > ppdu) const override
Checks if the signaled configuration (excluding bandwidth) is supported by the PHY.
Definition: ht-phy.cc:442
Ptr< WifiPpdu > BuildPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, Time ppduDuration) override
Build amendment-specific PPDU.
Definition: ht-phy.cc:379
uint8_t m_maxSupportedNss
Maximum supported number of spatial streams (used to build HT MCS indices)
Definition: ht-phy.h:583
virtual void BuildModeList()
Build mode list.
Definition: ht-phy.cc:75
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:124
static const PpduFormats m_htPpduFormats
HT PPDU formats.
Definition: ht-phy.h:586
void SetMaxSupportedNss(uint8_t maxNss)
Configure the maximum number of spatial streams supported by this HT PHY.
Definition: ht-phy.cc:195
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:407
virtual Time GetHtSigDuration() const
Definition: ht-phy.cc:271
uint8_t m_maxSupportedMcsIndexPerSs
the maximum supported MCS index per spatial stream
Definition: ht-phy.h:560
const PpduFormats & GetPpduFormats() const override
Return the PPDU formats of the PHY.
Definition: ht-phy.cc:130
virtual Time GetSymbolDuration(const WifiTxVector &txVector) const
Definition: ht-phy.cc:371
PHY entity for OFDM (11a)
Definition: ofdm-phy.h:61
static WifiMode GetOfdmRate6Mbps()
Return a WifiMode for OFDM at 6 Mbps.
uint8_t GetNumberServiceBits() const
Definition: ofdm-phy.cc:281
double GetCcaThreshold(const Ptr< const WifiPpdu > ppdu, WifiChannelListType channelType) const override
Return the CCA threshold in dBm for a given channel type.
Definition: ofdm-phy.cc:675
static uint64_t CalculateDataRate(WifiCodeRate codeRate, uint16_t constellationSize, uint16_t channelWidth)
Calculates data rate from the supplied parameters.
Definition: ofdm-phy.cc:612
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:355
static uint16_t GetUsableSubcarriers()
Definition: ofdm-phy.cc:631
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:191
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:307
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:152
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:580
Time GetSignalExtension(WifiPhyBand band) const
Definition: ofdm-phy.cc:287
std::tuple< double, double, double > GetTxMaskRejectionParams() const
Definition: phy-entity.cc:1349
virtual uint64_t ObtainNextUid(const WifiTxVector &txVector)
Obtain the next UID for the PPDU to transmit.
Definition: phy-entity.cc:1281
Time GetDelayUntilCcaEnd(double thresholdDbm, const WifiSpectrumBandInfo &band)
Return the delay until CCA busy is ended for a given sensitivity threshold (in dBm) and a given band.
Definition: phy-entity.cc:1227
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition: phy-entity.h:981
WifiSpectrumBandInfo GetSecondaryBand(uint16_t bandWidth) const
If the channel bonding is used, return the info corresponding to the secondary channel of the given b...
Definition: phy-entity.cc:1206
std::map< WifiPreamble, std::vector< WifiPpduField > > PpduFormats
A map of PPDU field elements per preamble type.
Definition: phy-entity.h:561
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const
Definition: phy-entity.cc:1343
virtual bool IsModeSupported(WifiMode mode) const
Check if the WifiMode is supported.
Definition: phy-entity.cc:97
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:969
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...
Definition: phy-entity.cc:1256
std::list< WifiMode > m_modeList
the list of supported modes
Definition: phy-entity.h:985
double GetRandomValue() const
Obtain a random value from the WifiPhy's generator.
Definition: phy-entity.cc:1177
SnrPer GetPhyHeaderSnrPer(WifiPpduField field, Ptr< Event > event) const
Obtain the SNR and PER of the PPDU field from the WifiPhy's InterferenceHelper class.
Definition: phy-entity.cc:268
uint16_t GetCenterFrequencyForChannelWidth(const WifiTxVector &txVector) const
Get the center frequency of the channel corresponding the current TxVector rather than that of the su...
Definition: phy-entity.cc:1294
@ DROP
drop PPDU and set CCA_BUSY
Definition: phy-entity.h:103
WifiSpectrumBandInfo GetPrimaryBand(uint16_t bandWidth) const
If the operating channel width is a multiple of 20 MHz, return the info corresponding to the primary ...
Definition: phy-entity.cc:1195
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:418
int64_t GetFemtoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:428
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:351
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:318
represent a single transmission mode
Definition: wifi-mode.h:51
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:122
uint8_t GetMcsValue() const
Definition: wifi-mode.cc:163
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:1051
uint8_t GetMaxSupportedRxSpatialStreams() const
Definition: wifi-phy.cc:1319
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:752
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1033
uint16_t GetSecondaryChannelCenterFrequency(uint16_t secondaryChannelWidth) const
Get the center frequency of the secondary channel of the given width.
uint16_t GetPrimaryChannelCenterFrequency(uint16_t primaryChannelWidth) const
Get the center frequency of the primary channel of the given width.
static Ptr< SpectrumValue > CreateHtOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40)
Create a transmit power spectral density corresponding to OFDM High Throughput (HT) (802....
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint16_t GetGuardInterval() const
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
uint16_t GetChannelWidth() const
uint8_t GetNess() const
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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:765
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time FemtoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1386
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
WifiPpduField
The type of PPDU field (grouped for convenience)
MpduType
The type of an MPDU.
@ UNSUPPORTED_SETTINGS
@ HT_SIG_FAILURE
@ WIFI_PREAMBLE_HT_MF
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ OFDM_PHY_DEFAULT
Definition: ofdm-phy.h:45
@ 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.
@ NORMAL_MPDU
The MPDU is not part of an A-MPDU.
@ FIRST_MPDU_IN_AGGREGATE
The MPDU is the first aggregate in an A-MPDU with multiple MPDUs, but is not the last aggregate.
@ SINGLE_MPDU
The MPDU is a single MPDU.
@ MIDDLE_MPDU_IN_AGGREGATE
The MPDU is part of an A-MPDU with multiple MPDUs, but is neither the first nor the last aggregate.
#define CASE(x)
#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:38
Declaration of ns3::HtPpdu class.
class anonymous_namespace{ht-phy.cc}::ConstructorHt g_constructor_ht
the constructor for HT modes
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25255
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double RatioToDb(double ratio)
Convert from ratio to dB.
Definition: wifi-utils.cc:52
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
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:704
constexpr uint8_t HT_MAX_NSS
Maximum number of supported NSS by HT PHY.
Definition: ht-phy.h:41
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:112
WifiPhyRxfailureReason reason
failure reason
Definition: phy-entity.h:114
PhyRxFailureAction actionIfFailure
action to perform in case of failure
Definition: phy-entity.h:115
bool isSuccess
outcome (true if success) of the reception
Definition: phy-entity.h:113
A struct for both SNR and PER.
Definition: phy-entity.h:147
double snr
SNR in linear scale.
Definition: phy-entity.h:148