A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-phy-operating-channel.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Stefano Avallone <stavallo@unina.it>
7 * Sébastien Deronne <sebastien.deronne@gmail.com>
8 */
9
11
12#include "wifi-phy-common.h"
13
14#include "ns3/assert.h"
15#include "ns3/log.h"
16
17#include <algorithm>
18#include <numeric>
19#include <sstream>
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("WifiPhyOperatingChannel");
25
26const std::set<FrequencyChannelInfo> WifiPhyOperatingChannel::m_frequencyChannels = {{
27 // 2.4 GHz channels
28 // 802.11b uses width of 22, while OFDM modes use width of 20
55 // Only defined for 802.11b
57 // 40 MHz channels
67
68 // Now the 5 GHz channels used for 802.11a/n/ac/ax/be
69 // 20 MHz channels
99 // 40 MHz channels
114 // 80 MHz channels
122 // 160 MHz channels
126
127 // 802.11p 10 MHz channels at the 5.855-5.925 band
135
136 // 802.11p 5 MHz channels at the 5.855-5.925 band (for simplification, we consider the same
137 // center frequencies as the 10 MHz channels)
145
146 // Now the 6 GHz channels for 802.11ax/be
147 // 20 MHz channels
207 // 40 MHz channels
237 // 80 MHz channels
252 // 160 MHz channels
260}};
261
262std::ostream&
263operator<<(std::ostream& os, const FrequencyChannelInfo& info)
264{
265 os << "{" << +info.number << " " << info.frequency << " " << info.width << " " << info.band
266 << "}";
267 return os;
268}
269
270bool
272 const ConstIterator& second) const
273{
274 return first->frequency < second->frequency;
275}
276
281
286
288 : m_channelIts(channelIts),
289 m_primary20Index(0)
290{
291 NS_LOG_FUNCTION(this);
292 NS_ASSERT_MSG(channelIts.size() <= 2,
293 "Operating channel does not support more than 2 segments");
294}
295
300
301bool
303{
304 return !m_channelIts.empty();
305}
306
307void
308WifiPhyOperatingChannel::Set(const std::vector<FrequencyChannelInfo>& segments,
309 WifiStandard standard)
310{
311 std::stringstream ss;
312 for (const auto& segment : segments)
313 {
314 ss << segment;
315 }
316 NS_LOG_FUNCTION(this << ss.str() << standard);
317
318 NS_ASSERT_MSG(!segments.empty(), "At least one frequency segment has to be provided");
319
320 ConstIteratorSet channelIts{};
321 for (const auto& segment : segments)
322 {
323 if (const auto channelIt =
324 FindFirst(segment.number, segment.frequency, segment.width, standard, segment.band);
325 channelIt != m_frequencyChannels.cend() &&
326 FindFirst(segment.number,
327 segment.frequency,
328 segment.width,
329 standard,
330 segment.band,
331 std::next(channelIt)) == m_frequencyChannels.cend())
332 {
333 // a unique channel matches the specified criteria
334 channelIts.insert(channelIt);
335 }
336 }
337
338 if (channelIts.size() != segments.size())
339 {
340 // if a unique channel was not found, throw an exception (mainly for unit testing this code)
341 throw std::runtime_error(
342 "WifiPhyOperatingChannel: No unique channel found given the specified criteria");
343 }
344
345 auto it = channelIts.begin();
346 for (std::size_t segment = 0; segment < (channelIts.size() - 1); ++segment)
347 {
348 const auto freq = (*it)->frequency;
349 const auto width = (*it)->width;
350 const auto band = (*it)->band;
351 const auto maxFreq = freq + (width / 2);
352 ++it;
353 const auto nextFreq = (*it)->frequency;
354 const auto nextWidth = (*it)->width;
355 const auto nextBand = (*it)->band;
356 const auto nextMinFreq = nextFreq - (nextWidth / 2);
357 if (maxFreq >= nextMinFreq)
358 {
359 throw std::runtime_error(
360 "WifiPhyOperatingChannel is invalid: segments cannot be adjacent nor overlap");
361 }
362 if (band != nextBand)
363 {
364 throw std::runtime_error("WifiPhyOperatingChannel is invalid: all segments shall "
365 "belong to the same band");
366 }
367 }
368
369 if ((channelIts.size() > 2) ||
370 ((channelIts.size() == 2) &&
371 !std::all_of(channelIts.cbegin(), channelIts.cend(), [](const auto& channel) {
372 return channel->width == 80;
373 })))
374 {
375 throw std::runtime_error("WifiPhyOperatingChannel is invalid: only 80+80MHz is "
376 "expected as non-contiguous channel");
377 }
378
379 m_channelIts = channelIts;
381}
382
383void
385{
386 NS_LOG_FUNCTION(this << width << standard << band);
387 Set({{GetDefaultChannelNumber(width, standard, band), 0, width, band}}, standard);
388}
389
390uint8_t
392 MHz_u width,
393 WifiStandard standard,
394 WifiPhyBand band,
395 std::optional<uint8_t> previousChannelNumber /* = std::nullopt */)
396{
397 auto start = m_frequencyChannels.begin();
398 auto prevSegmentChannelIt = m_frequencyChannels.end();
399 if (previousChannelNumber)
400 {
401 prevSegmentChannelIt = FindFirst(*previousChannelNumber, 0, width, standard, band, start);
402 if (prevSegmentChannelIt != m_frequencyChannels.end())
403 {
404 start = std::next(prevSegmentChannelIt);
405 }
406 }
407 auto channelIt = FindFirst(0, 0, width, standard, band, start);
408 if (prevSegmentChannelIt != m_frequencyChannels.end() && channelIt != m_frequencyChannels.end())
409 {
410 const auto prevFreq = prevSegmentChannelIt->frequency;
411 const auto prevWidth = prevSegmentChannelIt->width;
412 const auto prevMaxFreq = prevFreq + (prevWidth / 2);
413 const auto nextFreq = channelIt->frequency;
414 const auto nextWidth = channelIt->width;
415 const auto nextMinFreq = nextFreq - (nextWidth / 2);
416 if (prevMaxFreq <= nextMinFreq)
417 {
418 // segments are contiguous to each others, find next segment to make sure they are
419 // not contiguous
420 channelIt = FindFirst(0, 0, width, standard, band, std::next(channelIt));
421 }
422 }
423 if (channelIt != m_frequencyChannels.end())
424 {
425 // a channel matches the specified criteria
426 return channelIt->number;
427 }
428
429 // if a default channel was not found, throw an exception (mainly for unit testing this code)
430 throw std::runtime_error("WifiPhyOperatingChannel: No default channel found of the given width "
431 "and for the given PHY standard and band");
432}
433
436 MHz_u frequency,
437 MHz_u width,
438 WifiStandard standard,
439 WifiPhyBand band,
440 ConstIterator start)
441{
442 // lambda used to match channels against the specified criteria
443 auto predicate = [&](const FrequencyChannelInfo& channel) {
444 if (number != 0 && channel.number != number)
445 {
446 return false;
447 }
448 if (frequency != 0 && channel.frequency != frequency)
449 {
450 return false;
451 }
452 if (width != 0 && channel.width != width)
453 {
454 return false;
455 }
456 if (standard != WIFI_STANDARD_UNSPECIFIED &&
457 channel.type != GetFrequencyChannelType(standard))
458 {
459 return false;
460 }
461 if (band != WIFI_PHY_BAND_UNSPECIFIED && channel.band != band)
462 {
463 return false;
464 }
465 return true;
466 };
467
468 // Do not search for a channel matching the specified criteria if the given PHY band
469 // is not allowed for the given standard (if any) or the given channel width is not
470 // allowed for the given standard (if any)
471 if (const auto standardIt = wifiStandards.find(standard);
472 standardIt != wifiStandards.cend() &&
473 (std::find(standardIt->second.cbegin(), standardIt->second.cend(), band) ==
474 standardIt->second.cend() ||
476 {
477 return m_frequencyChannels.cend();
478 }
479
480 return std::find_if(start, m_frequencyChannels.cend(), predicate);
481}
482
483uint8_t
484WifiPhyOperatingChannel::GetNumber(std::size_t segment /* = 0 */) const
485{
486 NS_ASSERT(IsSet());
487 return (*std::next(m_channelIts.begin(), segment))->number;
488}
489
490MHz_u
491WifiPhyOperatingChannel::GetFrequency(std::size_t segment /* = 0 */) const
492{
493 NS_ASSERT(IsSet());
494 return (*std::next(m_channelIts.begin(), segment))->frequency;
495}
496
497MHz_u
498WifiPhyOperatingChannel::GetWidth(std::size_t /* segment = 0 */) const
499{
500 NS_ASSERT(IsSet());
501 // Current specs only allow all segments to be the same width
502 return (*m_channelIts.cbegin())->width;
503}
504
507{
508 NS_ASSERT(IsSet());
509 // Current specs only allow all segments to be the same band
510 return (*m_channelIts.cbegin())->band;
511}
512
513bool
515{
516 NS_ASSERT(IsSet());
517 return ((*m_channelIts.cbegin())->type == FrequencyChannelType::OFDM);
518}
519
520bool
522{
523 NS_ASSERT(IsSet());
524 return ((*m_channelIts.cbegin())->type == FrequencyChannelType::DSSS);
525}
526
527bool
529{
530 NS_ASSERT(IsSet());
531 return ((*m_channelIts.cbegin())->type == FrequencyChannelType::CH_80211P);
532}
533
534std::vector<uint8_t>
536{
537 NS_ASSERT(IsSet());
538 std::vector<uint8_t> channelNumbers{};
539 std::transform(m_channelIts.cbegin(),
540 m_channelIts.cend(),
541 std::back_inserter(channelNumbers),
542 [](const auto& channel) { return channel->number; });
543 return channelNumbers;
544}
545
546std::vector<MHz_u>
548{
549 NS_ASSERT(IsSet());
550 std::vector<MHz_u> centerFrequencies{};
551 std::transform(m_channelIts.cbegin(),
552 m_channelIts.cend(),
553 std::back_inserter(centerFrequencies),
554 [](const auto& channel) { return channel->frequency; });
555 return centerFrequencies;
556}
557
558std::vector<MHz_u>
560{
561 NS_ASSERT(IsSet());
562 std::vector<MHz_u> channelWidths{};
563 std::transform(m_channelIts.cbegin(),
564 m_channelIts.cend(),
565 std::back_inserter(channelWidths),
566 [](const auto& channel) { return channel->width; });
567 return channelWidths;
568}
569
570MHz_u
572{
573 NS_ASSERT(IsSet());
574 return std::accumulate(m_channelIts.cbegin(),
575 m_channelIts.cend(),
576 0,
577 [](MHz_u sum, const auto& channel) { return sum + channel->width; });
578}
579
582{
583 NS_ASSERT(IsSet());
584 switch (static_cast<uint16_t>(GetTotalWidth()))
585 {
586 case 20:
588 case 22:
590 case 5:
592 case 10:
594 case 40:
596 case 80:
598 case 160:
601 case 2160:
603 case 0:
604 default:
606 }
607}
608
609uint8_t
611{
612 if (static_cast<uint16_t>(primaryChannelWidth) % 20 != 0)
613 {
614 NS_LOG_DEBUG("The operating channel width is not a multiple of 20 MHz; return 0");
615 return 0;
616 }
617
618 NS_ASSERT(primaryChannelWidth <= GetTotalWidth());
619
620 // the index of primary40 is half the index of primary20; the index of
621 // primary80 is half the index of primary40, ...
622 MHz_u width = 20;
623 uint8_t index = m_primary20Index;
624
625 while (width < primaryChannelWidth)
626 {
627 index /= 2;
628 width *= 2;
629 }
630 return index;
631}
632
633uint8_t
635{
636 const uint8_t primaryIndex = GetPrimaryChannelIndex(secondaryChannelWidth);
637 const uint8_t secondaryIndex =
638 (primaryIndex % 2 == 0) ? (primaryIndex + 1) : (primaryIndex - 1);
639 return secondaryIndex;
640}
641
642void
644{
645 NS_LOG_FUNCTION(this << +index);
646
647 NS_ABORT_MSG_IF(index > 0 && index >= GetTotalWidth() / 20, "Primary20 index out of range");
648 m_primary20Index = index;
649}
650
651uint8_t
653{
654 if (m_channelIts.size() < 2)
655 {
656 return 0;
657 }
658 // Note: this function assumes no more than 2 segments are used
659 const auto numIndices = GetTotalWidth() / primaryChannelWidth;
660 const auto primaryIndex = GetPrimaryChannelIndex(primaryChannelWidth);
661 return (primaryIndex >= (numIndices / 2)) ? 1 : 0;
662}
663
664uint8_t
666{
667 NS_ABORT_MSG_IF(primaryChannelWidth > GetWidth(),
668 "Primary channel width cannot be larger than the width of a frequency segment");
669 if (m_channelIts.size() < 2)
670 {
671 return 0;
672 }
673 // Note: this function assumes no more than 2 segments are used
674 const auto numIndices = GetTotalWidth() / primaryChannelWidth;
675 const auto secondaryIndex = GetSecondaryChannelIndex(primaryChannelWidth);
676 return (secondaryIndex >= (numIndices / 2)) ? 1 : 0;
677}
678
679MHz_u
681{
682 const auto segmentIndex = GetPrimarySegmentIndex(primaryChannelWidth);
683 // we assume here that all segments have the same width
684 const auto segmentWidth = GetWidth(segmentIndex);
685 // segmentOffset has to be an (unsigned) integer to ensure correct calculation
686 const uint8_t segmentOffset = (segmentIndex * (segmentWidth / primaryChannelWidth));
687 return GetFrequency(segmentIndex) - segmentWidth / 2. +
688 (GetPrimaryChannelIndex(primaryChannelWidth) - segmentOffset + 0.5) *
689 primaryChannelWidth;
690}
691
692MHz_u
694{
695 const auto segmentIndex = GetSecondarySegmentIndex(secondaryChannelWidth);
696 // we assume here that all segments have the same width
697 const auto segmentWidth = GetWidth(segmentIndex);
698 // segmentOffset has to be an (unsigned) integer to ensure correct calculation
699 const uint8_t segmentOffset = (segmentIndex * (segmentWidth / secondaryChannelWidth));
700 return GetFrequency(segmentIndex) - segmentWidth / 2. +
701 (GetSecondaryChannelIndex(secondaryChannelWidth) - segmentOffset + 0.5) *
702 secondaryChannelWidth;
703}
704
705uint8_t
707 WifiStandard standard) const
708{
709 NS_ABORT_MSG_IF(primaryChannelWidth > GetWidth(),
710 "Primary channel width cannot be larger than the width of a frequency segment");
711 auto frequency = GetPrimaryChannelCenterFrequency(primaryChannelWidth);
712 NS_ASSERT_MSG(IsSet(), "No channel set");
713 auto primaryChanIt = FindFirst(0, frequency, primaryChannelWidth, standard, GetPhyBand());
714 NS_ASSERT_MSG(primaryChanIt != m_frequencyChannels.end(), "Primary channel number not found");
715 return primaryChanIt->number;
716}
717
720{
721 NS_ASSERT_MSG(IsSet(), "No channel set");
722 NS_ASSERT_MSG(primaryChannelWidth <= GetTotalWidth(),
723 "Requested primary channel width ("
724 << primaryChannelWidth << " MHz) exceeds total width (" << GetTotalWidth()
725 << " MHz)");
726
727 if (primaryChannelWidth == GetTotalWidth())
728 {
729 return *this;
730 }
731
732 const auto frequency = GetPrimaryChannelCenterFrequency(primaryChannelWidth);
733 auto primaryChanIt =
734 FindFirst(0, frequency, primaryChannelWidth, WIFI_STANDARD_UNSPECIFIED, GetPhyBand());
735 NS_ABORT_MSG_IF(primaryChanIt == m_frequencyChannels.end(), "Primary channel number not found");
736
737 WifiPhyOperatingChannel primaryChannel(primaryChanIt);
738
739 const auto primaryIndex = m_primary20Index - (GetPrimaryChannelIndex(primaryChannelWidth) *
740 (primaryChannelWidth / 20));
741 primaryChannel.SetPrimary20Index(primaryIndex);
742
743 return primaryChannel;
744}
745
746std::set<uint8_t>
748{
749 if (width > GetTotalWidth())
750 {
751 // a primary channel of the given width does not exist
752 return {};
753 }
754
755 MHz_u currWidth = 20;
756 std::set<uint8_t> indices;
757 indices.insert(m_primary20Index);
758
759 while (currWidth < width)
760 {
761 indices.merge(GetAll20MHzChannelIndicesInSecondary(indices));
762 currWidth *= 2;
763 }
764
765 return indices;
766}
767
768std::set<uint8_t>
773
774std::set<uint8_t>
776 const std::set<uint8_t>& primaryIndices) const
777{
778 if (primaryIndices.empty() || GetTotalWidth() == 20)
779 {
780 return {};
781 }
782
783 uint8_t size = 1;
784 MHz_u primaryWidth = 20;
785
786 // find the width of the primary channel corresponding to the size of the given set
787 while (size != primaryIndices.size())
788 {
789 size <<= 1;
790 primaryWidth *= 2;
791
792 if (primaryWidth >= GetTotalWidth())
793 {
794 // the width of the primary channel resulting from the given indices
795 // exceeds the width of the operating channel
796 return {};
797 }
798 }
799
800 std::set<uint8_t> secondaryIndices;
801 for (const auto& index : primaryIndices)
802 {
803 secondaryIndices.insert(index ^ size);
804 }
805
806 return secondaryIndices;
807}
808
809std::set<uint8_t>
811{
812 auto ruType = ru.GetRuType();
813
814 NS_ASSERT_MSG(HeRu::GetBandwidth(ruType) <= width,
815 "No RU of type " << ruType << " is contained in a " << width << " MHz channel");
816 NS_ASSERT_MSG(width <= GetTotalWidth(),
817 "The given width (" << width << " MHz) exceeds the operational width ("
818 << GetTotalWidth() << ")");
819
820 // trivial case: 2x996-tone RU
821 if (ruType == HeRu::RU_2x996_TONE)
822 {
823 return {0, 1, 2, 3, 4, 5, 6, 7};
824 }
825
826 // handle first the special case of center 26-tone RUs
827 if (ruType == HeRu::RU_26_TONE && ru.GetIndex() == 19)
828 {
829 NS_ASSERT_MSG(width >= 80,
830 "26-tone RU with index 19 is only present in channels of at least 80 MHz");
831 // the center 26-tone RU in an 80 MHz channel is not fully covered by
832 // any 20 MHz channel, but by the two central 20 MHz channels in the 80 MHz channel
835 indices.erase(indices.begin());
836 indices.erase(std::prev(indices.end()));
837 return indices;
838 }
839
840 auto ruIndex = ru.GetIndex();
841
842 if (ruType == HeRu::RU_26_TONE && ruIndex > 19)
843 {
844 // "ignore" the center 26-tone RU in an 80 MHz channel
845 ruIndex--;
846 }
847
848 // if the RU refers to a 160 MHz channel, we have to update the RU index (which
849 // refers to an 80 MHz channel) if the RU is not in the lower 80 MHz channel
850 if (width == 160)
851 {
852 bool primary80IsLower80 = (m_primary20Index < 4);
853 if (primary80IsLower80 != ru.GetPrimary80MHz())
854 {
855 auto nRusIn80MHz = HeRu::GetNRus(80, ruType);
856 // "ignore" the center 26-tone RU in an 80 MHz channel
857 if (ruType == HeRu::RU_26_TONE)
858 {
859 nRusIn80MHz--;
860 }
861 ruIndex += nRusIn80MHz;
862 }
863 }
864
865 uint8_t n20MHzChannels; // number of 20 MHz channels in the channel covering the RU
866
867 switch (ruType)
868 {
869 case HeRu::RU_26_TONE:
870 case HeRu::RU_52_TONE:
873 n20MHzChannels = 1;
874 break;
876 n20MHzChannels = 2;
877 break;
879 n20MHzChannels = 4;
880 break;
881 default:
882 NS_ABORT_MSG("Unhandled RU type: " << ruType);
883 }
884
885 auto nRusInCoveringChannel = HeRu::GetNRus(n20MHzChannels * 20, ruType);
886 // compute the index (starting at 0) of the covering channel within the given width
887 std::size_t indexOfCoveringChannelInGivenWidth = (ruIndex - 1) / nRusInCoveringChannel;
888
889 // expand the index of the covering channel in the indices of its constituent
890 // 20 MHz channels (within the given width)
891 NS_ASSERT(indexOfCoveringChannelInGivenWidth < 8); // max number of 20 MHz channels
892 std::set<uint8_t> indices({static_cast<uint8_t>(indexOfCoveringChannelInGivenWidth)});
893
894 while (n20MHzChannels > 1)
895 {
896 std::set<uint8_t> updatedIndices;
897 for (const auto& idx : indices)
898 {
899 updatedIndices.insert(idx * 2);
900 updatedIndices.insert(idx * 2 + 1);
901 }
902 indices.swap(updatedIndices);
903 n20MHzChannels /= 2;
904 }
905
906 // finally, add the appropriate offset if width is less than the operational channel width
907 auto offset = GetPrimaryChannelIndex(width) * width / 20;
908
909 if (offset > 0)
910 {
911 std::set<uint8_t> updatedIndices;
912 for (const auto& idx : indices)
913 {
914 updatedIndices.insert(idx + offset);
915 }
916 indices.swap(updatedIndices);
917 }
918
919 return indices;
920}
921
922std::size_t
924{
925 return m_channelIts.size();
926}
927
928bool
933
934bool
936{
937 return !(*this == other);
938}
939
940std::ostream&
941operator<<(std::ostream& os, const WifiPhyOperatingChannel& channel)
942{
943 if (channel.IsSet())
944 {
945 const auto numSegments = channel.GetNSegments();
946 for (std::size_t segmentId = 0; segmentId < numSegments; ++segmentId)
947 {
948 if (numSegments > 1)
949 {
950 os << "segment " << segmentId << " ";
951 }
952 os << "channel " << +channel.GetNumber() << " frequency " << channel.GetFrequency()
953 << " width " << channel.GetWidth() << " band " << channel.GetPhyBand();
954 if ((segmentId == 0) && (static_cast<uint16_t>(channel.GetTotalWidth()) % 20 == 0))
955 {
956 os << " primary20 " << +channel.GetPrimaryChannelIndex(20);
957 }
958 if (segmentId < numSegments - 1)
959 {
960 os << " ";
961 }
962 }
963 }
964 else
965 {
966 os << "channel not set";
967 }
968 return os;
969}
970
971} // namespace ns3
RU Specification.
Definition he-ru.h:57
std::size_t GetIndex() const
Get the RU index.
Definition he-ru.cc:454
RuType GetRuType() const
Get the RU type.
Definition he-ru.cc:447
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
Definition he-ru.cc:461
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition he-ru.cc:756
static std::size_t GetNRus(MHz_u bw, RuType ruType)
Get the number of distinct RUs of the given type (number of tones) available in a HE PPDU of the give...
Definition he-ru.cc:484
@ RU_26_TONE
Definition he-ru.h:33
@ RU_484_TONE
Definition he-ru.h:37
@ RU_996_TONE
Definition he-ru.h:38
@ RU_106_TONE
Definition he-ru.h:35
@ RU_52_TONE
Definition he-ru.h:34
@ RU_242_TONE
Definition he-ru.h:36
@ RU_2x996_TONE
Definition he-ru.h:39
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.
std::set< uint8_t > Get20MHzIndicesCoveringRu(HeRu::RuSpec ru, MHz_u width) const
Get the channel indices of the minimum subset of 20 MHz channels containing the given RU.
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.
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=m_frequencyChannels.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.
uint8_t GetPrimaryChannelNumber(MHz_u primaryChannelWidth, WifiStandard standard) const
Get channel number of the primary channel.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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.
Definition wifi-types.h:22
@ 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.
Definition first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
double MHz_u
MHz weak type.
Definition wifi-units.h:31
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.
A structure containing the information about a frequency channel.
uint8_t number
the channel number
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: