A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-tx-vector.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 CTTC
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Nicola Baldo <nbaldo@cttc.es>
7 * Ghada Badawy <gbadawy@gmail.com>
8 */
9
10#include "wifi-tx-vector.h"
11
12#include "wifi-phy-common.h"
13#include "wifi-utils.h"
14
15#include "ns3/abort.h"
16#include "ns3/eht-phy.h"
17
18#include <algorithm>
19#include <iterator>
20#include <numeric>
21#include <set>
22
23namespace ns3
24{
25
27 : m_txPowerLevel(1),
28 m_preamble(WIFI_PREAMBLE_LONG),
29 m_channelWidth(MHz_u{20}),
30 m_guardInterval(NanoSeconds(800)),
31 m_nTx(1),
32 m_nss(1),
33 m_ness(0),
34 m_aggregation(false),
35 m_stbc(false),
36 m_ldpc(false),
37 m_bssColor(0),
38 m_length(0),
39 m_triggerResponding(false),
40 m_modeInitialized(false),
41 m_inactiveSubchannels(),
42 m_ruAllocation(),
43 m_center26ToneRuIndication(std::nullopt),
44 m_ehtPpduType(1) // SU transmission by default
45{
46}
47
49 uint8_t powerLevel,
50 WifiPreamble preamble,
51 Time guardInterval,
52 uint8_t nTx,
53 uint8_t nss,
54 uint8_t ness,
55 MHz_u channelWidth,
56 bool aggregation,
57 bool stbc,
58 bool ldpc,
59 uint8_t bssColor,
60 uint16_t length,
61 bool triggerResponding)
62 : m_mode(mode),
63 m_txPowerLevel(powerLevel),
64 m_preamble(preamble),
65 m_channelWidth(channelWidth),
66 m_guardInterval(guardInterval),
67 m_nTx(nTx),
68 m_nss(nss),
69 m_ness(ness),
70 m_aggregation(aggregation),
71 m_stbc(stbc),
72 m_ldpc(ldpc),
73 m_bssColor(bssColor),
74 m_length(length),
75 m_triggerResponding(triggerResponding),
76 m_modeInitialized(true),
77 m_inactiveSubchannels(),
78 m_ruAllocation(),
79 m_center26ToneRuIndication(std::nullopt),
80 m_ehtPpduType(1) // SU transmission by default
81{
82}
83
85 : m_mode(txVector.m_mode),
86 m_txPowerLevel(txVector.m_txPowerLevel),
87 m_preamble(txVector.m_preamble),
88 m_channelWidth(txVector.m_channelWidth),
89 m_guardInterval(txVector.m_guardInterval),
90 m_nTx(txVector.m_nTx),
91 m_nss(txVector.m_nss),
92 m_ness(txVector.m_ness),
93 m_aggregation(txVector.m_aggregation),
94 m_stbc(txVector.m_stbc),
95 m_ldpc(txVector.m_ldpc),
96 m_bssColor(txVector.m_bssColor),
97 m_length(txVector.m_length),
98 m_triggerResponding(txVector.m_triggerResponding),
99 m_modeInitialized(txVector.m_modeInitialized),
100 m_inactiveSubchannels(txVector.m_inactiveSubchannels),
101 m_sigBMcs(txVector.m_sigBMcs),
102 m_ruAllocation(txVector.m_ruAllocation),
103 m_center26ToneRuIndication(txVector.m_center26ToneRuIndication),
104 m_ehtPpduType(txVector.m_ehtPpduType)
105{
106 m_muUserInfos.clear();
107 if (!txVector.m_muUserInfos.empty()) // avoids crashing for loop
108 {
109 for (auto& info : txVector.m_muUserInfos)
110 {
111 m_muUserInfos.insert(std::make_pair(info.first, info.second));
112 }
113 }
114}
115
116bool
121
123WifiTxVector::GetMode(uint16_t staId) const
124{
126 {
127 NS_FATAL_ERROR("WifiTxVector mode must be set before using");
128 }
129 if (!IsMu())
130 {
131 return m_mode;
132 }
133 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU (" << staId << ")");
134 const auto userInfoIt = m_muUserInfos.find(staId);
135 NS_ASSERT(userInfoIt != m_muUserInfos.cend());
137 {
139 return EhtPhy::GetEhtMcs(userInfoIt->second.mcs);
141 return HePhy::GetHeMcs(userInfoIt->second.mcs);
142 default:
143 NS_ABORT_MSG("Unsupported modulation class: " << GetModulationClassForPreamble(m_preamble));
144 }
145 return WifiMode(); // invalid WifiMode
146}
147
150{
151 NS_ABORT_MSG_IF(!m_modeInitialized, "WifiTxVector mode must be set before using");
152
153 if (IsMu())
154 {
155 NS_ASSERT(!m_muUserInfos.empty());
156 // all the modes belong to the same modulation class
158 }
159 return m_mode.GetModulationClass();
160}
161
162uint8_t
164{
165 return m_txPowerLevel;
166}
167
170{
171 return m_preamble;
172}
173
174MHz_u
176{
177 return m_channelWidth;
178}
179
180Time
185
186uint8_t
188{
189 return m_nTx;
190}
191
192uint8_t
193WifiTxVector::GetNss(uint16_t staId) const
194{
195 if (IsMu())
196 {
197 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU (" << staId << ")");
198 NS_ASSERT(m_muUserInfos.contains(staId));
199 return m_muUserInfos.at(staId).nss;
200 }
201 return m_nss;
202}
203
204uint8_t
206{
207 // We do not support mixed OFDMA and MU-MIMO
208 uint8_t nss = 0;
209 if (IsMu())
210 {
211 for (const auto& info : m_muUserInfos)
212 {
213 nss = (nss < info.second.nss) ? info.second.nss : nss;
214 }
215 }
216 else
217 {
218 nss = m_nss;
219 }
220 return nss;
221}
222
223uint8_t
225{
226 // We do not support mixed OFDMA and MU-MIMO
227 uint8_t nss = 0;
228 if (IsMu())
229 {
230 nss = std::accumulate(
231 m_muUserInfos.cbegin(),
232 m_muUserInfos.cend(),
233 0,
234 [](uint8_t prevNss, const auto& info) { return prevNss + info.second.nss; });
235 }
236 else
237 {
238 nss = m_nss;
239 }
240 return nss;
241}
242
243uint8_t
245{
246 return m_ness;
247}
248
249bool
251{
252 return m_aggregation;
253}
254
255bool
257{
258 return m_stbc;
259}
260
261bool
263{
264 return m_ldpc;
265}
266
267bool
269{
270 return ((m_channelWidth >= MHz_u{40}) && !IsMu() && (GetModulationClass() < WIFI_MOD_CLASS_HT));
271}
272
273void
275{
276 m_mode = mode;
277 m_modeInitialized = true;
278}
279
280void
281WifiTxVector::SetMode(WifiMode mode, uint16_t staId)
282{
283 NS_ABORT_MSG_IF(!IsMu(), "Not a MU transmission");
284 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
286 "Cannot add mode " << mode << " because the modulation class is "
287 << GetModulationClass());
288 m_muUserInfos[staId].mcs = mode.GetMcsValue();
289 m_modeInitialized = true;
290}
291
292void
294{
295 m_txPowerLevel = powerlevel;
296}
297
298void
300{
301 m_preamble = preamble;
302}
303
304void
306{
307 m_channelWidth = channelWidth;
308}
309
310void
312{
313 m_guardInterval = guardInterval;
314}
315
316void
318{
319 m_nTx = nTx;
320}
321
322void
324{
325 m_nss = nss;
326}
327
328void
329WifiTxVector::SetNss(uint8_t nss, uint16_t staId)
330{
331 NS_ABORT_MSG_IF(!IsMu(), "Not a MU transmission");
332 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
333 m_muUserInfos[staId].nss = nss;
334}
335
336void
338{
339 m_ness = ness;
340}
341
342void
344{
345 m_aggregation = aggregation;
346}
347
348void
350{
351 m_stbc = stbc;
352}
353
354void
356{
357 m_ldpc = ldpc;
358}
359
360void
362{
363 m_bssColor = color;
364}
365
366uint8_t
368{
369 return m_bssColor;
370}
371
372void
374{
375 m_length = length;
376}
377
378uint16_t
380{
381 return m_length;
382}
383
384bool
389
390void
392{
393 m_triggerResponding = triggerResponding;
394}
395
396void
398{
399 m_sigBMcs = mode;
400}
401
404{
405 return m_sigBMcs;
406}
407
408void
409WifiTxVector::SetRuAllocation(const RuAllocation& ruAlloc, uint8_t p20Index)
410{
411 if (ns3::IsDlMu(m_preamble) && !m_muUserInfos.empty())
412 {
413 NS_ASSERT(ruAlloc == DeriveRuAllocation(p20Index));
414 }
415 m_ruAllocation = ruAlloc;
416}
417
418const RuAllocation&
419WifiTxVector::GetRuAllocation(uint8_t p20Index) const
420{
421 if (ns3::IsDlMu(m_preamble) && m_ruAllocation.empty())
422 {
424 }
425 return m_ruAllocation;
426}
427
428void
430{
432 m_ehtPpduType = type;
433}
434
435uint8_t
437{
438 return m_ehtPpduType;
439}
440
441bool
443{
444 if (!GetModeInitialized())
445 {
446 return false;
447 }
448 const auto& modeName = m_mode.GetUniqueName();
449 if (m_channelWidth == MHz_u{20})
450 {
451 if (m_nss != 3 && m_nss != 6)
452 {
453 if (modeName == "VhtMcs9")
454 {
455 return false;
456 }
457 }
458 }
459 else if (m_channelWidth == MHz_u{80})
460 {
461 if (m_nss == 3 || m_nss == 7)
462 {
463 if (modeName == "VhtMcs6")
464 {
465 return false;
466 }
467 }
468 else if (m_nss == 6)
469 {
470 if (modeName == "VhtMcs9")
471 {
472 return false;
473 }
474 }
475 }
476 else if (m_channelWidth == MHz_u{160})
477 {
478 if (m_nss == 3)
479 {
480 if (modeName == "VhtMcs9")
481 {
482 return false;
483 }
484 }
485 }
486 for (const auto& userInfo : m_muUserInfos)
487 {
488 if (GetNumStasInRu(userInfo.second.ru) > 8)
489 {
490 return false;
491 }
492 }
493 std::map<HeRu::RuSpec, uint8_t> streamsPerRu{};
494 for (const auto& info : m_muUserInfos)
495 {
496 auto it = streamsPerRu.find(info.second.ru);
497 if (it == streamsPerRu.end())
498 {
499 streamsPerRu[info.second.ru] = info.second.nss;
500 }
501 else
502 {
503 it->second += info.second.nss;
504 }
505 }
506 for (auto& streams : streamsPerRu)
507 {
508 if (streams.second > 8)
509 {
510 return false;
511 }
512 }
513
514 if (band != WIFI_PHY_BAND_UNSPECIFIED)
515 {
517 "Cannot use OFDM modulation class in the 2.4 GHz band");
519 band != WIFI_PHY_BAND_2_4GHZ,
520 "ERP-OFDM modulation class can only be used in the 2.4 GHz band");
521 }
522
523 return true;
524}
525
526bool
528{
529 return IsDlMu() || IsUlMu();
530}
531
532bool
534{
535 return ns3::IsDlMu(m_preamble) && !(IsEht(m_preamble) && m_ehtPpduType == 1);
536}
537
538bool
540{
541 return ns3::IsUlMu(m_preamble);
542}
543
544bool
546{
547 if (!IsDlMu())
548 {
549 return false;
550 }
551 if (IsEht(m_preamble))
552 {
553 return m_ehtPpduType == 0;
554 }
555 if (m_muUserInfos.size() == 1)
556 {
557 return true;
558 }
559 std::set<HeRu::RuSpec> rus{};
560 for (const auto& userInfo : m_muUserInfos)
561 {
562 rus.insert(userInfo.second.ru);
563 if (rus.size() > 1)
564 {
565 return true;
566 }
567 }
568 return false;
569}
570
571bool
573{
574 if (!IsDlMu())
575 {
576 return false;
577 }
578 if (IsEht(m_preamble))
579 {
580 return m_ehtPpduType == 2;
581 }
582 if (m_muUserInfos.size() < 2)
583 {
584 return false;
585 }
586 // TODO: mixed OFDMA and MU-MIMO is not supported
587 return !IsDlOfdma();
588}
589
590uint8_t
592{
593 return std::count_if(m_muUserInfos.cbegin(),
594 m_muUserInfos.cend(),
595 [&ru](const auto& info) -> bool { return (ru == info.second.ru); });
596}
597
599WifiTxVector::GetRu(uint16_t staId) const
600{
601 NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
602 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
603 return m_muUserInfos.at(staId).ru;
604}
605
606void
608{
609 NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
610 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
611 m_muUserInfos[staId].ru = ru;
612}
613
615WifiTxVector::GetHeMuUserInfo(uint16_t staId) const
616{
617 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
618 return m_muUserInfos.at(staId);
619}
620
621void
623{
624 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
625 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
626 m_muUserInfos[staId] = userInfo;
627 m_modeInitialized = true;
628 m_ruAllocation.clear();
629}
630
633{
634 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
635 return m_muUserInfos;
636}
637
640{
641 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
642 m_ruAllocation.clear();
643 return m_muUserInfos;
644}
645
646bool
648{
649 // SIG-B compression is used in case of full-bandwidth MU-MIMO transmission (27.3.11.8.2
650 // HE-SIG-B content channels in IEEE802.11ax-2021) or if a single RU occupies the whole 160 MHz
651 // bandwidth (27.3.11.8.3 Common field in IEEE802.11ax-2021)
652 return (IsDlMuMimo() && !IsDlOfdma()) ||
653 ((m_muUserInfos.size() == 1) && (m_channelWidth >= MHz_u{160}) &&
654 (m_muUserInfos.cbegin()->second.ru.GetRuType() == HeRu::GetRuType(m_channelWidth)));
655}
656
657void
658WifiTxVector::SetInactiveSubchannels(const std::vector<bool>& inactiveSubchannels)
659{
661 "Only HE (or later) authorized for preamble puncturing");
663 m_channelWidth < MHz_u{80},
664 "Preamble puncturing only possible for transmission bandwidth of 80 MHz or larger");
665 NS_ABORT_MSG_IF(!inactiveSubchannels.empty() &&
666 inactiveSubchannels.size() != Count20MHzSubchannels(m_channelWidth),
667 "The size of the inactive subchannnels bitmap should be equal to the number of "
668 "20 MHz subchannels");
669 m_inactiveSubchannels = inactiveSubchannels;
670}
671
672const std::vector<bool>&
677
678void
680{
681 if (IsDlMu())
682 {
683 NS_ASSERT(center26ToneRuIndication == DeriveCenter26ToneRuIndication());
684 }
685 m_center26ToneRuIndication = center26ToneRuIndication;
686}
687
688std::optional<Center26ToneRuIndication>
690{
691 if (!IsDlMu() || (m_channelWidth < MHz_u{80}))
692 {
693 return std::nullopt;
694 }
695 if (!m_center26ToneRuIndication.has_value())
696 {
698 }
700}
701
702std::ostream&
703operator<<(std::ostream& os, const WifiTxVector& v)
704{
705 if (!v.IsValid())
706 {
707 os << "TXVECTOR not valid";
708 return os;
709 }
710 os << "txpwrlvl: " << +v.GetTxPowerLevel() << " preamble: " << v.GetPreambleType()
711 << " channel width: " << v.GetChannelWidth() << " GI: " << v.GetGuardInterval()
712 << " NTx: " << +v.GetNTx() << " Ness: " << +v.GetNess()
713 << " MPDU aggregation: " << v.IsAggregation() << " STBC: " << v.IsStbc()
714 << " FEC coding: " << (v.IsLdpc() ? "LDPC" : "BCC");
716 {
717 os << " BSS color: " << +v.GetBssColor();
718 }
719 if (v.IsUlMu())
720 {
721 os << " Length: " << v.GetLength();
722 }
724 {
725 os << " SIG-B mode: " << v.GetSigBMode();
726 }
727 if (v.IsMu())
728 {
730 os << " num User Infos: " << userInfoMap.size();
731 for (auto& ui : userInfoMap)
732 {
733 os << ", {STA-ID: " << ui.first << ", " << ui.second.ru << ", MCS: " << +ui.second.mcs
734 << ", Nss: " << +ui.second.nss << "}";
735 }
736 }
737 else
738 {
739 os << " mode: " << v.GetMode() << " Nss: " << +v.GetNss();
740 }
741 const auto& puncturedSubchannels = v.GetInactiveSubchannels();
742 if (!puncturedSubchannels.empty())
743 {
744 os << " Punctured subchannels: ";
745 std::copy(puncturedSubchannels.cbegin(),
746 puncturedSubchannels.cend(),
747 std::ostream_iterator<bool>(os, ", "));
748 }
749 if (IsEht(v.GetPreambleType()))
750 {
751 os << " EHT PPDU type: " << +v.GetEhtPpduType();
752 }
753 return os;
754}
755
756bool
758{
759 return ru == other.ru && mcs == other.mcs && nss == other.nss;
760}
761
762bool
764{
765 return !(*this == other);
766}
767
770{
771 auto heRuComparator = HeRu::RuSpecCompare(m_channelWidth, p20Index);
772 UserInfoMapOrderedByRus orderedMap{heRuComparator};
773 for (const auto& userInfo : m_muUserInfos)
774 {
775 const auto ru = userInfo.second.ru;
776 if (auto it = orderedMap.find(ru); it != orderedMap.end())
777 {
778 it->second.emplace(userInfo.first);
779 }
780 else
781 {
782 orderedMap.emplace(userInfo.second.ru, std::set<uint16_t>{userInfo.first});
783 }
784 }
785 return orderedMap;
786}
787
788RuAllocation
789WifiTxVector::DeriveRuAllocation(uint8_t p20Index) const
790{
791 RuAllocation ruAllocations(Count20MHzSubchannels(m_channelWidth), HeRu::EMPTY_242_TONE_RU);
792 std::vector<HeRu::RuType> ruTypes{};
793 ruTypes.resize(ruAllocations.size());
794 const auto& orderedMap = GetUserInfoMapOrderedByRus(p20Index);
795 std::pair<std::size_t /* number of RUs in content channel 1 */,
796 std::size_t /* number of RUs in content channel 2 */>
797 ccSizes{0, 0};
798 for (const auto& [ru, staIds] : orderedMap)
799 {
800 if ((ru.GetRuType() == HeRu::RU_26_TONE) && (ru.GetIndex() == 19))
801 {
802 continue;
803 }
804 const auto ruType = ru.GetRuType();
805 const auto ruBw = HeRu::GetBandwidth(ruType);
806 const auto rusPerSubchannel =
807 HeRu::GetRusOfType(ruBw > MHz_u{20} ? ruBw : MHz_u{20}, ruType);
808 auto ruIndex = ru.GetIndex();
809 if ((m_channelWidth >= MHz_u{80}) && (ruIndex > 19))
810 {
811 // take into account the center 26-tone RU in the low 80 MHz
812 ruIndex--;
813 }
814 const auto isPrimary80MHz = ru.GetPrimary80MHz();
815 const auto primary80IsLower80 = (p20Index < m_channelWidth / MHz_u{40});
816 const auto isLow80 =
817 (primary80IsLower80 && isPrimary80MHz) || (!primary80IsLower80 && !isPrimary80MHz);
818 if ((m_channelWidth > MHz_u{80}) && !isLow80 && (ruIndex > 19))
819 {
820 // take into account the center 26-tone RU in the high 80 MHz
821 ruIndex--;
822 }
823 if ((m_channelWidth > MHz_u{80}) && !isLow80 && (ruType != HeRu::GetRuType(m_channelWidth)))
824 {
825 // adjust RU index for the high 80 MHz: in that case index is restarting at 1,
826 // hence we need to add an offset corresponding to the number of RUs of the same type in
827 // the low 80 MHz
828 ruIndex += HeRu::GetRusOfType(MHz_u{80}, ruType).size();
829 }
830 const auto numSubchannelsForRu = (ruBw < MHz_u{20}) ? 1 : Count20MHzSubchannels(ruBw);
831 const auto index = (ruBw < MHz_u{20}) ? ((ruIndex - 1) / rusPerSubchannel.size())
832 : ((ruIndex - 1) * numSubchannelsForRu);
833 NS_ABORT_IF(index >= Count20MHzSubchannels(m_channelWidth));
834 auto ruAlloc = HeRu::GetEqualizedRuAllocation(ruType, false, true);
835 if (ruAllocations.at(index) != HeRu::EMPTY_242_TONE_RU)
836 {
837 if (ruType == ruTypes.at(index))
838 {
839 continue;
840 }
841 if (ruType == HeRu::RU_26_TONE)
842 {
843 ruAlloc = HeRu::GetEqualizedRuAllocation(ruTypes.at(index), true, true);
844 }
845 else if (ruTypes.at(index) == HeRu::RU_26_TONE)
846 {
847 ruAlloc = HeRu::GetEqualizedRuAllocation(ruType, true, true);
848 }
849 else
850 {
851 NS_ASSERT_MSG(false, "unsupported RU combination");
852 }
853 }
854 std::size_t ccIndex;
855 if (ruType >= HeRu::RU_484_TONE)
856 {
857 ccIndex = (ccSizes.first <= ccSizes.second) ? 0 : 1;
858 }
859 else
860 {
861 ccIndex = (index % 2 == 0) ? 0 : 1;
862 }
863 if (ccIndex == 0)
864 {
865 ccSizes.first += staIds.size();
866 }
867 else
868 {
869 ccSizes.second += staIds.size();
870 }
871 for (std::size_t i = 0; i < numSubchannelsForRu; ++i)
872 {
873 auto ruAllocNoUsers = HeRu::GetEqualizedRuAllocation(ruType, false, false);
874 ruTypes.at(index + i) = ruType;
875 ruAllocations.at(index + i) =
876 (IsSigBCompression() || ((index + i) % 2) == ccIndex) ? ruAlloc : ruAllocNoUsers;
877 }
878 }
879 return ruAllocations;
880}
881
883WifiTxVector::DeriveCenter26ToneRuIndication() const
884{
885 uint8_t center26ToneRuIndication{0};
886 for (const auto& userInfo : m_muUserInfos)
887 {
888 if ((userInfo.second.ru.GetRuType() == HeRu::RU_26_TONE) &&
889 (userInfo.second.ru.GetIndex() == 19))
890 {
891 center26ToneRuIndication |= (userInfo.second.ru.GetPrimary80MHz())
894 }
895 }
896 return static_cast<Center26ToneRuIndication>(center26ToneRuIndication);
897}
898
899} // namespace ns3
static WifiMode GetEhtMcs(uint8_t index)
Return the EHT MCS corresponding to the provided index.
Definition eht-phy.cc:232
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
Definition he-phy.cc:1544
RU Specification.
Definition he-ru.h:57
static RuType GetRuType(MHz_u bandwidth)
Get the RU corresponding to the approximate bandwidth.
Definition he-ru.cc:781
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
represent a single transmission mode
Definition wifi-mode.h:40
const std::string & GetUniqueName() const
Definition wifi-mode.cc:137
WifiModulationClass GetModulationClass() const
Definition wifi-mode.cc:174
uint8_t GetMcsValue() const
Definition wifi-mode.cc:152
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetCenter26ToneRuIndication(Center26ToneRuIndication center26ToneRuIndication)
Set CENTER_26_TONE_RU field.
void SetRuAllocation(const RuAllocation &ruAlloc, uint8_t p20Index)
Set RU_ALLOCATION field.
void SetStbc(bool stbc)
Sets if STBC is being used.
void SetNess(uint8_t ness)
Sets the Ness number.
UserInfoMapOrderedByRus GetUserInfoMapOrderedByRus(uint8_t p20Index) const
Get the map of specific user info parameters ordered per increasing frequency RUs.
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.
uint8_t GetNumStasInRu(const HeRu::RuSpec &ru) const
Get the number of STAs in a given RU.
bool IsSigBCompression() const
Indicate whether the Common field is present in the HE-SIG-B field.
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
void SetLdpc(bool ldpc)
Sets if LDPC FEC coding is being used.
uint8_t GetBssColor() const
Get the BSS color.
bool GetModeInitialized() const
const RuAllocation & GetRuAllocation(uint8_t p20Index) const
Get RU_ALLOCATION field.
std::optional< Center26ToneRuIndication > m_center26ToneRuIndication
CENTER_26_TONE_RU field when format is HE_MU and when channel width is set to 80 MHz or larger (Table...
std::vector< bool > m_inactiveSubchannels
Bitmap of inactive subchannels used for preamble puncturing.
void SetGuardInterval(Time guardInterval)
Sets the guard interval duration (in nanoseconds)
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
bool IsValid(WifiPhyBand band=WIFI_PHY_BAND_UNSPECIFIED) const
The standard disallows certain combinations of WifiMode, number of spatial streams,...
std::optional< Center26ToneRuIndication > GetCenter26ToneRuIndication() const
Get CENTER_26_TONE_RU field This field is present if format is HE_MU and when channel width is set to...
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.
MHz_u m_channelWidth
channel width
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.
void SetChannelWidth(MHz_u channelWidth)
Sets the selected channelWidth.
bool m_ldpc
LDPC FEC coding if true, BCC otherwise.
uint16_t GetLength() const
Get the LENGTH field of the L-SIG.
bool m_stbc
STBC used or not.
uint8_t m_nss
number of spatial streams
uint8_t GetNssTotal() const
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.
uint8_t GetEhtPpduType() const
Get the EHT_PPDU_TYPE parameter.
Time m_guardInterval
guard interval duration
bool IsDlOfdma() const
Return true if this TX vector is used for a downlink multi-user transmission using OFDMA.
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
MHz_u GetChannelWidth() 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.
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
std::map< HeRu::RuSpec, std::set< uint16_t >, HeRu::RuSpecCompare > UserInfoMapOrderedByRus
map of specific user info parameters ordered per increasing frequency RUs
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.
WifiPreamble m_preamble
preamble
Center26ToneRuIndication DeriveCenter26ToneRuIndication() const
Derive the CENTER_26_TONE_RU field from the TXVECTOR for which its CENTER_26_TONE_RU has not been set...
RuAllocation DeriveRuAllocation(uint8_t p20Index) const
Derive the RU_ALLOCATION field from the TXVECTOR for which its RU_ALLOCATION field has not been set y...
Time GetGuardInterval() const
bool m_modeInitialized
Internal initialization flag.
bool IsDlMuMimo() const
Return true if this TX vector is used for a downlink multi-user transmission using MU-MIMO.
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: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_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
Center26ToneRuIndication
Enum for the different values for CENTER_26_TONE_RU.
WifiPhyBand
Identifies the PHY band.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_HE_SU
@ CENTER_26_TONE_RU_HIGH_80_MHZ_ALLOCATED
@ CENTER_26_TONE_RU_LOW_80_MHZ_ALLOCATED
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_MOD_CLASS_OFDM
OFDM (Clause 17)
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ WIFI_MOD_CLASS_ERP_OFDM
ERP-OFDM (18.4)
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::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
double MHz_u
MHz weak type.
Definition wifi-units.h:31
WifiModulationClass GetModulationClassForPreamble(WifiPreamble preamble)
Return the modulation class corresponding to the given preamble type.
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
Definition wifi-utils.h:135
bool IsDlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a downlink multi-user transmission.
bool IsUlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a uplink multi-user transmission.
std::vector< uint16_t > RuAllocation
9 bits RU_ALLOCATION per 20 MHz
STL namespace.
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.
Struct providing a function call operator to compare two RUs.
Definition he-ru.h:132
Declaration of the following enums: