15#include "ns3/assert.h" 
  279const std::set<FrequencyChannelInfo>&
 
  308                  "Operating channel does not support more than 2 segments");
 
 
  326    std::stringstream ss;
 
  327    for (
const auto& segment : segments)
 
  333    NS_ASSERT_MSG(!segments.empty(), 
"At least one frequency segment has to be provided");
 
  336    for (
const auto& segment : segments)
 
  338        if (
const auto channelIt =
 
  339                FindFirst(segment.number, segment.frequency, segment.width, standard, segment.band);
 
  349            channelIts.insert(channelIt);
 
  353    if (channelIts.size() != segments.size())
 
  356        throw std::runtime_error(
 
  357            "WifiPhyOperatingChannel: No unique channel found given the specified criteria");
 
  360    auto it = channelIts.begin();
 
  361    for (std::size_t segment = 0; segment < (channelIts.size() - 1); ++segment)
 
  363        const auto freq = (*it)->frequency;
 
  364        const auto width = (*it)->width;
 
  365        const auto band = (*it)->band;
 
  366        const auto maxFreq = freq + (width / 2);
 
  368        const auto nextFreq = (*it)->frequency;
 
  369        const auto nextWidth = (*it)->width;
 
  370        const auto nextBand = (*it)->band;
 
  371        const auto nextMinFreq = nextFreq - (nextWidth / 2);
 
  372        if (maxFreq >= nextMinFreq)
 
  374            throw std::runtime_error(
 
  375                "WifiPhyOperatingChannel is invalid: segments cannot be adjacent nor overlap");
 
  377        if (band != nextBand)
 
  379            throw std::runtime_error(
"WifiPhyOperatingChannel is invalid: all segments shall " 
  380                                     "belong to the same band");
 
  384    if ((channelIts.size() > 2) ||
 
  385        ((channelIts.size() == 2) &&
 
  386         !std::all_of(channelIts.cbegin(), channelIts.cend(), [](
const auto& channel) {
 
  387             return channel->width == MHz_u{80};
 
  390        throw std::runtime_error(
"WifiPhyOperatingChannel is invalid: only 80+80MHz is " 
  391                                 "expected as non-contiguous channel");
 
  394    m_channelIts = channelIts;
 
  395    m_primary20Index = 0;
 
 
  410    std::optional<uint8_t> previousChannelNumber )
 
  414    if (previousChannelNumber)
 
  416        prevSegmentChannelIt =
 
  417            FindFirst(*previousChannelNumber, 
MHz_u{0}, width, standard, band, start);
 
  420            start = std::next(prevSegmentChannelIt);
 
  423    auto channelIt = 
FindFirst(0, 
MHz_u{0}, width, standard, band, start);
 
  426        const auto prevFreq = prevSegmentChannelIt->frequency;
 
  427        const auto prevWidth = prevSegmentChannelIt->width;
 
  428        const auto prevMaxFreq = prevFreq + (prevWidth / 2);
 
  429        const auto nextFreq = channelIt->frequency;
 
  430        const auto nextWidth = channelIt->width;
 
  431        const auto nextMinFreq = nextFreq - (nextWidth / 2);
 
  432        if (prevMaxFreq <= nextMinFreq)
 
  436            channelIt = 
FindFirst(0, 
MHz_u{0}, width, standard, band, std::next(channelIt));
 
  442        return channelIt->number;
 
  446    throw std::runtime_error(
"WifiPhyOperatingChannel: No default channel found of the given width " 
  447                             "and for the given PHY standard and band");
 
 
  460        if (number != 0 && channel.number != number)
 
  464        if (frequency != 
MHz_u{0} && channel.frequency != frequency)
 
  468        if (width != 
MHz_u{0} && channel.width != width)
 
  489        (std::find(standardIt->second.cbegin(), standardIt->second.cend(), band) ==
 
  490             standardIt->second.cend() ||
 
 
  503    return (*std::next(
m_channelIts.begin(), segment))->number;
 
 
  510    return (*std::next(
m_channelIts.begin(), segment))->frequency;
 
 
  554    std::vector<uint8_t> channelNumbers{};
 
  557                   std::back_inserter(channelNumbers),
 
  558                   [](
const auto& channel) { return channel->number; });
 
  559    return channelNumbers;
 
 
  566    std::vector<MHz_u> centerFrequencies{};
 
  569                   std::back_inserter(centerFrequencies),
 
  570                   [](
const auto& channel) { return channel->frequency; });
 
  571    return centerFrequencies;
 
 
  578    std::vector<MHz_u> channelWidths{};
 
  581                   std::back_inserter(channelWidths),
 
  582                   [](
const auto& channel) { return channel->width; });
 
  583    return channelWidths;
 
 
  593                           [](
MHz_u sum, 
const auto& channel) { return sum + channel->width; });
 
 
  630    if (
static_cast<uint16_t
>(primaryChannelWidth) % 20 != 0)
 
  632        NS_LOG_DEBUG(
"The operating channel width is not a multiple of 20 MHz; return 0");
 
  643    while (width < primaryChannelWidth)
 
 
  655    const uint8_t secondaryIndex =
 
  656        (primaryIndex % 2 == 0) ? (primaryIndex + 1) : (primaryIndex - 1);
 
  657    return secondaryIndex;
 
 
  666                    "Primary20 index out of range");
 
 
  678    const auto numIndices = 
