12#include "ns3/assert.h" 
   13#include "ns3/wifi-ru.h" 
  100       {{-16, -4}, {4, 16}},
 
  364std::vector<HeRu::RuSpec>
 
  367    std::optional<std::size_t> idx;
 
  368    if ((ruAllocation <= 15) || (ruAllocation == 112))
 
  372    else if (((ruAllocation >= 16) && (ruAllocation <= 95)) ||
 
  373             ((ruAllocation >= 192) && (ruAllocation <= 215)))
 
  375        idx = ruAllocation & 0xF8;
 
  377    else if ((ruAllocation >= 96) && (ruAllocation <= 111))
 
  379        idx = ruAllocation & 0xF0;
 
  381    else if ((ruAllocation >= 113) && (ruAllocation <= 115))
 
  385    else if ((ruAllocation >= 128) && (ruAllocation <= 191))
 
  387        idx = ruAllocation & 0xC0;
 
  393    return idx.has_value() ? 
m_heRuAllocations.at(idx.value()) : std::vector<HeRu::RuSpec>{};
 
 
  404        return isOdd ? 15 : 112;
 
  406        return isOdd ? 128 : 96;
 
  408        return hasUsers ? 192 : 113;
 
  410        return hasUsers ? 200 : 114;
 
  412        return hasUsers ? 208 : 115;
 
 
  448    bool primary80IsLower80 = (p20Index < bw / 
MHz_u{40});
 
 
  468    const auto primary80IsLower80 = (p20Index < bw / 
MHz_u{40});
 
  469    const auto indicesPer80MHz = 
GetNRus(
MHz_u{80}, ruType);
 
  470    return ((primary80IsLower80 && (phyIndex <= indicesPer80MHz)) ||
 
  471            (!primary80IsLower80 && (phyIndex > indicesPer80MHz)));
 
 
  477    std::size_t index{phyIndex};
 
  478    const auto indicesPer80MHz = 
GetNRus(
MHz_u{80}, ruType);
 
  483    else if (bw > 
MHz_u{80} && phyIndex > indicesPer80MHz)
 
  485        index = (((phyIndex - 1) % indicesPer80MHz) + 1);
 
 
  507    return (bw == 
MHz_u{160} ? 2 : 1) * it->second.size();
 
 
  510std::vector<HeRu::RuSpec>
 
  521        return {{ruType, 1, 
true}};
 
  524    std::vector<HeRu::RuSpec> ret;
 
  525    std::vector<bool> primary80MHzSet{
true};
 
  527    if (bw == 
MHz_u{160})
 
  529        primary80MHzSet.push_back(
false);
 
  533    for (
auto primary80MHz : primary80MHzSet)
 
  535        for (std::size_t ruIndex = 1;
 
  539            ret.emplace_back(ruType, ruIndex, primary80MHz);
 
 
  545std::vector<HeRu::RuSpec>
 
  548    std::vector<std::size_t> indices;
 
  554            indices.push_back(5);
 
  556        else if (bw == 
MHz_u{40})
 
  558            indices.insert(indices.end(), {5, 14});
 
  560        else if (bw >= 
MHz_u{80})
 
  562            indices.insert(indices.end(), {5, 14, 19, 24, 33});
 
  569            indices.push_back(19);
 
  573    std::vector<HeRu::RuSpec> ret;
 
  574    std::vector<bool> primary80MHzSet{
true};
 
  576    if (bw == 
MHz_u{160})
 
  578        primary80MHzSet.push_back(
false);
 
  581    for (
auto primary80MHz : primary80MHzSet)
 
  583        for (
const auto& index : indices)
 
 
  597        return {{-1012, -515}, {-509, -12}, {12, 509}, {515, 1012}};
 
  603    std::size_t indexInLower80MHz = phyIndex;
 
  604    std::size_t numRus = 
GetNRus(bw, ruType);
 
  605    int16_t shift = (bw == 
MHz_u{160}) ? -512 : 0;
 
  606    if (bw == 
MHz_u{160} && phyIndex > (numRus / 2))
 
  609        indexInLower80MHz = phyIndex - (numRus / 2);
 
  616    NS_ABORT_MSG_IF(indexInLower80MHz > it->second.size(), 
"RU index not available");
 
  619    if (bw == 
MHz_u{160})
 
  621        for (
auto& range : group)
 
  623            range.first += shift;
 
  624            range.second += shift;
 
 
  657        for (
const auto& rangeRu : rangesRu)
 
  660            for (
auto& rangeP : rangesP)
 
  662                if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
 
 
  677    std::size_t numRusPer80Mhz;
 
  678    std::vector<bool> primary80MhzFlags;
 
  679    if (bw == 
MHz_u{160})
 
  681        primary80MhzFlags.push_back(
true);
 
  682        primary80MhzFlags.push_back(
false);
 
  688        numRusPer80Mhz = numRus;
 
  691    for (
const auto primary80MHz : primary80MhzFlags)
 
  693        std::size_t index = 1;
 
  694        for (std::size_t indexPer80Mhz = 1; indexPer80Mhz <= numRusPer80Mhz;
 
  695             ++indexPer80Mhz, ++index)
 
  697            RuSpec searchedRu(searchedRuType, index, primary80MHz);
 
  704    NS_ABORT_MSG(
"The searched RU type " << searchedRuType << 
" was not found for bw=" << bw
 
  705                                         << 
" and referenceRu=" << referenceRu);
 
 
  720                                  std::size_t& nStations,
 
  721                                  std::size_t& nCentral26TonesRus)
 
  724    uint8_t nRusAssigned = 0;
 
  729        if (ru.first.first == bandwidth && ru.second.size() <= nStations)
 
  731            ruType = ru.first.second;
 
  732            nRusAssigned = ru.second.size();
 
  735        else if (bandwidth == 
MHz_u{160} && ru.first.first == 
MHz_u{80} &&
 
  736                 (2 * ru.second.size() <= nStations))
 
  738            ruType = ru.first.second;
 
  739            nRusAssigned = 2 * ru.second.size();
 
  743    if (nRusAssigned == 0)
 
  750    nStations = nRusAssigned;
 
 
  759    uint8_t nCentral26TonesRus{0};
 
  764        if (bandwidth == 
MHz_u{20})
 
  766            nCentral26TonesRus = 1;
 
  768        else if (bandwidth == 
MHz_u{40})
 
  770            nCentral26TonesRus = 2;
 
  774            nCentral26TonesRus = 5;
 
  779        nCentral26TonesRus = (bandwidth >= 
MHz_u{80} ? 1 : 0);
 
  782        nCentral26TonesRus = 0;
 
  785    if (bandwidth == 
MHz_u{160})
 
  787        nCentral26TonesRus *= 2;
 
  790    return nCentral26TonesRus;
 
 
  806    return !(*
this == other);
 
 
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.
RuSpec()=default
Default constructor.
RuType GetRuType() const
Get the RU type.
bool operator<(const RuSpec &other) const
Compare this RU to the given RU.
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< RuSpec > GetRuSpecs(uint16_t ruAllocation)
Get the RU specs based on RU_ALLOCATION.
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.
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 std::vector< RuSpec > GetRusOfType(MHz_u bw, RuType ruType)
Get the set of distinct RUs of the given type (number of tones) available in a HE PPDU of the given b...
std::map< uint8_t, std::vector< RuSpec > > RuAllocationMap
RU allocation map.
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...
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 GetNumCentral26TonesRus(MHz_u bw, RuType ruType)
Get the number of 26-tone RUs that can be allocated if returned RU size is greater than 26 tones.
static bool GetPrimary80MHzFlag(MHz_u bw, RuType ruType, std::size_t phyIndex, uint8_t p20Index)
Get the primary 80 MHz flag of a given RU transmitted in a PPDU.
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...
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 std::vector< RuSpec > GetCentral26TonesRus(MHz_u bw, RuType ruType)
Get the set of 26-tone RUs that can be additionally allocated if the given bandwidth is split in RUs ...
static uint16_t GetEqualizedRuAllocation(RuType ruType, bool isOdd, bool hasUsers)
Get the RU_ALLOCATION value for equal size RUs.
static const RuAllocationMap m_heRuAllocations
Table 27-26 of IEEE 802.11ax-2021.
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
#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)
RuType
The different Resource Unit (RU) types.
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
std::map< BwTonesPair, std::vector< SubcarrierGroup > > SubcarrierGroups
map (bandwidth, number of tones) pairs to the group of subcarrier ranges
double MHz_u
MHz weak type.