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;
151 NS_ABORT_MSG(
"The provided channel has an unspecified PHY band");
156 "Operating class not found for channel number "
157 << channelNumber <<
" width " << channel.GetWidth() <<
" MHz "
158 <<
"band " << channel.GetPhyBand());
161 MHz_u startingFreq{0};
163 switch (channel.GetPhyBand())
166 startingFreq =
MHz_u{2407};
169 startingFreq =
MHz_u{5000};
172 startingFreq =
MHz_u{5950};
176 NS_ABORT_MSG(
"The provided channel has an unspecified PHY band");
180 uint8_t primaryChannelNumber =
181 (channel.GetPrimaryChannelCenterFrequency(
MHz_u{20}) - startingFreq) /
MHz_u{5};
249 MHz_u startingFreq{0};
254 startingFreq =
MHz_u{2407};
257 startingFreq =
MHz_u{5000};
260 startingFreq =
MHz_u{5950};
269 auto primaryChannelCenterFrequency = startingFreq + primaryChannelNumber *
MHz_u{5};
271 uint8_t channelNumber = 0;
277 channel.band == band &&
278 primaryChannelCenterFrequency > (channel.frequency - (width / 2)) &&
279 primaryChannelCenterFrequency < (channel.frequency + (width / 2)))
294 switch (
static_cast<uint16_t
>(width))
297 if (channel.frequency == primaryChannelCenterFrequency)
303 if ((channel.frequency == primaryChannelCenterFrequency +
MHz_u{10}) ||
304 (channel.frequency == primaryChannelCenterFrequency -
MHz_u{10}))
310 NS_ABORT_MSG(
"No channel of width " << width <<
" MHz in the 2.4 GHz band");
316 channelNumber = channel.number;
317 frequency = channel.frequency;
323 NS_ABORT_IF(channelNumber == 0 || frequency == MHz_u{0});
325 WifiPhyOperatingChannel
channel;
328 const auto channelLowestFreq = frequency - width / 2;
329 const auto primaryChannelLowestFreq = primaryChannelCenterFrequency -
MHz_u{10};
336ReducedNeighborReport::GetNTbttInformationFields(std::size_t nbrApInfoId)
const
338 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
339 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size();
343ReducedNeighborReport::AddTbttInformationField(std::size_t nbrApInfoId)
345 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
346 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.emplace_back();
350ReducedNeighborReport::WriteTbttInformationLength(std::size_t nbrApInfoId)
const
352 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
356 auto it = std::next(m_nbrApInfoFields.begin(), nbrApInfoId);
358 if (it->hasBssid && !it->hasShortSsid && !it->hasBssParams && !it->has20MHzPsd &&
363 else if (it->hasBssid && it->hasShortSsid && it->hasBssParams && it->has20MHzPsd &&
370 NS_ABORT_MSG(
"Unsupported TBTT Information field contents");
374 it->tbttInfoHdr.tbttInfoLength = length;
378ReducedNeighborReport::ReadTbttInformationLength(std::size_t nbrApInfoId)
380 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
382 auto it = std::next(m_nbrApInfoFields.begin(), nbrApInfoId);
384 switch (it->tbttInfoHdr.tbttInfoLength)
388 it->hasShortSsid =
false;
389 it->hasBssParams =
false;
390 it->has20MHzPsd =
false;
391 it->hasMldParams =
false;
395 it->hasShortSsid =
true;
396 it->hasBssParams =
true;
397 it->has20MHzPsd =
true;
398 it->hasMldParams =
true;
402 "Unsupported TBTT Information Length value: " << it->tbttInfoHdr.tbttInfoLength);
407ReducedNeighborReport::SetBssid(std::size_t nbrApInfoId, std::size_t index,
Mac48Address bssid)
409 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
410 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
412 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssid = bssid;
414 m_nbrApInfoFields.at(nbrApInfoId).hasBssid =
true;
418ReducedNeighborReport::HasBssid(std::size_t nbrApInfoId)
const
420 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
422 return m_nbrApInfoFields.at(nbrApInfoId).hasBssid;
426ReducedNeighborReport::GetBssid(std::size_t nbrApInfoId, std::size_t index)
const
429 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
431 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssid;
435ReducedNeighborReport::SetShortSsid(std::size_t nbrApInfoId, std::size_t index,
uint32_t shortSsid)
437 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
438 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
440 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).shortSsid = shortSsid;
442 m_nbrApInfoFields.at(nbrApInfoId).hasShortSsid =
true;
446ReducedNeighborReport::HasShortSsid(std::size_t nbrApInfoId)
const
448 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
450 return m_nbrApInfoFields.at(nbrApInfoId).hasShortSsid;
454ReducedNeighborReport::GetShortSsid(std::size_t nbrApInfoId, std::size_t index)
const
457 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
459 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).shortSsid;
463ReducedNeighborReport::SetBssParameters(std::size_t nbrApInfoId,
465 uint8_t bssParameters)
467 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
468 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
470 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssParameters = bssParameters;
472 m_nbrApInfoFields.at(nbrApInfoId).hasBssParams =
true;
476ReducedNeighborReport::HasBssParameters(std::size_t nbrApInfoId)
const
478 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
480 return m_nbrApInfoFields.at(nbrApInfoId).hasBssParams;
484ReducedNeighborReport::GetBssParameters(std::size_t nbrApInfoId, std::size_t index)
const
486 NS_ASSERT(HasBssParameters(nbrApInfoId));
487 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
489 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssParameters;
493ReducedNeighborReport::SetPsd20MHz(std::size_t nbrApInfoId, std::size_t index, uint8_t psd20MHz)
495 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
496 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
498 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).psd20MHz = psd20MHz;
500 m_nbrApInfoFields.at(nbrApInfoId).has20MHzPsd =
true;
504ReducedNeighborReport::HasPsd20MHz(std::size_t nbrApInfoId)
const
506 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
508 return m_nbrApInfoFields.at(nbrApInfoId).has20MHzPsd;
512ReducedNeighborReport::GetPsd20MHz(std::size_t nbrApInfoId, std::size_t index)
const
515 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
517 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).psd20MHz;
521ReducedNeighborReport::SetMldParameters(std::size_t nbrApInfoId,
527 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
528 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
530 auto it = std::next(m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.begin(), index);
531 it->mldParameters.mldId = mldId;
532 it->mldParameters.linkId = (linkId & 0x0f);
533 it->mldParameters.bssParamsChangeCount = changeCount;
535 m_nbrApInfoFields.at(nbrApInfoId).hasMldParams =
true;
539ReducedNeighborReport::HasMldParameters(std::size_t nbrApInfoId)
const
541 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
543 return m_nbrApInfoFields.at(nbrApInfoId).hasMldParams;
547ReducedNeighborReport::GetMldId(std::size_t nbrApInfoId, std::size_t index)
const
549 NS_ASSERT(HasMldParameters(nbrApInfoId));
550 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
552 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).mldParameters.mldId;
556ReducedNeighborReport::GetLinkId(std::size_t nbrApInfoId, std::size_t index)
const
558 NS_ASSERT(HasMldParameters(nbrApInfoId));
559 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
561 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).mldParameters.linkId &
566ReducedNeighborReport::WriteTbttInformationCount(std::size_t nbrApInfoId)
const
568 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
569 NS_ASSERT(!m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.empty());
572 m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount =
573 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size() - 1;
577ReducedNeighborReport::ReadTbttInformationCount(std::size_t nbrApInfoId)
const
579 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
581 return 1 + m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount;
585ReducedNeighborReport::GetInformationFieldSize()
const
589 for (
const auto& neighborApInfo : m_nbrApInfoFields)
593 size += 1 * neighborApInfo.tbttInformationSet.size();
595 if (neighborApInfo.hasBssid)
597 size += 6 * neighborApInfo.tbttInformationSet.size();
599 if (neighborApInfo.hasShortSsid)
601 size += 4 * neighborApInfo.tbttInformationSet.size();
603 if (neighborApInfo.hasBssParams)
605 size += 1 * neighborApInfo.tbttInformationSet.size();
607 if (neighborApInfo.has20MHzPsd)
609 size += 1 * neighborApInfo.tbttInformationSet.size();
611 if (neighborApInfo.hasMldParams)
613 size += 3 * neighborApInfo.tbttInformationSet.size();
623 for (std::size_t
id = 0;
id < m_nbrApInfoFields.size(); ++id)
625 WriteTbttInformationCount(
id);
626 WriteTbttInformationLength(
id);
629 for (
auto& neighborApInfo : m_nbrApInfoFields)
632 uint16_t tbttInfoHdr = 0;
633 tbttInfoHdr |= neighborApInfo.tbttInfoHdr.type;
634 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.filtered << 2);
635 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoCount << 4);
636 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoLength << 8);
637 start.WriteHtolsbU16(tbttInfoHdr);
639 start.WriteU8(neighborApInfo.operatingClass);
640 start.WriteU8(neighborApInfo.channelNumber);
642 for (
const auto& tbttInformation : neighborApInfo.tbttInformationSet)
644 start.WriteU8(tbttInformation.neighborApTbttOffset);
646 if (neighborApInfo.hasBssid)
648 WriteTo(start, tbttInformation.bssid);
650 if (neighborApInfo.hasShortSsid)
652 start.WriteHtolsbU32(tbttInformation.shortSsid);
654 if (neighborApInfo.hasBssParams)
656 start.WriteU8(tbttInformation.bssParameters);
658 if (neighborApInfo.has20MHzPsd)
660 start.WriteU8(tbttInformation.psd20MHz);
662 if (neighborApInfo.hasMldParams)
664 start.WriteU8(tbttInformation.mldParameters.mldId);
666 other |= (tbttInformation.mldParameters.linkId & 0x0f);
667 other |= (tbttInformation.mldParameters.bssParamsChangeCount << 4);
668 start.WriteHtolsbU16(other);
680 while (count < length)
685 m_nbrApInfoFields.back().tbttInfoHdr.type = tbttInfoHdr & 0x0003;
686 m_nbrApInfoFields.back().tbttInfoHdr.filtered = (tbttInfoHdr >> 2) & 0x0001;
687 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoCount = (tbttInfoHdr >> 4) & 0x000f;
688 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoLength = (tbttInfoHdr >> 8) & 0x00ff;
690 m_nbrApInfoFields.back().operatingClass = i.
ReadU8();
691 m_nbrApInfoFields.back().channelNumber = i.
ReadU8();
694 std::size_t neighborId = m_nbrApInfoFields.size() - 1;
695 ReadTbttInformationLength(neighborId);
697 for (uint8_t j = 0; j < ReadTbttInformationCount(neighborId); j++)
699 AddTbttInformationField(neighborId);
701 m_nbrApInfoFields.back().tbttInformationSet.back().neighborApTbttOffset = i.
ReadU8();
704 if (m_nbrApInfoFields.back().hasBssid)
706 ReadFrom(i, m_nbrApInfoFields.back().tbttInformationSet.back().bssid);
709 if (m_nbrApInfoFields.back().hasShortSsid)
711 m_nbrApInfoFields.back().tbttInformationSet.back().shortSsid = i.
ReadLsbtohU32();
714 if (m_nbrApInfoFields.back().hasBssParams)
716 m_nbrApInfoFields.back().tbttInformationSet.back().bssParameters = i.
ReadU8();
719 if (m_nbrApInfoFields.back().has20MHzPsd)
721 m_nbrApInfoFields.back().tbttInformationSet.back().psd20MHz = i.
ReadU8();
724 if (m_nbrApInfoFields.back().hasMldParams)
726 m_nbrApInfoFields.back().tbttInformationSet.back().mldParameters.mldId = i.
ReadU8();
729 m_nbrApInfoFields.back().tbttInformationSet.back().mldParameters.linkId =
731 m_nbrApInfoFields.back()
732 .tbttInformationSet.back()
733 .mldParameters.bssParamsChangeCount = (other >> 4) & 0x00ff;
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.