GetTotalWidth() / primaryChannelWidth;
 
  680    return (primaryIndex >= (numIndices / 2)) ? 1 : 0;
 
 
  687                    "Primary channel width cannot be larger than the width of a frequency segment");
 
  693    const auto numIndices = 
GetTotalWidth() / primaryChannelWidth;
 
  695    return (secondaryIndex >= (numIndices / 2)) ? 1 : 0;
 
 
  703    const auto segmentWidth = 
GetWidth(segmentIndex);
 
  705    const uint8_t segmentOffset = (segmentIndex * (segmentWidth / primaryChannelWidth));
 
 
  716    const auto segmentWidth = 
GetWidth(segmentIndex);
 
  718    const uint8_t segmentOffset = (segmentIndex * (segmentWidth / secondaryChannelWidth));
 
  721               secondaryChannelWidth;
 
 
  729                    "Primary channel width cannot be larger than the width of a frequency segment");
 
  734    return primaryChanIt->number;
 
 
  742                  "Requested primary channel width (" 
  743                      << primaryChannelWidth << 
" MHz) exceeds total width (" << 
GetTotalWidth()
 
  762    return primaryChannel;
 
 
  775    std::set<uint8_t> indices;
 
  778    while (currWidth < width)
 
 
  795    const std::set<uint8_t>& primaryIndices)
 const 
  803    MHz_u primaryWidth{20};
 
  806    while (size != primaryIndices.size())
 
  819    std::set<uint8_t> secondaryIndices;
 
  820    for (
const auto& index : primaryIndices)
 
  822        secondaryIndices.insert(index ^ size);
 
  825    return secondaryIndices;
 
 
  834                  "No RU of type " << ruType << 
" is contained in a " << width << 
" MHz channel");
 
  836                  "The given width (" << width << 
" MHz) exceeds the operational width (" 
  844                      "26-tone RU with index 19 is only present in channels of at least 80 MHz");
 
  847        auto indices = std::get<HeRu::RuSpec>(ru).GetPrimary80MHz()
 
  850        indices.erase(indices.begin());
 
  851        indices.erase(std::prev(indices.end()));
 
  862            ruPhyIndex -= (ruPhyIndex - 19) / 37;
 
  866    uint8_t n20MHzChannels; 
 
  892    auto nRusInCoveringChannel =
 
  897    std::size_t indexOfCoveringChannelInGivenWidth = (ruPhyIndex - 1) / nRusInCoveringChannel;
 
  901    NS_ASSERT(indexOfCoveringChannelInGivenWidth < 16); 
 
  902    std::set<uint8_t> indices({
static_cast<uint8_t
>(indexOfCoveringChannelInGivenWidth)});
 
  904    while (n20MHzChannels > 1)
 
  906        std::set<uint8_t> updatedIndices;
 
  907        for (
const auto& idx : indices)
 
  909            updatedIndices.insert(idx * 2);
 
  910            updatedIndices.insert(idx * 2 + 1);
 
  912        indices.swap(updatedIndices);
 
  921        std::set<uint8_t> updatedIndices;
 
  922        for (
const auto& idx : indices)
 
  924            updatedIndices.insert(idx + offset);
 
  926        indices.swap(updatedIndices);
 
 
  947    return !(*
this == other);
 
 
  955        const auto numSegments = channel.GetNSegments();
 
  956        for (std::size_t segmentId = 0; segmentId < numSegments; ++segmentId)
 
  960                os << 
