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,
525 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
526 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
528 auto it = std::next(m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.begin(), index);
529 it->mldParameters = mldParams;
531 m_nbrApInfoFields.at(nbrApInfoId).hasMldParams =
true;
535ReducedNeighborReport::HasMldParameters(std::size_t nbrApInfoId)
const
537 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
539 return m_nbrApInfoFields.at(nbrApInfoId).hasMldParams;
543ReducedNeighborReport::GetMldParameters(std::size_t nbrApInfoId, std::size_t index)
const
545 NS_ASSERT(HasMldParameters(nbrApInfoId));
546 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
548 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).mldParameters;
552ReducedNeighborReport::WriteTbttInformationCount(std::size_t nbrApInfoId)
const
554 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
555 NS_ASSERT(!m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.empty());
558 m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount =
559 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size() - 1;
563ReducedNeighborReport::ReadTbttInformationCount(std::size_t nbrApInfoId)
const
565 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
567 return 1 + m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount;
571ReducedNeighborReport::GetInformationFieldSize()
const
575 for (
const auto& neighborApInfo : m_nbrApInfoFields)
579 size += 1 * neighborApInfo.tbttInformationSet.size();
581 if (neighborApInfo.hasBssid)
583 size += 6 * neighborApInfo.tbttInformationSet.size();
585 if (neighborApInfo.hasShortSsid)
587 size += 4 * neighborApInfo.tbttInformationSet.size();
589 if (neighborApInfo.hasBssParams)
591 size += 1 * neighborApInfo.tbttInformationSet.size();
593 if (neighborApInfo.has20MHzPsd)
595 size += 1 * neighborApInfo.tbttInformationSet.size();
597 if (neighborApInfo.hasMldParams)
599 size += 3 * neighborApInfo.tbttInformationSet.size();
609 for (std::size_t
id = 0;
id < m_nbrApInfoFields.size(); ++id)
611 WriteTbttInformationCount(
id);
612 WriteTbttInformationLength(
id);
615 for (
auto& neighborApInfo : m_nbrApInfoFields)
618 uint16_t tbttInfoHdr = 0;
619 tbttInfoHdr |= neighborApInfo.tbttInfoHdr.type;
620 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.filtered << 2);
621 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoCount << 4);
622 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoLength << 8);
623 start.WriteHtolsbU16(tbttInfoHdr);
625 start.WriteU8(neighborApInfo.operatingClass);
626 start.WriteU8(neighborApInfo.channelNumber);
628 for (
const auto& tbttInformation : neighborApInfo.tbttInformationSet)
630 start.WriteU8(tbttInformation.neighborApTbttOffset);
632 if (neighborApInfo.hasBssid)
634 WriteTo(start, tbttInformation.bssid);
636 if (neighborApInfo.hasShortSsid)
638 start.WriteHtolsbU32(tbttInformation.shortSsid);
640 if (neighborApInfo.hasBssParams)
642 start.WriteU8(tbttInformation.bssParameters);
644 if (neighborApInfo.has20MHzPsd)
646 start.WriteU8(tbttInformation.psd20MHz);
648 if (neighborApInfo.hasMldParams)
650 start.WriteU8(tbttInformation.mldParameters.apMldId);
652 other |= (tbttInformation.mldParameters.linkId & 0x0f);
653 other |= (tbttInformation.mldParameters.bssParamsChangeCount << 4);
654 other |= (tbttInformation.mldParameters.allUpdates << 12);
655 other |= (tbttInformation.mldParameters.disabledLink << 13);
656 start.WriteHtolsbU16(other);
668 while (count < length)
673 m_nbrApInfoFields.back().tbttInfoHdr.type = tbttInfoHdr & 0x0003;
674 m_nbrApInfoFields.back().tbttInfoHdr.filtered = (tbttInfoHdr >> 2) & 0x0001;
675 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoCount = (tbttInfoHdr >> 4) & 0x000f;
676 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoLength = (tbttInfoHdr >> 8) & 0x00ff;
678 m_nbrApInfoFields.back().operatingClass = i.
ReadU8();
679 m_nbrApInfoFields.back().channelNumber = i.
ReadU8();
682 std::size_t neighborId = m_nbrApInfoFields.size() - 1;
683 ReadTbttInformationLength(neighborId);
685 for (uint8_t j = 0; j < ReadTbttInformationCount(neighborId); j++)
687 AddTbttInformationField(neighborId);
689 m_nbrApInfoFields.back().tbttInformationSet.back().neighborApTbttOffset = i.
ReadU8();
692 if (m_nbrApInfoFields.back().hasBssid)
694 ReadFrom(i, m_nbrApInfoFields.back().tbttInformationSet.back().bssid);
697 if (m_nbrApInfoFields.back().hasShortSsid)
699 m_nbrApInfoFields.back().tbttInformationSet.back().shortSsid = i.
ReadLsbtohU32();
702 if (m_nbrApInfoFields.back().hasBssParams)
704 m_nbrApInfoFields.back().tbttInformationSet.back().bssParameters = i.
ReadU8();
707 if (m_nbrApInfoFields.back().has20MHzPsd)
709 m_nbrApInfoFields.back().tbttInformationSet.back().psd20MHz = i.
ReadU8();
712 if (m_nbrApInfoFields.back().hasMldParams)
714 auto& mldParams = m_nbrApInfoFields.back().tbttInformationSet.back().mldParameters;
715 mldParams.apMldId = i.
ReadU8();
718 mldParams.linkId = other & 0x000f;
719 mldParams.bssParamsChangeCount = (other >> 4) & 0x00ff;
720 mldParams.allUpdates = (other >> 12) & 0x01;
721 mldParams.disabledLink = (other >> 13) & 0x01;
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.