wifi: Add Probe Request MLE variant
This commit is contained in:
committed by
Stefano Avallone
parent
7c54cf1212
commit
e95689673e
@@ -9,10 +9,13 @@
|
||||
#include "multi-link-element.h"
|
||||
|
||||
#include "ns3/address-utils.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/mgt-headers.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("MultiLinkElement");
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
@@ -58,6 +61,9 @@ MultiLinkElement::SetVariant(Variant variant)
|
||||
case BASIC_VARIANT:
|
||||
m_commonInfo = CommonInfoBasicMle();
|
||||
break;
|
||||
case PROBE_REQUEST_VARIANT:
|
||||
m_commonInfo = CommonInfoProbeReqMle();
|
||||
break;
|
||||
default:
|
||||
NS_ABORT_MSG("Unsupported variant: " << +variant);
|
||||
}
|
||||
@@ -401,9 +407,39 @@ MultiLinkElement::PerStaProfileSubelement::GetAssocResponse() const
|
||||
return *std::get<std::unique_ptr<MgtAssocResponseHeader>>(m_staProfile);
|
||||
}
|
||||
|
||||
void
|
||||
MultiLinkElement::PerStaProfileSubelement::SetProbeResponse(const MgtProbeResponseHeader& probeResp)
|
||||
{
|
||||
m_staProfile = std::make_unique<MgtProbeResponseHeader>(probeResp);
|
||||
}
|
||||
|
||||
void
|
||||
MultiLinkElement::PerStaProfileSubelement::SetProbeResponse(MgtProbeResponseHeader&& probeResp)
|
||||
{
|
||||
m_staProfile = std::make_unique<MgtProbeResponseHeader>(std::move(probeResp));
|
||||
}
|
||||
|
||||
bool
|
||||
MultiLinkElement::PerStaProfileSubelement::HasProbeResponse() const
|
||||
{
|
||||
return std::holds_alternative<std::unique_ptr<MgtProbeResponseHeader>>(m_staProfile);
|
||||
}
|
||||
|
||||
MgtProbeResponseHeader&
|
||||
MultiLinkElement::PerStaProfileSubelement::GetProbeResponse() const
|
||||
{
|
||||
NS_ABORT_IF(!HasProbeResponse());
|
||||
return *std::get<std::unique_ptr<MgtProbeResponseHeader>>(m_staProfile);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
MultiLinkElement::PerStaProfileSubelement::GetStaInfoLength() const
|
||||
{
|
||||
if (m_variant == PROBE_REQUEST_VARIANT)
|
||||
{
|
||||
return 0; // IEEE 802.11be 6.0 Figure 9-1072s
|
||||
}
|
||||
|
||||
uint8_t ret = 1; // STA Info Length
|
||||
|
||||
if (HasStaMacAddress())
|
||||
@@ -453,6 +489,13 @@ MultiLinkElement::PerStaProfileSubelement::GetInformationFieldSize() const
|
||||
void
|
||||
MultiLinkElement::PerStaProfileSubelement::SerializeInformationField(Buffer::Iterator start) const
|
||||
{
|
||||
if (m_variant == PROBE_REQUEST_VARIANT)
|
||||
{
|
||||
NS_ASSERT_MSG(IsCompleteProfileSet(), "Encoding of STA Profile not supported");
|
||||
start.WriteHtolsbU16(m_staControl);
|
||||
return;
|
||||
}
|
||||
|
||||
start.WriteHtolsbU16(m_staControl);
|
||||
start.WriteU8(GetStaInfoLength());
|
||||
|
||||
@@ -486,6 +529,11 @@ uint16_t
|
||||
MultiLinkElement::PerStaProfileSubelement::DeserializeInformationField(Buffer::Iterator start,
|
||||
uint16_t length)
|
||||
{
|
||||
if (m_variant == PROBE_REQUEST_VARIANT)
|
||||
{
|
||||
return DeserProbeReqMlePerSta(start, length);
|
||||
}
|
||||
|
||||
Buffer::Iterator i = start;
|
||||
|
||||
m_staControl = i.ReadLsbtohU16();
|
||||
@@ -522,6 +570,42 @@ MultiLinkElement::PerStaProfileSubelement::DeserializeInformationField(Buffer::I
|
||||
return count;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
MultiLinkElement::PerStaProfileSubelement::DeserProbeReqMlePerSta(ns3::Buffer::Iterator start,
|
||||
uint16_t length)
|
||||
{
|
||||
NS_ASSERT_MSG(m_variant == PROBE_REQUEST_VARIANT,
|
||||
"Invalid Multi-link Element variant = " << static_cast<uint8_t>(m_variant));
|
||||
Buffer::Iterator i = start;
|
||||
uint16_t count = 0;
|
||||
|
||||
m_staControl = i.ReadLsbtohU16();
|
||||
count += 2;
|
||||
|
||||
NS_ASSERT_MSG(count <= length,
|
||||
"Incorrect decoded size count =" << count << ", length=" << length);
|
||||
if (count == length)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
// TODO: Support decoding of Partial Per-STA Profile
|
||||
// IEEE 802.11be D5.0 9.4.2.312.3 Probe Request Multi-Link element
|
||||
// If the Complete Profile Requested subfield is set to 0 and the STA Profile field
|
||||
// is present in a Per-STA Profile subelement,
|
||||
// the STA Profile field includes exactly one of the following:
|
||||
// - one Request element (see 9.4.2.9 (Request element)), or
|
||||
// — one Extended Request element (see 9.4.2.10 (Extended Request element)), or
|
||||
// — one Request element and one Extended Request element
|
||||
NS_LOG_DEBUG("Decoding of STA Profile in Per-STA Profile subelement not supported");
|
||||
while (count < length)
|
||||
{
|
||||
i.ReadU8();
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
MultiLinkElement::AddPerStaProfileSubelement()
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define MULTI_LINK_ELEMENT_H
|
||||
|
||||
#include "common-info-basic-mle.h"
|
||||
#include "common-info-probe-req-mle.h"
|
||||
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/wifi-information-element.h"
|
||||
@@ -25,6 +26,7 @@ namespace ns3
|
||||
class MgtAssocRequestHeader;
|
||||
class MgtReassocRequestHeader;
|
||||
class MgtAssocResponseHeader;
|
||||
class MgtProbeResponseHeader;
|
||||
|
||||
/// variant holding a reference to a (Re)Association Request
|
||||
using AssocReqRefVariant = std::variant<std::reference_wrapper<MgtAssocRequestHeader>,
|
||||
@@ -56,7 +58,7 @@ class MultiLinkElement : public WifiInformationElement
|
||||
enum Variant : uint8_t
|
||||
{
|
||||
BASIC_VARIANT = 0,
|
||||
// PROBE_REQUEST_VARIANT,
|
||||
PROBE_REQUEST_VARIANT,
|
||||
// RECONFIGURATION_VARIANT,
|
||||
// TDLS_VARIANT,
|
||||
// PRIORITY_ACCESS_VARIANT,
|
||||
@@ -76,7 +78,8 @@ class MultiLinkElement : public WifiInformationElement
|
||||
using ContainingFrame = std::variant<std::monostate,
|
||||
std::reference_wrapper<const MgtAssocRequestHeader>,
|
||||
std::reference_wrapper<const MgtReassocRequestHeader>,
|
||||
std::reference_wrapper<const MgtAssocResponseHeader>>;
|
||||
std::reference_wrapper<const MgtAssocResponseHeader>,
|
||||
std::reference_wrapper<const MgtProbeResponseHeader>>;
|
||||
|
||||
/**
|
||||
* Construct a Multi-Link Element with no variant set.
|
||||
@@ -388,6 +391,33 @@ class MultiLinkElement : public WifiInformationElement
|
||||
*/
|
||||
MgtAssocResponseHeader& GetAssocResponse() const;
|
||||
|
||||
/**
|
||||
* Include the given Probe Response frame body in the STA Profile field
|
||||
* of this Per-STA Profile subelement
|
||||
*
|
||||
* @param probeResp the given Probe Response frame body
|
||||
*/
|
||||
void SetProbeResponse(const MgtProbeResponseHeader& probeResp);
|
||||
|
||||
/// @copydoc SetProbeResponse
|
||||
void SetProbeResponse(MgtProbeResponseHeader&& probeResp);
|
||||
|
||||
/**
|
||||
* Return true if a Probe Response frame body is included in the
|
||||
* STA Profile field of this Per-STA Profile subelement
|
||||
*
|
||||
* @return true if a Probe Response frame body is included
|
||||
*/
|
||||
bool HasProbeResponse() const;
|
||||
|
||||
/**
|
||||
* Get the Probe Response frame body included in the STA Profile
|
||||
* field of this Per-STA Profile subelement
|
||||
*
|
||||
* @return the Probe Response frame body
|
||||
*/
|
||||
MgtProbeResponseHeader& GetProbeResponse() const;
|
||||
|
||||
/**
|
||||
* Get the size in bytes of the serialized STA Info Length subfield of
|
||||
* the STA Info field
|
||||
@@ -404,13 +434,24 @@ class MultiLinkElement : public WifiInformationElement
|
||||
void SerializeInformationField(Buffer::Iterator start) const override;
|
||||
uint16_t DeserializeInformationField(Buffer::Iterator start, uint16_t length) override;
|
||||
|
||||
/**
|
||||
* Deserialize information of Per-STA Profile Subelement in Probe Request Multi-link
|
||||
* Element.
|
||||
*
|
||||
* @param start an iterator which points to where the information should be written
|
||||
* @param length the expected number of octets to read
|
||||
* @return the number of octets read
|
||||
*/
|
||||
uint16_t DeserProbeReqMlePerSta(ns3::Buffer::Iterator start, uint16_t length);
|
||||
|
||||
Variant m_variant; //!< Multi-Link element variant
|
||||
uint16_t m_staControl; //!< STA Control field
|
||||
Mac48Address m_staMacAddress; //!< STA MAC address
|
||||
std::variant<std::monostate,
|
||||
std::unique_ptr<MgtAssocRequestHeader>,
|
||||
std::unique_ptr<MgtReassocRequestHeader>,
|
||||
std::unique_ptr<MgtAssocResponseHeader>>
|
||||
std::unique_ptr<MgtAssocResponseHeader>,
|
||||
std::unique_ptr<MgtProbeResponseHeader>>
|
||||
m_staProfile; /**< STA Profile field, containing the frame body of a frame of the
|
||||
same type as the frame containing the Multi-Link Element */
|
||||
};
|
||||
@@ -450,6 +491,7 @@ class MultiLinkElement : public WifiInformationElement
|
||||
|
||||
/// Typedef for structure holding a Common Info field
|
||||
using CommonInfo = std::variant<CommonInfoBasicMle,
|
||||
CommonInfoProbeReqMle,
|
||||
// TODO Add other variants
|
||||
std::monostate /* UNSET variant*/>;
|
||||
|
||||
|
||||
@@ -93,6 +93,8 @@ MgtProbeResponseHeader::GetTimestamp() const
|
||||
uint32_t
|
||||
MgtProbeResponseHeader::GetSerializedSizeImpl() const
|
||||
{
|
||||
SetMleContainingFrame();
|
||||
|
||||
uint32_t size = 8 /* timestamp */ + 2 /* beacon interval */;
|
||||
size += m_capability.GetSerializedSize();
|
||||
size += WifiMgtHeader<MgtProbeResponseHeader, ProbeResponseElems>::GetSerializedSizeImpl();
|
||||
@@ -102,6 +104,8 @@ MgtProbeResponseHeader::GetSerializedSizeImpl() const
|
||||
void
|
||||
MgtProbeResponseHeader::SerializeImpl(Buffer::Iterator start) const
|
||||
{
|
||||
SetMleContainingFrame();
|
||||
|
||||
Buffer::Iterator i = start;
|
||||
i.WriteHtolsbU64(Simulator::Now().GetMicroSeconds());
|
||||
i.WriteHtolsbU16(static_cast<uint16_t>(m_beaconInterval / 1024));
|
||||
@@ -118,7 +122,20 @@ MgtProbeResponseHeader::DeserializeImpl(Buffer::Iterator start)
|
||||
m_beaconInterval *= 1024;
|
||||
i = m_capability.Deserialize(i);
|
||||
auto distance = i.GetDistanceFrom(start);
|
||||
return distance + WifiMgtHeader<MgtProbeResponseHeader, ProbeResponseElems>::DeserializeImpl(i);
|
||||
distance += WifiMgtHeader<MgtProbeResponseHeader, ProbeResponseElems>::DeserializeImpl(i);
|
||||
if (auto& mle = Get<MultiLinkElement>())
|
||||
{
|
||||
for (std::size_t id = 0; id < mle->GetNPerStaProfileSubelements(); ++id)
|
||||
{
|
||||
auto& perStaProfile = mle->GetPerStaProfile(id);
|
||||
if (perStaProfile.HasProbeResponse())
|
||||
{
|
||||
auto& frameInPerStaProfile = perStaProfile.GetProbeResponse();
|
||||
frameInPerStaProfile.CopyIesFromContainingFrame(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
@@ -270,6 +287,44 @@ MgtAssocRequestHeader::DeserializeFromPerStaProfileImpl(Buffer::Iterator start,
|
||||
DeserializeFromPerStaProfileImpl(i, length - distance, frame);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MgtProbeResponseHeader::GetSerializedSizeInPerStaProfileImpl(
|
||||
const MgtProbeResponseHeader& frame) const
|
||||
{
|
||||
uint32_t size = 0;
|
||||
size += m_capability.GetSerializedSize();
|
||||
size +=
|
||||
MgtHeaderInPerStaProfile<MgtProbeResponseHeader,
|
||||
ProbeResponseElems>::GetSerializedSizeInPerStaProfileImpl(frame);
|
||||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
MgtProbeResponseHeader::SerializeInPerStaProfileImpl(Buffer::Iterator start,
|
||||
const MgtProbeResponseHeader& frame) const
|
||||
{
|
||||
auto i = start;
|
||||
i = m_capability.Serialize(i);
|
||||
MgtHeaderInPerStaProfile<MgtProbeResponseHeader,
|
||||
ProbeResponseElems>::SerializeInPerStaProfileImpl(i, frame);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MgtProbeResponseHeader::DeserializeFromPerStaProfileImpl(Buffer::Iterator start,
|
||||
uint16_t length,
|
||||
const MgtProbeResponseHeader& frame)
|
||||
{
|
||||
auto i = start;
|
||||
m_timestamp = frame.GetTimestamp();
|
||||
m_beaconInterval = frame.GetBeaconIntervalUs();
|
||||
i = m_capability.Deserialize(i);
|
||||
auto distance = i.GetDistanceFrom(start);
|
||||
NS_ASSERT_MSG(distance <= length,
|
||||
"Bytes read (" << distance << ") exceed expected number (" << length << ")");
|
||||
return distance + MgtHeaderInPerStaProfile<MgtProbeResponseHeader, ProbeResponseElems>::
|
||||
DeserializeFromPerStaProfileImpl(i, length - distance, frame);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Ressoc Request
|
||||
***********************************************************/
|
||||
|
||||
@@ -87,6 +87,7 @@ using ProbeRequestElems = std::tuple<Ssid,
|
||||
std::optional<VhtCapabilities>,
|
||||
std::optional<HeCapabilities>,
|
||||
std::optional<He6GhzBandCapabilities>,
|
||||
std::optional<MultiLinkElement>,
|
||||
std::optional<EhtCapabilities>>;
|
||||
|
||||
/// List of Information Elements included in Probe Response frames
|
||||
@@ -441,9 +442,11 @@ class MgtProbeRequestHeader : public WifiMgtHeader<MgtProbeRequestHeader, ProbeR
|
||||
* @ingroup wifi
|
||||
* Implement the header for management frames of type probe response.
|
||||
*/
|
||||
class MgtProbeResponseHeader : public WifiMgtHeader<MgtProbeResponseHeader, ProbeResponseElems>
|
||||
class MgtProbeResponseHeader
|
||||
: public MgtHeaderInPerStaProfile<MgtProbeResponseHeader, ProbeResponseElems>
|
||||
{
|
||||
friend class WifiMgtHeader<MgtProbeResponseHeader, ProbeResponseElems>;
|
||||
friend class MgtHeaderInPerStaProfile<MgtProbeResponseHeader, ProbeResponseElems>;
|
||||
|
||||
public:
|
||||
~MgtProbeResponseHeader() override = default;
|
||||
@@ -492,6 +495,34 @@ class MgtProbeResponseHeader : public WifiMgtHeader<MgtProbeResponseHeader, Prob
|
||||
/** @copydoc Header::Deserialize */
|
||||
uint32_t DeserializeImpl(Buffer::Iterator start);
|
||||
|
||||
/**
|
||||
* @param frame the frame containing the Multi-Link Element
|
||||
* @return the number of bytes that are needed to serialize this header into a Per-STA Profile
|
||||
* subelement of the Multi-Link Element
|
||||
*/
|
||||
uint32_t GetSerializedSizeInPerStaProfileImpl(const MgtProbeResponseHeader& frame) const;
|
||||
|
||||
/**
|
||||
* Serialize this header into a Per-STA Profile subelement of a Multi-Link Element
|
||||
*
|
||||
* @param start an iterator which points to where the header should be written
|
||||
* @param frame the frame containing the Multi-Link Element
|
||||
*/
|
||||
void SerializeInPerStaProfileImpl(Buffer::Iterator start,
|
||||
const MgtProbeResponseHeader& frame) const;
|
||||
|
||||
/**
|
||||
* Deserialize this header from a Per-STA Profile subelement of a Multi-Link Element.
|
||||
*
|
||||
* @param start an iterator which points to where the header should be read from
|
||||
* @param length the expected number of bytes to read
|
||||
* @param frame the frame containing the Multi-Link Element
|
||||
* @return the number of bytes read
|
||||
*/
|
||||
uint32_t DeserializeFromPerStaProfileImpl(Buffer::Iterator start,
|
||||
uint16_t length,
|
||||
const MgtProbeResponseHeader& frame);
|
||||
|
||||
private:
|
||||
uint64_t m_timestamp; //!< Timestamp
|
||||
uint64_t m_beaconInterval; //!< Beacon interval
|
||||
|
||||
Reference in New Issue
Block a user