11#include "ns3/address-utils.h" 
   13#include "ns3/mgt-headers.h" 
   23    : m_containingFrame(frame),
 
   24      m_commonInfo(
std::in_place_type<
std::monostate>) 
 
 
   87    std::get<BASIC_VARIANT>(
m_commonInfo).m_mldMacAddress = address;
 
 
   93    return std::get<BASIC_VARIANT>(
m_commonInfo).m_mldMacAddress;
 
 
   99    std::get<BASIC_VARIANT>(
m_commonInfo).m_linkIdInfo = (linkIdInfo & 0x0f);
 
 
  105    return std::get<BASIC_VARIANT>(
m_commonInfo).m_linkIdInfo.has_value();
 
 
  111    return std::get<BASIC_VARIANT>(
m_commonInfo).m_linkIdInfo.value();
 
 
  117    std::get<BASIC_VARIANT>(
m_commonInfo).m_bssParamsChangeCount = count;
 
 
  123    return std::get<BASIC_VARIANT>(
m_commonInfo).m_bssParamsChangeCount.has_value();
 
 
  129    return std::get<BASIC_VARIANT>(
m_commonInfo).m_bssParamsChangeCount.value();
 
 
  135    auto& emlCapabilities = std::get<BASIC_VARIANT>(
m_commonInfo).m_emlCapabilities;
 
  136    if (!emlCapabilities.has_value())
 
 
  146    auto& emlCapabilities = std::get<BASIC_VARIANT>(
m_commonInfo).m_emlCapabilities;
 
  147    if (!emlCapabilities.has_value())
 
 
  157    auto& emlCapabilities = std::get<BASIC_VARIANT>(
m_commonInfo).m_emlCapabilities;
 
  158    if (!emlCapabilities.has_value())
 
 
  168    auto& emlCapabilities = std::get<BASIC_VARIANT>(
m_commonInfo).m_emlCapabilities;
 
  169    if (!emlCapabilities.has_value())
 
  177        emlCapabilities->transitionTimeout = 0;
 
  182        for (i = 1; i <= 10; i++)
 
  184            if (1 << (i + 6) == timeoutUs)
 
  186                emlCapabilities->transitionTimeout = i;
 
 
  197    return std::get<BASIC_VARIANT>(
m_commonInfo).m_emlCapabilities.has_value();
 
 
  203    return std::get<BASIC_VARIANT>(
m_commonInfo).m_emlCapabilities->emlsrSupport;
 
 
  209    auto& emlCapabilities = std::get<BASIC_VARIANT>(
m_commonInfo).m_emlCapabilities;
 
 
  217    auto& emlCapabilities = std::get<BASIC_VARIANT>(
m_commonInfo).m_emlCapabilities;
 
 
  225    auto& emlCapabilities = std::get<BASIC_VARIANT>(
m_commonInfo).m_emlCapabilities;
 
  227    if (emlCapabilities->transitionTimeout == 0)
 
  231    return MicroSeconds(1 << (6 + emlCapabilities->transitionTimeout));
 
 
  241        std::get<CommonInfoBasicMle>(
m_commonInfo).m_apMldId = id;
 
  244        std::get<CommonInfoProbeReqMle>(
m_commonInfo).m_apMldId = id;
 
  247        NS_ABORT_MSG(
"AP MLD ID field not present in input variant " << variant);
 
 
  251std::optional<uint8_t>
 
  258        return std::get<CommonInfoBasicMle>(
m_commonInfo).m_apMldId;
 
  260        return std::get<CommonInfoProbeReqMle>(
m_commonInfo).m_apMldId;
 
  262        NS_LOG_DEBUG(
"AP MLD ID field not present in input variant");
 
 
  268    : m_variant(variant),
 
 
  275    : m_variant(perStaProfile.m_variant),
 
  276      m_staControl(perStaProfile.m_staControl),
 
  277      m_staMacAddress(perStaProfile.m_staMacAddress),
 
  278      m_bssParamsChgCnt(perStaProfile.m_bssParamsChgCnt)
 
  281    auto staProfileCopy = [&](
auto&& frame) {
 
  282        using Ptr = std::decay_t<
decltype(frame)>;
 
  283        if constexpr (std::is_same_v<Ptr, std::monostate>)
 
  289            using T = std::decay_t<
decltype(*frame.get())>;
 
 
  300    if (&perStaProfile == 
this)
 
  311    auto staProfileCopy = [&](
auto&& frame) {
 
  312        using Ptr = std::decay_t<
decltype(frame)>;
 
  313        if constexpr (std::is_same_v<Ptr, std::monostate>)
 
  319            using T = std::decay_t<
decltype(*frame.get())>;
 
  320            m_staProfile = std::make_unique<T>(*frame.get());
 
 
  331    m_staControl &= 0xfff0; 
 
  332    m_staControl |= (linkId & 0x0f);
 
 
  338    return static_cast<uint8_t
>(m_staControl & 0x000f);
 
 
  344    m_staControl |= 0x0010;
 
 
  350    return (m_staControl & 0x0010) != 0;
 
 
  357    m_staMacAddress = address;
 
  358    m_staControl |= 0x0020;
 
 
  364    return (m_staControl & 0x0020) != 0;
 
 
  371    return m_staMacAddress;
 
 
  378                    "Expected Basic Variant, variant:" << +
static_cast<uint8_t
>(m_variant));
 
  379    m_bssParamsChgCnt = count;
 
  380    m_staControl |= 0x0800;
 
 
  386    return (m_staControl & 0x0800) != 0;
 
 
  392    NS_ASSERT_MSG(m_bssParamsChgCnt.has_value(), 
"No value set for m_bssParamsChgCnt");
 
  393    NS_ASSERT_MSG(HasBssParamsChgCnt(), 
"BSS Parameters Change count bit not set");
 
  394    return m_bssParamsChgCnt.value();
 
 
  399    const std::variant<MgtAssocRequestHeader, MgtReassocRequestHeader>& assoc)
 
  403            m_staProfile = std::make_unique<std::decay_t<
