wifi: Add Probe Request MLE variant

This commit is contained in:
Sharan Naribole
2024-05-06 13:19:32 +02:00
committed by Stefano Avallone
parent 7c54cf1212
commit e95689673e
4 changed files with 217 additions and 5 deletions

View File

@@ -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()
{

View File

@@ -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*/>;

View File

@@ -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
***********************************************************/

View File

@@ -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