15#include "ns3/address-utils.h"
50 uint8_t operatingClass = 0;
51 uint8_t channelNumber = channel.GetNumber();
54 switch (channel.GetPhyBand())
57 if (channel.GetWidth() ==
MHz_u{20})
61 else if (channel.GetWidth() ==
MHz_u{40})
67 if (channel.GetWidth() ==
MHz_u{20})
69 if (channelNumber == 36 || channelNumber == 40 || channelNumber == 44 ||
74 else if (channelNumber == 52 || channelNumber == 56 || channelNumber == 60 ||
79 else if (channelNumber == 100 || channelNumber == 104 || channelNumber == 108 ||
80 channelNumber == 112 || channelNumber == 116 || channelNumber == 120 ||
81 channelNumber == 124 || channelNumber == 128 || channelNumber == 132 ||
82 channelNumber == 136 || channelNumber == 140 || channelNumber == 144)
86 else if (channelNumber == 149 || channelNumber == 153 || channelNumber == 157 ||
87 channelNumber == 161 || channelNumber == 165 || channelNumber == 169 ||
88 channelNumber == 173 || channelNumber == 177 || channelNumber == 181)
93 else if (channel.GetWidth() ==
MHz_u{40})
95 if (channelNumber == 38 || channelNumber == 46)
99 else if (channelNumber == 54 || channelNumber == 62)
101 operatingClass = 119;
103 else if (channelNumber == 102 || channelNumber == 110 || channelNumber == 118 ||
104 channelNumber == 126 || channelNumber == 134 || channelNumber == 142)
106 operatingClass = 122;
108 else if (channelNumber == 151 || channelNumber == 159 || channelNumber == 167 ||
109 channelNumber == 175)
111 operatingClass = 126;
114 else if (channel.GetWidth() ==
MHz_u{80})
116 if (channelNumber == 42 || channelNumber == 58 || channelNumber == 106 ||
117 channelNumber == 122 || channelNumber == 138 || channelNumber == 155 ||
118 channelNumber == 171)
120 operatingClass = 128;
123 else if (channel.GetWidth() ==
MHz_u{160})
125 if (channelNumber == 50 || channelNumber == 114 || channelNumber == 163)
127 operatingClass = 129;
132 if (channel.GetWidth() ==
MHz_u{20})
134 operatingClass = 131;
136 else if (channel.GetWidth() ==
MHz_u{40})
138 operatingClass = 132;
140 else if (channel.GetWidth() ==
MHz_u{80})
142 operatingClass = 133;
144 else if (channel.GetWidth() ==
MHz_u{160})
146 operatingClass = 134;
148 else if (channel.GetWidth() ==
MHz_u{320})
150 operatingClass = 137;
155 NS_ABORT_MSG(
"The provided channel has an unspecified PHY band");
160 "Operating class not found for channel number "
161 << +channelNumber <<
" width " << channel.GetWidth() <<
" MHz "
162 <<
"band " << channel.GetPhyBand());
165 MHz_u startingFreq{0};
167 switch (channel.GetPhyBand())
170 startingFreq =
MHz_u{2407};
173 startingFreq =
MHz_u{5000};
176 startingFreq =
MHz_u{5950};
180 NS_ABORT_MSG(
"The provided channel has an unspecified PHY band");
184 uint8_t primaryChannelNumber =
185 (channel.GetPrimaryChannelCenterFrequency(
MHz_u{20}) - startingFreq) /
MHz_u{5};
257 MHz_u startingFreq{0};
262 startingFreq =
MHz_u{2407};
265 startingFreq =
MHz_u{5000};
268 startingFreq =
MHz_u{5950};
277 auto primaryChannelCenterFrequency = startingFreq + primaryChannelNumber *
MHz_u{5};
279 uint8_t channelNumber = 0;
285 channel.band == band &&
286 primaryChannelCenterFrequency > (channel.frequency - (width / 2)) &&
287 primaryChannelCenterFrequency < (channel.frequency + (width / 2)))
302 switch (
static_cast<uint16_t
>(width))
305 if (channel.frequency == primaryChannelCenterFrequency)
311 if ((channel.frequency == primaryChannelCenterFrequency +
MHz_u{10}) ||
312 (channel.frequency == primaryChannelCenterFrequency -
MHz_u{10}))
318 NS_ABORT_MSG(
"No channel of width " << width <<
" MHz in the 2.4 GHz band");
324 channelNumber = channel.number;
325 frequency = channel.frequency;
331 NS_ABORT_IF(channelNumber == 0 || frequency == MHz_u{0});
333 WifiPhyOperatingChannel
channel;
336 const auto channelLowestFreq = frequency - width / 2;
337 const auto primaryChannelLowestFreq = primaryChannelCenterFrequency -
MHz_u{10};
344ReducedNeighborReport::GetNTbttInformationFields(std::size_t nbrApInfoId)
const
346 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
347 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size();
351ReducedNeighborReport::AddTbttInformationField(std::size_t nbrApInfoId)
353 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
354 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.emplace_back();
358ReducedNeighborReport::WriteTbttInformationLength(std::size_t nbrApInfoId)
const
360 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
364 auto it = std::next(m_nbrApInfoFields.begin(), nbrApInfoId);
366 if (it->hasBssid && !it->hasShortSsid && !it->hasBssParams && !it->has20MHzPsd &&
371 else if (it->hasBssid && it->hasShortSsid && it->hasBssParams && it->has20MHzPsd &&
378 NS_ABORT_MSG(
"Unsupported TBTT Information field contents");
382 it->tbttInfoHdr.tbttInfoLength = length;
386ReducedNeighborReport::ReadTbttInformationLength(std::size_t nbrApInfoId)
388 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
390 auto it = std::next(m_nbrApInfoFields.begin(), nbrApInfoId);
392 switch (it->tbttInfoHdr.tbttInfoLength)
396 it->hasShortSsid =
false;
397 it->hasBssParams =
false;
398 it->has20MHzPsd =
false;
399 it->hasMldParams =
false;
403 it->hasShortSsid =
true;
404 it->hasBssParams =
true;
405 it->has20MHzPsd =
true;
406 it->hasMldParams =
true;
410 "Unsupported TBTT Information Length value: " << it->tbttInfoHdr.tbttInfoLength);
415ReducedNeighborReport::SetBssid(std::size_t nbrApInfoId, std::size_t index,
Mac48Address bssid)
417 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
418 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
420 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssid = bssid;
422 m_nbrApInfoFields.at(nbrApInfoId).hasBssid =
true;
426ReducedNeighborReport::HasBssid(std::size_t nbrApInfoId)
const
428 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
430 return m_nbrApInfoFields.at(nbrApInfoId).hasBssid;
434ReducedNeighborReport::GetBssid(std::size_t nbrApInfoId, std::size_t index)
const
437 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
439 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssid;
443ReducedNeighborReport::SetShortSsid(std::size_t nbrApInfoId, std::size_t index,
uint32_t shortSsid)
445 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
446 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
448 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).shortSsid = shortSsid;
450 m_nbrApInfoFields.at(nbrApInfoId).hasShortSsid =
true;
454ReducedNeighborReport::HasShortSsid(std::size_t nbrApInfoId)
const
456 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
458 return m_nbrApInfoFields.at(nbrApInfoId).hasShortSsid;
462ReducedNeighborReport::GetShortSsid(std::size_t nbrApInfoId, std::size_t index)
const
465 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
467 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).shortSsid;
471ReducedNeighborReport::SetBssParameters(std::size_t nbrApInfoId,
473 uint8_t bssParameters)
475 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
476 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
478 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssParameters = bssParameters;
480 m_nbrApInfoFields.at(nbrApInfoId).hasBssParams =
true;
484ReducedNeighborReport::HasBssParameters(std::size_t nbrApInfoId)
const
486 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
488 return m_nbrApInfoFields.at(nbrApInfoId).hasBssParams;
492ReducedNeighborReport::GetBssParameters(std::size_t nbrApInfoId, std::size_t index)
const
494 NS_ASSERT(HasBssParameters(nbrApInfoId));
495 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
497 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssParameters;
501ReducedNeighborReport::SetPsd20MHz(std::size_t nbrApInfoId, std::size_t index, uint8_t psd20MHz)
503 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
504 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
506 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).psd20MHz = psd20MHz;
508 m_nbrApInfoFields.at(nbrApInfoId).has20MHzPsd =
true;
512ReducedNeighborReport::HasPsd20MHz(std::size_t nbrApInfoId)
const
514 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
516 return m_nbrApInfoFields.at(nbrApInfoId).has20MHzPsd;
520ReducedNeighborReport::GetPsd20MHz(std::size_t nbrApInfoId, std::size_t index)
const
523 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
525 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).psd20MHz;
529ReducedNeighborReport::SetMldParameters(std::size_t nbrApInfoId,
533 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
534 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
536 auto it = std::next(m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.begin(), index);
537 it->mldParameters = mldParams;
539 m_nbrApInfoFields.at(nbrApInfoId).hasMldParams =
true;
543ReducedNeighborReport::HasMldParameters(std::size_t nbrApInfoId)
const
545 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
547 return m_nbrApInfoFields.at(nbrApInfoId).hasMldParams;
551ReducedNeighborReport::GetMldParameters(std::size_t nbrApInfoId, std::size_t index)
const
553 NS_ASSERT(HasMldParameters(nbrApInfoId));
554 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
556 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).mldParameters;
560ReducedNeighborReport::WriteTbttInformationCount(std::size_t nbrApInfoId)
const
562 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
563 NS_ASSERT(!m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.empty());
566 m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount =
567 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size() - 1;
571ReducedNeighborReport::ReadTbttInformationCount(std::size_t nbrApInfoId)
const
573 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
575 return 1 + m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount;
579ReducedNeighborReport::GetInformationFieldSize()
const
583 for (
const auto& neighborApInfo : m_nbrApInfoFields)
587 size += 1 * neighborApInfo.tbttInformationSet.size();
589 if (neighborApInfo.hasBssid)
591 size += 6 * neighborApInfo.tbttInformationSet.size();
593 if (neighborApInfo.hasShortSsid)
595 size += 4 * neighborApInfo.tbttInformationSet.size();
597 if (neighborApInfo.hasBssParams)
599 size += 1 * neighborApInfo.tbttInformationSet.size();
601 if (neighborApInfo.has20MHzPsd)
603 size += 1 * neighborApInfo.tbttInformationSet.size();
605 if (neighborApInfo.hasMldParams)
607 size += 3 * neighborApInfo.tbttInformationSet.size();
617 for (std::size_t
id = 0;
id < m_nbrApInfoFields.size(); ++id)
619 WriteTbttInformationCount(
id);
620 WriteTbttInformationLength(
id);
623 for (
auto& neighborApInfo : m_nbrApInfoFields)
626 uint16_t tbttInfoHdr = 0;
627 tbttInfoHdr |= neighborApInfo.tbttInfoHdr.type;
628 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.filtered << 2);
629 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoCount << 4);
630 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoLength << 8);
631 start.WriteHtolsbU16(tbttInfoHdr);
633 start.WriteU8(neighborApInfo.operatingClass);
634 start.WriteU8(neighborApInfo.channelNumber);
636 for (
const auto& tbttInformation : neighborApInfo.tbttInformationSet)
638 start.WriteU8(tbttInformation.neighborApTbttOffset);
640 if (neighborApInfo.hasBssid)
642 WriteTo(start, tbttInformation.bssid);
644 if (neighborApInfo.hasShortSsid)
646 start.WriteHtolsbU32(tbttInformation.shortSsid);
648 if (neighborApInfo.hasBssParams)
650 start.WriteU8(tbttInformation.bssParameters);
652 if (neighborApInfo.has20MHzPsd)
654 start.WriteU8(tbttInformation.psd20MHz);
656 if (neighborApInfo.hasMldParams)
658 start.WriteU8(tbttInformation.mldParameters.apMldId);
660 other |= (tbttInformation.mldParameters.linkId & 0x0f);
661 other |= (tbttInformation.mldParameters.bssParamsChangeCount << 4);
662 other |= (tbttInformation.mldParameters.allUpdates << 12);
663 other |= (tbttInformation.mldParameters.disabledLink << 13);
664 start.WriteHtolsbU16(other);
676 while (count < length)
681 m_nbrApInfoFields.back().tbttInfoHdr.type = tbttInfoHdr & 0x0003;
682 m_nbrApInfoFields.back().tbttInfoHdr.filtered = (tbttInfoHdr >> 2) & 0x0001;
683 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoCount = (tbttInfoHdr >> 4) & 0x000f;
684 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoLength = (tbttInfoHdr >> 8) & 0x00ff;
686 m_nbrApInfoFields.back().operatingClass = i.
ReadU8();
687 m_nbrApInfoFields.back().channelNumber = i.
ReadU8();
690 std::size_t neighborId = m_nbrApInfoFields.size() - 1;
691 ReadTbttInformationLength(neighborId);
693 for (uint8_t j = 0; j < ReadTbttInformationCount(neighborId); j++)
695 AddTbttInformationField(neighborId);
697 m_nbrApInfoFields.back().tbttInformationSet.back().neighborApTbttOffset = i.
ReadU8();
700 if (m_nbrApInfoFields.back().hasBssid)
702 ReadFrom(i, m_nbrApInfoFields.back().tbttInformationSet.back().bssid);
705 if (m_nbrApInfoFields.back().hasShortSsid)
707 m_nbrApInfoFields.back().tbttInformationSet.back().shortSsid = i.
ReadLsbtohU32();
710 if (m_nbrApInfoFields.back().hasBssParams)
712 m_nbrApInfoFields.back().tbttInformationSet.back().bssParameters = i.
ReadU8();
715 if (m_nbrApInfoFields.back().has20MHzPsd)
717 m_nbrApInfoFields.back().tbttInformationSet.back().psd20MHz = i.
ReadU8();
720 if (m_nbrApInfoFields.back().hasMldParams)
722 auto& mldParams = m_nbrApInfoFields.back().tbttInformationSet.back().mldParameters;
723 mldParams.apMldId = i.
ReadU8();
726 mldParams.linkId = other & 0x000f;
727 mldParams.bssParamsChangeCount = (other >> 4) & 0x00ff;
728 mldParams.allUpdates = (other >> 12) & 0x01;
729 mldParams.disabledLink = (other >> 13) & 0x01;
738ReducedNeighborReport::Print(std::ostream& os)
const
740 os <<
"Reduced Neighbor Report=[";
741 for (
const auto& neighborApInfo : m_nbrApInfoFields)
743 os <<
"{Operating Class: " << +neighborApInfo.operatingClass
744 <<
", Channel Number: " << +neighborApInfo.channelNumber
745 <<
", TBTT Information Count: " << +neighborApInfo.tbttInfoHdr.tbttInfoCount
746 <<
", TBTT Information Length: " << +neighborApInfo.tbttInfoHdr.tbttInfoLength <<
"}, ";
iterator in a Buffer instance
std::vector< NeighborApInformation > m_nbrApInfoFields
one or more Neighbor AP Information fields
std::size_t GetNNbrApInfoFields() const
Get the number of Neighbor AP Information fields.
WifiInformationElementId ElementId() const override
Get the wifi information element ID.
void AddNbrApInfoField()
Add a Neighbor AP Information field.
WifiPhyOperatingChannel GetOperatingChannel(std::size_t nbrApInfoId) const
Get the operating channel coded into the Operating Class and the Channel Number fields of the given N...
void SetOperatingChannel(std::size_t nbrApInfoId, const WifiPhyOperatingChannel &channel)
Set the Operating Class and the Channel Number fields of the given Neighbor AP Information field base...
Class that keeps track of all information about the current PHY operating channel.
static const std::set< FrequencyChannelInfo > m_frequencyChannels
Available frequency channels.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#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_ABORT_IF(cond)
Abnormal program termination if a condition is true.
WifiPhyBand
Identifies the PHY band.
@ 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.
double MHz_u
MHz weak type.
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
uint8_t WifiInformationElementId
This type is used to represent an Information Element ID.
void ReadFrom(Buffer::Iterator &i, Ipv4Address &ad)
Read an Ipv4Address from a Buffer.