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");
285 m_muUserInfos[staId].mcs = mode.GetMcsValue();
286 m_modeInitialized = true;
287}
288
289void
291{
292 m_txPowerLevel = powerlevel;
293}
294
295void
297{
298 m_preamble = preamble;
299}
300
301void
303{
304 m_channelWidth = channelWidth;
305}
306
307void
309{
310 m_guardInterval = guardInterval;
311}
312
313void
315{
316 m_nTx = nTx;
317}
318
319void
321{
322 m_nss = nss;
323}
324
325void
326WifiTxVector::SetNss(uint8_t nss, uint16_t staId)
327{
328 NS_ABORT_MSG_IF(!IsMu(), "Not a MU transmission");
329 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
330 m_muUserInfos[staId].nss = nss;
331}
332
333void
335{
336 m_ness = ness;
337}
338
339void
341{
342 m_aggregation = aggregation;
343}
344
345void
347{
348 m_stbc = stbc;
349}
350
351void
353{
354 m_ldpc = ldpc;
355}
356
357void
359{
360 m_bssColor = color;
361}
362
363uint8_t
365{
366 return m_bssColor;
367}
368
369void
371{
372 m_length = length;
373}
374
375uint16_t
377{
378 return m_length;
379}
380
381bool
386
387void
389{
390 m_triggerResponding = triggerResponding;
391}
392
393void
395{
396 m_sigBMcs = mode;
397}
398
401{
402 return m_sigBMcs;
403}
404
405void
406WifiTxVector::SetRuAllocation(const RuAllocation& ruAlloc, uint8_t p20Index)
407{
408 if (ns3::IsDlMu(m_preamble) && !m_muUserInfos.empty())
409 {
410 NS_ASSERT(ruAlloc == DeriveRuAllocation(p20Index));
411 }
412 m_ruAllocation = ruAlloc;
413}
414
415const RuAllocation&
416WifiTxVector::GetRuAllocation(uint8_t p20Index) const
417{
418 if (ns3::IsDlMu(m_preamble) && m_ruAllocation.empty())
419 {
421 }
422 return m_ruAllocation;
423}
424
425void
427{
429 m_ehtPpduType = type;
430}
431
432uint8_t
434{
435 return m_ehtPpduType;
436}
437
438bool
440{
441 if (!GetModeInitialized())
442 {
443 return false;
444 }
445 const auto& modeName = m_mode.GetUniqueName();
446 if (m_channelWidth == MHz_u{20})
447 {
448 if (m_nss != 3 && m_nss != 6)
449 {
450 if (modeName == "VhtMcs9")
451 {
452 return false;
453 }
454 }
455 }
456 else if (m_channelWidth == MHz_u{80})
457 {
458 if (m_nss == 3 || m_nss == 7)
459 {
460 if (modeName == "VhtMcs6")
461 {
462 return false;
463 }
464 }
465 else if (m_nss == 6)
466 {
467 if (modeName == "VhtMcs9")
468 {
469 return false;
470 }
471 }
472 }
473 else if (m_channelWidth == MHz_u{160})
474 {
475 if (m_nss == 3)
476 {
477 if (modeName == "VhtMcs9")
478 {
479 return false;
480 }
481 }
482 }
483 for (const auto& userInfo : m_muUserInfos)
484 {
485 if (GetNumStasInRu(userInfo.second.ru) > 8)
486 {
487 return false;
488 }
489 }
490 std::map<HeRu::RuSpec, uint8_t> streamsPerRu{};
491 for (const auto& info : m_muUserInfos)
492 {
493 auto it = streamsPerRu.find(info.second.ru);
494 if (it == streamsPerRu.end())
495 {
496 streamsPerRu[info.second.ru] = info.second.nss;
497 }
498 else
499 {
500 it->second += info.second.nss;
501 }
502 }
503 for (auto& streams : streamsPerRu)
504 {
505 if (streams.second > 8)
506 {
507 return false;
508 }
509 }
510
511 if (band != WIFI_PHY_BAND_UNSPECIFIED)
512 {
514 "Cannot use OFDM modulation class in the 2.4 GHz band");
516 band != WIFI_PHY_BAND_2_4GHZ,
517 "ERP-OFDM modulation class can only be used in the 2.4 GHz band");
518 }
519
520 return true;
521}
522
523bool
525{
526 return IsDlMu() || IsUlMu();
527}
528
529bool
531{
532 return ns3::IsDlMu(m_preamble) && !(IsEht(m_preamble) && m_ehtPpduType == 1);
533}
534
535bool
537{
538 return ns3::IsUlMu(m_preamble);
539}
540
541bool
543{
544 if (!IsDlMu())
545 {
546 return false;
547 }
548 if (IsEht(m_preamble))
549 {
550 return m_ehtPpduType == 0;
551 }
552 if (m_muUserInfos.size() == 1)
553 {
554 return true;
555 }
556 std::set<HeRu::RuSpec> rus{};
557 for (const auto& userInfo : m_muUserInfos)
558 {
559 rus.insert(userInfo.second.ru);
560 if (rus.size() > 1)
561 {
562 return true;
563 }
564 }
565 return false;
566}
567
568bool
570{
571 if (!IsDlMu())
572 {
573 return false;
574 }
575 if (IsEht(m_preamble))
576 {
577 return m_ehtPpduType == 2;
578 }
579 if (m_muUserInfos.size() < 2)
580 {
581 return false;
582 }
583 // TODO: mixed OFDMA and MU-MIMO is not supported
584 return !IsDlOfdma();
585}
586
587uint8_t
589{
590 return std::count_if(m_muUserInfos.cbegin(),
591 m_muUserInfos.cend(),
592 [&ru](const auto& info) -> bool { return (ru == info.second.ru); });
593}
594
595bool
596WifiTxVector::IsAllocated(uint16_t staId) const
597{
598 return m_muUserInfos.contains(staId);
599}
600
602WifiTxVector::GetRu(uint16_t staId) const
603{
604 NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
605 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
606 return m_muUserInfos.at(staId).ru;
607}
608
609void
611{
612 NS_ABORT_MSG_IF(!IsMu(), "RU only available for MU");
613 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
614 m_muUserInfos[staId].ru = ru;
615}
616
618WifiTxVector::GetHeMuUserInfo(uint16_t staId) const
619{
620 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
621 return m_muUserInfos.at(staId);
622}
623
624void
626{
627 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info only available for MU");
628 NS_ABORT_MSG_IF(staId > 2048, "STA-ID should be correctly set for MU");
629 m_muUserInfos[staId] = userInfo;
630 m_modeInitialized = true;
631 m_ruAllocation.clear();
632}
633
636{
637 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
638 return m_muUserInfos;
639}
640
643{
644 NS_ABORT_MSG_IF(!IsMu(), "HE MU user info map only available for MU");
645 m_ruAllocation.clear();
646 return m_muUserInfos;
647}
648
649bool
651{
652 return IsDlMuMimo() && !IsDlOfdma();
653}
654
655void
656WifiTxVector::SetInactiveSubchannels(const std::vector<bool>& inactiveSubchannels)
657{
659 "Only HE (or later) authorized for preamble puncturing");
661 m_channelWidth < MHz_u{80},
662 "Preamble puncturing only possible for transmission bandwidth of 80 MHz or larger");
663 NS_ABORT_MSG_IF(!inactiveSubchannels.empty() &&
664 inactiveSubchannels.size() != Count20MHzSubchannels(m_channelWidth),
665 "The size of the inactive subchannnels bitmap should be equal to the number of "
666 "20 MHz subchannels");
667 m_inactiveSubchannels = inactiveSubchannels;
668}
669
670const std::vector<bool>&
675
676void
678{
679 if (IsDlMu())
680 {
681 NS_ASSERT(center26ToneRuIndication == DeriveCenter26ToneRuIndication());
682 }
683 m_center26ToneRuIndication = center26ToneRuIndication;
684}
685
686std::optional<Center26ToneRuIndication>
688{
689 if (!IsDlMu() || (m_channelWidth < MHz_u{80}))
690 {
691 return std::nullopt;
692 }
693 if (!m_center26ToneRuIndication.has_value())
694 {
696 }
698}
699
700std::ostream&
701operator<<(std::ostream& os, const WifiTxVector& v)
702{
703 if (!v.IsValid())
704 {
705 os << "TXVECTOR not valid";
706 return os;
707 }
708 os << "txpwrlvl: " << +v.GetTxPowerLevel() << " preamble: " << v.GetPreambleType()
709 << " channel width: " << v.GetChannelWidth() << " GI: " << v.GetGuardInterval()
710 << " NTx: " << +v.GetNTx() << " Ness: " << +v.GetNess()
711 << " MPDU aggregation: " << v.IsAggregation() << " STBC: " << v.IsStbc()
712 << " FEC coding: " << (v.IsLdpc() ? "LDPC" : "BCC");
714 {
715 os << " BSS color: " << +v.GetBssColor();
716 }
717 if (v.IsUlMu())
718 {
719 os << " Length: " << v.GetLength();
720 }
722 {
723 os << " SIG-B mode: " << v.GetSigBMode();
724 }
725 if (v.IsMu())
726 {
728 os << " num User Infos: " << userInfoMap.size();
729 for (auto& ui : userInfoMap)
730 {
731 os << ", {STA-ID: " << ui.first << ", " << ui.second.ru << ", MCS: " << +ui.second.mcs
732 << ", Nss: " << +ui.second.nss << "}";
733 }
734 }
735 else
736 {
737 os << " mode: " << v.GetMode() << " Nss: " << +v.GetNss();
738 }
739 const auto& puncturedSubchannels = v.GetInactiveSubchannels();
740 if (!puncturedSubchannels.empty())
741 {
742 os << " Punctured subchannels: ";
743 std::copy(puncturedSubchannels.cbegin(),
744 puncturedSubchannels.cend(),
745 std::ostream_iterator<bool>(os, ", "));
746 }
747 if (IsEht(v.GetPreambleType()))
748 {
749 os << " EHT PPDU type: " << +v.GetEhtPpduType();
750 }
751 return os;
752}
753
754bool
756{
757 return ru == other.ru && mcs == other.mcs && nss == other.nss;
758}
759
760bool
762{
763 return !(*this == other);
764}
765
768{
769 auto heRuComparator = HeRu::RuSpecCompare(m_channelWidth, p20Index);
770 UserInfoMapOrderedByRus orderedMap{heRuComparator};
771 for (const auto& userInfo : m_muUserInfos)
772 {
773 const auto ru = userInfo.second.ru;
774 if (auto it = orderedMap.find(ru); it != orderedMap.end())
775 {
776 it->second.emplace(userInfo.first);
777 }
778 else
779 {
780 orderedMap.emplace(userInfo.second.ru, std::set<uint16_t>{userInfo.first});
781 }
782 }
783 return orderedMap;
784}
785
786RuAllocation
787WifiTxVector::DeriveRuAllocation(uint8_t p20Index) const
788{
789 RuAllocation ruAllocations(Count20MHzSubchannels(m_channelWidth), HeRu::EMPTY_242_TONE_RU);
790 std::vector<HeRu::RuType> ruTypes{};
791 ruTypes.resize(ruAllocations.size());
792 const auto& orderedMap = GetUserInfoMapOrderedByRus(p20Index);
793 for (const auto& [ru, staIds] : orderedMap)
794 {
795 const auto ruType = ru.GetRuType();
796 const auto ruBw = HeRu::GetBandwidth(ruType);
797 const auto isPrimary80MHz = ru.GetPrimary80MHz();
798 const auto rusPerSubchannel =
799 HeRu::GetRusOfType(ruBw > MHz_u{20} ? ruBw : MHz_u{20}, ruType);
800 auto ruIndex = ru.GetIndex();
801 if ((m_channelWidth >= MHz_u{80}) && (ruIndex > 19))
802 {
803 // take into account the center 26-tone RU in the primary 80 MHz
804 ruIndex--;
805 }
806 if ((!isPrimary80MHz) && (ruIndex > 19))
807 {
808 // take into account the center 26-tone RU in the secondary 80 MHz
809 ruIndex--;
810 }
811 if (!isPrimary80MHz && (ruType != HeRu::RU_2x996_TONE))
812 {
813 NS_ASSERT(m_channelWidth > MHz_u{80});
814 // adjust RU index for the secondary 80 MHz: in that case index is restarting at 1,
815 // hence we need to add an offset corresponding to the number of RUs of the same type in
816 // the primary 80 MHz
817 ruIndex += HeRu::GetRusOfType(MHz_u{80}, ruType).size();
818 }
819 const auto numSubchannelsForRu = (ruBw < MHz_u{20}) ? 1 : Count20MHzSubchannels(ruBw);
820 const auto index = (ruBw < MHz_u{20}) ? ((ruIndex - 1) / rusPerSubchannel.size())
821 : ((ruIndex - 1) * numSubchannelsForRu);
822 NS_ABORT_IF(index >= Count20MHzSubchannels(m_channelWidth));
823 auto ruAlloc = HeRu::GetEqualizedRuAllocation(ruType, false);
824 if (ruAllocations.at(index) != HeRu::EMPTY_242_TONE_RU)
825 {
826 if (ruType == ruTypes.at(index))
827 {
828 continue;
829 }
830 if (ruType == HeRu::RU_26_TONE)
831 {
832 ruAlloc = HeRu::GetEqualizedRuAllocation(ruTypes.at(index), true);
833 }
834 else if (ruTypes.at(index) == HeRu::RU_26_TONE)
835 {
836 ruAlloc = HeRu::GetEqualizedRuAllocation(ruType, true);
837 }
838 else
839 {
840 NS_ASSERT_MSG(false, "unsupported RU combination");
841 }
842 }
843 for (std::size_t i = 0; i < numSubchannelsForRu; ++i)
844 {
845 ruTypes.at(index + i) = ruType;
846 ruAllocations.at(index + i) = ruAlloc;
847 }
848 }
849 return ruAllocations;
850}
851
853WifiTxVector::DeriveCenter26ToneRuIndication() const
854{
855 uint8_t center26ToneRuIndication{0};
856 for (const auto& userInfo : m_muUserInfos)
857 {
858 if ((userInfo.second.ru.GetRuType() == HeRu::RU_26_TONE) &&
859 (userInfo.second.ru.GetIndex() == 19))
860 {
861 center26ToneRuIndication |= (userInfo.second.ru.GetPrimary80MHz())
864 }
865 }
866 return static_cast<Center26ToneRuIndication>(center26ToneRuIndication);
867}
868
869} // 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:1580
RU Specification.
Definition he-ru.h:57
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.
bool IsAllocated(uint16_t staId) const
Check if STA ID is allocated.
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:1380
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: