12#include "ns3/assert.h"
13#include "ns3/wifi-ru.h"
154 { {{-500, -259}, {-253, -12}},
155 {{12, 253}, {259, 500}}}},
293 { {{-1012, -771}, {-765, -524}},
294 {{-500, -259}, {-253, -12}},
295 {{12, 253}, {259, 500}},
296 {{524, 765}, {771, 1012}}}},
298 { {{-1012, -515}, {-509, -12}},
299 {{12, 509}, {515, 1012}}}},
301 { {{-1012, -515}, {-509, -12}, {12, 509}, {515, 1012}}}},
568 { {{-2036, -1795}, {-1789, -1548}},
569 {{-1524, -1283}, {-1277, -1036}},
570 {{-1012, -771}, {-765, -524}},
571 {{-500, -259}, {-253, -12}},
572 {{12, 253}, {259, 500}},
573 {{524, 765}, {771, 1012}},
574 {{1036, 1277}, {1283, 1524}},
575 {{1548, 1789}, {1795, 2036}}}},
577 { {{-2036, -1539}, {-1533, -1036}},
578 {{-1012, -515}, {-509, -12}},
579 {{12, 509}, {515, 1012}},
580 {{1036, 1533}, {1539, 2036}}}},
582 { {{-2036, -1539}, {-1533, -1036}, {-1012, -515}, {-509, -12}},
583 {{12, 509}, {515, 1012}, {1036, 1533}, {1539, 2036}}}},
797std::vector<EhtRu::RuSpec>
800 std::optional<std::size_t> idx;
801 if ((ruAllocation <= 25) || (ruAllocation == 48))
805 else if ((ruAllocation >= 26) && (ruAllocation <= 31))
809 else if (((ruAllocation >= 64) && (ruAllocation <= 95)))
811 idx = ruAllocation & 0x1F8;
817 return idx.has_value() ?
m_ruAllocations.at(idx.value()) : std::vector<EhtRu::RuSpec>{};
828 return isOdd ? 15 : 24;
831 return isOdd ? 25 : 48;
833 return hasUsers ? 64 : 28;
835 return hasUsers ? 72 : 29;
837 return hasUsers ? 80 : 30;
839 return hasUsers ? 88 : 30;
846 bool primary80MHzOrLower80MHz)
849 m_primary160MHz{primary160MHz},
850 m_primary80MHzOrLower80MHz{primary80MHzOrLower80MHz}
873 return m_primary160MHz;
880 return m_primary80MHzOrLower80MHz;
886 auto phyIndex{m_index};
887 const auto primary160IsLower160 = (p20Index < (
MHz_u{320} /
MHz_u{20}) / 2);
889 ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
893 const auto indicesPer80MHz =
GetNRus(
MHz_u{80}, m_ruType,
true);
895 ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
897 phyIndex += 2 * indicesPer80MHz;
899 const uint8_t num20MHzSubchannelsIn160 =
MHz_u{160} /
MHz_u{20};
900 const auto primary80IsLower80 =
901 ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
903 ((m_primary160MHz && ((primary80IsLower80 && !m_primary80MHzOrLower80MHz) ||
904 (!primary80IsLower80 && m_primary80MHzOrLower80MHz))) ||
905 (!m_primary160MHz && !m_primary80MHzOrLower80MHz)))
907 phyIndex += indicesPer80MHz;
915 const auto nRus =
GetNRus(bw, ruType);
917 const auto indicesPer80MHz = (ruWidth <=
MHz_u{80}) ?
GetNRus(
MHz_u{80}, ruType,
true) : 1;
918 const auto undefinedRusPer80MHz =
920 const auto primary160IsLower160 = (p20Index < (
MHz_u{320} /
MHz_u{20}) / 2);
921 const auto primary160 =
923 (primary160IsLower160 && phyIndex <= (nRus / 2) + (2 * undefinedRusPer80MHz)) ||
924 (!primary160IsLower160 && phyIndex > (nRus / 2) + (2 * undefinedRusPer80MHz)));
925 bool primary80OrLow80;
928 const uint8_t num20MHzSubchannelsIn160 =
MHz_u{160} /
MHz_u{20};
929 const auto primary80IsLower80 =
930 ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
931 const auto threshold =
932 ((bw <
MHz_u{320}) || primary160IsLower160) ? indicesPer80MHz : 3 * indicesPer80MHz;
934 (primary80IsLower80 && phyIndex <= threshold) ||
935 (!primary80IsLower80 && phyIndex > threshold);
940 ((((phyIndex - 1) / indicesPer80MHz) % 2) == 0);
942 return {primary160, primary80OrLow80};
953 if (
const auto indicesPer80MHz =
GetNRus(
MHz_u{80}, ruType,
true);
954 bw >
MHz_u{80} && phyIndex > indicesPer80MHz)
956 return (((phyIndex - 1) % indicesPer80MHz) + 1);
976 auto nRus = it->second.size();
977 if (!includeUndefinedRus)
979 const auto num80MHz = std::max<uint16_t>(bw /
MHz_u{80}, 1);
980 const auto undefinedRus =
982 nRus -= undefinedRus;
987std::vector<EhtRu::RuSpec>
997 return {{ruType, 1,
true,
true}};
1003 return {{ruType, 1,
true,
true}, {ruType, 1,
false,
true}};
1006 std::vector<EhtRu::RuSpec> ret;
1008 const auto indices =
GetNRus(std::min(bw,
MHz_u{80}), ruType,
true);
1009 for (uint8_t idx80MHz = 0; idx80MHz < (bw /
MHz_u{80}); ++idx80MHz)
1011 const auto p160 = (idx80MHz < 2);
1012 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1013 for (std::size_t ruIndex = 1; ruIndex <= indices; ++ruIndex)
1015 if (subcarrierGroup.at(ruIndex - 1).empty())
1020 ret.emplace_back(ruType, ruIndex, p160, p80orLow80);
1026std::vector<EhtRu::RuSpec>
1034 std::vector<std::size_t> indices;
1035 if (bw >=
MHz_u{20})
1037 indices.push_back(5);
1039 if (bw >=
MHz_u{40})
1041 indices.push_back(14);
1043 if (bw >=
MHz_u{80})
1045 indices.insert(indices.end(), {24, 33});
1048 std::vector<EhtRu::RuSpec> ret;
1049 for (uint8_t idx80MHz = 0; idx80MHz < (bw /
MHz_u{80}); ++idx80MHz)
1051 const auto p160 = (idx80MHz < 2);
1052 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1053 std::transform(indices.cbegin(),
1055 std::back_inserter(ret),
1056 [p160, p80orLow80](
const auto indice) {
1057 return EhtRu::RuSpec{RuType::RU_26_TONE, indice, p160, p80orLow80};
1068 return it->second.at(phyIndex - 1);
1099 (ruBw <=
MHz_u{80}) && (otherRuBw <=
MHz_u{80}) &&
1105 for (
const auto& rangeRu : rangesRu)
1108 for (
auto& rangeP : rangesP)
1110 if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
1124 for (uint8_t idx80MHz = 0; idx80MHz < (bw /
MHz_u{80}); ++idx80MHz)
1126 const auto p160 = (idx80MHz < 2);
1127 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1128 for (std::size_t index = 1; index <= numRus; ++index)
1130 EhtRu::RuSpec searchedRu(searchedRuType, index, p160, p80orLow80);
1137 NS_ABORT_MSG(
"The searched RU type " << searchedRuType <<
" was not found for bw=" << bw
1138 <<
" and referenceRu=" << referenceRu);
1144 std::size_t& nStations,
1145 std::size_t& nCentral26TonesRus)
1162 ruType =
static_cast<RuType>(i);
1165 nStations =
GetNRus(bandwidth, ruType);
1174 ? (bandwidth /
MHz_u{20})
1191 return !(*
this == other);
1200 return std::tie(m_ruType, m_index, m_primary160MHz, m_primary80MHzOrLower80MHz) <
1201 std::tie(other.
m_ruType, other.
m_index, m_primary160MHz, m_primary80MHzOrLower80MHz);
bool m_primary160MHz
true if the RU is allocated in the primary 160MHz channel
std::size_t m_index
RU index (starting at 1) within the 80 MHz segment.
bool operator!=(const RuSpec &other) const
Compare this RU to the given RU.
bool GetPrimary80MHzOrLower80MHz() const
bool operator==(const RuSpec &other) const
Compare this RU to the given RU.
bool m_primary80MHzOrLower80MHz
if the RU is allocated in the primary 160MHz channel, true if the RU is allocated in the primary 80MH...
bool operator<(const RuSpec &other) const
Compare this RU to the given RU.
RuSpec()=default
Default constructor.
RuType GetRuType() const
Get the RU type.
std::size_t GetPhyIndex(MHz_u bw, uint8_t p20Index) const
Get the RU PHY index.
std::size_t GetIndex() const
Get the RU index within the 80 MHz segment.
bool GetPrimary160MHz() const
Get whether the RU is allocated in the primary 160MHz channel.
static const RuAllocationMap m_ruAllocations
Table 36-34 of IEEE802.11be-D7.0.
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::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 uint16_t GetEqualizedRuAllocation(RuType ruType, bool isOdd, bool hasUsers)
Get the RU_ALLOCATION value for equal size RUs.
std::map< uint8_t, std::vector< RuSpec > > RuAllocationMap
RU allocation map.
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 an PPDU of the given ban...
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 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 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 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_ruSubcarrierGroups
Subcarrier groups for all EHT RUs.
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 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::size_t GetNRus(MHz_u bw, RuType ruType, bool includeUndefinedRus=false)
Get the number of distinct RUs of the given type (number of tones) available in a PPDU of the given b...
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_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#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.
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.