A Discrete-Event Network Simulator
API
wifi-tx-vector.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 CTTC
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: Nicola Baldo <nbaldo@cttc.es>
18  * Ghada Badawy <gbadawy@gmail.com>
19  */
20 
21 #include "wifi-tx-vector.h"
22 
23 #include "wifi-phy-common.h"
24 
25 #include "ns3/abort.h"
26 #include "ns3/eht-phy.h"
27 
28 #include <algorithm>
29 #include <iterator>
30 
31 namespace ns3
32 {
33 
35  : m_txPowerLevel(1),
36  m_preamble(WIFI_PREAMBLE_LONG),
37  m_channelWidth(20),
38  m_guardInterval(800),
39  m_nTx(1),
40  m_nss(1),
41  m_ness(0),
42  m_aggregation(false),
43  m_stbc(false),
44  m_ldpc(false),
45  m_bssColor(0),
46  m_length(0),
47  m_triggerResponding(false),
48  m_modeInitialized(false),
49  m_inactiveSubchannels(),
50  m_ruAllocation(),
51  m_ehtPpduType(1) // SU transmission by default
52 {
53 }
54 
56  uint8_t powerLevel,
57  WifiPreamble preamble,
58  uint16_t guardInterval,
59  uint8_t nTx,
60  uint8_t nss,
61  uint8_t ness,
62  uint16_t channelWidth,
63  bool aggregation,
64  bool stbc,
65  bool ldpc,
66  uint8_t bssColor,
67  uint16_t length,
68  bool triggerResponding)
69  : m_mode(mode),
70  m_txPowerLevel(powerLevel),
71  m_preamble(preamble),
72  m_channelWidth(channelWidth),
73  m_guardInterval(guardInterval),
74  m_nTx(nTx),
75  m_nss(nss),
76  m_ness(ness),
77  m_aggregation(aggregation),
78  m_stbc(stbc),
79  m_ldpc(ldpc),
80  m_bssColor(bssColor),
81  m_length(length),
82  m_triggerResponding(triggerResponding),
83  m_modeInitialized(true),
84  m_inactiveSubchannels(),
85  m_ruAllocation(),
86  m_ehtPpduType(1) // SU transmission by default
87 {
88 }
89 
91  : m_mode(txVector.m_mode),
92  m_txPowerLevel(txVector.m_txPowerLevel),
93  m_preamble(txVector.m_preamble),
94  m_channelWidth(txVector.m_channelWidth),
95  m_guardInterval(txVector.m_guardInterval),
96  m_nTx(txVector.m_nTx),
97  m_nss(txVector.m_nss),
98  m_ness(txVector.m_ness),
99  m_aggregation(txVector.m_aggregation),
100  m_stbc(txVector.m_stbc),
101  m_ldpc(txVector.m_ldpc),
102  m_bssColor(txVector.m_bssColor),
103  m_length(txVector.m_length),
104  m_triggerResponding(txVector.m_triggerResponding),
105  m_modeInitialized(txVector.m_modeInitialized),
106  m_inactiveSubchannels(txVector.m_inactiveSubchannels),
107  m_sigBMcs(txVector.m_sigBMcs),
108  m_ruAllocation(txVector.m_ruAllocation),
109  m_ehtPpduType(txVector.m_ehtPpduType)
110 {
111  m_muUserInfos.clear();
112  if (!txVector.m_muUserInfos.empty()) // avoids crashing for loop
113  {
114  for (auto& info : txVector.m_muUserInfos)
115  {
116  m_muUserInfos.insert(std::make_pair(info.first, info.second));
117  }
118  }
119 }
120 
122 {
123  m_muUserInfos.clear();
124 }
125 
126 bool
128 {
129  return m_modeInitialized;
130 }
131 
132 WifiMode
133 WifiTxVector::GetMode(uint16_t staId) const
134 {
135  if (!m_modeInitialized)
136  {
137  NS_FATAL_ERROR("WifiTxVector mode must be set before using");
138  }
139  if (!IsMu())
140  {
141  return m_mode;
142  }
143  NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU (" << staId << ")");
144  const auto userInfoIt = m_muUserInfos.find(staId);
145  NS_ASSERT(userInfoIt != m_muUserInfos.cend());
147  {
148  case WIFI_MOD_CLASS_EHT:
149  return EhtPhy::GetEhtMcs(userInfoIt->second.mcs);
150  case WIFI_MOD_CLASS_HE:
151  return HePhy::GetHeMcs(userInfoIt->second.mcs);
152  default:
153  NS_ABORT_MSG("Unsupported modulation class: " << GetModulationClassForPreamble(m_preamble));
154  }
155  return WifiMode(); // invalid WifiMode
156 }
157 
160 {
161  NS_ABORT_MSG_IF(!m_modeInitialized, "WifiTxVector mode must be set before using");
162 
163  if (IsMu())
164  {
165  NS_ASSERT(!m_muUserInfos.empty());
166  // all the modes belong to the same modulation class
168  }
169  return m_mode.GetModulationClass();
170 }
171 
172 uint8_t
174 {
175  return m_txPowerLevel;
176 }
177 
180 {
181  return m_preamble;
182 }
183 
184 uint16_t
186 {
187  return m_channelWidth;
188 }
189 
190 uint16_t
192 {
193  return m_guardInterval;
194 }
195 
196 uint8_t
198 {
199  return m_nTx;
200 }
201 
202 uint8_t
203 WifiTxVector::GetNss(uint16_t staId) const
204 {
205  if (IsMu())
206  {
207  NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU (" << staId << ")");
208  NS_ASSERT(m_muUserInfos.find(staId) != m_muUserInfos.end());
209  return m_muUserInfos.at(staId).nss;
210  }
211  return m_nss;
212 }
213 
214 uint8_t
216 {
217  uint8_t nss = 0;
218  if (IsMu())
219  {
220  for (const auto& info : m_muUserInfos)
221  {
222  nss = (nss < info.second.nss) ? info.second.nss : nss;
223  }
224  }
225  else
226  {
227  nss = m_nss;
228  }
229  return nss;
230 }
231 
232 uint8_t
234 {
235  return m_ness;
236 }
237 
238 bool
240 {
241  return m_aggregation;
242 }
243 
244 bool
246 {
247  return m_stbc;
248 }
249 
250 bool
252 {
253  return m_ldpc;
254 }
255 
256 bool
258 {
259  return ((m_channelWidth >= 40) && !IsMu() &&
261 }
262 
263 void
265 {
266  m_mode = mode;
267  m_modeInitialized = true;
268 }
269 
270 void
271 WifiTxVector::SetMode(WifiMode mode, uint16_t staId)
272 {
273  NS_ABORT_MSG_IF(!IsMu(), "Not a MU transmission");
274  NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
275  m_muUserInfos[staId].mcs = mode.GetMcsValue();
276  m_modeInitialized = true;
277 }
278 
279 void
280 WifiTxVector::SetTxPowerLevel(uint8_t powerlevel)
281 {
282  m_txPowerLevel = powerlevel;
283 }
284 
285 void
287 {
288  m_preamble = preamble;
289 }
290 
291 void
292 WifiTxVector::SetChannelWidth(uint16_t channelWidth)
293 {
294  m_channelWidth = channelWidth;
295 }
296 
297 void
298 WifiTxVector::SetGuardInterval(uint16_t guardInterval)
299 {
300  m_guardInterval = guardInterval;
301 }
302 
303 void
305 {
306  m_nTx = nTx;
307 }
308 
309 void
311 {
312  m_nss = nss;
313 }
314 
315 void
316 WifiTxVector::SetNss(uint8_t nss, uint16_t staId)
317 {
318  NS_ABORT_MSG_IF(!IsMu(), "Not a MU transmission");
319  NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
320  m_muUserInfos[staId].nss = nss;
321 }
322 
323 void
325 {
326  m_ness = ness;
327 }
328 
329 void
331 {
332  m_aggregation = aggregation;
333 }
334 
335 void
337 {
338  m_stbc = stbc;
339 }
340 
341 void
343 {
344  m_ldpc = ldpc;
345 }
346 
347 void
349 {
350  m_bssColor = color;
351 }
352 
353 uint8_t
355 {
356  return m_bssColor;
357 }
358 
359 void
360 WifiTxVector::SetLength(uint16_t length)
361 {
362  m_length = length;
363 }
364 
365 uint16_t
367 {
368  return m_length;
369 }
370 
371 bool
373 {
374  return m_triggerResponding;
375 }
376 
377 void
378 WifiTxVector::SetTriggerResponding(bool triggerResponding)
379 {
380  m_triggerResponding = triggerResponding;
381 }
382 
383 void
385 {
386  m_sigBMcs = mode;
387 }
388 
389 WifiMode
391 {
392  return m_sigBMcs;
393 }
394 
395 void
397 {
398  if (ns3::IsDlMu(m_preamble) && !m_muUserInfos.empty())
399  {
400  NS_ASSERT(ruAlloc == DeriveRuAllocation());
401  }
402  m_ruAllocation = ruAlloc;
403 }
404 
405 const RuAllocation&
407 {
408  if (ns3::IsDlMu(m_preamble) && m_ruAllocation.empty())
409  {
411  }
412  return m_ruAllocation;
413 }
414 
415 void
417 {
420 }
421 
422 uint8_t
424 {
425  return m_ehtPpduType;
426 }
427 
428 bool
430 {
431  if (!GetModeInitialized())
432  {
433  return false;
434  }
435  std::string modeName = m_mode.GetUniqueName();
436  if (m_channelWidth == 20)
437  {
438  if (m_nss != 3 && m_nss != 6)
439  {
440  return (modeName != "VhtMcs9");
441  }
442  }
443  else if (m_channelWidth == 80)
444  {
445  if (m_nss == 3 || m_nss == 7)
446  {
447  return (modeName != "VhtMcs6");
448  }
449  else if (m_nss == 6)
450  {
451  return (modeName != "VhtMcs9");
452  }
453  }
454  else if (m_channelWidth == 160)
455  {
456  if (m_nss == 3)
457  {
458  return (modeName != "VhtMcs9");
459  }
460  }
461  return true;
462 }
463 
464 bool
466 {
467  return IsDlMu() || IsUlMu();
468 }
469 
470 bool
472 {
473  return ns3::IsDlMu(m_preamble) && !(IsEht(m_preamble) && m_ehtPpduType == 1);
474 }
475 
476 bool
478 {
479  return ns3::IsUlMu(m_preamble);
480 }
481 
483 WifiTxVector::GetRu(uint16_t staId) const
484 {
485  NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
486  NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
487  return m_muUserInfos.at(staId).ru;
488 }
489 
490 void
492 {
493  NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
494  NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
495  m_muUserInfos[staId].ru = ru;
496 }
497 
499 WifiTxVector::GetHeMuUserInfo(uint16_t staId) const
500 {
501  NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
502  return m_muUserInfos.at(staId);
503 }
504 
505 void
507 {
508  NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
509  NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
510  m_muUserInfos[staId] = userInfo;
511  m_modeInitialized = true;
512  m_ruAllocation.clear();
513 }
514 
517 {
518  NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
519  return m_muUserInfos;
520 }
521 
524 {
525  NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
526  m_ruAllocation.clear();
527  return m_muUserInfos;
528 }
529 
530 std::pair<std::size_t, std::size_t>
532 {
534  {
535  return {1, 0};
536  }
537 
538  // MU-MIMO is not handled for now, i.e. one station per RU
539  auto ruAllocation = GetRuAllocation();
540  NS_ASSERT_MSG(!ruAllocation.empty(), "RU allocation is not set");
541  if (ruAllocation.size() != m_channelWidth / 20)
542  {
543  ruAllocation = DeriveRuAllocation();
544  }
545  NS_ASSERT_MSG(ruAllocation.size() == m_channelWidth / 20,
546  "RU allocation is not consistent with packet bandwidth");
547 
548  std::pair<std::size_t /* number of RUs in content channel 1 */,
549  std::size_t /* number of RUs in content channel 2 */>
550  chSize{0, 0};
551 
552  switch (GetChannelWidth())
553  {
554  case 40:
555  chSize.second += HeRu::GetRuSpecs(ruAllocation[1]).size();
556  [[fallthrough]];
557  case 20:
558  chSize.first += HeRu::GetRuSpecs(ruAllocation[0]).size();
559  break;
560  default:
561  for (auto n = 0; n < m_channelWidth / 20;)
562  {
563  chSize.first += HeRu::GetRuSpecs(ruAllocation[n]).size();
564  chSize.second += HeRu::GetRuSpecs(ruAllocation[n + 1]).size();
565  if (ruAllocation[n] >= 208)
566  {
567  // 996 tone RU occupies 80 MHz
568  n += 4;
569  continue;
570  }
571  n += 2;
572  }
573  break;
574  }
575  return chSize;
576 }
577 
578 void
579 WifiTxVector::SetInactiveSubchannels(const std::vector<bool>& inactiveSubchannels)
580 {
582  "Only HE (or later) authorized for preamble puncturing");
584  m_channelWidth < 80,
585  "Preamble puncturing only possible for transmission bandwidth of 80 MHz or larger");
586  NS_ABORT_MSG_IF(!inactiveSubchannels.empty() &&
587  inactiveSubchannels.size() != (m_channelWidth / 20),
588  "The size of the inactive subchannnels bitmap should be equal to the number of "
589  "20 MHz subchannels");
590  m_inactiveSubchannels = inactiveSubchannels;
591 }
592 
593 const std::vector<bool>&
595 {
596  return m_inactiveSubchannels;
597 }
598 
599 std::ostream&
600 operator<<(std::ostream& os, const WifiTxVector& v)
601 {
602  if (!v.IsValid())
603  {
604  os << "TXVECTOR not valid";
605  return os;
606  }
607  os << "txpwrlvl: " << +v.GetTxPowerLevel() << " preamble: " << v.GetPreambleType()
608  << " channel width: " << v.GetChannelWidth() << " GI: " << v.GetGuardInterval()
609  << " NTx: " << +v.GetNTx() << " Ness: " << +v.GetNess()
610  << " MPDU aggregation: " << v.IsAggregation() << " STBC: " << v.IsStbc()
611  << " FEC coding: " << (v.IsLdpc() ? "LDPC" : "BCC");
613  {
614  os << " BSS color: " << +v.GetBssColor();
615  }
616  if (v.IsUlMu())
617  {
618  os << " Length: " << v.GetLength();
619  }
620  if (ns3::IsDlMu(v.GetPreambleType()))
621  {
622  os << " SIG-B mode: " << v.GetSigBMode();
623  }
624  if (v.IsMu())
625  {
627  os << " num User Infos: " << userInfoMap.size();
628  for (auto& ui : userInfoMap)
629  {
630  os << ", {STA-ID: " << ui.first << ", " << ui.second.ru << ", MCS: " << +ui.second.mcs
631  << ", Nss: " << +ui.second.nss << "}";
632  }
633  }
634  else
635  {
636  os << " mode: " << v.GetMode() << " Nss: " << +v.GetNss();
637  }
638  const auto& puncturedSubchannels = v.GetInactiveSubchannels();
639  if (!puncturedSubchannels.empty())
640  {
641  os << " Punctured subchannels: ";
642  std::copy(puncturedSubchannels.cbegin(),
643  puncturedSubchannels.cend(),
644  std::ostream_iterator<bool>(os, ", "));
645  }
646  if (IsEht(v.GetPreambleType()))
647  {
648  os << " EHT PPDU type: " << +v.GetEhtPpduType();
649  }
650  return os;
651 }
652 
653 bool
655 {
656  return ru == other.ru && mcs == other.mcs && nss == other.nss;
657 }
658 
659 bool
661 {
662  return !(*this == other);
663 }
664 
667 {
668  ContentChannelAllocation channelAlloc{{}};
669 
670  if (m_channelWidth > 20)
671  {
672  channelAlloc.emplace_back();
673  }
674 
675  for (const auto& [staId, userInfo] : m_muUserInfos)
676  {
677  auto ruType = userInfo.ru.GetRuType();
678  auto ruIdx = userInfo.ru.GetIndex();
679 
680  if ((ruType == HeRu::RU_484_TONE) || (ruType == HeRu::RU_996_TONE))
681  {
682  channelAlloc[0].push_back(staId);
683  channelAlloc[1].push_back(staId);
684  continue;
685  }
686 
687  size_t numRus{1};
688  if (ruType < HeRu::RU_242_TONE)
689  {
690  numRus = HeRu::m_heRuSubcarrierGroups.at({20, ruType}).size();
691  }
692 
693  if (((ruIdx - 1) / numRus) % 2 == 0)
694  {
695  channelAlloc[0].push_back(staId);
696  }
697  else
698  {
699  channelAlloc[1].push_back(staId);
700  }
701  }
702 
703  return channelAlloc;
704 }
705 
708 {
709  std::all_of(m_muUserInfos.cbegin(), m_muUserInfos.cend(), [&](const auto& userInfo) {
710  return userInfo.second.ru.GetRuType() == m_muUserInfos.cbegin()->second.ru.GetRuType();
711  });
713  std::vector<HeRu::RuType> ruTypes{};
714  ruTypes.resize(ruAllocations.size());
715  for (auto it = m_muUserInfos.begin(); it != m_muUserInfos.end(); ++it)
716  {
717  const auto ruType = it->second.ru.GetRuType();
718  const auto ruBw = HeRu::GetBandwidth(ruType);
719  const auto isPrimary80MHz = it->second.ru.GetPrimary80MHz();
720  const auto rusPerSubchannel = HeRu::GetRusOfType(ruBw > 20 ? ruBw : 20, ruType);
721  auto ruIndex = it->second.ru.GetIndex();
722  if ((m_channelWidth >= 80) && (ruIndex > 19))
723  {
724  // take into account the center 26-tone RU in the primary 80 MHz
725  ruIndex--;
726  }
727  if ((!isPrimary80MHz) && (ruIndex > 19))
728  {
729  // take into account the center 26-tone RU in the secondary 80 MHz
730  ruIndex--;
731  }
732  if (!isPrimary80MHz && (ruType != HeRu::RU_2x996_TONE))
733  {
735  // adjust RU index for the secondary 80 MHz: in that case index is restarting at 1,
736  // hence we need to add an offset corresponding to the number of RUs of the same type in
737  // the primary 80 MHz
738  ruIndex += HeRu::GetRusOfType(80, ruType).size();
739  }
740  const auto index =
741  (ruBw < 20) ? ((ruIndex - 1) / rusPerSubchannel.size()) : ((ruIndex - 1) * (ruBw / 20));
742  const auto numSubchannelsForRu = (ruBw < 20) ? 1 : (ruBw / 20);
743  NS_ABORT_IF(index >= (m_channelWidth / 20));
744  auto ruAlloc = HeRu::GetEqualizedRuAllocation(ruType, false);
745  if (ruAllocations.at(index) != HeRu::EMPTY_242_TONE_RU)
746  {
747  if (ruType == ruTypes.at(index))
748  {
749  continue;
750  }
751  if (ruType == HeRu::RU_26_TONE)
752  {
753  ruAlloc = HeRu::GetEqualizedRuAllocation(ruTypes.at(index), true);
754  }
755  else if (ruTypes.at(index) == HeRu::RU_26_TONE)
756  {
757  ruAlloc = HeRu::GetEqualizedRuAllocation(ruType, true);
758  }
759  else
760  {
761  NS_ASSERT_MSG(false, "unsupported RU combination");
762  }
763  }
764  for (auto i = 0; i < numSubchannelsForRu; ++i)
765  {
766  ruTypes.at(index + i) = ruType;
767  ruAllocations.at(index + i) = ruAlloc;
768  }
769  }
770  return ruAllocations;
771 }
772 
773 } // namespace ns3
static WifiMode GetEhtMcs(uint8_t index)
Return the EHT MCS corresponding to the provided index.
Definition: eht-phy.cc:226
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
Definition: he-phy.cc:1559
RU Specification.
Definition: he-ru.h:66
static std::vector< RuSpec > GetRuSpecs(uint8_t ruAllocation)
Get the RU specs based on RU_ALLOCATION.
Definition: he-ru.cc:374
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:744
static constexpr uint8_t EMPTY_242_TONE_RU
Empty 242-tone RU identifier.
Definition: he-ru.h:276
static std::vector< HeRu::RuSpec > GetRusOfType(uint16_t bw, HeRu::RuType ruType)
Get the set of distinct RUs of the given type (number of tones) available in a HE PPDU of the given b...
Definition: he-ru.cc:492
static const SubcarrierGroups m_heRuSubcarrierGroups
Subcarrier groups for all RUs (with indices being applicable to primary 80 MHz channel)
Definition: he-ru.h:256
static uint8_t GetEqualizedRuAllocation(RuType ruType, bool isOdd)
Get the RU_ALLOCATION value for equal size RUs.
Definition: he-ru.cc:402
@ RU_26_TONE
Definition: he-ru.h:42
@ RU_484_TONE
Definition: he-ru.h:46
@ RU_996_TONE
Definition: he-ru.h:47
@ RU_242_TONE
Definition: he-ru.h:45
@ RU_2x996_TONE
Definition: he-ru.h:48
represent a single transmission mode
Definition: wifi-mode.h:50
std::string GetUniqueName() const
Definition: wifi-mode.cc:148
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:185
uint8_t GetMcsValue() const
Definition: wifi-mode.cc:163
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint16_t m_channelWidth
channel width in MHz
void SetStbc(bool stbc)
Sets if STBC is being used.
void SetNess(uint8_t ness)
Sets the Ness number.
bool IsTriggerResponding() const
Return true if the Trigger Responding parameter is set to true, false otherwise.
bool m_aggregation
Flag whether the PSDU contains A-MPDU.
void SetEhtPpduType(uint8_t type)
Set the EHT_PPDU_TYPE parameter.
const RuAllocation & GetRuAllocation() const
Get RU Allocation of SIG-B.
uint16_t GetGuardInterval() const
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
bool IsValid() const
The standard disallows certain combinations of WifiMode, number of spatial streams,...
void SetLdpc(bool ldpc)
Sets if LDPC FEC coding is being used.
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
uint8_t GetBssColor() const
Get the BSS color.
bool GetModeInitialized() const
std::vector< bool > m_inactiveSubchannels
Bitmap of inactive subchannels used for preamble puncturing.
WifiMode m_mode
The DATARATE parameter in Table 15-4.
std::map< uint16_t, HeMuUserInfo > HeMuUserInfoMap
map of HE MU specific user info parameters indexed by STA-ID
uint8_t GetNTx() const
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void SetTriggerResponding(bool triggerResponding)
Set the Trigger Responding parameter to the given value.
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.
RuAllocation m_ruAllocation
RU allocations that are going to be carried in SIG-B common field per Table 27-1 IEEE.
void SetInactiveSubchannels(const std::vector< bool > &inactiveSubchannels)
Set the 20 MHz subchannels that are punctured.
bool IsStbc() const
Check if STBC is used or not.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
HeMuUserInfo GetHeMuUserInfo(uint16_t staId) const
Get the HE MU user-specific transmission information for the given STA-ID.
uint8_t m_nTx
number of TX antennas
bool m_triggerResponding
The Trigger Responding parameter.
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
HeMuUserInfoMap m_muUserInfos
HE MU specific per-user information indexed by station ID (STA-ID) corresponding to the 11 LSBs of th...
uint8_t m_txPowerLevel
The TXPWR_LEVEL parameter in Table 15-4.
bool m_ldpc
LDPC FEC coding if true, BCC otherwise.
uint16_t GetLength() const
Get the LENGTH field of the L-SIG.
uint16_t m_guardInterval
guard interval duration in nanoseconds
bool IsDlMu() const
bool m_stbc
STBC used or not.
uint8_t m_nss
number of spatial streams
void SetRuAllocation(const RuAllocation &ruAlloc)
Set RU Allocation of SIG-B common field.
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetRu(HeRu::RuSpec ru, uint16_t staId)
Set the RU specification for the STA-ID.
RuAllocation DeriveRuAllocation() const
Derive the RU allocation from the TXVECTOR for which its RU allocation has not been set yet.
uint8_t GetEhtPpduType() const
Get the EHT_PPDU_TYPE parameter.
ContentChannelAllocation GetContentChannelAllocation() const
Get the HE SIG-B content channel STA ID allocation IEEE 802.11ax-2021 27.3.11.8.2 HE-SIG-B content ch...
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
uint8_t GetNssMax() const
bool IsUlMu() const
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
uint16_t m_length
LENGTH field of the L-SIG.
uint8_t m_bssColor
BSS color.
std::pair< std::size_t, std::size_t > GetNumRusPerHeSigBContentChannel() const
Get the number of RUs per HE-SIG-B content channel.
WifiMode m_sigBMcs
MCS_SIG_B per Table 27-1 IEEE 802.11ax-2021.
void SetBssColor(uint8_t color)
Set the BSS color.
bool IsLdpc() const
Check if LDPC FEC coding is used or not.
void SetNTx(uint8_t nTx)
Sets the number of TX antennas.
uint8_t GetTxPowerLevel() const
bool IsAggregation() const
Checks whether the PSDU contains A-MPDU.
uint8_t m_ehtPpduType
EHT_PPDU_TYPE per Table 36-1 IEEE 802.11be D2.3.
uint16_t GetChannelWidth() const
WifiPreamble m_preamble
preamble
bool m_modeInitialized
Internal initialization flag.
uint8_t GetNess() const
uint8_t m_ness
number of spatial streams in beamforming
bool IsNonHtDuplicate() const
Checks whether this TXVECTOR corresponds to a non-HT duplicate.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
WifiMode GetSigBMode() const
Get MCS used for SIG-B.
void SetNss(uint8_t nss)
Sets the number of Nss.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
const std::vector< bool > & GetInactiveSubchannels() const
Get the 20 MHz subchannels that are punctured.
#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_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:76
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_EHT_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool IsEht(WifiPreamble preamble)
Return true if a preamble corresponds to an EHT transmission.
std::vector< std::vector< uint16_t > > ContentChannelAllocation
HE SIG-B Content Channels STA ID Allocation.
WifiModulationClass GetModulationClassForPreamble(WifiPreamble preamble)
Return the modulation class corresponding to the given preamble type.
std::vector< uint8_t > RuAllocation
8 bit RU_ALLOCATION per 20 MHz
bool IsDlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a downlink multi-user transmission.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129
bool IsUlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a uplink multi-user transmission.
HE MU specific user transmission parameters.
uint8_t mcs
MCS index.
HeRu::RuSpec ru
RU specification.
uint8_t nss
number of spatial streams
bool operator!=(const HeMuUserInfo &other) const
Compare this user info to the given user info.
bool operator==(const HeMuUserInfo &other) const
Compare this user info to the given user info.
Declaration of the following enums: