A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
eht-ppdu.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 DERONNE SOFTWARE ENGINEERING
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "eht-ppdu.h"
10
11#include "eht-phy.h"
12
13#include "ns3/log.h"
14#include "ns3/wifi-phy-operating-channel.h"
15#include "ns3/wifi-psdu.h"
16#include "ns3/wifi-utils.h"
17
18#include <algorithm>
19#include <initializer_list>
20#include <numeric>
21
22namespace ns3
23{
24
26
28 const WifiTxVector& txVector,
29 const WifiPhyOperatingChannel& channel,
30 Time ppduDuration,
31 uint64_t uid,
32 TxPsdFlag flag)
33 : HePpdu(psdus, txVector, channel, ppduDuration, uid, flag, false)
34{
35 NS_LOG_FUNCTION(this << psdus << txVector << channel << ppduDuration << uid << flag);
36 SetPhyHeaders(txVector, ppduDuration);
37}
38
39void
40EhtPpdu::SetPhyHeaders(const WifiTxVector& txVector, Time ppduDuration)
41{
42 NS_LOG_FUNCTION(this << txVector << ppduDuration);
43 SetLSigHeader(ppduDuration);
44 SetEhtPhyHeader(txVector);
45}
46
47void
49{
50 const auto bssColor = txVector.GetBssColor();
51 NS_ASSERT(bssColor < 64);
53 {
54 const auto p20Index = m_operatingChannel.GetPrimaryChannelIndex(MHz_u{20});
58 .m_bssColor = bssColor,
59 .m_ppduType = txVector.GetEhtPpduType(),
60 // TODO: EHT PPDU should store U-SIG per 20 MHz band, assume it is the lowest 20 MHz
61 // band for now
62 .m_puncturedChannelInfo =
64 txVector.GetEhtPpduType(),
65 (txVector.IsDlMu() && (txVector.GetChannelWidth() > MHz_u{80}))
66 ? std::optional{true}
67 : std::nullopt),
68 .m_ehtSigMcs = txVector.GetSigBMode().GetMcsValue(),
69 .m_giLtfSize = GetGuardIntervalAndNltfEncoding(txVector.GetGuardInterval(),
70 2 /*NLTF currently unused*/),
71 /* See section 36.3.12.8.2 of IEEE 802.11be D3.0 (EHT-SIG content channels):
72 * In non-OFDMA transmission, the Common field of the EHT-SIG content channel does not
73 * contain the RU Allocation subfield. For non-OFDMA transmission except for EHT
74 * sounding NDP, the Common field of the EHT-SIG content channel is encoded together
75 * with the first User field and this encoding block contains a CRC and Tail, referred
76 * to as a common encoding block. */
77 .m_ruAllocationA = txVector.IsMu() && !txVector.IsSigBCompression()
78 ? std::optional{txVector.GetRuAllocation(p20Index)}
79 : std::nullopt,
80 // TODO: RU Allocation-B not supported yet
81 .m_contentChannels = GetEhtSigContentChannels(txVector, p20Index)});
82 }
83 else if (ns3::IsUlMu(m_preamble))
84 {
88 .m_bssColor = bssColor,
89 .m_ppduType = txVector.GetEhtPpduType()});
90 }
91}
92
93uint8_t
95{
96 NS_ASSERT(channel.GetTotalWidth() >= channelWidth);
97 if (channelWidth == MHz_u{320})
98 {
99 switch (channel.GetNumber())
100 {
101 case 31:
102 case 95:
103 case 159:
104 return 4;
105 case 63:
106 case 127:
107 case 191:
108 return 5;
109 default:
110 NS_ASSERT_MSG(false, "Invalid 320 MHz channel number " << +channel.GetNumber());
111 return 4;
112 }
113 }
114 return HePpdu::GetChannelWidthEncodingFromMhz(channelWidth);
115}
116
117MHz_u
119{
120 if ((bandwidth == 4) || (bandwidth == 5))
121 {
122 return MHz_u{320};
123 }
125}
126
129{
130 if (m_psdus.contains(SU_STA_ID))
131 {
132 return WIFI_PPDU_TYPE_SU;
133 }
134 switch (m_preamble)
135 {
140 default:
141 NS_ASSERT_MSG(false, "invalid preamble " << m_preamble);
142 return WIFI_PPDU_TYPE_SU;
143 }
144}
145
146bool
148{
149 return (m_preamble == WIFI_PREAMBLE_EHT_MU) && !m_psdus.contains(SU_STA_ID);
150}
151
152bool
154{
155 return (m_preamble == WIFI_PREAMBLE_EHT_TB) && !m_psdus.contains(SU_STA_ID);
156}
157
158void
160{
161 txVector.SetLength(m_lSig.GetLength());
162 txVector.SetAggregation(m_psdus.size() > 1 || m_psdus.begin()->second->IsAggregate());
164 {
165 auto ehtPhyHeader = std::get_if<EhtMuPhyHeader>(&m_ehtPhyHeader);
166 NS_ASSERT(ehtPhyHeader);
167 const auto bw = GetChannelWidthMhzFromEncoding(ehtPhyHeader->m_bandwidth);
168 txVector.SetChannelWidth(bw);
169 txVector.SetBssColor(ehtPhyHeader->m_bssColor);
170 txVector.SetEhtPpduType(ehtPhyHeader->m_ppduType);
171 if (bw > MHz_u{80})
172 {
173 // TODO: use punctured channel information
174 }
175 txVector.SetSigBMode(EhtPhy::GetVhtMcs(ehtPhyHeader->m_ehtSigMcs));
176 txVector.SetGuardInterval(GetGuardIntervalFromEncoding(ehtPhyHeader->m_giLtfSize));
177 const auto ruAllocation = ehtPhyHeader->m_ruAllocationA; // RU Allocation-B not supported
178 // yet
179 if (const auto p20Index = m_operatingChannel.GetPrimaryChannelIndex(MHz_u{20});
180 ruAllocation.has_value())
181 {
182 txVector.SetRuAllocation(ruAllocation.value(), p20Index);
183 const auto isMuMimo = (ehtPhyHeader->m_ppduType == 2);
184 const auto muMimoUsers =
185 isMuMimo
186 ? std::accumulate(ehtPhyHeader->m_contentChannels.cbegin(),
187 ehtPhyHeader->m_contentChannels.cend(),
188 0,
189 [](uint8_t prev, const auto& cc) { return prev + cc.size(); })
190 : 0;
191 SetHeMuUserInfos(txVector,
193 ruAllocation.value(),
194 std::nullopt,
195 ehtPhyHeader->m_contentChannels,
196 ehtPhyHeader->m_ppduType == 2,
197 muMimoUsers);
198 }
199 else if (ehtPhyHeader->m_ppduType == 1) // EHT SU
200 {
201 NS_ASSERT(ehtPhyHeader->m_contentChannels.size() == 1 &&
202 ehtPhyHeader->m_contentChannels.front().size() == 1);
203 txVector.SetMode(
204 EhtPhy::GetEhtMcs(ehtPhyHeader->m_contentChannels.front().front().mcs));
205 txVector.SetNss(ehtPhyHeader->m_contentChannels.front().front().nss);
206 }
207 else
208 {
209 const auto fullBwRu{EhtRu::RuSpec(WifiRu::GetRuType(bw), 1, true, true)};
210 txVector.SetHeMuUserInfo(ehtPhyHeader->m_contentChannels.front().front().staId,
211 {fullBwRu,
212 ehtPhyHeader->m_contentChannels.front().front().mcs,
213 ehtPhyHeader->m_contentChannels.front().front().nss});
214 }
215 }
216 else if (ns3::IsUlMu(m_preamble))
217 {
218 auto ehtPhyHeader = std::get_if<EhtTbPhyHeader>(&m_ehtPhyHeader);
219 NS_ASSERT(ehtPhyHeader);
220 txVector.SetChannelWidth(GetChannelWidthMhzFromEncoding(ehtPhyHeader->m_bandwidth));
221 txVector.SetBssColor(ehtPhyHeader->m_bssColor);
222 txVector.SetEhtPpduType(ehtPhyHeader->m_ppduType);
223 }
224}
225
226std::pair<std::size_t, std::size_t>
228 uint8_t ehtPpduType,
229 const RuAllocation& ruAllocation,
230 bool compression,
231 std::size_t numMuMimoUsers)
232{
233 if (ehtPpduType == 1)
234 {
235 return {1, 0};
236 }
239 ruAllocation,
240 std::nullopt,
241 compression,
242 numMuMimoUsers);
243}
244
246EhtPpdu::GetEhtSigContentChannels(const WifiTxVector& txVector, uint8_t p20Index)
247{
248 if (txVector.GetEhtPpduType() == 1)
249 {
250 // according to spec the TXVECTOR shall have a correct STA-ID even for SU transmission,
251 // but this is not set by the MAC for simplification, so set to 0 for now.
252 return HeSigBContentChannels{{{0, txVector.GetNss(), txVector.GetMode().GetMcsValue()}}};
253 }
254 return HePpdu::GetHeSigBContentChannels(txVector, p20Index);
255}
256
259 const RuAllocation& ruAllocation,
260 uint8_t ehtPpduType,
261 bool compression,
262 std::size_t numMuMimoUsers)
263{
264 // FIXME: EHT-SIG is not implemented yet, hence this is a copy of HE-SIG-B
265 uint32_t commonFieldSize = 0;
266 if (!compression)
267 {
268 commonFieldSize = 4 /* CRC */ + 6 /* tail */;
269 if (channelWidth <= MHz_u{40})
270 {
271 commonFieldSize += 8; // only one allocation subfield
272 }
273 else
274 {
275 commonFieldSize +=
276 8 * (channelWidth / MHz_u{40}) /* one allocation field per 40 MHz */ +
277 1 /* center RU */;
278 }
279 }
280
281 auto numRusPerContentChannel = GetNumRusPerEhtSigBContentChannel(channelWidth,
282 ehtPpduType,
283 ruAllocation,
284 compression,
285 numMuMimoUsers);
286 auto maxNumRusPerContentChannel =
287 std::max(numRusPerContentChannel.first, numRusPerContentChannel.second);
288 auto maxNumUserBlockFields = maxNumRusPerContentChannel /
289 2; // handle last user block with single user, if any, further down
290 std::size_t userSpecificFieldSize =
291 maxNumUserBlockFields * (2 * 21 /* user fields (2 users) */ + 4 /* tail */ + 6 /* CRC */);
292 if (maxNumRusPerContentChannel % 2 != 0)
293 {
294 userSpecificFieldSize += 21 /* last user field */ + 4 /* CRC */ + 6 /* tail */;
295 }
296
297 return commonFieldSize + userSpecificFieldSize;
298}
299
300uint8_t
301EhtPpdu::GetPuncturedInfo(const std::vector<bool>& inactiveSubchannels,
302 uint8_t ehtPpduType,
303 std::optional<bool> isLow80MHz)
304{
305 if (inactiveSubchannels.size() < 4)
306 {
307 // no puncturing if less than 80 MHz
308 return 0;
309 }
310 NS_ASSERT_MSG(inactiveSubchannels.size() <= 8,
311 "Puncturing over more than 160 MHz is not supported");
312 if (ehtPpduType == 0)
313 {
314 // IEEE 802.11be D5.0 Table 36-28
315 NS_ASSERT(inactiveSubchannels.size() <= 4 || isLow80MHz.has_value());
316 const auto startIndex = (inactiveSubchannels.size() <= 4) ? 0 : (*isLow80MHz ? 0 : 4);
317 const auto stopIndex =
318 (inactiveSubchannels.size() <= 4) ? inactiveSubchannels.size() : (*isLow80MHz ? 4 : 8);
319 uint8_t puncturedInfoField = 0;
320 for (std::size_t i = startIndex; i < stopIndex; ++i)
321 {
322 if (!inactiveSubchannels.at(i))
323 {
324 puncturedInfoField |= 1 << (i / 4);
325 }
326 }
327 return puncturedInfoField;
328 }
329 // IEEE 802.11be D5.0 Table 36-30
330 const auto numPunctured = std::count_if(inactiveSubchannels.cbegin(),
331 inactiveSubchannels.cend(),
332 [](bool punctured) { return punctured; });
333 if (numPunctured == 0)
334 {
335 // no puncturing
336 return 0;
337 }
338 const auto firstPunctured = std::find_if(inactiveSubchannels.cbegin(),
339 inactiveSubchannels.cend(),
340 [](bool punctured) { return punctured; });
341 const auto firstIndex = std::distance(inactiveSubchannels.cbegin(), firstPunctured);
342 switch (numPunctured)
343 {
344 case 1:
345 return firstIndex + 1;
346 case 2:
347 NS_ASSERT_MSG(((firstIndex % 2) == 0) && inactiveSubchannels.at(firstIndex + 1),
348 "invalid 40 MHz puncturing pattern");
349 return 9 + (firstIndex / 2);
350 default:
351 break;
352 }
353 NS_ASSERT_MSG(false, "invalid puncturing pattern");
354 return 0;
355}
356
358EhtPpdu::GetPsdu(uint8_t bssColor, uint16_t staId /* = SU_STA_ID */) const
359{
360 if (m_psdus.contains(SU_STA_ID))
361 {
362 NS_ASSERT(m_psdus.size() == 1);
363 return m_psdus.at(SU_STA_ID);
364 }
365
366 if (IsUlMu())
367 {
368 auto ehtPhyHeader = std::get_if<EhtTbPhyHeader>(&m_ehtPhyHeader);
369 NS_ASSERT(ehtPhyHeader);
370 NS_ASSERT(m_psdus.size() == 1);
371 if ((bssColor == 0) || (ehtPhyHeader->m_bssColor == 0) ||
372 (bssColor == ehtPhyHeader->m_bssColor))
373 {
374 return m_psdus.cbegin()->second;
375 }
376 }
377 else if (IsDlMu())
378 {
379 auto ehtPhyHeader = std::get_if<EhtMuPhyHeader>(&m_ehtPhyHeader);
380 NS_ASSERT(ehtPhyHeader);
381 if ((bssColor == 0) || (ehtPhyHeader->m_bssColor == 0) ||
382 (bssColor == ehtPhyHeader->m_bssColor))
383 {
384 const auto it = m_psdus.find(staId);
385 if (it != m_psdus.cend())
386 {
387 return it->second;
388 }
389 }
390 }
391
392 return nullptr;
393}
394
396EhtPpdu::GetRuSpec(std::size_t ruAllocIndex, MHz_u bw, RuType ruType, std::size_t phyIndex) const
397{
398 if (ruType == RuType::RU_26_TONE)
399 {
400 for (const auto undefinedRu : std::initializer_list<std::size_t>{19, 56, 93, 130})
401 {
402 if (phyIndex >= undefinedRu)
403 {
404 ++phyIndex;
405 }
406 }
407 }
408 const auto p20Index = m_operatingChannel.GetPrimaryChannelIndex(MHz_u{20});
409 const auto& [primary160, primary80OrLow80] =
410 EhtRu::GetPrimaryFlags(bw, ruType, phyIndex, p20Index);
411 const auto index = EhtRu::GetIndexIn80MHzSegment(bw, ruType, phyIndex);
412 return EhtRu::RuSpec{ruType, index, primary160, primary80OrLow80};
413}
414
417{
418 return Ptr<WifiPpdu>(new EhtPpdu(*this), false);
419}
420
421} // namespace ns3
static WifiMode GetEhtMcs(uint8_t index)
Return the EHT MCS corresponding to the provided index.
Definition eht-phy.cc:255
static uint32_t GetEhtSigFieldSize(MHz_u channelWidth, const RuAllocation &ruAllocation, uint8_t ehtPpduType, bool compression, std::size_t numMuMimoUsers)
Get variable length EHT-SIG field size.
Definition eht-ppdu.cc:258
static HeSigBContentChannels GetEhtSigContentChannels(const WifiTxVector &txVector, uint8_t p20Index)
Get the EHT-SIG content channels for a given PPDU IEEE 802.11be-D3.1 36.3.12.8.2 EHT-SIG content chan...
Definition eht-ppdu.cc:246
bool IsDlMu() const override
Return true if the PPDU is a DL MU PPDU.
Definition eht-ppdu.cc:147
static MHz_u GetChannelWidthMhzFromEncoding(uint8_t bandwidth)
Convert channel width expressed in MHz from bandwidth field encoding in U-SIG.
Definition eht-ppdu.cc:118
void SetPhyHeaders(const WifiTxVector &txVector, Time ppduDuration) override
Fill in the PHY headers.
Definition eht-ppdu.cc:40
WifiRu::RuSpec GetRuSpec(std::size_t ruAllocIndex, MHz_u bw, RuType ruType, std::size_t phyIndex) const override
Get the RU specification that has been assigned a given user.
Definition eht-ppdu.cc:396
static uint8_t GetChannelWidthEncodingFromMhz(MHz_u channelWidth, const WifiPhyOperatingChannel &channel)
Convert channel width expressed in MHz to bandwidth field encoding in U-SIG.
Definition eht-ppdu.cc:94
bool IsUlMu() const override
Return true if the PPDU is an UL MU PPDU.
Definition eht-ppdu.cc:153
void SetEhtPhyHeader(const WifiTxVector &txVector)
Fill in the EHT PHY header.
Definition eht-ppdu.cc:48
static std::pair< std::size_t, std::size_t > GetNumRusPerEhtSigBContentChannel(MHz_u channelWidth, uint8_t ehtPpduType, const RuAllocation &ruAllocation, bool compression, std::size_t numMuMimoUsers)
Get the number of RUs per EHT-SIG-B content channel.
Definition eht-ppdu.cc:227
Ptr< WifiPpdu > Copy() const override
Copy this instance.
Definition eht-ppdu.cc:416
void SetTxVectorFromPhyHeaders(WifiTxVector &txVector) const override
Fill in the TXVECTOR from PHY headers.
Definition eht-ppdu.cc:159
WifiPpduType GetType() const override
Return the PPDU type (.
Definition eht-ppdu.cc:128
static uint8_t GetPuncturedInfo(const std::vector< bool > &inactiveSubchannels, uint8_t ehtPpduType, std::optional< bool > isLow80MHz)
Get the Punctured Channel Information field in the U-SIG.
Definition eht-ppdu.cc:301
EhtPhyHeader m_ehtPhyHeader
the EHT PHY header
Definition eht-ppdu.h:198
EhtPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, const WifiPhyOperatingChannel &channel, Time ppduDuration, uint64_t uid, TxPsdFlag flag)
Create an EHT PPDU, storing a map of PSDUs.
Definition eht-ppdu.cc:27
RU Specification.
Definition eht-ru.h:34
static std::pair< bool, bool > GetPrimaryFlags(MHz_u bw, RuType ruType, std::size_t phyIndex, uint8_t p20Index)
Get the primary flags of a given RU transmitted in a PPDU.
Definition eht-ru.cc:912
static std::size_t GetIndexIn80MHzSegment(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the index of a given RU transmitted in a PPDU within its 80 MHz segment.
Definition eht-ru.cc:945
HE PPDU (11ax)
Definition he-ppdu.h:39
TxPsdFlag
The transmit power spectral density flag, namely used to correctly build PSDs for pre-HE and HE porti...
Definition he-ppdu.h:104
static std::pair< std::size_t, std::size_t > GetNumRusPerHeSigBContentChannel(MHz_u channelWidth, WifiModulationClass mc, const RuAllocation &ruAllocation, std::optional< Center26ToneRuIndication > center26ToneRuIndication, bool sigBCompression, uint8_t numMuMimoUsers)
Get the number of STAs per HE-SIG-B content channel.
Definition he-ppdu.cc:552
static Time GetGuardIntervalFromEncoding(uint8_t giAndNltfSize)
Convert guard interval from its encoding in HE-SIG-A.
Definition he-ppdu.cc:957
static HeSigBContentChannels GetHeSigBContentChannels(const WifiTxVector &txVector, uint8_t p20Index)
Get the HE SIG-B content channels for a given PPDU IEEE 802.11ax-2021 27.3.11.8.2 HE-SIG-B content ch...
Definition he-ppdu.cc:663
std::vector< std::vector< HeSigBUserSpecificField > > HeSigBContentChannels
HE SIG-B Content Channels.
Definition he-ppdu.h:50
static MHz_u GetChannelWidthMhzFromEncoding(uint8_t bandwidth)
Convert channel width expressed in MHz from bandwidth field encoding in HE-SIG-A.
Definition he-ppdu.cc:914
static uint8_t GetChannelWidthEncodingFromMhz(MHz_u channelWidth)
Convert channel width expressed in MHz to bandwidth field encoding in HE-SIG-A.
Definition he-ppdu.cc:893
void SetLSigHeader(Time ppduDuration)
Fill in the L-SIG header.
Definition he-ppdu.cc:102
void SetHeMuUserInfos(WifiTxVector &txVector, WifiModulationClass mc, const RuAllocation &ruAllocation, std::optional< Center26ToneRuIndication > center26ToneRuIndication, const HeSigBContentChannels &contentChannels, bool sigBCompression, uint8_t numMuMimoUsers) const
Reconstruct HeMuUserInfoMap from HE-SIG-B header.
Definition he-ppdu.cc:251
static uint8_t GetGuardIntervalAndNltfEncoding(Time guardInterval, uint8_t nltf)
Convert guard interval and NLTF to its encoding in HE-SIG-A.
Definition he-ppdu.cc:935
uint16_t GetLength() const
Return the LENGTH field of L-SIG (in bytes).
Definition ofdm-ppdu.cc:199
LSigHeader m_lSig
the L-SIG PHY header
Definition ofdm-ppdu.h:101
Smart pointer class similar to boost::intrusive_ptr.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
static WifiMode GetVhtMcs(uint8_t index)
Return the VHT MCS corresponding to the provided index.
Definition vht-phy.cc:324
uint8_t GetMcsValue() const
Definition wifi-mode.cc:151
Class that keeps track of all information about the current PHY operating channel.
uint8_t GetPrimaryChannelIndex(MHz_u primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
const WifiPhyOperatingChannel & m_operatingChannel
the operating channel of the PHY
Definition wifi-ppdu.h:201
WifiPreamble m_preamble
the PHY preamble
Definition wifi-ppdu.h:192
Ptr< const WifiPsdu > GetPsdu() const
Get the payload of the PPDU.
Definition wifi-ppdu.cc:142
WifiConstPsduMap m_psdus
the PSDUs contained in this PPDU
Definition wifi-ppdu.h:194
std::variant< HeRu::RuSpec, EhtRu::RuSpec > RuSpec
variant of the RU specification
Definition wifi-ru.h:27
static RuType GetRuType(RuSpec ru)
Get the type of a given RU.
Definition wifi-ru.cc:45
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetRuAllocation(const RuAllocation &ruAlloc, uint8_t p20Index)
Set RU_ALLOCATION field.
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.
uint8_t GetBssColor() const
Get the BSS color.
const RuAllocation & GetRuAllocation(uint8_t p20Index) const
Get RU_ALLOCATION field.
void SetGuardInterval(Time guardInterval)
Sets the guard interval duration (in nanoseconds)
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.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
void SetChannelWidth(MHz_u channelWidth)
Sets the selected channelWidth.
uint8_t GetEhtPpduType() const
Get the EHT_PPDU_TYPE parameter.
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.
MHz_u GetChannelWidth() const
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
void SetBssColor(uint8_t color)
Set the BSS color.
Time GetGuardInterval() const
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.
const std::vector< bool > & GetInactiveSubchannels() const
Get the 20 MHz subchannels that are punctured.
Declaration of ns3::EhtPhy class.
Declaration of ns3::EhtPpdu class.
#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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
WifiPpduType
The type of PPDU (SU, DL MU, or UL MU)
@ WIFI_PREAMBLE_EHT_TB
@ WIFI_PREAMBLE_EHT_MU
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_PPDU_TYPE_UL_MU
@ WIFI_PPDU_TYPE_SU
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
RuType
The different Resource Unit (RU) types.
Definition wifi-types.h:99
double MHz_u
MHz weak type.
Definition wifi-units.h:31
bool IsDlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a downlink multi-user transmission.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
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
PHY header for EHT MU PPDUs.
Definition eht-ppdu.h:50
uint8_t m_bandwidth
Bandwidth field.
Definition eht-ppdu.h:53
PHY header for EHT TB PPDUs.
Definition eht-ppdu.h:38
uint8_t m_bandwidth
Bandwidth field.
Definition eht-ppdu.h:41
uint32_t prev