"segment " << segmentId << 
" ";
 
  962            os << 
"channel " << +channel.GetNumber() << 
" frequency " << channel.GetFrequency()
 
  963               << 
" width " << channel.GetWidth() << 
" band " << channel.GetPhyBand();
 
  964            if ((segmentId == 0) && (
static_cast<uint16_t
>(channel.GetTotalWidth()) % 20 == 0))
 
  966                os << 
" primary20 " << +channel.GetPrimaryChannelIndex(
MHz_u{20});
 
  968            if (segmentId < numSegments - 1)
 
  976        os << 
"channel not set";
 
 
Class that keeps track of all information about the current PHY operating channel.
 
MHz_u GetTotalWidth() const
Return the width of the whole operating channel.
 
bool IsSet() const
Return true if a valid channel has been set, false otherwise.
 
std::set< ConstIterator, Compare > ConstIteratorSet
Typedef for a set of const iterator pointing to the segments of a channel.
 
uint8_t GetNumber(std::size_t segment=0) const
Return the channel number for a given frequency segment.
 
bool operator==(const WifiPhyOperatingChannel &other) const
Check if the given WifiPhyOperatingChannel is equivalent.
 
WifiPhyOperatingChannel()
Create an uninitialized PHY operating channel.
 
WifiChannelWidthType GetWidthType() const
Return the width type of the operating channel.
 
MHz_u GetSecondaryChannelCenterFrequency(MHz_u secondaryChannelWidth) const
Get the center frequency of the secondary channel of the given width.
 
static const std::set< FrequencyChannelInfo > m_frequencyChannels
Available frequency channels.
 
std::set< FrequencyChannelInfo >::const_iterator ConstIterator
Typedef for a const iterator pointing to a channel in the set of available channels.
 
static const std::set< FrequencyChannelInfo > & GetFrequencyChannels()
Return a reference to the set of all available frequency channels.
 
bool operator!=(const WifiPhyOperatingChannel &other) const
Check if the given WifiPhyOperatingChannel is different.
 
std::set< uint8_t > GetAll20MHzChannelIndicesInSecondary(MHz_u width) const
Get the channel indices of all the 20 MHz channels included in the secondary channel of the given wid...
 
bool IsDsss() const
Return whether the operating channel is a DSSS channel.
 
