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;
838 return hasUsers ? ruAlloc : 30;
845 bool primary80MHzOrLower80MHz)
848 m_primary160MHz{primary160MHz},
849 m_primary80MHzOrLower80MHz{primary80MHzOrLower80MHz}
872 return m_primary160MHz;
879 return m_primary80MHzOrLower80MHz;
885 auto phyIndex{m_index};
886 const auto primary160IsLower160 = (p20Index < (
MHz_u{320} /
MHz_u{20}) / 2);
888 ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
892 const auto indicesPer80MHz =
GetNRus(
MHz_u{80}, m_ruType,
true);
894 ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
896 phyIndex += 2 * indicesPer80MHz;
898 const uint8_t num20MHzSubchannelsIn160 =
MHz_u{160} /
MHz_u{20};
899 const auto primary80IsLower80 =
900 ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
902 ((m_primary160MHz && ((primary80IsLower80 && !m_primary80MHzOrLower80MHz) ||
903 (!primary80IsLower80 && m_primary80MHzOrLower80MHz))) ||
904 (!m_primary160MHz && !m_primary80MHzOrLower80MHz)))
906 phyIndex += indicesPer80MHz;
914 const auto nRus =
GetNRus(bw, ruType);
916 const auto indicesPer80MHz = (ruWidth <=
MHz_u{80}) ?
GetNRus(
MHz_u{80}, ruType,
true) : 1;
917 const auto undefinedRusPer80MHz =
919 const auto primary160IsLower160 = (p20Index < (
MHz_u{320} /
MHz_u{20}) / 2);
920 const auto primary160 =
922 (primary160IsLower160 && phyIndex <= (nRus / 2) + (2 * undefinedRusPer80MHz)) ||
923 (!primary160IsLower160 && phyIndex > (nRus / 2) + (2 * undefinedRusPer80MHz)));
924 bool primary80OrLow80;
927 const uint8_t num20MHzSubchannelsIn160 =
MHz_u{160} /
MHz_u{20};
928 const auto primary80IsLower80 =
929 ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
930 const auto threshold =
931 ((bw <
MHz_u{320}) || primary160IsLower160) ? indicesPer80MHz : 3 * indicesPer80MHz;
933 (primary80IsLower80 && phyIndex <= threshold) ||
934 (!primary80IsLower80 && phyIndex > threshold);
939 ((((phyIndex - 1) / indicesPer80MHz) % 2) == 0);
941 return {primary160, primary80OrLow80};
952 if (
const auto indicesPer80MHz =
GetNRus(
MHz_u{80}, ruType,
true);
953 bw >
MHz_u{80} && phyIndex > indicesPer80MHz)
955 return (((phyIndex - 1) % indicesPer80MHz) + 1);
975 auto nRus = it->second.size();
976 if (!includeUndefinedRus)
978 const auto num80MHz = std::max<uint16_t>(bw /
MHz_u{80}, 1);
979 const auto undefinedRus =
981 nRus -= undefinedRus;
986std::vector<EhtRu::RuSpec>
996 return {{ruType, 1,
true,
true}};
1002 return {{ruType, 1,
true,
true}, {ruType, 1,
false,
true}};
1005 std::vector<EhtRu::RuSpec> ret;
1007 const auto indices =
GetNRus(std::min(bw,
MHz_u{80}), ruType,
true);
1008 for (uint8_t idx80MHz = 0; idx80MHz < (bw /
MHz_u{80}); ++idx80MHz)
1010 const auto p160 = (idx80MHz < 2);
1011 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1012 for (std::size_t ruIndex = 1; ruIndex <= indices; ++ruIndex)
1014 if (subcarrierGroup.at(ruIndex - 1).empty())
1019 ret.emplace_back(ruType, ruIndex, p160, p80orLow80);
1025std::vector<EhtRu::RuSpec>
1033 std::vector<std::size_t> indices;
1034 if (bw >=
MHz_u{20})
1036 indices.push_back(5);
1038 if (bw >=
MHz_u{40})
1040 indices.push_back(14);
1042 if (bw >=
MHz_u{80})
1044 indices.insert(indices.end(), {24, 33});
1047 std::vector<EhtRu::RuSpec> ret;
1048 for (uint8_t idx80MHz = 0; idx80MHz < (bw /
MHz_u{80}); ++idx80MHz)
1050 const auto p160 = (idx80MHz < 2);
1051 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1052 std::transform(indices.cbegin(),
1054 std::back_inserter(ret),
1055 [p160, p80orLow80](
const auto indice) {
1056 return EhtRu::RuSpec{RuType::RU_26_TONE, indice, p160, p80orLow80};
1067 return it->second.at(phyIndex - 1);
1098 (ruBw <=
MHz_u{80}) && (otherRuBw <=
MHz_u{80}) &&
1104 for (
const auto& rangeRu : rangesRu)
1107 for (
auto& rangeP : rangesP)
1109 if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
1123 for (uint8_t idx80MHz = 0; idx80MHz < (bw /
MHz_u{80}); ++idx80MHz)
1125 const auto p160 = (idx80MHz < 2);
1126 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1127 for (std::size_t index = 1; index <= numRus; ++index)
1129 EhtRu::RuSpec searchedRu(searchedRuType, index, p160, p80orLow80);
1136 NS_ABORT_MSG(
"The searched RU type " << searchedRuType <<
" was not found for bw=" << bw
1137 <<
" and referenceRu=" << referenceRu);
1143 std::size_t& nStations,
1144 std::size_t& nCentral26TonesRus)
1161 ruType =
static_cast<RuType>(i);
1164 nStations =
GetNRus(bandwidth, ruType);
1173 ? (bandwidth /
MHz_u{20})
1190 return !(*
this == other);
1199 return std::tie(m_ruType, m_index, m_primary160MHz, m_primary80MHzOrLower80MHz) <
1200 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.