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 for (const auto& userInfo : m_muUserInfos)
488 {
489 if (GetNumStasInRu(userInfo.second.ru) > 8)
490 {
491 return false;
492 }
493 }
494 std::map<WifiRu::RuSpec, uint8_t> streamsPerRu{};
495 for (const auto& info : m_muUserInfos)
496 {
497 auto it = streamsPerRu.find(info.second.ru);
498 if (it == streamsPerRu.end())
499 {
500 streamsPerRu[info.second.ru] = info.second.nss;
501 }
502 else
503 {
504 it->second += info.second.nss;
505 }
506 }
507 for (auto& streams : streamsPerRu)
508 {
509 if (streams.second > 8)
510 {
511 return false;
512 }
513 }
514
515 if (band != WIFI_PHY_BAND_UNSPECIFIED)
516 {
518 "Cannot use OFDM modulation class in the 2.4 GHz band");
520 band != WIFI_PHY_BAND_2_4GHZ,
521 "ERP-OFDM modulation class can only be used in the 2.4 GHz band");
522 }
523
524 return true;
525}
526
527bool
529{
530 return IsDlMu() || IsUlMu();
531}
532
533bool
535{
536 return ns3::IsDlMu(m_preamble) && !(IsEht(m_preamble) && m_ehtPpduType == 1);
537}
538
539bool
541{
542 return ns3::IsUlMu(m_preamble);
543}
544
545bool
547{
548 if (!IsDlMu())
549 {
550 return false;
551 }
552 if (IsEht(m_preamble))
553 {
554 return m_ehtPpduType == 0;
555 }
556 if (m_muUserInfos.size() == 1)
557 {
558 return true;
559 }
560 std::set<WifiRu::RuSpec> rus{};
561 for (const auto& userInfo : m_muUserInfos)
562 {
563 rus.insert(userInfo.second.ru);
564 if (rus.size() > 1)
565 {
566 return true;
567 }
568 }
569 return false;
570}
571
572bool
574{
575 if (!IsDlMu())
576 {
577 return false;
578 }
579 if (IsEht(m_preamble))
580 {
581 return m_ehtPpduType == 2;
582 }
583 if (m_muUserInfos.size() < 2)
584 {
585 return false;
586 }
587 // TODO: mixed OFDMA and MU-MIMO is not supported
588 return !IsDlOfdma();
589}
590
591uint8_t
593{
594 return std::count_if(m_muUserInfos.cbegin(),
595 m_muUserInfos.cend(),
596 [&ru](const auto& info) -> bool { return (ru == info.second.ru); });
597}
598
600WifiTxVector::GetRu(uint16_t staId) const
601{
602 NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
603 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
604 return m_muUserInfos.at(staId).ru;
605}
606
607void
609{
610 NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
611 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
612 m_muUserInfos[staId].ru = ru;
613}
614
616WifiTxVector::GetHeMuUserInfo(uint16_t staId) const
617{
618 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
619 return m_muUserInfos.at(staId);
620}
621
622void
624{
625 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
626 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
627 m_muUserInfos[staId] = userInfo;
628 m_modeInitialized = true;
629 m_ruAllocation.clear();
630}
631
634{
635 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
636 return m_muUserInfos;
637}
638
641{
642 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
643 m_ruAllocation.clear();
644 return m_muUserInfos;
645}
646
647bool
649{
650 // SIG-B compression is used in case of full-bandwidth MU-MIMO transmission (27.3.11.8.2
651 // HE-SIG-B content channels in IEEE802.11ax-2021) or if a single RU occupies the whole 160 MHz
652 // bandwidth (27.3.11.8.3 Common field in IEEE802.11ax-2021)
653 return (IsDlMuMimo() && !IsDlOfdma()) ||
654 ((m_muUserInfos.size() == 1) && (m_channelWidth >= MHz_u{160}) &&
655 (WifiRu::GetRuType(m_muUserInfos.cbegin()->second.ru) ==
657}
658
659void
660WifiTxVector::SetInactiveSubchannels(const std::vector<bool>& inactiveSubchannels)
661{
663 "Only HE (or later) authorized for preamble puncturing");
665 m_channelWidth < MHz_u{80},
666 "Preamble puncturing only possible for transmission bandwidth of 80 MHz or larger");
667 NS_ABORT_MSG_IF(!inactiveSubchannels.empty() &&
668 inactiveSubchannels.size() != Count20MHzSubchannels(m_channelWidth),
669 "The size of the inactive subchannnels bitmap should be equal to the number of "
670 "20 MHz subchannels");
671 m_inactiveSubchannels = inactiveSubchannels;
672}
673
674const std::vector<bool>&
679
680void
682{
683 if (IsDlMu())
684 {
685 NS_ASSERT(center26ToneRuIndication == DeriveCenter26ToneRuIndication());
686 }
687 m_center26ToneRuIndication = center26ToneRuIndication;
688}
689
690std::optional<Center26ToneRuIndication>
692{
693 if (!IsDlMu() || (m_channelWidth < MHz_u{80}))
694 {
695 return std::nullopt;
696 }
697 if (!m_center26ToneRuIndication.has_value())
698 {
700 }
702}
703
704std::ostream&
705operator<<(std::ostream& os, const WifiTxVector& v)
706{
707 if (!v.IsValid())
708 {
709 os << "TXVECTOR not valid";
710 return os;
711 }
712 os << "txpwrlvl: " << +v.GetTxPowerLevel() << " preamble: " << v.GetPreambleType()
713 << " channel width: " << v.GetChannelWidth() << " GI: " << v.GetGuardInterval()
714 << " NTx: " << +v.GetNTx() << " Ness: " << +v.GetNess()
715 << " MPDU aggregation: " << v.IsAggregation() << " STBC: " << v.IsStbc()
716 << " FEC coding: " << (v.IsLdpc() ? "LDPC" : "BCC");
718 {
719 os << " BSS color: " << +v.GetBssColor();
720 }
721 if (v.IsUlMu())
722 {
723 os << " Length: " << v.GetLength();
724 }
726 {
727 os << " SIG-B mode: " << v.GetSigBMode();
728 }
729 if (v.IsMu())
730 {
732 os << " num User Infos: " << userInfoMap.size();
733 for (auto& ui : userInfoMap)
734 {
735 os << ", {STA-ID: " << ui.first << ", " << ui.second.ru << ", MCS: " << +ui.second.mcs
736 << ", Nss: " << +ui.second.nss << "}";
737 }
738 }
739 else
740 {
741 os << " mode: " << v.GetMode() << " Nss: " << +v.GetNss();
742 }
743 const auto& puncturedSubchannels = v.GetInactiveSubchannels();
744 if (!puncturedSubchannels.empty())
745 {
746 os << " Punctured subchannels: ";
747 std::copy(puncturedSubchannels.cbegin(),
748 puncturedSubchannels.cend(),
749 std::ostream_iterator<bool>(os, ", "));
750 }
751 if (IsEht(v.GetPreambleType()))
752 {
753 os << " EHT PPDU type: " << +v.GetEhtPpduType();
754 }
755 return os;
756}
757
758bool
760{
761 return ru == other.ru && mcs == other.mcs && nss == other.nss;
762}
763
764bool
766{
767 return !(*this == other);
768}
769
772{
773 auto heRuComparator = WifiRu::RuSpecCompare(m_channelWidth, p20Index);
774 UserInfoMapOrderedByRus orderedMap{heRuComparator};
775 for (const auto& userInfo : m_muUserInfos)
776 {
777 const auto ru = userInfo.second.ru;
778 if (auto it = orderedMap.find(ru); it != orderedMap.end())
779 {
780 it->second.emplace(userInfo.first);
781 }
782 else
783 {
784 orderedMap.emplace(ru, std::set<uint16_t>{userInfo.first});
785 }
786 }
787 return orderedMap;
788}
789
791WifiTxVector::DeriveRuAllocation(uint8_t p20Index) const
792{
794 std::vector<RuType> ruTypes{};
795 ruTypes.resize(ruAllocations.size());
796 const auto& orderedMap = GetUserInfoMapOrderedByRus(p20Index);
797 std::pair<std::size_t /* number of RUs in content channel 1 */,
798 std::size_t /* number of RUs in content channel 2 */>
799 ccSizes{0, 0};
800 for (const auto& [ru, staIds] : orderedMap)
801 {
802 const auto ruType = WifiRu::GetRuType(ru);
803 auto ruIndex = WifiRu::GetPhyIndex(ru, m_channelWidth, p20Index);
804 if ((ruType == RuType::RU_26_TONE) && (ruIndex == 19))
805 {
806 continue;
807 }
808 const auto ruBw = WifiRu::GetBandwidth(ruType);
809 NS_ASSERT_MSG(WifiRu::IsHe(ru), "EHT RUs should not be used yet");
810 const auto mc{WIFI_MOD_CLASS_HE};
811 const auto rusPerSubchannel =
812 WifiRu::GetRusOfType(ruBw > MHz_u{20} ? ruBw : MHz_u{20}, ruType, mc);
813 if ((m_channelWidth >= MHz_u{80}) && (ruIndex > 19))
814 {
815 // "ignore" the center 26-tone RUs in 80 MHz channels
816 ruIndex--;
817 if (ruIndex > 37)
818 {
819 ruIndex -= (ruIndex - 19) / 37;
820 }
821 }
822 const auto numSubchannelsForRu = (ruBw < MHz_u{20}) ? 1 : Count20MHzSubchannels(ruBw);
823 const auto index = (ruBw < MHz_u{20}) ? ((ruIndex - 1) / rusPerSubchannel.size())
824 : ((ruIndex - 1) * numSubchannelsForRu);
826 auto ruAlloc = WifiRu::GetEqualizedRuAllocation(ruType, false, true, mc);
827 if (ruAllocations.at(index) != HeRu::EMPTY_242_TONE_RU)
828 {
829 if (ruType == ruTypes.at(index))
830 {
831 continue;
832 }
833 if (ruType == RuType::RU_26_TONE)
834 {
835 ruAlloc = WifiRu::GetEqualizedRuAllocation(ruTypes.at(index), true, true, mc);
836 }
837 else if (ruTypes.at(index) == RuType::RU_26_TONE)
838 {
839 ruAlloc = WifiRu::GetEqualizedRuAllocation(ruType, true, true, mc);
840 }
841 else
842 {
843 NS_ASSERT_MSG(false, "unsupported RU combination");
844 }
845 }
846 std::size_t ccIndex;
847 if (ruType >= RuType::RU_484_TONE)
848 {
849 ccIndex = (ccSizes.first <= ccSizes.second) ? 0 : 1;
850 }
851 else
852 {
853 ccIndex = (index % 2 == 0) ? 0 : 1;
854 }
855 if (ccIndex == 0)
856 {
857 ccSizes.first += staIds.size();
858 }
859 else
860 {
861 ccSizes.second += staIds.size();
862 }
863 for (std::size_t i = 0; i < numSubchannelsForRu; ++i)
864 {
865 auto ruAllocNoUsers = HeRu::GetEqualizedRuAllocation(ruType, false, false);
866 ruTypes.at(index + i) = ruType;
867 ruAllocations.at(index + i) =
868 (IsSigBCompression() || ((index + i) % 2) == ccIndex) ? ruAlloc : ruAllocNoUsers;
869 }
870 }
871 return ruAllocations;
872}
873
876{
877 uint8_t center26ToneRuIndication{0};
878 for (const auto& userInfo : m_muUserInfos)
879 {
880 NS_ASSERT(WifiRu::IsHe(userInfo.second.ru));
881 if ((WifiRu::GetRuType(userInfo.second.ru) == RuType::RU_26_TONE) &&
882 (WifiRu::GetIndex(userInfo.second.ru) == 19))
883 {
884 center26ToneRuIndication |=
885 (std::get<HeRu::RuSpec>(userInfo.second.ru).GetPrimary80MHz())
888 }
889 }
890 return static_cast<Center26ToneRuIndication>(center26ToneRuIndication);
891}
892
893} // 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:244
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
Definition he-phy.cc:1550
static constexpr uint8_t EMPTY_242_TONE_RU
Empty 242-tone RU identifier.
Definition he-ru.h:243
static uint16_t GetEqualizedRuAllocation(RuType ruType, bool isOdd, bool hasUsers)
Get the RU_ALLOCATION value for equal size RUs.
Definition he-ru.cc:397
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: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_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:136
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: