12#include "ns3/assert.h"
364 : m_channelWidth(channelWidth),
372 const auto lhsIndex = lhs.
GetPhyIndex(m_channelWidth, m_p20Index);
373 const auto rhsIndex = rhs.
GetPhyIndex(m_channelWidth, m_p20Index);
374 const auto lhsStartTone =
376 const auto rhsStartTone =
378 return lhsStartTone < rhsStartTone;
381std::vector<HeRu::RuSpec>
384 std::optional<std::size_t> idx;
385 if (((ruAllocation >= 0) && (ruAllocation <= 15)) || (ruAllocation == 112))
389 else if (((ruAllocation >= 16) && (ruAllocation <= 95)) ||
390 ((ruAllocation >= 192) && (ruAllocation <= 215)))
392 idx = ruAllocation & 0xF8;
394 else if ((ruAllocation >= 96) && (ruAllocation <= 111))
396 idx = ruAllocation & 0xF0;
398 else if ((ruAllocation >= 113) && (ruAllocation <= 115))
402 else if ((ruAllocation >= 128) && (ruAllocation <= 191))
404 idx = ruAllocation & 0xC0;
410 return idx.has_value() ?
m_heRuAllocations.at(idx.value()) : std::vector<HeRu::RuSpec>{};
421 return isOdd ? 15 : 112;
423 return isOdd ? 128 : 96;
441 m_primary80MHz(primary80MHz)
464 return m_primary80MHz;
470 bool primary80IsLower80 = (p20Index < bw / 40);
472 if (bw < 160 || m_ruType ==
HeRu::RU_2x996_TONE || (primary80IsLower80 && m_primary80MHz) ||
473 (!primary80IsLower80 && !m_primary80MHz))
479 return m_index +
GetNRus(bw, m_ruType) / 2;
500 return (bw == 160 ? 2 : 1) * it->second.size();
503std::vector<HeRu::RuSpec>
509 return {{ruType, 1,
true}};
512 std::vector<HeRu::RuSpec> ret;
513 std::vector<bool> primary80MHzSet{
true};
517 primary80MHzSet.push_back(
false);
521 for (
auto primary80MHz : primary80MHzSet)
523 for (std::size_t ruIndex = 1;
527 ret.emplace_back(ruType, ruIndex, primary80MHz);
533std::vector<HeRu::RuSpec>
536 std::vector<std::size_t> indices;
542 indices.push_back(5);
546 indices.insert(indices.end(), {5, 14});
550 indices.insert(indices.end(), {5, 14, 19, 24, 33});
557 indices.push_back(19);
561 std::vector<HeRu::RuSpec> ret;
562 std::vector<bool> primary80MHzSet{
true};
566 primary80MHzSet.push_back(
false);
569 for (
auto primary80MHz : primary80MHzSet)
571 for (
const auto& index : indices)
584 NS_ABORT_MSG_IF(bw != 160,
"2x996 tone RU can only be used on 160 MHz band");
585 return {{-1012, -3}, {3, 1012}};
591 std::size_t indexInLower80MHz = phyIndex;
592 std::size_t numRus =
GetNRus(bw, ruType);
593 int16_t shift = (bw == 160) ? -512 : 0;
594 if (bw == 160 && phyIndex > (numRus / 2))
597 indexInLower80MHz = phyIndex - (numRus / 2);
604 NS_ABORT_MSG_IF(indexInLower80MHz > it->second.size(),
"RU index not available");
609 for (
auto& range : group)
611 range.first += shift;
612 range.second += shift;
639 for (
const auto& rangeRu : rangesRu)
642 for (
auto& rangeP : rangesP)
644 if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
657 for (
const auto& range : toneRanges)
666 for (
auto& r : rangesRu)
668 if (range.second >= r.first && r.second >= range.first)
682 std::size_t numRusPer80Mhz;
683 std::vector<bool> primary80MhzFlags;
686 primary80MhzFlags.push_back(
true);
687 primary80MhzFlags.push_back(
false);
693 numRusPer80Mhz = numRus;
696 for (
const auto primary80MHz : primary80MhzFlags)
698 std::size_t index = 1;
699 for (std::size_t indexPer80Mhz = 1; indexPer80Mhz <= numRusPer80Mhz;
700 ++indexPer80Mhz, ++index)
702 RuSpec searchedRu(searchedRuType, index, primary80MHz);
709 NS_ABORT_MSG(
"The searched RU type " << searchedRuType <<
" was not found for bw=" << bw
710 <<
" and referenceRu=" << referenceRu);
783 switch (
static_cast<uint16_t
>(bandwidth))
807 std::size_t& nStations,
808 std::size_t& nCentral26TonesRus)
811 uint8_t nRusAssigned = 0;
816 if (ru.first.first == bandwidth && ru.second.size() <= nStations)
818 ruType = ru.first.second;
819 nRusAssigned = ru.second.size();
822 else if (bandwidth == 160 && ru.first.first == 80 && (2 * ru.second.size() <= nStations))
824 ruType = ru.first.second;
825 nRusAssigned = 2 * ru.second.size();
829 if (nRusAssigned == 0)
836 nStations = nRusAssigned;
844 nCentral26TonesRus = 1;
846 else if (bandwidth == 40)
848 nCentral26TonesRus = 2;
852 nCentral26TonesRus = 5;
857 nCentral26TonesRus = (bandwidth >= 80 ? 1 : 0);
860 nCentral26TonesRus = 0;
863 if (bandwidth == 160)
865 nCentral26TonesRus *= 2;
884 return !(*
this == other);
893 return std::tie(m_ruType, m_index, m_primary80MHz) <
std::size_t GetIndex() const
Get the RU index.
std::size_t m_index
RU index (starting at 1) as defined by Tables 27-7 to 27-9 of 802.11ax D8.0.
RuType GetRuType() const
Get the RU type.
bool operator<(const RuSpec &other) const
Compare this RU to the given RU.
RuSpec()
Default constructor.
bool m_primary80MHz
true if the RU is allocated in the primary 80MHz channel
std::size_t GetPhyIndex(MHz_u bw, uint8_t p20Index) const
Get the RU PHY index.
bool operator==(const RuSpec &other) const
Compare this RU to the given RU.
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
bool operator!=(const RuSpec &other) const
Compare this RU to the given RU.
static std::vector< HeRu::RuSpec > GetCentral26TonesRus(MHz_u bw, HeRu::RuType ruType)
Get the set of 26-tone RUs that can be additionally allocated if the given bandwidth is split in RUs ...
static std::vector< RuSpec > GetRuSpecs(uint8_t ruAllocation)
Get the RU specs based on RU_ALLOCATION.
static bool DoesOverlap(MHz_u bw, RuSpec ru, const std::vector< RuSpec > &v)
Check whether the given RU overlaps with the given set of RUs.
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
std::map< uint8_t, std::vector< RuSpec > > RuAllocationMap
RU allocation map.
static RuType GetRuType(MHz_u bandwidth)
Get the RU corresponding to the approximate bandwidth.
static std::vector< HeRu::RuSpec > GetRusOfType(MHz_u bw, HeRu::RuType ruType)
Get the set of distinct RUs of the given type (number of tones) available in a HE PPDU of the given b...
static RuType GetEqualSizedRusForStations(MHz_u bandwidth, std::size_t &nStations, std::size_t &nCentral26TonesRus)
Given the channel bandwidth and the number of stations candidate for being assigned an RU,...
static SubcarrierGroup GetSubcarrierGroup(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the subcarrier group of the RU having the given PHY index among all the RUs of the given type (nu...
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
static RuSpec FindOverlappingRu(MHz_u bw, RuSpec referenceRu, RuType searchedRuType)
Find the RU allocation of the given RU type overlapping the given reference RU allocation.
static const SubcarrierGroups m_heRuSubcarrierGroups
Subcarrier groups for all RUs (with indices being applicable to primary 80 MHz channel)
static uint8_t GetEqualizedRuAllocation(RuType ruType, bool isOdd)
Get the RU_ALLOCATION value for equal size RUs.
static std::size_t GetNRus(MHz_u bw, RuType ruType)
Get the number of distinct RUs of the given type (number of tones) available in a HE PPDU of the give...
RuType
The different HE Resource Unit (RU) types.
static const RuAllocationMap m_heRuAllocations
Table 27-26 of IEEE 802.11ax-2021.
std::map< BwTonesPair, std::vector< SubcarrierGroup > > SubcarrierGroups
map (bandwidth, number of tones) pairs to the group of subcarrier ranges
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#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.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
double MHz_u
MHz weak type.
RuSpecCompare(MHz_u channelWidth, uint8_t p20Index)
Constructor.
bool operator()(const RuSpec &lhs, const RuSpec &rhs) const
Function call operator.