decltype(frame)>>(frame);
 
 
  410    std::variant<MgtAssocRequestHeader, MgtReassocRequestHeader>&& assoc)
 
  414            using T = std::decay_t<
decltype(frame)>;
 
  415            m_staProfile = std::make_unique<T>(std::forward<T>(frame));
 
 
  423    return std::holds_alternative<std::unique_ptr<MgtAssocRequestHeader>>(m_staProfile);
 
 
  429    return std::holds_alternative<std::unique_ptr<MgtReassocRequestHeader>>(m_staProfile);
 
 
  435    if (HasAssocRequest())
 
  437        return *std::get<std::unique_ptr<MgtAssocRequestHeader>>(m_staProfile);
 
  440    return *std::get<std::unique_ptr<MgtReassocRequestHeader>>(m_staProfile);
 
 
  446    m_staProfile = std::make_unique<MgtAssocResponseHeader>(assoc);
 
 
  452    m_staProfile = std::make_unique<MgtAssocResponseHeader>(std::move(assoc));
 
 
  458    return std::holds_alternative<std::unique_ptr<MgtAssocResponseHeader>>(m_staProfile);
 
 
  465    return *std::get<std::unique_ptr<MgtAssocResponseHeader>>(m_staProfile);
 
 
  471    m_staProfile = std::make_unique<MgtProbeResponseHeader>(probeResp);
 
 
  477    m_staProfile = std::make_unique<MgtProbeResponseHeader>(std::move(probeResp));
 
 
  483    return std::holds_alternative<std::unique_ptr<MgtProbeResponseHeader>>(m_staProfile);
 
 
  490    return *std::get<std::unique_ptr<MgtProbeResponseHeader>>(m_staProfile);
 
 
  503    if (HasStaMacAddress())
 
  507    if (HasBssParamsChgCnt())
 
 
  526    ret += GetStaInfoLength();
 
  528    auto staProfileSize = [&](
auto&& frame) {
 
  529        using T = std::decay_t<
decltype(frame)>;
 
  530        if constexpr (std::is_same_v<T, std::monostate>)
 
  533                          "Missing management frame for Per-STA Profile subelement");
 
  538            using U = std::decay_t<
decltype(*frame)>;
 
  541                "Containing frame type and frame type in Per-STA Profile do not match");
 
  542            const auto& containing = std::get<std::reference_wrapper<const U>>(
m_containingFrame);
 
  543            return frame->GetSerializedSizeInPerStaProfile(containing);
 
  546    ret += std::visit(staProfileSize, m_staProfile);
 
 
  556        NS_ASSERT_MSG(IsCompleteProfileSet(), 
"Encoding of STA Profile not supported");
 
  557        start.WriteHtolsbU16(m_staControl);
 
  561    start.WriteHtolsbU16(m_staControl);
 
  562    start.WriteU8(GetStaInfoLength());
 
  564    if (HasStaMacAddress())
 
  566        WriteTo(start, m_staMacAddress);
 
  568    if (HasBssParamsChgCnt())
 
  570        start.WriteU8(GetBssParamsChgCnt());
 
  573    auto staProfileSerialize = [&](
auto&& frame) {
 
  574        using T = std::decay_t<
decltype(frame)>;
 
  575        if constexpr (std::is_same_v<T, std::monostate>)
 
  578                          "Missing management frame for Per-STA Profile subelement");
 
  583            using U = std::decay_t<