void SetPrimary20Index(uint8_t index)
Set the index of the primary 20 MHz channel (0 indicates the 20 MHz subchannel with the lowest center...
 
static uint8_t GetDefaultChannelNumber(MHz_u width, WifiStandard standard, WifiPhyBand band, std::optional< uint8_t > previousChannelNumber=std::nullopt)
Get the default channel number for a given segment of the given width and for the given standard and ...
 
uint8_t GetSecondarySegmentIndex(MHz_u secondaryChannelWidth) const
Get the index of the segment that contains a given secondary channel.
 
std::set< uint8_t > GetAll20MHzChannelIndicesInPrimary(MHz_u width) const
Get the channel indices of all the 20 MHz channels included in the primary channel of the given width...
 
uint8_t GetSecondaryChannelIndex(MHz_u secondaryChannelWidth) const
If the operating channel width is made of a multiple of 20 MHz, return the index of the secondary cha...
 
std::size_t GetNSegments() const
Get the number of frequency segments in the operating channel.
 
void Set(const std::vector< FrequencyChannelInfo > &segments, WifiStandard standard)
Set the channel according to the specified parameters if a unique frequency channel matches the speci...
 
void SetDefault(MHz_u width, WifiStandard standard, WifiPhyBand band)
Set the default channel of the given width and for the given standard and band.
 
ConstIteratorSet m_channelIts
const iterators pointing to the configured frequency channel
 
MHz_u GetWidth(std::size_t segment=0) const
Return the channel width for a given frequency segment.
 
uint8_t GetPrimaryChannelIndex(MHz_u primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
 
bool Is80211p() const
Return whether the operating channel is an 802.11p channel.
 
MHz_u GetPrimaryChannelCenterFrequency(MHz_u primaryChannelWidth) const
Get the center frequency of the primary channel of the given width.
 
std::vector< uint8_t > GetNumbers() const
Return the channel number per segment.
 
std::vector< MHz_u > GetFrequencies() const
Return the center frequency per segment.
 
bool IsOfdm() const
Return whether the operating channel is an OFDM channel.
 
MHz_u GetFrequency(std::size_t segment=0) const
Return the center frequency for a given frequency segment.
 
static ConstIterator FindFirst(uint8_t number, MHz_u frequency, MHz_u width, WifiStandard standard, WifiPhyBand band, ConstIterator start=GetFrequencyChannels().begin())
Find the first frequency segment matching the specified parameters.
 
uint8_t m_primary20Index
index of the primary20 channel (0 indicates the 20 MHz subchannel with the lowest center frequency)
 
std::vector< MHz_u > GetWidths() const
Return the channel width per segment.
 
uint8_t GetPrimarySegmentIndex(MHz_u primaryChannelWidth) const
Get the index of the segment that contains a given primary channel.
 
WifiPhyBand GetPhyBand() const
Return the PHY band of the operating channel.
 
WifiPhyOperatingChannel GetPrimaryChannel(MHz_u primaryChannelWidth) const
Get a WifiPhyOperatingChannel object corresponding to the primary channel of the given width.
 
virtual ~WifiPhyOperatingChannel()
 
uint8_t GetPrimaryChannelNumber(MHz_u primaryChannelWidth, WifiStandard standard) const
Get channel number of the primary channel.
 
std::set< uint8_t > Get20MHzIndicesCoveringRu(WifiRu::RuSpec ru, MHz_u width) const
Get the channel indices of the minimum subset of 20 MHz channels containing the given RU.
 
static std::size_t GetNRus(MHz_u bw, RuType ruType, WifiModulationClass mc)
Get the number of distinct RUs of the given type (number of tones) available in a PPDU of the given b...
 
std::variant< HeRu::RuSpec, EhtRu::RuSpec > RuSpec
variant of the RU specification
 
static bool IsHe(RuSpec ru)
Get whether a given RU variant is a HE RU.
 
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
 
static RuType GetRuType(RuSpec ru)
Get the type of a given RU.
 
static std::size_t GetPhyIndex(RuSpec ru, MHz_u bw, uint8_t p20Index)
Get the RU PHY index.
 
static std::size_t GetIndex(RuSpec ru)
Get the index of a given 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_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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
 
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
 
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
 
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
 
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
 
WifiPhyBand
Identifies the PHY band.
 
WifiChannelWidthType
Enumeration of the possible channel widths.
 
@ WIFI_STANDARD_UNSPECIFIED
 
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
 
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
 
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
 
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
 
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36).
 
@ WIFI_MOD_CLASS_HE
HE (Clause 27).
 
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.
 
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
 
MHz_u GetMaximumChannelWidth(WifiModulationClass modulation)
Get the maximum channel width allowed for the given modulation class.
 
WifiModulationClass GetModulationClassForStandard(WifiStandard standard)
Return the modulation class corresponding to a given standard.
 
const std::map< WifiStandard, std::list< WifiPhyBand > > wifiStandards
map a given standard configured by the user to the allowed PHY bands
 
FrequencyChannelType GetFrequencyChannelType(WifiStandard standard)
Get the type of the frequency channel for the given standard.
 
std::ostream & operator<<(std::ostream &os, const PairObject &obj)
Stream insertion operator.
 
A structure containing the information about a frequency channel.
 
WifiPhyBand band
the PHY band
 
uint8_t number
the channel number
 
MHz_u width
the channel width
 
MHz_u frequency
the center frequency
 
bool operator()(const ConstIterator &a, const ConstIterator &b) const
Functional operator for sorting the frequency segments.
 
Declaration of the following enums: