wifi: Add support for FILS Discovery action frame
This commit is contained in:
committed by
Stefano Avallone
parent
4fcdc10998
commit
e87b1e0d34
@@ -25,6 +25,9 @@
|
||||
|
||||
#include "ns3/multi-link-element.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
@@ -191,6 +194,9 @@ WifiActionHeader::GetAction() const
|
||||
case QAB_RESPONSE:
|
||||
retval.publicAction = QAB_RESPONSE;
|
||||
break;
|
||||
case FILS_DISCOVERY:
|
||||
retval.publicAction = FILS_DISCOVERY;
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR("Unknown public action code");
|
||||
retval.publicAction = QAB_REQUEST; /* quiet compiler */
|
||||
@@ -553,6 +559,7 @@ WifiActionHeader::Print(std::ostream& os) const
|
||||
{
|
||||
CASE_ACTION_VALUE(QAB_REQUEST);
|
||||
CASE_ACTION_VALUE(QAB_RESPONSE);
|
||||
CASE_ACTION_VALUE(FILS_DISCOVERY);
|
||||
default:
|
||||
NS_FATAL_ERROR("Unknown public action code");
|
||||
}
|
||||
@@ -1349,4 +1356,411 @@ MgtEmlOmn::GetLinkBitmap() const
|
||||
return list;
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
* FILS Discovery
|
||||
****************************************************/
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(FilsDiscHeader);
|
||||
|
||||
TypeId
|
||||
FilsDiscHeader::GetTypeId()
|
||||
{
|
||||
static TypeId tid = TypeId("ns3::FilsDiscHeader")
|
||||
.SetParent<Header>()
|
||||
.SetGroupName("Wifi")
|
||||
.AddConstructor<FilsDiscHeader>();
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
FilsDiscHeader::GetInstanceTypeId() const
|
||||
{
|
||||
return GetTypeId();
|
||||
}
|
||||
|
||||
FilsDiscHeader::FilsDiscHeader()
|
||||
: m_len(m_frameCtl.m_lenPresenceInd),
|
||||
m_fdCap(m_frameCtl.m_capPresenceInd),
|
||||
m_primaryCh(m_frameCtl.m_primChPresenceInd),
|
||||
m_apConfigSeqNum(m_frameCtl.m_apCsnPresenceInd),
|
||||
m_accessNetOpt(m_frameCtl.m_anoPresenceInd),
|
||||
m_chCntrFreqSeg1(m_frameCtl.m_chCntrFreqSeg1PresenceInd)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
FilsDiscHeader::SetSsid(const std::string& ssid)
|
||||
{
|
||||
m_ssid = ssid;
|
||||
m_frameCtl.m_ssidLen = ssid.length() - 1;
|
||||
}
|
||||
|
||||
const std::string&
|
||||
FilsDiscHeader::GetSsid() const
|
||||
{
|
||||
return m_ssid;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
FilsDiscHeader::GetInformationFieldSize() const
|
||||
{
|
||||
auto size = GetSizeNonOptSubfields();
|
||||
size += m_len.has_value() ? 1 : 0;
|
||||
size += m_fdCap.has_value() ? 2 : 0;
|
||||
size += m_opClass.has_value() ? 1 : 0;
|
||||
size += m_primaryCh.has_value() ? 1 : 0;
|
||||
size += m_apConfigSeqNum.has_value() ? 1 : 0;
|
||||
size += m_accessNetOpt.has_value() ? 1 : 0;
|
||||
size += m_chCntrFreqSeg1.has_value() ? 1 : 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
FilsDiscHeader::GetSerializedSize() const
|
||||
{
|
||||
auto size = GetInformationFieldSize();
|
||||
// Optional elements
|
||||
size += m_rnr.has_value() ? m_rnr->GetSerializedSize() : 0;
|
||||
size += m_tim.has_value() ? m_tim->GetSerializedSize() : 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
FilsDiscHeader::GetSizeNonOptSubfields() const
|
||||
{
|
||||
return 2 /* FILS Discovery Frame Control */
|
||||
+ 8 /* Timestamp */
|
||||
+ 2 /* Beacon Interval */
|
||||
+ m_ssid.length(); /* SSID */
|
||||
}
|
||||
|
||||
void
|
||||
FilsDiscHeader::SetLengthSubfield()
|
||||
{
|
||||
m_len.reset(); // so that Length size is not included by GetInformationFieldSize()
|
||||
auto infoFieldSize = GetInformationFieldSize();
|
||||
auto nonOptSubfieldsSize = GetSizeNonOptSubfields();
|
||||
NS_ABORT_MSG_IF(infoFieldSize < nonOptSubfieldsSize, "Length subfield is less than 0");
|
||||
m_len = infoFieldSize - nonOptSubfieldsSize;
|
||||
}
|
||||
|
||||
void
|
||||
FilsDiscHeader::Print(std::ostream& os) const
|
||||
{
|
||||
os << "Control=" << m_frameCtl << ", "
|
||||
<< "Time Stamp=" << m_timeStamp << ", "
|
||||
<< "Beacon Interval=" << m_beaconInt << ", "
|
||||
<< "SSID=" << m_ssid << ", ";
|
||||
if (m_len.has_value())
|
||||
{
|
||||
os << "Length=" << *m_len << ", ";
|
||||
}
|
||||
if (m_fdCap.has_value())
|
||||
{
|
||||
os << "FD Capability=" << *m_fdCap << ", ";
|
||||
}
|
||||
if (m_opClass.has_value())
|
||||
{
|
||||
os << "Operating Class=" << *m_opClass << ", ";
|
||||
}
|
||||
if (m_primaryCh.has_value())
|
||||
{
|
||||
os << "Primary Channel=" << *m_primaryCh << ", ";
|
||||
}
|
||||
if (m_apConfigSeqNum.has_value())
|
||||
{
|
||||
os << "AP-CSN=" << *m_apConfigSeqNum << ", ";
|
||||
}
|
||||
if (m_accessNetOpt.has_value())
|
||||
{
|
||||
os << "ANO=" << *m_accessNetOpt << ", ";
|
||||
}
|
||||
if (m_chCntrFreqSeg1.has_value())
|
||||
{
|
||||
os << "Channel Center Frequency Seg 1=" << *m_chCntrFreqSeg1 << ", ";
|
||||
}
|
||||
if (m_tim.has_value())
|
||||
{
|
||||
os << "Traffic Indicator Map=" << *m_tim;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FilsDiscHeader::Serialize(Buffer::Iterator start) const
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
m_frameCtl.Serialize(i);
|
||||
i.WriteHtolsbU64(Simulator::Now().GetMicroSeconds()); // Time stamp
|
||||
i.WriteHtolsbU16(m_beaconInt);
|
||||
i.Write(reinterpret_cast<const uint8_t*>(m_ssid.data()), m_ssid.length());
|
||||
if (m_len.has_value())
|
||||
{
|
||||
i.WriteU8(*m_len);
|
||||
}
|
||||
if (m_fdCap.has_value())
|
||||
{
|
||||
m_fdCap->Serialize(i);
|
||||
}
|
||||
NS_ASSERT(m_opClass.has_value() == m_primaryCh.has_value());
|
||||
if (m_opClass.has_value())
|
||||
{
|
||||
i.WriteU8(*m_opClass);
|
||||
}
|
||||
if (m_primaryCh.has_value())
|
||||
{
|
||||
i.WriteU8(*m_primaryCh);
|
||||
}
|
||||
if (m_apConfigSeqNum.has_value())
|
||||
{
|
||||
i.WriteU8(*m_apConfigSeqNum);
|
||||
}
|
||||
if (m_accessNetOpt.has_value())
|
||||
{
|
||||
i.WriteU8(*m_accessNetOpt);
|
||||
}
|
||||
if (m_chCntrFreqSeg1.has_value())
|
||||
{
|
||||
i.WriteU8(*m_chCntrFreqSeg1);
|
||||
}
|
||||
i = m_rnr.has_value() ? m_rnr->Serialize(i) : i;
|
||||
i = m_tim.has_value() ? m_tim->Serialize(i) : i;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
FilsDiscHeader::Deserialize(Buffer::Iterator start)
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
auto nOctets = m_frameCtl.Deserialize(i);
|
||||
i.Next(nOctets);
|
||||
m_timeStamp = i.ReadLsbtohU64();
|
||||
m_beaconInt = i.ReadLsbtohU16();
|
||||
std::vector<uint8_t> ssid(m_frameCtl.m_ssidLen + 2);
|
||||
i.Read(ssid.data(), m_frameCtl.m_ssidLen + 1);
|
||||
ssid[m_frameCtl.m_ssidLen + 1] = 0;
|
||||
m_ssid = std::string(reinterpret_cast<char*>(ssid.data()));
|
||||
// Optional subfields
|
||||
if (m_frameCtl.m_lenPresenceInd)
|
||||
{
|
||||
m_len = i.ReadU8();
|
||||
}
|
||||
if (m_frameCtl.m_capPresenceInd)
|
||||
{
|
||||
nOctets = m_fdCap->Deserialize(i);
|
||||
i.Next(nOctets);
|
||||
}
|
||||
if (m_frameCtl.m_primChPresenceInd)
|
||||
{
|
||||
m_opClass = i.ReadU8();
|
||||
m_primaryCh = i.ReadU8();
|
||||
}
|
||||
if (m_frameCtl.m_apCsnPresenceInd)
|
||||
{
|
||||
m_apConfigSeqNum = i.ReadU8();
|
||||
}
|
||||
if (m_frameCtl.m_anoPresenceInd)
|
||||
{
|
||||
m_accessNetOpt = i.ReadU8();
|
||||
}
|
||||
if (m_frameCtl.m_chCntrFreqSeg1PresenceInd)
|
||||
{
|
||||
m_chCntrFreqSeg1 = i.ReadU8();
|
||||
}
|
||||
// Optional elements
|
||||
m_rnr.emplace();
|
||||
auto tmp = i;
|
||||
i = m_rnr->DeserializeIfPresent(i);
|
||||
if (i.GetDistanceFrom(tmp) == 0)
|
||||
{
|
||||
m_rnr.reset();
|
||||
}
|
||||
|
||||
m_tim.emplace();
|
||||
tmp = i;
|
||||
i = m_tim->DeserializeIfPresent(i);
|
||||
if (i.GetDistanceFrom(tmp) == 0)
|
||||
{
|
||||
m_tim.reset();
|
||||
}
|
||||
|
||||
return i.GetDistanceFrom(start);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FilsDiscHeader::FilsDiscFrameControl& control)
|
||||
{
|
||||
os << "ssidLen:" << control.m_ssidLen << " capPresenceInd:" << control.m_capPresenceInd
|
||||
<< " shortSsidInd:" << control.m_shortSsidInd
|
||||
<< " apCsnPresenceInd:" << control.m_apCsnPresenceInd
|
||||
<< " anoPresenceInd:" << control.m_anoPresenceInd
|
||||
<< " chCntrFreqSeg1PresenceInd:" << control.m_chCntrFreqSeg1PresenceInd
|
||||
<< " primChPresenceInd:" << control.m_primChPresenceInd
|
||||
<< " rsnInfoPresenceInd:" << control.m_rsnInfoPresenceInd
|
||||
<< " lenPresenceInd:" << control.m_lenPresenceInd
|
||||
<< " mdPresenceInd:" << control.m_mdPresenceInd;
|
||||
return os;
|
||||
}
|
||||
|
||||
void
|
||||
FilsDiscHeader::FilsDiscFrameControl::Serialize(Buffer::Iterator& start) const
|
||||
{
|
||||
uint16_t val = m_ssidLen | ((m_capPresenceInd ? 1 : 0) << 5) | (m_shortSsidInd << 6) |
|
||||
((m_apCsnPresenceInd ? 1 : 0) << 7) | ((m_anoPresenceInd ? 1 : 0) << 8) |
|
||||
((m_chCntrFreqSeg1PresenceInd ? 1 : 0) << 9) |
|
||||
((m_primChPresenceInd ? 1 : 0) << 10) | (m_rsnInfoPresenceInd << 11) |
|
||||
((m_lenPresenceInd ? 1 : 0) << 12) | (m_mdPresenceInd << 13);
|
||||
start.WriteHtolsbU16(val);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
FilsDiscHeader::FilsDiscFrameControl::Deserialize(Buffer::Iterator start)
|
||||
{
|
||||
auto val = start.ReadLsbtohU16();
|
||||
|
||||
m_ssidLen = val & 0x001f;
|
||||
m_capPresenceInd = ((val >> 5) & 0x0001) == 1;
|
||||
m_shortSsidInd = (val >> 6) & 0x0001;
|
||||
m_apCsnPresenceInd = ((val >> 7) & 0x0001) == 1;
|
||||
m_anoPresenceInd = ((val >> 8) & 0x0001) == 1;
|
||||
m_chCntrFreqSeg1PresenceInd = ((val >> 9) & 0x0001) == 1;
|
||||
m_primChPresenceInd = ((val >> 10) & 0x0001) == 1;
|
||||
m_rsnInfoPresenceInd = (val >> 11) & 0x0001;
|
||||
m_lenPresenceInd = ((val >> 12) & 0x0001) == 1;
|
||||
m_mdPresenceInd = (val >> 13) & 0x0001;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const FilsDiscHeader::FdCapability& capability)
|
||||
{
|
||||
os << "ess:" << capability.m_ess << " privacy:" << capability.m_privacy
|
||||
<< " channelWidth:" << capability.m_chWidth << " maxNss:" << capability.m_maxNss
|
||||
<< " multiBssidInd:" << capability.m_multiBssidPresenceInd
|
||||
<< " phyIdx:" << capability.m_phyIdx << " minRate:" << capability.m_minRate;
|
||||
return os;
|
||||
}
|
||||
|
||||
void
|
||||
FilsDiscHeader::FdCapability::Serialize(Buffer::Iterator& start) const
|
||||
{
|
||||
uint16_t val = m_ess | (m_privacy << 1) | (m_chWidth << 2) | (m_maxNss << 5) |
|
||||
(m_multiBssidPresenceInd << 9) | (m_phyIdx << 10) | (m_minRate << 13);
|
||||
start.WriteHtolsbU16(val);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
FilsDiscHeader::FdCapability::Deserialize(Buffer::Iterator start)
|
||||
{
|
||||
auto val = start.ReadLsbtohU16();
|
||||
|
||||
m_ess = val & 0x0001;
|
||||
m_privacy = (val >> 1) & 0x0001;
|
||||
m_chWidth = (val >> 2) & 0x0007;
|
||||
m_maxNss = (val >> 5) & 0x0007;
|
||||
m_multiBssidPresenceInd = (val >> 9) & 0x0001;
|
||||
m_phyIdx = (val >> 10) & 0x0007;
|
||||
m_minRate = (val >> 13) & 0x0007;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
void
|
||||
FilsDiscHeader::FdCapability::SetOpChannelWidth(uint16_t width)
|
||||
{
|
||||
m_chWidth = (width == 20 || width == 22) ? 0
|
||||
: (width == 40) ? 1
|
||||
: (width == 80) ? 2
|
||||
: (width == 160) ? 3
|
||||
: 4;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
FilsDiscHeader::FdCapability::GetOpChannelWidth() const
|
||||
{
|
||||
switch (m_chWidth)
|
||||
{
|
||||
case 0:
|
||||
return m_phyIdx == 0 ? 22 : 20; // PHY Index 0 indicates 802.11b
|
||||
case 1:
|
||||
return 40;
|
||||
case 2:
|
||||
return 80;
|
||||
case 3:
|
||||
return 160;
|
||||
default:
|
||||
NS_ABORT_MSG("Reserved value: " << +m_chWidth);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
FilsDiscHeader::FdCapability::SetMaxNss(uint8_t maxNss)
|
||||
{
|
||||
NS_ABORT_MSG_IF(maxNss < 1, "NSS is equal to 0");
|
||||
maxNss--;
|
||||
// 4 is the maximum value for the Maximum Number of Spatial Streams subfield
|
||||
m_maxNss = std::min<uint8_t>(maxNss, 4);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
FilsDiscHeader::FdCapability::GetMaxNss() const
|
||||
{
|
||||
return m_maxNss + 1;
|
||||
}
|
||||
|
||||
void
|
||||
FilsDiscHeader::FdCapability::SetStandard(WifiStandard standard)
|
||||
{
|
||||
switch (standard)
|
||||
{
|
||||
case WIFI_STANDARD_80211b:
|
||||
m_phyIdx = 0;
|
||||
break;
|
||||
case WIFI_STANDARD_80211a:
|
||||
case WIFI_STANDARD_80211g:
|
||||
m_phyIdx = 1;
|
||||
break;
|
||||
case WIFI_STANDARD_80211n:
|
||||
m_phyIdx = 2;
|
||||
break;
|
||||
case WIFI_STANDARD_80211ac:
|
||||
m_phyIdx = 3;
|
||||
break;
|
||||
case WIFI_STANDARD_80211ax:
|
||||
m_phyIdx = 4;
|
||||
break;
|
||||
case WIFI_STANDARD_80211be:
|
||||
m_phyIdx = 5;
|
||||
break;
|
||||
default:
|
||||
NS_ABORT_MSG("Unsupported standard: " << standard);
|
||||
}
|
||||
}
|
||||
|
||||
WifiStandard
|
||||
FilsDiscHeader::FdCapability::GetStandard(WifiPhyBand band) const
|
||||
{
|
||||
switch (m_phyIdx)
|
||||
{
|
||||
case 0:
|
||||
return WIFI_STANDARD_80211b;
|
||||
case 1:
|
||||
NS_ABORT_MSG_IF(band != WIFI_PHY_BAND_2_4GHZ && band != WIFI_PHY_BAND_5GHZ,
|
||||
"Invalid PHY band (" << band << ") with PHY index of 1");
|
||||
return band == WIFI_PHY_BAND_5GHZ ? WIFI_STANDARD_80211a : WIFI_STANDARD_80211g;
|
||||
case 2:
|
||||
return WIFI_STANDARD_80211n;
|
||||
case 3:
|
||||
return WIFI_STANDARD_80211ac;
|
||||
case 4:
|
||||
return WIFI_STANDARD_80211ax;
|
||||
case 5:
|
||||
return WIFI_STANDARD_80211be;
|
||||
default:
|
||||
NS_ABORT_MSG("Invalid PHY index: " << m_phyIdx);
|
||||
}
|
||||
|
||||
return WIFI_STANDARD_UNSPECIFIED;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -22,7 +22,11 @@
|
||||
#ifndef MGT_ACTION_HEADERS_H
|
||||
#define MGT_ACTION_HEADERS_H
|
||||
|
||||
#include "reduced-neighbor-report.h"
|
||||
#include "status-code.h"
|
||||
#include "tim.h"
|
||||
#include "wifi-opt-field.h"
|
||||
#include "wifi-standards.h"
|
||||
|
||||
#include "ns3/header.h"
|
||||
|
||||
@@ -99,6 +103,7 @@ class WifiActionHeader : public Header
|
||||
{
|
||||
QAB_REQUEST = 16,
|
||||
QAB_RESPONSE = 17,
|
||||
FILS_DISCOVERY = 34
|
||||
};
|
||||
|
||||
/// RadioMeasurementActionValue enumeration
|
||||
@@ -666,6 +671,175 @@ class MgtEmlOmn : public Header
|
||||
std::optional<EmlsrParamUpdate> m_emlsrParamUpdate{}; //!< EMLSR Parameter Update field
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup wifi
|
||||
* Implement the FILS (Fast Initial Link Setup) action frame.
|
||||
* See sec. 9.6.7.36 of IEEE 802.11-2020 and IEEE 802.11ax-2021.
|
||||
*/
|
||||
class FilsDiscHeader : public Header
|
||||
{
|
||||
public:
|
||||
FilsDiscHeader();
|
||||
|
||||
/// \return the object TypeId
|
||||
static TypeId GetTypeId();
|
||||
TypeId GetInstanceTypeId() const override;
|
||||
void Print(std::ostream& os) const override;
|
||||
uint32_t GetSerializedSize() const override;
|
||||
void Serialize(Buffer::Iterator start) const override;
|
||||
uint32_t Deserialize(Buffer::Iterator start) override;
|
||||
|
||||
/**
|
||||
* Set the SSID field.
|
||||
*
|
||||
* \param ssid the SSID
|
||||
*/
|
||||
void SetSsid(const std::string& ssid);
|
||||
|
||||
/// \return the SSID
|
||||
const std::string& GetSsid() const;
|
||||
|
||||
/// \return size of FILS Discovery Information field in octets
|
||||
uint32_t GetInformationFieldSize() const;
|
||||
|
||||
/// \return size of non-optional subfields in octets
|
||||
uint32_t GetSizeNonOptSubfields() const;
|
||||
|
||||
/// \brief sets value of Length subfield
|
||||
void SetLengthSubfield();
|
||||
|
||||
/// FILS Discovery Frame Control subfield of FILS Discovery Information field
|
||||
struct FilsDiscFrameControl // 2 octets
|
||||
{
|
||||
uint8_t m_ssidLen : 5 {0}; ///< SSID Length
|
||||
bool m_capPresenceInd{false}; ///< Capability Presence Indicator
|
||||
uint8_t m_shortSsidInd : 1 {0}; ///< Short SSID Indicator (not supported)
|
||||
bool m_apCsnPresenceInd{false}; ///< AP-CSN Presence Indicator
|
||||
bool m_anoPresenceInd{false}; ///< ANO Presence Indicator
|
||||
bool m_chCntrFreqSeg1PresenceInd{false}; ///< Channel Center Frequency Segment 1
|
||||
///< Presence Indicator
|
||||
bool m_primChPresenceInd{false}; ///< Primary Channel Presence Indicator
|
||||
uint8_t m_rsnInfoPresenceInd : 1 {0}; ///< RSN info Presence Indicator (not supported)
|
||||
bool m_lenPresenceInd{false}; ///< Length Presence Indicator
|
||||
uint8_t m_mdPresenceInd : 1 {0}; ///< MD Presence Indicator (not supported)
|
||||
uint8_t m_reserved : 2 {0}; ///< Reserved Bits
|
||||
|
||||
/**
|
||||
* \brief serialize content to a given buffer
|
||||
* \param start given input buffer iterator
|
||||
*/
|
||||
void Serialize(Buffer::Iterator& start) const;
|
||||
|
||||
/**
|
||||
* \brief read content from a given buffer
|
||||
* \param start input buffer iterator
|
||||
* \return number of read octets
|
||||
*/
|
||||
uint32_t Deserialize(Buffer::Iterator start);
|
||||
};
|
||||
|
||||
/// FD Capability subfield of FILS Discovery Information field
|
||||
struct FdCapability // 2 octets
|
||||
{
|
||||
uint8_t m_ess : 1 {0}; ///< ESS
|
||||
uint8_t m_privacy : 1 {0}; ///< Privacy
|
||||
uint8_t m_chWidth : 3 {0}; ///< BSS Operating Channel Width
|
||||
uint8_t m_maxNss : 3 {0}; ///< Maximum Number of Spatial Streams
|
||||
uint8_t m_reserved : 1 {0}; ///< Reserved Bit
|
||||
uint8_t m_multiBssidPresenceInd : 1 {0}; ///< Multiple BSSIDs Presence Indicator
|
||||
uint8_t m_phyIdx : 3 {0}; ///< PHY Index
|
||||
uint8_t m_minRate : 3 {0}; ///< FILS Minimum Rate
|
||||
|
||||
/**
|
||||
* \brief Set the BSS Operating Channel Width field based on the operating channel width
|
||||
* \param width the operating channel width in MHz
|
||||
*/
|
||||
void SetOpChannelWidth(uint16_t width);
|
||||
|
||||
/// \return the operating channel width encoded in the BSS Operating Channel Width field
|
||||
uint16_t GetOpChannelWidth() const;
|
||||
|
||||
/**
|
||||
* \brief Set the Maximum Number of Spatial Streams field
|
||||
* \param maxNss the maximum number of supported spatial streams
|
||||
*/
|
||||
void SetMaxNss(uint8_t maxNss);
|
||||
|
||||
/**
|
||||
* Note that this function returns 5 if the maximum number of supported spatial streams
|
||||
* is greater than 4.
|
||||
*
|
||||
* \return the maximum number of supported spatial streams
|
||||
*/
|
||||
uint8_t GetMaxNss() const;
|
||||
|
||||
/**
|
||||
* \brief Set the PHY Index field based on the given wifi standard
|
||||
* \param standard the wifi standard
|
||||
*/
|
||||
void SetStandard(WifiStandard standard);
|
||||
|
||||
/**
|
||||
* \param band the PHY band in which the device is operating (needed to distinguish
|
||||
* between 802.11a and 802.11g)
|
||||
* \return the wifi standard encoded in the PHY Index field
|
||||
*/
|
||||
WifiStandard GetStandard(WifiPhyBand band) const;
|
||||
|
||||
/**
|
||||
* \brief serialize content to a given buffer
|
||||
* \param start given input buffer iterator
|
||||
*/
|
||||
void Serialize(Buffer::Iterator& start) const;
|
||||
|
||||
/**
|
||||
* \brief read content from a given buffer
|
||||
* \param start input buffer iterator
|
||||
* \return number of read octets
|
||||
*/
|
||||
uint32_t Deserialize(Buffer::Iterator start);
|
||||
};
|
||||
|
||||
// FILS Discovery Frame Information field
|
||||
// TODO: add optional FD-RSN and Mobility domain subfields
|
||||
FilsDiscFrameControl m_frameCtl; ///< FILS Discovery Frame Control
|
||||
uint64_t m_timeStamp{0}; ///< Timestamp
|
||||
uint16_t m_beaconInt{0}; ///< Beacon Interval in TU (1024 us)
|
||||
OptFieldWithPresenceInd<uint8_t> m_len; ///< Length
|
||||
OptFieldWithPresenceInd<FdCapability> m_fdCap; ///< FD Capability
|
||||
std::optional<uint8_t> m_opClass; ///< Operating Class
|
||||
OptFieldWithPresenceInd<uint8_t> m_primaryCh; ///< Primary Channel
|
||||
OptFieldWithPresenceInd<uint8_t>
|
||||
m_apConfigSeqNum; ///< AP Configuration Sequence Number (AP-CSN)
|
||||
OptFieldWithPresenceInd<uint8_t> m_accessNetOpt; ///< Access Network Options
|
||||
OptFieldWithPresenceInd<uint8_t> m_chCntrFreqSeg1; ///< Channel Center Frequency Segment 1
|
||||
|
||||
// (Optional) Information Elements
|
||||
std::optional<ReducedNeighborReport> m_rnr; ///< Reduced Neighbor Report
|
||||
std::optional<Tim> m_tim; ///< Traffic Indication Map element
|
||||
|
||||
private:
|
||||
std::string m_ssid; ///< SSID
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Stream insertion operator.
|
||||
*
|
||||
* \param os the output stream
|
||||
* \param control the Fils Discovery Frame Control field
|
||||
* \returns a reference to the stream
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os, const FilsDiscHeader::FilsDiscFrameControl& control);
|
||||
|
||||
/**
|
||||
* \brief Stream insertion operator.
|
||||
*
|
||||
* \param os the output stream
|
||||
* \param capability the Fils Discovery Frame Capability field
|
||||
* \returns a reference to the stream
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os, const FilsDiscHeader::FdCapability& capability);
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* MGT_ACTION_HEADERS_H */
|
||||
|
||||
@@ -26,6 +26,7 @@ interm
|
||||
|
||||
#Wi-Fi
|
||||
aci
|
||||
fils
|
||||
|
||||
#Wimax
|
||||
aas
|
||||
|
||||
Reference in New Issue
Block a user