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.