14#include "ns3/wifi-phy-operating-channel.h"
15#include "ns3/wifi-psdu.h"
16#include "ns3/wifi-utils.h"
19#include <initializer_list>
33 :
HePpdu(psdus, txVector, channel, ppduDuration, uid, flag, false)
35 NS_LOG_FUNCTION(
this << psdus << txVector << channel << ppduDuration << uid << flag);
58 .m_bssColor = bssColor,
62 .m_puncturedChannelInfo =
88 .m_bssColor = bssColor,
96 NS_ASSERT(channel.GetTotalWidth() >= channelWidth);
97 if (channelWidth ==
MHz_u{320})
99 switch (channel.GetNumber())
110 NS_ASSERT_MSG(
false,
"Invalid 320 MHz channel number " << +channel.GetNumber());
120 if ((bandwidth == 4) || (bandwidth == 5))
177 const auto ruAllocation = ehtPhyHeader->m_ruAllocationA;
180 ruAllocation.has_value())
183 const auto isMuMimo = (ehtPhyHeader->m_ppduType == 2);
184 const auto muMimoUsers =
186 ? std::accumulate(ehtPhyHeader->m_contentChannels.cbegin(),
187 ehtPhyHeader->m_contentChannels.cend(),
189 [](uint8_t
prev,
const auto& cc) { return prev + cc.size(); })
193 ruAllocation.value(),
195 ehtPhyHeader->m_contentChannels,
196 ehtPhyHeader->m_ppduType == 2,
199 else if (ehtPhyHeader->m_ppduType == 1)
201 NS_ASSERT(ehtPhyHeader->m_contentChannels.size() == 1 &&
202 ehtPhyHeader->m_contentChannels.front().size() == 1);
205 txVector.
SetNss(ehtPhyHeader->m_contentChannels.front().front().nss);
210 txVector.
SetHeMuUserInfo(ehtPhyHeader->m_contentChannels.front().front().staId,
212 ehtPhyHeader->m_contentChannels.front().front().mcs,
213 ehtPhyHeader->m_contentChannels.front().front().nss});
226std::pair<std::size_t, std::size_t>
231 std::size_t numMuMimoUsers)
233 if (ehtPpduType == 1)
262 std::size_t numMuMimoUsers)
268 commonFieldSize = 4 + 6 ;
269 if (channelWidth <=
MHz_u{40})
271 commonFieldSize += 8;
276 8 * (channelWidth /
MHz_u{40}) +
286 auto maxNumRusPerContentChannel =
287 std::max(numRusPerContentChannel.first, numRusPerContentChannel.second);
288 auto maxNumUserBlockFields = maxNumRusPerContentChannel /
290 std::size_t userSpecificFieldSize =
291 maxNumUserBlockFields * (2 * 21 + 4 + 6 );
292 if (maxNumRusPerContentChannel % 2 != 0)
294 userSpecificFieldSize += 21 + 4 + 6 ;
297 return commonFieldSize + userSpecificFieldSize;
303 std::optional<bool> isLow80MHz)
305 if (inactiveSubchannels.size() < 4)
311 "Puncturing over more than 160 MHz is not supported");
312 if (ehtPpduType == 0)
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)
322 if (!inactiveSubchannels.at(i))
324 puncturedInfoField |= 1 << (i / 4);
327 return puncturedInfoField;
330 const auto numPunctured = std::count_if(inactiveSubchannels.cbegin(),
331 inactiveSubchannels.cend(),
332 [](
bool punctured) { return punctured; });
333 if (numPunctured == 0)
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)
345 return firstIndex + 1;
347 NS_ASSERT_MSG(((firstIndex % 2) == 0) && inactiveSubchannels.at(firstIndex + 1),
348 "invalid 40 MHz puncturing pattern");
349 return 9 + (firstIndex / 2);
371 if ((bssColor == 0) || (ehtPhyHeader->m_bssColor == 0) ||
372 (bssColor == ehtPhyHeader->m_bssColor))
374 return m_psdus.cbegin()->second;
381 if ((bssColor == 0) || (ehtPhyHeader->m_bssColor == 0) ||
382 (bssColor == ehtPhyHeader->m_bssColor))
384 const auto it =
m_psdus.find(staId);
400 for (
const auto undefinedRu : std::initializer_list<std::size_t>{19, 56, 93, 130})
402 if (phyIndex >= undefinedRu)
409 const auto& [primary160, primary80OrLow80] =
412 return EhtRu::RuSpec{ruType, index, primary160, primary80OrLow80};
static WifiMode GetEhtMcs(uint8_t index)
Return the EHT MCS corresponding to the provided index.
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.
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...
bool IsDlMu() const override
Return true if the PPDU is a DL MU PPDU.
static MHz_u GetChannelWidthMhzFromEncoding(uint8_t bandwidth)
Convert channel width expressed in MHz from bandwidth field encoding in U-SIG.
void SetPhyHeaders(const WifiTxVector &txVector, Time ppduDuration) override
Fill in the PHY headers.
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.
static uint8_t GetChannelWidthEncodingFromMhz(MHz_u channelWidth, const WifiPhyOperatingChannel &channel)
Convert channel width expressed in MHz to bandwidth field encoding in U-SIG.
bool IsUlMu() const override
Return true if the PPDU is an UL MU PPDU.
void SetEhtPhyHeader(const WifiTxVector &txVector)
Fill in the EHT PHY header.
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.
Ptr< WifiPpdu > Copy() const override
Copy this instance.
void SetTxVectorFromPhyHeaders(WifiTxVector &txVector) const override
Fill in the TXVECTOR from PHY headers.
WifiPpduType GetType() const override
Return the PPDU type (.
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.
EhtPhyHeader m_ehtPhyHeader
the EHT PHY header
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.
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.
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.
TxPsdFlag
The transmit power spectral density flag, namely used to correctly build PSDs for pre-HE and HE porti...
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.
static Time GetGuardIntervalFromEncoding(uint8_t giAndNltfSize)
Convert guard interval from its encoding in HE-SIG-A.
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...
std::vector< std::vector< HeSigBUserSpecificField > > HeSigBContentChannels
HE SIG-B Content Channels.
static MHz_u GetChannelWidthMhzFromEncoding(uint8_t bandwidth)
Convert channel width expressed in MHz from bandwidth field encoding in HE-SIG-A.
static uint8_t GetChannelWidthEncodingFromMhz(MHz_u channelWidth)
Convert channel width expressed in MHz to bandwidth field encoding in HE-SIG-A.
void SetLSigHeader(Time ppduDuration)
Fill in the L-SIG header.
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.
static uint8_t GetGuardIntervalAndNltfEncoding(Time guardInterval, uint8_t nltf)
Convert guard interval and NLTF to its encoding in HE-SIG-A.
LSigHeader m_lSig
the L-SIG PHY header
Smart pointer class similar to boost::intrusive_ptr.
Simulation virtual time values and global simulation resolution.
static WifiMode GetVhtMcs(uint8_t index)
Return the VHT MCS corresponding to the provided index.
uint8_t GetMcsValue() const
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
WifiPreamble m_preamble
the PHY preamble
Ptr< const WifiPsdu > GetPsdu() const
Get the payload of the PPDU.
WifiConstPsduMap m_psdus
the PSDUs contained in this PPDU
std::variant< HeRu::RuSpec, EhtRu::RuSpec > RuSpec
variant of the RU specification
static RuType GetRuType(RuSpec ru)
Get the type of a given RU.
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,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#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_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.
double MHz_u
MHz weak type.
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.
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