decltype(*frame)>;
 
  586                "Containing frame type and frame type in Per-STA Profile do not match");
 
  587            const auto& containing = std::get<std::reference_wrapper<const U>>(
m_containingFrame);
 
  588            frame->SerializeInPerStaProfile(start, containing);
 
  591    std::visit(staProfileSerialize, m_staProfile);
 
 
  600        return DeserProbeReqMlePerSta(start, length);
 
  608    if (HasStaMacAddress())
 
  612    if (HasBssParamsChgCnt())
 
  614        m_bssParamsChgCnt = i.
ReadU8();
 
  621                  "Bytes read (" << count << 
") exceed expected number (" << length << 
")");
 
  628    auto staProfileDeserialize = [&](
auto&& frame) {
 
  629        using T = std::decay_t<
decltype(frame)>;
 
  630        if constexpr (!std::is_same_v<T, std::monostate>)
 
  632            using U = std::decay_t<
decltype(frame.get())>;
 
  634            count += assoc.DeserializeFromPerStaProfile(i, length - count, frame.get());
 
  635            m_staProfile = std::make_unique<U>(std::move(assoc));
 
 
  648                  "Invalid Multi-link Element variant = " << 
static_cast<uint8_t
>(m_variant));
 
  656                  "Incorrect decoded size count =" << count << 
", length=" << length);
 
  670    NS_LOG_DEBUG(
"Decoding of STA Profile in Per-STA Profile subelement not supported");
 
  671    while (count < length)
 
 
  682    os << 
"Per-STA Profile Subelement=[";
 
  683    os << 
"Variant: " << +
static_cast<uint8_t
>(m_variant);
 
  684    os << 
", STA Control: " << +m_staControl;
 
  685    if (HasStaMacAddress())
 
  687        os << 
", STA MAC Address: " << m_staMacAddress;
 
  689    if (m_bssParamsChgCnt)
 
  691        os << 
