15#include "ns3/assert.h"
289 : m_channelIts(channelIts),
294 "Operating channel does not support more than 2 segments");
312 std::stringstream ss;
313 for (
const auto& segment : segments)
319 NS_ASSERT_MSG(!segments.empty(),
"At least one frequency segment has to be provided");
322 for (
const auto& segment : segments)
324 if (
const auto channelIt =
325 FindFirst(segment.number, segment.frequency, segment.width, standard, segment.band);
335 channelIts.insert(channelIt);
339 if (channelIts.size() != segments.size())
342 throw std::runtime_error(
343 "WifiPhyOperatingChannel: No unique channel found given the specified criteria");
346 auto it = channelIts.begin();
347 for (std::size_t segment = 0; segment < (channelIts.size() - 1); ++segment)
349 const auto freq = (*it)->frequency;
350 const auto width = (*it)->width;
351 const auto band = (*it)->band;
352 const auto maxFreq = freq + (width / 2);
354 const auto nextFreq = (*it)->frequency;
355 const auto nextWidth = (*it)->width;
356 const auto nextBand = (*it)->band;
357 const auto nextMinFreq = nextFreq - (nextWidth / 2);
358 if (maxFreq >= nextMinFreq)
360 throw std::runtime_error(
361 "WifiPhyOperatingChannel is invalid: segments cannot be adjacent nor overlap");
363 if (band != nextBand)
365 throw std::runtime_error(
"WifiPhyOperatingChannel is invalid: all segments shall "
366 "belong to the same band");
370 if ((channelIts.size() > 2) ||
371 ((channelIts.size() == 2) &&
372 !std::all_of(channelIts.cbegin(), channelIts.cend(), [](
const auto& channel) {
373 return channel->width == MHz_u{80};
376 throw std::runtime_error(
"WifiPhyOperatingChannel is invalid: only 80+80MHz is "
377 "expected as non-contiguous channel");
380 m_channelIts = channelIts;
381 m_primary20Index = 0;
388 Set({{GetDefaultChannelNumber(width, standard, band),
MHz_u{0}, width, band}}, standard);
392WifiPhyOperatingChannel::GetDefaultChannelNumber(
396 std::optional<uint8_t> previousChannelNumber )
398 auto start = m_frequencyChannels.begin();
399 auto prevSegmentChannelIt = m_frequencyChannels.end();
400 if (previousChannelNumber)
402 prevSegmentChannelIt =
403 FindFirst(*previousChannelNumber,
MHz_u{0}, width, standard, band, start);
404 if (prevSegmentChannelIt != m_frequencyChannels.end())
406 start = std::next(prevSegmentChannelIt);
409 auto channelIt = FindFirst(0,
MHz_u{0}, width, standard, band, start);
410 if (prevSegmentChannelIt != m_frequencyChannels.end() && channelIt != m_frequencyChannels.end())
412 const auto prevFreq = prevSegmentChannelIt->frequency;
413 const auto prevWidth = prevSegmentChannelIt->width;
414 const auto prevMaxFreq = prevFreq + (prevWidth / 2);
415 const auto nextFreq = channelIt->frequency;
416 const auto nextWidth = channelIt->width;
417 const auto nextMinFreq = nextFreq - (nextWidth / 2);
418 if (prevMaxFreq <= nextMinFreq)
422 channelIt = FindFirst(0,
MHz_u{0}, width, standard, band, std::next(channelIt));
425 if (channelIt != m_frequencyChannels.end())
428 return channelIt->number;
432 throw std::runtime_error(
"WifiPhyOperatingChannel: No default channel found of the given width "
433 "and for the given PHY standard and band");
437WifiPhyOperatingChannel::FindFirst(uint8_t number,
446 if (number != 0 && channel.number != number)
450 if (frequency !=
MHz_u{0} && channel.frequency != frequency)
454 if (width !=
MHz_u{0} && channel.width != width)
475 (std::find(standardIt->second.cbegin(), standardIt->second.cend(), band) ==
476 standardIt->second.cend() ||
479 return m_frequencyChannels.cend();
482 return std::find_if(start, m_frequencyChannels.cend(), predicate);
486WifiPhyOperatingChannel::GetNumber(std::size_t segment )
const
489 return (*std::next(m_channelIts.begin(), segment))->number;
493WifiPhyOperatingChannel::GetFrequency(std::size_t segment )
const
496 return (*std::next(m_channelIts.begin(), segment))->frequency;
500WifiPhyOperatingChannel::GetWidth(std::size_t )
const
504 return (*m_channelIts.cbegin())->width;
508WifiPhyOperatingChannel::GetPhyBand()
const
512 return (*m_channelIts.cbegin())->band;
516WifiPhyOperatingChannel::IsOfdm()
const
519 return ((*m_channelIts.cbegin())->type == FrequencyChannelType::OFDM);
523WifiPhyOperatingChannel::IsDsss()
const
526 return ((*m_channelIts.cbegin())->type == FrequencyChannelType::DSSS);
530WifiPhyOperatingChannel::Is80211p()
const
533 return ((*m_channelIts.cbegin())->type == FrequencyChannelType::CH_80211P);
537WifiPhyOperatingChannel::GetNumbers()
const
540 std::vector<uint8_t> channelNumbers{};
541 std::transform(m_channelIts.cbegin(),
543 std::back_inserter(channelNumbers),
544 [](
const auto& channel) { return channel->number; });
545 return channelNumbers;
549WifiPhyOperatingChannel::GetFrequencies()
const
552 std::vector<MHz_u> centerFrequencies{};
553 std::transform(m_channelIts.cbegin(),
555 std::back_inserter(centerFrequencies),
556 [](
const auto& channel) { return channel->frequency; });
557 return centerFrequencies;
561WifiPhyOperatingChannel::GetWidths()
const
564 std::vector<MHz_u> channelWidths{};
565 std::transform(m_channelIts.cbegin(),
567 std::back_inserter(channelWidths),
568 [](
const auto& channel) { return channel->width; });
569 return channelWidths;
573WifiPhyOperatingChannel::GetTotalWidth()
const
576 return std::accumulate(m_channelIts.cbegin(),
579 [](
MHz_u sum,
const auto& channel) { return sum + channel->width; });
583WifiPhyOperatingChannel::GetWidthType()
const
586 switch (
static_cast<uint16_t
>(GetTotalWidth()))
589 return WifiChannelWidthType::CW_20MHZ;
591 return WifiChannelWidthType::CW_22MHZ;
593 return WifiChannelWidthType::CW_5MHZ;
595 return WifiChannelWidthType::CW_10MHZ;
597 return WifiChannelWidthType::CW_40MHZ;
599 return WifiChannelWidthType::CW_80MHZ;
601 return (m_channelIts.size() == 2) ? WifiChannelWidthType::CW_80_PLUS_80MHZ
602 : WifiChannelWidthType::CW_160MHZ;
604 return WifiChannelWidthType::CW_2160MHZ;
607 return WifiChannelWidthType::UNKNOWN;
612WifiPhyOperatingChannel::GetPrimaryChannelIndex(
MHz_u primaryChannelWidth)
const
614 if (
static_cast<uint16_t
>(primaryChannelWidth) % 20 != 0)
616 NS_LOG_DEBUG(
"The operating channel width is not a multiple of 20 MHz; return 0");
620 NS_ASSERT(primaryChannelWidth <= GetTotalWidth());
625 uint8_t index = m_primary20Index;
627 while (width < primaryChannelWidth)
636WifiPhyOperatingChannel::GetSecondaryChannelIndex(
MHz_u secondaryChannelWidth)
const
638 const uint8_t primaryIndex = GetPrimaryChannelIndex(secondaryChannelWidth);
639 const uint8_t secondaryIndex =
640 (primaryIndex % 2 == 0) ? (primaryIndex + 1) : (primaryIndex - 1);
641 return secondaryIndex;
645WifiPhyOperatingChannel::SetPrimary20Index(uint8_t index)
650 "Primary20 index out of range");
651 m_primary20Index = index;
655WifiPhyOperatingChannel::GetPrimarySegmentIndex(
MHz_u primaryChannelWidth)
const
657 if (m_channelIts.size() < 2)
662 const auto numIndices = GetTotalWidth() / primaryChannelWidth;
663 const auto primaryIndex = GetPrimaryChannelIndex(primaryChannelWidth);
664 return (primaryIndex >= (numIndices / 2)) ? 1 : 0;
668WifiPhyOperatingChannel::GetSecondarySegmentIndex(
MHz_u primaryChannelWidth)
const
671 "Primary channel width cannot be larger than the width of a frequency segment");
672 if (m_channelIts.size() < 2)
677 const auto numIndices = GetTotalWidth() / primaryChannelWidth;
678 const auto secondaryIndex = GetSecondaryChannelIndex(primaryChannelWidth);
679 return (secondaryIndex >= (numIndices / 2)) ? 1 : 0;
683WifiPhyOperatingChannel::GetPrimaryChannelCenterFrequency(
MHz_u primaryChannelWidth)
const
685 const auto segmentIndex = GetPrimarySegmentIndex(primaryChannelWidth);
687 const auto segmentWidth = GetWidth(segmentIndex);
689 const uint8_t segmentOffset = (segmentIndex * (segmentWidth / primaryChannelWidth));
690 return GetFrequency(segmentIndex) - segmentWidth / 2. +
691 (GetPrimaryChannelIndex(primaryChannelWidth) - segmentOffset + 0.5) *
696WifiPhyOperatingChannel::GetSecondaryChannelCenterFrequency(
MHz_u secondaryChannelWidth)
const
698 const auto segmentIndex = GetSecondarySegmentIndex(secondaryChannelWidth);
700 const auto segmentWidth = GetWidth(segmentIndex);
702 const uint8_t segmentOffset = (segmentIndex * (segmentWidth / secondaryChannelWidth));
703 return GetFrequency(segmentIndex) - segmentWidth / 2. +
704 (GetSecondaryChannelIndex(secondaryChannelWidth) - segmentOffset + 0.5) *
705 secondaryChannelWidth;
709WifiPhyOperatingChannel::GetPrimaryChannelNumber(
MHz_u primaryChannelWidth,
713 "Primary channel width cannot be larger than the width of a frequency segment");
714 auto frequency = GetPrimaryChannelCenterFrequency(primaryChannelWidth);
716 auto primaryChanIt = FindFirst(0, frequency, primaryChannelWidth, standard, GetPhyBand());
717 NS_ASSERT_MSG(primaryChanIt != m_frequencyChannels.end(),
"Primary channel number not found");
718 return primaryChanIt->number;
722WifiPhyOperatingChannel::GetPrimaryChannel(
MHz_u primaryChannelWidth)
const
726 "Requested primary channel width ("
727 << primaryChannelWidth <<
" MHz) exceeds total width (" << GetTotalWidth()
730 if (primaryChannelWidth == GetTotalWidth())
735 const auto frequency = GetPrimaryChannelCenterFrequency(primaryChannelWidth);
738 NS_ABORT_MSG_IF(primaryChanIt == m_frequencyChannels.end(),
"Primary channel number not found");
742 const auto primaryIndex = m_primary20Index - (GetPrimaryChannelIndex(primaryChannelWidth) *
746 return primaryChannel;
750WifiPhyOperatingChannel::GetAll20MHzChannelIndicesInPrimary(
MHz_u width)
const
752 if (width > GetTotalWidth())
759 std::set<uint8_t> indices;
760 indices.insert(m_primary20Index);
762 while (currWidth < width)
764 indices.merge(GetAll20MHzChannelIndicesInSecondary(indices));
772WifiPhyOperatingChannel::GetAll20MHzChannelIndicesInSecondary(
MHz_u width)
const
774 return GetAll20MHzChannelIndicesInSecondary(GetAll20MHzChannelIndicesInPrimary(width));
778WifiPhyOperatingChannel::GetAll20MHzChannelIndicesInSecondary(
779 const std::set<uint8_t>& primaryIndices)
const
781 if (primaryIndices.empty() || GetTotalWidth() ==
MHz_u{20})
787 MHz_u primaryWidth{20};
790 while (size != primaryIndices.size())
795 if (primaryWidth >= GetTotalWidth())
803 std::set<uint8_t> secondaryIndices;
804 for (
const auto& index : primaryIndices)
806 secondaryIndices.insert(index ^ size);
809 return secondaryIndices;
818 "No RU of type " << ruType <<
" is contained in a " << width <<
" MHz channel");
820 "The given width (" << width <<
" MHz) exceeds the operational width ("
821 << GetTotalWidth() <<
")");
824 if (ruType == HeRu::RU_2x996_TONE)
826 return {0, 1, 2, 3, 4, 5, 6, 7};
830 if (ruType == HeRu::RU_26_TONE && ru.
GetIndex() == 19)
833 "26-tone RU with index 19 is only present in channels of at least 80 MHz");
837 : GetAll20MHzChannelIndicesInSecondary(
MHz_u{80});
838 indices.erase(indices.begin());
839 indices.erase(std::prev(indices.end()));
845 if (ruType == HeRu::RU_26_TONE && ruIndex > 19)
853 if (width ==
MHz_u{160})
855 bool primary80IsLower80 = (m_primary20Index < 4);
858 auto nRusIn80MHz = HeRu::GetNRus(
MHz_u{80}, ruType);
860 if (ruType == HeRu::RU_26_TONE)
864 ruIndex += nRusIn80MHz;
868 uint8_t n20MHzChannels;
872 case HeRu::RU_26_TONE:
873 case HeRu::RU_52_TONE:
874 case HeRu::RU_106_TONE:
875 case HeRu::RU_242_TONE:
878 case HeRu::RU_484_TONE:
881 case HeRu::RU_996_TONE:
888 auto nRusInCoveringChannel = HeRu::GetNRus(n20MHzChannels *
MHz_u{20}, ruType);
890 std::size_t indexOfCoveringChannelInGivenWidth = (ruIndex - 1) / nRusInCoveringChannel;
894 NS_ASSERT(indexOfCoveringChannelInGivenWidth < 8);
895 std::set<uint8_t> indices({
static_cast<uint8_t
>(indexOfCoveringChannelInGivenWidth)});
897 while (n20MHzChannels > 1)
899 std::set<uint8_t> updatedIndices;
900 for (
const auto& idx : indices)
902 updatedIndices.insert(idx * 2);
903 updatedIndices.insert(idx * 2 + 1);
905 indices.swap(updatedIndices);
914 std::set<uint8_t> updatedIndices;
915 for (
const auto& idx : indices)
917 updatedIndices.insert(idx + offset);
919 indices.swap(updatedIndices);
926WifiPhyOperatingChannel::GetNSegments()
const
928 return m_channelIts.size();
940 return !(*
this == other);
948 const auto numSegments = channel.GetNSegments();
949 for (std::size_t segmentId = 0; segmentId < numSegments; ++segmentId)
953 os <<
"segment " << segmentId <<
" ";
955 os <<
"channel " << +channel.GetNumber() <<
" frequency " << channel.GetFrequency()
956 <<
" width " << channel.GetWidth() <<
" band " << channel.GetPhyBand();
957 if ((segmentId == 0) && (
static_cast<uint16_t
>(channel.GetTotalWidth()) % 20 == 0))
959 os <<
" primary20 " << +channel.GetPrimaryChannelIndex(
MHz_u{20});
961 if (segmentId < numSegments - 1)
969 os <<
"channel not set";
std::size_t GetIndex() const
Get the RU index.
RuType GetRuType() const
Get the RU type.
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
Class that keeps track of all information about the current PHY 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.
WifiPhyOperatingChannel()
Create an uninitialized PHY operating channel.
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.
void SetPrimary20Index(uint8_t index)
Set the index of the primary 20 MHz channel (0 indicates the 20 MHz subchannel with the lowest center...
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...
ConstIteratorSet m_channelIts
const iterators pointing to the configured frequency channel
static ConstIterator FindFirst(uint8_t number, MHz_u frequency, MHz_u width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first frequency segment matching the specified parameters.
virtual ~WifiPhyOperatingChannel()
#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.
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: