23#include "ns3/assert.h" 
  109       {{-16, -4}, {4, 16}},
 
  372std::vector<HeRu::RuSpec>
 
  375    std::optional<std::size_t> idx;
 
  376    switch (ruAllocation)
 
  384        idx = ruAllocation & 0xF8;
 
  387        idx = ruAllocation & 0xF0;
 
  392        idx = ruAllocation & 0xC0;
 
  397    return idx.has_value() ? 
m_heRuAllocations.at(idx.value()) : std::vector<HeRu::RuSpec>{};
 
  408        return isOdd ? 15 : 112;
 
  410        return isOdd ? 128 : 96;
 
  428      m_primary80MHz(primary80MHz),
 
  452    return m_primary80MHz;
 
  458    bool primary80IsLower80 = (p20Index < bw / 40);
 
  460    if (bw < 160 || m_ruType == 
HeRu::RU_2x996_TONE || (primary80IsLower80 && m_primary80MHz) ||
 
  461        (!primary80IsLower80 && !m_primary80MHz))
 
  463        m_phyIndex = m_index;
 
  467        m_phyIndex = m_index + 
GetNRus(bw, m_ruType) / 2;
 
  474    return (m_phyIndex != 0);
 
  501    return (bw == 160 ? 2 : 1) * it->second.size();
 
  504std::vector<HeRu::RuSpec>
 
  510        return {{ruType, 1, 
true}};
 
  513    std::vector<HeRu::RuSpec> ret;
 
  514    std::vector<bool> primary80MHzSet{
true};
 
  518        primary80MHzSet.push_back(
false);
 
  522    for (
auto primary80MHz : primary80MHzSet)
 
  524        for (std::size_t ruIndex = 1;
 
  528            ret.emplace_back(ruType, ruIndex, primary80MHz);
 
  534std::vector<HeRu::RuSpec>
 
  537    std::vector<std::size_t> indices;
 
  543            indices.push_back(5);
 
  547            indices.insert(indices.end(), {5, 14});
 
  551            indices.insert(indices.end(), {5, 14, 19, 24, 33});
 
  558            indices.push_back(19);
 
  562    std::vector<HeRu::RuSpec> ret;
 
  563    std::vector<bool> primary80MHzSet{
true};
 
  567        primary80MHzSet.push_back(
false);
 
  570    for (
auto primary80MHz : primary80MHzSet)
 
  572        for (
const auto& index : indices)
 
  585        NS_ABORT_MSG_IF(bw != 160, 
"2x996 tone RU can only be used on 160 MHz band");
 
  586        return {{-1012, -3}, {3, 1012}};
 
  592    std::size_t indexInLower80MHz = phyIndex;
 
  593    std::size_t numRus = 
GetNRus(bw, ruType);
 
  594    int16_t shift = (bw == 160) ? -512 : 0;
 
  595    if (bw == 160 && phyIndex > (numRus / 2))
 
  598        indexInLower80MHz = phyIndex - (numRus / 2);
 
  605    NS_ABORT_MSG_IF(indexInLower80MHz > it->second.size(), 
"RU index not available");
 
  610        for (
auto& range : group)
 
  612            range.first += shift;
 
  613            range.second += shift;
 
  640        for (
const auto& rangeRu : rangesRu)
 
  643            for (
auto& rangeP : rangesP)
 
  645                if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
 
  658    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);
 
  811                                  std::size_t& nStations,
 
  812                                  std::size_t& nCentral26TonesRus)
 
  815    uint8_t nRusAssigned = 0;
 
  820        if (ru.first.first == bandwidth && ru.second.size() <= nStations)
 
  822            ruType = ru.first.second;
 
  823            nRusAssigned = ru.second.size();
 
  826        else if (bandwidth == 160 && ru.first.first == 80 && (2 * ru.second.size() <= nStations))
 
  828            ruType = ru.first.second;
 
  829            nRusAssigned = 2 * ru.second.size();
 
  833    if (nRusAssigned == 0)
 
  840    nStations = nRusAssigned;
 
  848            nCentral26TonesRus = 1;
 
  850        else if (bandwidth == 40)
 
  852            nCentral26TonesRus = 2;
 
  856            nCentral26TonesRus = 5;
 
  861        nCentral26TonesRus = (bandwidth >= 80 ? 1 : 0);
 
  864        nCentral26TonesRus = 0;
 
  867    if (bandwidth == 160)
 
  869        nCentral26TonesRus *= 2;
 
  888    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.
 
RuType GetRuType() const
Get the RU type.
 
std::size_t GetPhyIndex() const
Get the RU PHY index.
 
RuSpec()
Default constructor.
 
bool IsPhyIndexSet() const
Return true if the RU PHY index has been set, false otherwise.
 
bool m_primary80MHz
true if the RU is allocated in the primary 80MHz channel
 
bool operator==(const RuSpec &other) const
Compare this RU to the given RU.
 
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
 
void SetPhyIndex(uint16_t bw, uint8_t p20Index)
Set the RU PHY index.
 
bool operator!=(const RuSpec &other) const
Compare this RU to the given RU.
 
static RuSpec FindOverlappingRu(uint16_t bw, RuSpec referenceRu, RuType searchedRuType)
Find the RU allocation of the given RU type overlapping the given reference RU allocation.
 
static bool DoesOverlap(uint16_t bw, RuSpec ru, const std::vector< RuSpec > &v)
Check whether the given RU overlaps with the given set of RUs.
 
static std::vector< RuSpec > GetRuSpecs(uint8_t ruAllocation)
Get the RU specs based on RU_ALLOCATION.
 
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
 
static SubcarrierGroup GetSubcarrierGroup(uint16_t 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 std::size_t GetNRus(uint16_t 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 std::vector< HeRu::RuSpec > GetRusOfType(uint16_t 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...
 
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
 
std::map< uint8_t, std::vector< RuSpec > > RuAllocationMap
RU allocation map.
 
static std::vector< HeRu::RuSpec > GetCentral26TonesRus(uint16_t 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 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.
 
RuType
The different HE Resource Unit (RU) types.
 
static RuType GetEqualSizedRusForStations(uint16_t 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 RuType GetRuType(uint16_t bandwidth)
Get the RU corresponding to the approximate bandwidth.
 
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)