", BSS Params Change Count: " << +m_bssParamsChgCnt.value();
 
 
  729        [](
auto&& arg) -> uint8_t {
 
  730            using T = std::decay_t<
decltype(arg)>;
 
  731            if constexpr (std::is_same_v<T, std::monostate>)
 
  738                return arg.GetSize();
 
  746        ret += subelement.GetSerializedSize();
 
 
  757        [
this, &start](
auto&& arg) {
 
  758            using T = std::decay_t<
decltype(arg)>;
 
  759            if constexpr (std::is_same_v<T, std::monostate>)
 
  766                    static_cast<uint8_t
>(
GetVariant()) + (arg.GetPresenceBitmap() << 4);
 
  767                start.WriteHtolsbU16(mlControl);
 
  768                arg.Serialize(start);
 
  775        start = subelement.Serialize(start);
 
 
  789    uint16_t presence = mlControl >> 4;
 
  791    uint8_t nBytes = std::visit(
 
  792        [&i, &presence](
auto&& arg) -> uint8_t {
 
  793            using T = std::decay_t<
decltype(arg)>;
 
  794            if constexpr (std::is_same_v<T, std::monostate>)
 
  801                return arg.Deserialize(i, presence);
 
  808    while (count < length)
 
  816            i = perStaProfile.Deserialize(i);
 
 
  831    os << 
"Multi-Link Element=[Per-STA Profile Subelements: {";
 
  834        subelement.Print(os);
 
 
iterator in a Buffer instance
uint32_t GetDistanceFrom(const Iterator &o) const
void Next()
go forward by one byte
Per-STA Profile Subelement of Multi-Link element.
PerStaProfileSubelement(Variant variant)
Constructor.
Variant m_variant
Multi-Link element variant.
MgtAssocResponseHeader & GetAssocResponse() const
Get the (Re)Association Response frame body included in the STA Profile field of this Per-STA Profile...
std::optional< uint8_t > m_bssParamsChgCnt
BSS Params Change Count (Basic MLE)
AssocReqRefVariant GetAssocRequest() const
Get the (Re)Association Request frame body included in the STA Profile field of this Per-STA Profile ...
std::variant< std::monostate, std::unique_ptr< MgtAssocRequestHeader >, std::unique_ptr< MgtReassocRequestHeader >, 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 ...
void SetProbeResponse(const MgtProbeResponseHeader &probeResp)
Include the given Probe Response frame body in the STA Profile field of this Per-STA Profile subeleme...
bool HasReassocRequest() const
Return true if a Reassociation Request frame body is included in the STA Profile field of this Per-ST...
void Print(std::ostream &os) const override
Generate human-readable form of IE.
Mac48Address GetStaMacAddress() const
Get the STA MAC Address subfield in the STA Info field, if present.
bool HasStaMacAddress() const
Return true if the STA MAC Address subfield in the STA Info field is present.
void SetAssocResponse(const MgtAssocResponseHeader &assoc)
Include the given (Re)Association Response frame body in the STA Profile field of this Per-STA Profil...
PerStaProfileSubelement & operator=(const PerStaProfileSubelement &perStaProfile)
Copy assignment operator performing a deep copy of the object.
uint16_t DeserializeInformationField(Buffer::Iterator start, uint16_t length) override
Deserialize information (i.e., the body of the IE, not including the Element ID and length octets)
uint8_t GetStaInfoLength() const
Get the size in bytes of the serialized STA Info Length subfield of the STA Info field.
WifiInformationElementId ElementId() const override
Get the wifi information element ID.
void SerializeInformationField(Buffer::Iterator start) const override
Serialize information (i.e., the body of the IE, not including the Element ID and length octets)
void SetStaMacAddress(Mac48Address address)
Set the STA MAC Address subfield in the STA Info field.
Mac48Address m_staMacAddress
STA MAC address.
void SetCompleteProfile()
Set the Complete Profile flag in the STA Control field.
void SetAssocRequest(const std::variant< MgtAssocRequestHeader, MgtReassocRequestHeader > &assoc)
Include the given (Re)Association Request frame body in the STA Profile field of this Per-STA Profile...
void SetBssParamsChgCnt(uint8_t count)
Set the BSS Parameters Change Count subfield in the STA Info field.
bool HasProbeResponse() const
Return true if a Probe Response frame body is included in the STA Profile field of this Per-STA Profi...
uint16_t GetInformationFieldSize() const override
Length of serialized information (i.e., the length of the body of the IE, not including the Element I...
bool IsCompleteProfileSet() const
void SetLinkId(uint8_t linkId)
Set the Link ID subfield in the STA Control field.
uint16_t DeserProbeReqMlePerSta(ns3::Buffer::Iterator start, uint16_t length)
Deserialize information of Per-STA Profile Subelement in Probe Request Multi-link Element.
uint8_t GetBssParamsChgCnt() const
Get BSS Parameters Change Count subfield in the STA Info field.
bool HasAssocRequest() const
Return true if an Association Request frame body is included in the STA Profile field of this Per-STA...
uint16_t m_staControl
STA Control field.
uint8_t GetLinkId() const
Get the Link ID subfield in the STA Control field.
bool HasAssocResponse() const
Return true if a (Re)Association Response frame body is included in the STA Profile field of this Per...
MgtProbeResponseHeader & GetProbeResponse() const
Get the Probe Response frame body included in the STA Profile field of this Per-STA Profile subelemen...
bool HasBssParamsChgCnt() const
ContainingFrame m_containingFrame
reference to the mgt frame containing this MLE
uint16_t DeserializeInformationField(Buffer::Iterator start, uint16_t length) override
Deserialize information (i.e., the body of the IE, not including the Element ID and length octets)
uint16_t GetInformationFieldSize() const override
Length of serialized information (i.e., the length of the body of the IE, not including the Element I...
bool HasBssParamsChangeCount() const
Return true if the BSS Parameters Change Count subfield in the Common Info field is present and false...
void AddPerStaProfileSubelement()
Add a Per-STA Profile Subelement in the Link Info field.
void SetEmlsrSupported(bool supported)
Set the EMLSR Support subfield of the EML Capabilities subfield in the Common Info field to 1 if EMLS...
Time GetTransitionTimeout() const
Get the Transition Timeout subfield of the EML Capabilities subfield in the Common Info field.
void SetBssParamsChangeCount(uint8_t count)
Set the BSS Parameters Change Count subfield in the Common Info field.
uint8_t GetBssParamsChangeCount() const
Return the BSS Parameters Change Count subfield in the Common Info field.
void SerializeInformationField(Buffer::Iterator start) const override
Serialize information (i.e., the body of the IE, not including the Element ID and length octets)
void SetLinkIdInfo(uint8_t linkIdInfo)
Set the Link ID Info subfield in the Common Info field.
void SetVariant(Variant variant)
Set the variant of this Multi-Link Element.
Time GetEmlsrTransitionDelay() const
Get the EMLSR Transition Delay subfield of the EML Capabilities subfield in the Common Info field.
std::vector< PerStaProfileSubelement > m_perStaProfileSubelements
Per-STA Profile Subelements.
CommonInfoBasicMle & GetCommonInfoBasic()
void SetEmlsrTransitionDelay(Time delay)
Set the EMLSR Transition Delay subfield of the EML Capabilities subfield in the Common Info field.
std::variant< std::monostate, std::reference_wrapper< const MgtAssocRequestHeader >, std::reference_wrapper< const MgtReassocRequestHeader >, std::reference_wrapper< const MgtAssocResponseHeader >, std::reference_wrapper< const MgtProbeResponseHeader > > ContainingFrame
Typedef for structure holding a reference to the containing frame.
PerStaProfileSubelement & GetPerStaProfile(std::size_t i)
Get a reference to the i-th Per-STA Profile Subelement in the Link Info field.
Variant GetVariant() const
Get the Multi-Link element variant.
Time GetEmlsrPaddingDelay() const
Get the EMLSR Padding Delay subfield of the EML Capabilities subfield in the Common Info field.
void SetEmlsrPaddingDelay(Time delay)
Set the EMLSR Padding Delay subfield of the EML Capabilities subfield in the Common Info field.
CommonInfo m_commonInfo
Common Info field.
bool HasLinkIdInfo() const
Return true if the Link ID Info subfield in the Common Info field is present and false otherwise.
Mac48Address GetMldMacAddress() const
Return the MLD MAC Address subfield in the Common Info field.
void SetApMldId(uint8_t id)
Set the AP MLD ID subfield of Common Info field.
bool HasEmlCapabilities() const
Return true if the EML Capabilities subfield in the Common Info field is present and false otherwise.
bool IsEmlsrSupported() const
Return true if the EMLSR Support subfield of the EML Capabilities subfield in the Common Info field i...
void Print(std::ostream &os) const override
Generate human-readable form of IE.
void SetMldMacAddress(Mac48Address address)
Set the MLD MAC Address subfield in the Common Info field.
MultiLinkElement(ContainingFrame frame={})
Construct a Multi-Link Element with no variant set.
WifiInformationElementId ElementIdExt() const override
Get the wifi information element ID extension.
WifiInformationElementId ElementId() const override
Get the wifi information element ID.
void SetTransitionTimeout(Time timeout)
Set the Transition Timeout subfield of the EML Capabilities subfield in the Common Info field.
std::size_t GetNPerStaProfileSubelements() const
Return the number of Per-STA Profile Subelement in the Link Info field.
uint8_t GetLinkIdInfo() const
Return the Link ID Info subfield in the Common Info field.
std::optional< uint8_t > GetApMldId() const
Get the AP MLD ID subfield of Common Info field (if present).
Smart pointer class similar to boost::intrusive_ptr.
Simulation virtual time values and global simulation resolution.
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_ABORT_UNLESS(cond)
Abnormal program termination if a condition is false.
#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.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Variant
Multi-Link element variants.
SubElementId
SubElement IDs.
@ PER_STA_PROFILE_SUBELEMENT_ID
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
std::variant< std::reference_wrapper< MgtAssocRequestHeader >, std::reference_wrapper< MgtReassocRequestHeader > > AssocReqRefVariant
variant holding a reference to a (Re)Association Request
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.
EML Capabilities subfield.
uint8_t emlsrSupport
EMLSR Support.
uint8_t emlsrPaddingDelay
EMLSR Padding Delay.
uint8_t emlsrTransitionDelay
EMLSR Transition Delay.
Common Info field of the Basic Multi-Link element.
static uint8_t EncodeEmlsrTransitionDelay(Time delay)
static Time DecodeEmlsrTransitionDelay(uint8_t value)
static Time DecodeEmlsrPaddingDelay(uint8_t value)
static uint8_t EncodeEmlsrPaddingDelay(Time delay)
Common Info field of Multi-link Element Probe Request variant.