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_sigBMcs(EhtPhy::GetVhtMcs(0)),
79 m_ruAllocation(),
80 m_center26ToneRuIndication(std::nullopt),
81 m_ehtPpduType(1) // SU transmission by default
82{
83}
84
86 : m_mode(txVector.m_mode),
87 m_txPowerLevel(txVector.m_txPowerLevel),
88 m_preamble(txVector.m_preamble),
89 m_channelWidth(txVector.m_channelWidth),
90 m_guardInterval(txVector.m_guardInterval),
91 m_nTx(txVector.m_nTx),
92 m_nss(txVector.m_nss),
93 m_ness(txVector.m_ness),
94 m_aggregation(txVector.m_aggregation),
95 m_stbc(txVector.m_stbc),
96 m_ldpc(txVector.m_ldpc),
97 m_bssColor(txVector.m_bssColor),
98 m_length(txVector.m_length),
99 m_triggerResponding(txVector.m_triggerResponding),
100 m_modeInitialized(txVector.m_modeInitialized),
101 m_inactiveSubchannels(txVector.m_inactiveSubchannels),
102 m_sigBMcs(txVector.m_sigBMcs),
103 m_ruAllocation(txVector.m_ruAllocation),
104 m_center26ToneRuIndication(txVector.m_center26ToneRuIndication),
105 m_ehtPpduType(txVector.m_ehtPpduType)
106{
107 m_muUserInfos.clear();
108 if (!txVector.m_muUserInfos.empty()) // avoids crashing for loop
109 {
110 for (auto& info : txVector.m_muUserInfos)
111 {
112 m_muUserInfos.insert(std::make_pair(info.first, info.second));
113 }
114 }
115}
116
117bool
122
124WifiTxVector::GetMode(uint16_t staId) const
125{
127 {
128 NS_FATAL_ERROR("WifiTxVector mode must be set before using");
129 }
130 if (!IsMu())
131 {
132 return m_mode;
133 }
134 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU (" << staId << ")");
135 const auto userInfoIt = m_muUserInfos.find(staId);
136 NS_ASSERT(userInfoIt != m_muUserInfos.cend());
138 {
140 return EhtPhy::GetEhtMcs(userInfoIt->second.mcs);
142 return HePhy::GetHeMcs(userInfoIt->second.mcs);
143 default:
144 NS_ABORT_MSG("Unsupported modulation class: " << GetModulationClassForPreamble(m_preamble));
145 }
146 return WifiMode(); // invalid WifiMode
147}
148
151{
152 NS_ABORT_MSG_IF(!m_modeInitialized, "WifiTxVector mode must be set before using");
153
154 if (IsMu())
155 {
156 NS_ASSERT(!m_muUserInfos.empty());
157 // all the modes belong to the same modulation class
159 }
160 return m_mode.GetModulationClass();
161}
162
163uint8_t
165{
166 return m_txPowerLevel;
167}
168
171{
172 return m_preamble;
173}
174
175MHz_u
177{
178 return m_channelWidth;
179}
180
181Time
186
187uint8_t
189{
190 return m_nTx;
191}
192
193uint8_t
194WifiTxVector::GetNss(uint16_t staId) const
195{
196 if (IsMu())
197 {
198 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU (" << staId << ")");
199 NS_ASSERT(m_muUserInfos.contains(staId));
200 return m_muUserInfos.at(staId).nss;
201 }
202 return m_nss;
203}
204
205uint8_t
207{
208 // We do not support mixed OFDMA and MU-MIMO
209 uint8_t nss = 0;
210 if (IsMu())
211 {
212 for (const auto& info : m_muUserInfos)
213 {
214 nss = (nss < info.second.nss) ? info.second.nss : nss;
215 }
216 }
217 else
218 {
219 nss = m_nss;
220 }
221 return nss;
222}
223
224uint8_t
226{
227 // We do not support mixed OFDMA and MU-MIMO
228 uint8_t nss = 0;
229 if (IsMu())
230 {
231 nss = std::accumulate(
232 m_muUserInfos.cbegin(),
233 m_muUserInfos.cend(),
234 0,
235 [](uint8_t prevNss, const auto& info) { return prevNss + info.second.nss; });
236 }
237 else
238 {
239 nss = m_nss;
240 }
241 return nss;
242}
243
244uint8_t
246{
247 return m_ness;
248}
249
250bool
252{
253 return m_aggregation;
254}
255
256bool
258{
259 return m_stbc;
260}
261
262bool
264{
265 return m_ldpc;
266}
267
268bool
270{
271 return ((m_channelWidth >= MHz_u{40}) && !IsMu() && (GetModulationClass() < WIFI_MOD_CLASS_HT));
272}
273
274void
276{
277 m_mode = mode;
278 m_modeInitialized = true;
279}
280
281void
282WifiTxVector::SetMode(WifiMode mode, uint16_t staId)
283{
284 NS_ABORT_MSG_IF(!IsMu(), "Not a MU transmission");
285 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
287 "Cannot add mode " << mode << " because the modulation class is "
288 << GetModulationClass());
289 m_muUserInfos[staId].mcs = mode.GetMcsValue();
290 m_modeInitialized = true;
291}
292
293void
295{
296 m_txPowerLevel = powerlevel;
297}
298
299void
301{
302 m_preamble = preamble;
303}
304
305void
307{
308 m_channelWidth = channelWidth;
309}
310
311void
313{
314 m_guardInterval = guardInterval;
315}
316
317void
319{
320 m_nTx = nTx;
321}
322
323void
325{
326 m_nss = nss;
327}
328
329void
330WifiTxVector::SetNss(uint8_t nss, uint16_t staId)
331{
332 NS_ABORT_MSG_IF(!IsMu(), "Not a MU transmission");
333 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
334 m_muUserInfos[staId].nss = nss;
335}
336
337void
339{
340 m_ness = ness;
341}
342
343void
345{
346 m_aggregation = aggregation;
347}
348
349void
351{
352 m_stbc = stbc;
353}
354
355void
357{
358 m_ldpc = ldpc;
359}
360
361void
363{
364 m_bssColor = color;
365}
366
367uint8_t
369{
370 return m_bssColor;
371}
372
373void
375{
376 m_length = length;
377}
378
379uint16_t
381{
382 return m_length;
383}
384
385bool
390
391void
393{
394 m_triggerResponding = triggerResponding;
395}
396
397void
399{
400 m_sigBMcs = mode;
401}
402
405{
406 return m_sigBMcs;
407}
408
409void
410WifiTxVector::SetRuAllocation(const RuAllocation& ruAlloc, uint8_t p20Index)
411{
412 if (ns3::IsDlMu(m_preamble) && !m_muUserInfos.empty())
413 {
414 NS_ASSERT(ruAlloc == DeriveRuAllocation(p20Index));
415 }
416 m_ruAllocation = ruAlloc;
417}
418
419const RuAllocation&
420WifiTxVector::GetRuAllocation(uint8_t p20Index) const
421{
422 if (ns3::IsDlMu(m_preamble) && m_ruAllocation.empty())
423 {
425 }
426 return m_ruAllocation;
427}
428
429void
431{
433 m_ehtPpduType = type;
434}
435
436uint8_t
438{
439 return m_ehtPpduType;
440}
441
442bool
444{
445 if (!GetModeInitialized())
446 {
447 return false;
448 }
449 const auto& modeName = m_mode.GetUniqueName();
450 if (m_channelWidth == MHz_u{20})
451 {
452 if (m_nss != 3 && m_nss != 6)
453 {
454 if (modeName == "VhtMcs9")
455 {
456 return false;
457 }
458 }
459 }
460 else if (m_channelWidth == MHz_u{80})
461 {
462 if (m_nss == 3 || m_nss == 7)
463 {
464 if (modeName == "VhtMcs6")
465 {
466 return false;
467 }
468 }
469 else if (m_nss == 6)
470 {
471 if (modeName == "VhtMcs9")
472 {
473 return false;
474 }
475 }
476 }
477 else if (m_channelWidth == MHz_u{160})
478 {
479 if (m_nss == 3)
480 {
481 if (modeName == "VhtMcs9")
482 {
483 return false;
484 }
485 }
486 }
487 else if (m_channelWidth > 160)
488 {
490 {
491 return false;
492 }
493 if ((band == WIFI_PHY_BAND_2_4GHZ) || (band == WIFI_PHY_BAND_5GHZ))
494 {
495 return false;
496 }
497 }
498 for (const auto& userInfo : m_muUserInfos)
499 {
500 if (GetNumStasInRu(userInfo.second.ru) > 8)
501 {
502 return false;
503 }
504 }
505 std::map<WifiRu::RuSpec, uint8_t> streamsPerRu{};
506 for (const auto& info : m_muUserInfos)
507 {
508 auto it = streamsPerRu.find(info.second.ru);
509 if (it == streamsPerRu.end())
510 {
511 streamsPerRu[info.second.ru] = info.second.nss;
512 }
513 else
514 {
515 it->second += info.second.nss;
516 }
517 }
518 for (auto& streams : streamsPerRu)
519 {
520 if (streams.second > 8)
521 {
522 return false;
523 }
524 }
525
526 if (band != WIFI_PHY_BAND_UNSPECIFIED)
527 {
529 "Cannot use OFDM modulation class in the 2.4 GHz band");
531 band != WIFI_PHY_BAND_2_4GHZ,
532 "ERP-OFDM modulation class can only be used in the 2.4 GHz band");
533 }
534
535 return true;
536}
537
538bool
540{
541 return IsDlMu() || IsUlMu();
542}
543
544bool
546{
547 return ns3::IsDlMu(m_preamble) && !(IsEht(m_preamble) && m_ehtPpduType == 1);
548}
549
550bool
552{
553 return ns3::IsUlMu(m_preamble);
554}
555
556bool
558{
559 if (!IsDlMu())
560 {
561 return false;
562 }
563 if (IsEht(m_preamble))
564 {
565 return m_ehtPpduType == 0;
566 }
567 if (m_muUserInfos.size() == 1)
568 {
569 return true;
570 }
571 std::set<WifiRu::RuSpec> rus{};
572 for (const auto& userInfo : m_muUserInfos)
573 {
574 rus.insert(userInfo.second.ru);
575 if (rus.size() > 1)
576 {
577 return true;
578 }
579 }
580 return false;
581}
582
583bool
585{
586 if (!IsDlMu())
587 {
588 return false;
589 }
590 if (IsEht(m_preamble))
591 {
592 return m_ehtPpduType == 2;
593 }
594 if (m_muUserInfos.size() < 2)
595 {
596 return false;
597 }
598 // TODO: mixed OFDMA and MU-MIMO is not supported
599 return !IsDlOfdma();
600}
601
602uint8_t
604{
605 return std::count_if(m_muUserInfos.cbegin(),
606 m_muUserInfos.cend(),
607 [&ru](const auto& info) -> bool { return (ru == info.second.ru); });
608}
609
611WifiTxVector::GetRu(uint16_t staId) const
612{
613 NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
614 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
615 return m_muUserInfos.at(staId).ru;
616}
617
618void
620{
621 NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
622 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
623 m_muUserInfos[staId].ru = ru;
624}
625
627WifiTxVector::GetHeMuUserInfo(uint16_t staId) const
628{
629 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
630 return m_muUserInfos.at(staId);
631}
632
633void
635{
636 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
637 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
638 m_muUserInfos[staId] = userInfo;
639 m_modeInitialized = true;
640 m_ruAllocation.clear();
641}
642
645{
646 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
647 return m_muUserInfos;
648}
649
652{
653 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
654 m_ruAllocation.clear();
655 return m_muUserInfos;
656}
657
658bool
660{
661 // SIG-B compression is used in case of full-bandwidth MU-MIMO transmission (27.3.11.8.2
662 // HE-SIG-B content channels in IEEE802.11ax-2021) or if a single RU occupies the whole 160 MHz
663 // bandwidth (27.3.11.8.3 Common field in IEEE802.11ax-2021)
664 return (IsDlMuMimo() && !IsDlOfdma()) ||
665 ((m_muUserInfos.size() == 1) && (m_channelWidth >= MHz_u{160}) &&
666 (WifiRu::GetRuType(m_muUserInfos.cbegin()->second.ru) ==
668}
669
670void
671WifiTxVector::SetInactiveSubchannels(const std::vector<bool>& inactiveSubchannels)
672{
674 "Only HE (or later) authorized for preamble puncturing");
676 m_channelWidth < MHz_u{80},
677 "Preamble puncturing only possible for transmission bandwidth of 80 MHz or larger");
678 NS_ABORT_MSG_IF(!inactiveSubchannels.empty() &&
679 inactiveSubchannels.size() != Count20MHzSubchannels(m_channelWidth),
680 "The size of the inactive subchannnels bitmap should be equal to the number of "
681 "20 MHz subchannels");
682 m_inactiveSubchannels = inactiveSubchannels;
683}
684
685const std::vector<bool>&
690
691void
693{
695 if (IsDlMu())
696 {
697 NS_ASSERT(center26ToneRuIndication == DeriveCenter26ToneRuIndication());
698 }
699 m_center26ToneRuIndication = center26ToneRuIndication;
700}
701
702std::optional<Center26ToneRuIndication>
704{
706 {
707 return std::nullopt;
708 }
709 if (!m_center26ToneRuIndication.has_value())
710 {
712 }
714}
715
716std::ostream&
717operator<<(std::ostream& os, const WifiTxVector& v)
718{
719 if (!v.IsValid())
720 {
721 os << "TXVECTOR not valid";
722 return os;
723 }
724 os << "txpwrlvl: " << +v.GetTxPowerLevel() << " preamble: " << v.GetPreambleType()
725 << " channel width: " << v.GetChannelWidth() << " GI: " << v.GetGuardInterval()
726 << " NTx: " << +v.GetNTx() << " Ness: " << +v.GetNess()
727 << " MPDU aggregation: " << v.IsAggregation() << " STBC: " << v.IsStbc()
728 << " FEC coding: " << (v.IsLdpc() ? "LDPC" : "BCC");
730 {
731 os << " BSS color: " << +v.GetBssColor();
732 }
733 if (v.IsUlMu())
734 {
735 os << " Length: " << v.GetLength();
736 }
738 {
739 os << " SIG-B mode: " << v.GetSigBMode();
740 }
741 if (v.IsMu())
742 {
744 os << " num User Infos: " << userInfoMap.size();
745 for (auto& ui : userInfoMap)
746 {
747 os << ", {STA-ID: " << ui.first << ", " << ui.second.ru << ", MCS: " << +ui.second.mcs
748 << ", Nss: " << +ui.second.nss << "}";
749 }
750 }
751 else
752 {
753 os << " mode: " << v.GetMode() << " Nss: " << +v.GetNss();
754 }
755 const auto& puncturedSubchannels = v.GetInactiveSubchannels();
756 if (!puncturedSubchannels.empty())
757 {
758 os << " Punctured subchannels: ";
759 std::copy(puncturedSubchannels.cbegin(),
760 puncturedSubchannels.cend(),
761 std::ostream_iterator<bool>(os, ", "));
762 }
763 if (IsEht(v.GetPreambleType()))
764 {
765 os << " EHT PPDU type: " << +v.GetEhtPpduType();
766 }
767 return os;
768}
769
770bool
772{
773 return ru == other.ru && mcs == other.mcs && nss == other.nss;
774}
775
776bool
778{
779 return !(*this == other);
780}
781
784{
785 auto heRuComparator = WifiRu::RuSpecCompare(m_channelWidth, p20Index);
786 UserInfoMapOrderedByRus orderedMap{heRuComparator};
787 for (const auto& userInfo : m_muUserInfos)
788 {
789 const auto ru = userInfo.second.ru;
790 if (auto it = orderedMap.find(ru); it != orderedMap.end())
791 {
792 it->second.emplace(userInfo.first);
793 }
794 else
795 {
796 orderedMap.emplace(ru, std::set<uint16_t>{userInfo.first});
797 }
798 }
799 return orderedMap;
800}
801
803WifiTxVector::DeriveRuAllocation(uint8_t p20Index) const
804{
805 const auto mc = GetModulationClass();
806 const auto emptyRu =
808 RuAllocation ruAllocations(Count20MHzSubchannels(m_channelWidth), emptyRu);
809 std::vector<RuType> ruTypes{};
810 ruTypes.resize(ruAllocations.size());
811 const auto& orderedMap = GetUserInfoMapOrderedByRus(p20Index);
812 std::pair<std::size_t /* number of RUs in content channel 1 */,
813 std::size_t /* number of RUs in content channel 2 */>
814 ccSizes{0, 0};
815 for (const auto& [ru, staIds] : orderedMap)
816 {
817 const auto ruType = WifiRu::GetRuType(ru);
818 auto ruIndex = WifiRu::GetPhyIndex(ru, m_channelWidth, p20Index);
819 if ((ruType == RuType::RU_26_TONE) && (ruIndex == 19))
820 {
821 continue;
822 }
823 const auto ruBw = WifiRu::GetBandwidth(ruType);
824 const auto rusPerSubchannel =
825 WifiRu::GetRusOfType(ruBw > MHz_u{20} ? ruBw : MHz_u{20}, ruType, mc);
826 if ((m_channelWidth >= MHz_u{80}) && (ruIndex > 19))
827 {
828 // "ignore" the center 26-tone RUs in 80 MHz channels
829 ruIndex--;
830 if (ruIndex > 37)
831 {
832 ruIndex -= (ruIndex - 19) / 37;
833 }
834 }
835 const auto numSubchannelsForRu = (ruBw < MHz_u{20}) ? 1 : Count20MHzSubchannels(ruBw);
836 const auto index = (ruBw < MHz_u{20}) ? ((ruIndex - 1) / rusPerSubchannel.size())
837 : ((ruIndex - 1) * numSubchannelsForRu);
839 auto ruAlloc = WifiRu::GetEqualizedRuAllocation(ruType, false, true, mc);
840 if (ruAllocations.at(index) != emptyRu)
841 {
842 if (ruType == ruTypes.at(index))
843 {
844 continue;
845 }
846 if (ruType == RuType::RU_26_TONE)
847 {
848 ruAlloc = WifiRu::GetEqualizedRuAllocation(ruTypes.at(index), true, true, mc);
849 }
850 else if (ruTypes.at(index) == RuType::RU_26_TONE)
851 {
852 ruAlloc = WifiRu::GetEqualizedRuAllocation(ruType, true, true, mc);
853 }
854 else
855 {
856 NS_ASSERT_MSG(false, "unsupported RU combination");
857 }
858 }
859 std::size_t ccIndex;
860 if (ruType >= RuType::RU_484_TONE)
861 {
862 ccIndex = (ccSizes.first <= ccSizes.second) ? 0 : 1;
863 }
864 else
865 {
866 ccIndex = (index % 2 == 0) ? 0 : 1;
867 }
868 if (ccIndex == 0)
869 {
870 ccSizes.first += staIds.size();
871 }
872 else
873 {
874 ccSizes.second += staIds.size();
875 }
876 for (std::size_t i = 0; i < numSubchannelsForRu; ++i)
877 {
878 auto ruAllocNoUsers = WifiRu::GetEqualizedRuAllocation(ruType, false, false, mc);
879 ruTypes.at(index + i) = ruType;
880 ruAllocations.at(index + i) =
881 (IsSigBCompression() || ((index + i) % 2) == ccIndex) ? ruAlloc : ruAllocNoUsers;
882 }
883 }
884 return ruAllocations;
885}
886
889{
890 uint8_t center26ToneRuIndication{0};
891 for (const auto& userInfo : m_muUserInfos)
892 {
893 NS_ASSERT(WifiRu::IsHe(userInfo.second.ru));
894 if ((WifiRu::GetRuType(userInfo.second.ru) == RuType::RU_26_TONE) &&
895 (WifiRu::GetIndex(userInfo.second.ru) == 19))
896 {
897 center26ToneRuIndication |=
898 (std::get<HeRu::RuSpec>(userInfo.second.ru).GetPrimary80MHz())
901 }
902 }
903 return static_cast<Center26ToneRuIndication>(center26ToneRuIndication);
904}
905
906} // namespace ns3
PHY entity for EHT (11be)
Definition eht-phy.h:37
static WifiMode GetEhtMcs(uint8_t index)
Return the EHT MCS corresponding to the provided index.
Definition eht-phy.cc:255
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
Definition he-phy.cc:1555
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
represent a single transmission mode
Definition wifi-mode.h:38
const std::string & GetUniqueName() const
Definition wifi-mode.cc:136
WifiModulationClass GetModulationClass() const
Definition wifi-mode.cc:172
uint8_t GetMcsValue() const
Definition wifi-mode.cc:151
std::variant< HeRu::RuSpec, EhtRu::RuSpec > RuSpec
variant of the RU specification
Definition wifi-ru.h:27
static std::vector< RuSpec > GetRusOfType(MHz_u bw, RuType ruType, WifiModulationClass mc)
Get the set of distinct RUs of the given type (number of tones) available in an MU PPDU of the given ...
Definition wifi-ru.cc:173
static bool IsHe(RuSpec ru)
Get whether a given RU variant is a HE RU.
Definition wifi-ru.cc:248
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition wifi-ru.cc:78
static RuType GetRuType(RuSpec ru)
Get the type of a given RU.
Definition wifi-ru.cc:45
static uint16_t GetEqualizedRuAllocation(RuType ruType, bool isOdd, bool hasUsers, WifiModulationClass mc)
Get the RU_ALLOCATION value for equal size RUs.
Definition wifi-ru.cc:149
static std::size_t GetPhyIndex(RuSpec ru, MHz_u bw, uint8_t p20Index)
Get the RU PHY index.
Definition wifi-ru.cc:57
static std::size_t GetIndex(RuSpec ru)
Get the index of a given RU.
Definition wifi-ru.cc:51
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.
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
void SetRu(WifiRu::RuSpec ru, uint16_t staId)
Set the RU specification for the 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.
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.
std::map< WifiRu::RuSpec, std::set< uint16_t >, WifiRu::RuSpecCompare > UserInfoMapOrderedByRus
map of specific user info parameters ordered per increasing frequency RUs
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.
uint8_t GetNumStasInRu(const WifiRu::RuSpec &ru) const
Get the number of STAs in a given RU.
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
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
WifiRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
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_PHY_BAND_5GHZ
The 5 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.
static constexpr uint8_t EMPTY_242_TONE_HE_RU
Empty 242-tone RU identifier for HE (Section 26.11.7 802.11ax-2021)
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
static constexpr uint8_t UNASSIGNED_242_TONE_EHT_RU
Unassigned 242-tone RU identifier for EHT (Table Table 36-34 IEEE 802.11be D7.0)
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:138
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.
uint8_t nss
number of spatial streams
WifiRu::RuSpec ru
RU specification.
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 wifi-ru.h:33
Declaration of the following enums: