From ea474ecbbc170f1e5ff242773838d78a84dec6e3 Mon Sep 17 00:00:00 2001 From: Sharan Naribole Date: Mon, 6 May 2024 17:04:49 +0200 Subject: [PATCH] wifi: Add StaWifiMac Multi-link Probe Request generation --- src/wifi/model/sta-wifi-mac.cc | 81 ++++++++++++++++---- src/wifi/model/sta-wifi-mac.h | 50 ++++++++++-- src/wifi/model/wifi-default-assoc-manager.cc | 7 +- 3 files changed, 116 insertions(+), 22 deletions(-) diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index ca69bc438..7f0f2d1c1 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -349,18 +349,9 @@ StaWifiMac::IsEmlsrLink(uint8_t linkId) const return GetLink(linkId).emlsrEnabled; } -void -StaWifiMac::SendProbeRequest(uint8_t linkId) +MgtProbeRequestHeader +StaWifiMac::GetProbeRequest(uint8_t linkId) const { - NS_LOG_FUNCTION(this << linkId); - WifiMacHeader hdr; - hdr.SetType(WIFI_MAC_MGT_PROBE_REQUEST); - hdr.SetAddr1(Mac48Address::GetBroadcast()); - hdr.SetAddr2(GetFrameExchangeManager(linkId)->GetAddress()); - hdr.SetAddr3(Mac48Address::GetBroadcast()); - hdr.SetDsNotFrom(); - hdr.SetDsNotTo(); - Ptr packet = Create(); MgtProbeRequestHeader probe; probe.Get() = GetSsid(); auto supportedRates = GetSupportedRates(linkId); @@ -387,7 +378,45 @@ StaWifiMac::SendProbeRequest(uint8_t linkId) { probe.Get() = GetEhtCapabilities(linkId); } - packet->AddHeader(probe); + return probe; +} + +MgtProbeRequestHeader +StaWifiMac::GetMultiLinkProbeRequest(uint8_t linkId, + const std::vector& apLinkIds, + std::optional apMldId) const +{ + NS_LOG_FUNCTION(this << linkId << apMldId.has_value()); + auto req = GetProbeRequest(linkId); + + if (GetNLinks() == 1) + { + // Single link (non-EHT) device + NS_LOG_DEBUG("Single link device does not support Multi-link operation, not including " + "Multi-link Element"); + return req; + } + + req.Get() = GetProbeReqMultiLinkElement(apLinkIds, apMldId); + return req; +} + +void +StaWifiMac::EnqueueProbeRequest(const MgtProbeRequestHeader& probeReq, + uint8_t linkId, + const Mac48Address& addr1, + const Mac48Address& addr3) +{ + NS_LOG_FUNCTION(this << linkId << addr1 << addr3); + WifiMacHeader hdr(WIFI_MAC_MGT_PROBE_REQUEST); + hdr.SetAddr1(addr1); + hdr.SetAddr2(GetFrameExchangeManager(linkId)->GetAddress()); + hdr.SetAddr3(addr3); + hdr.SetDsNotFrom(); + hdr.SetDsNotTo(); + + auto packet = Create(); + packet->AddHeader(probeReq); if (!GetQosSupported()) { @@ -460,7 +489,7 @@ StaWifiMac::GetAssociationRequest(bool isReassoc, uint8_t linkId) const } MultiLinkElement -StaWifiMac::GetMultiLinkElement(bool isReassoc, uint8_t linkId) const +StaWifiMac::GetBasicMultiLinkElement(bool isReassoc, uint8_t linkId) const { NS_LOG_FUNCTION(this << isReassoc << +linkId); @@ -538,6 +567,30 @@ StaWifiMac::GetMultiLinkElement(bool isReassoc, uint8_t linkId) const return multiLinkElement; } +MultiLinkElement +StaWifiMac::GetProbeReqMultiLinkElement(const std::vector& apLinkIds, + std::optional apMldId) const +{ + // IEEE 802.11be D6.0 9.4.2.321.3 + MultiLinkElement mle(MultiLinkElement::PROBE_REQUEST_VARIANT); + if (apMldId.has_value()) + { + mle.SetApMldId(*apMldId); + } + + for (const auto apLinkId : apLinkIds) + { + mle.AddPerStaProfileSubelement(); + auto& perStaProfile = mle.GetPerStaProfile(mle.GetNPerStaProfileSubelements() - 1); + perStaProfile.SetLinkId(apLinkId); + // Current support limited to Complete Profile request per link ID + // TODO: Add support for Partial Per-STA Profile request + perStaProfile.SetCompleteProfile(); + }; + + return mle; +} + std::vector StaWifiMac::GetTidToLinkMappingElements(WifiTidToLinkMappingNegSupport apNegSupport) { @@ -647,7 +700,7 @@ StaWifiMac::SendAssociationRequest(bool isReassoc) GetWifiRemoteStationManager(linkId)->GetMldAddress(*link.bssid).has_value()) { auto addMle = [&](auto&& frame) { - frame.template Get() = GetMultiLinkElement(isReassoc, linkId); + frame.template Get() = GetBasicMultiLinkElement(isReassoc, linkId); }; std::visit(addMle, frame); diff --git a/src/wifi/model/sta-wifi-mac.h b/src/wifi/model/sta-wifi-mac.h index 28b10400b..832df1803 100644 --- a/src/wifi/model/sta-wifi-mac.h +++ b/src/wifi/model/sta-wifi-mac.h @@ -204,11 +204,38 @@ class StaWifiMac : public WifiMac Ptr GetEmlsrManager() const; /** - * Enqueue a probe request packet for transmission on the given link. + * Get the frame body of the Probe Request to transmit on the given link. * * @param linkId the ID of the given link + * @return the Probe Request frame body */ - void SendProbeRequest(uint8_t linkId); + MgtProbeRequestHeader GetProbeRequest(uint8_t linkId) const; + + /** + * Get the frame body of the Multi-Link Probe Request to transmit on the given link. + * + * @param linkId the ID of the given link + * @param apLinkIds ID of the links on which the requested APs, affiliated with the + * AP MLD, operate + * @param apMldId the AP MLD ID to include in the Common Info field + * @return the Multi-Link Probe Request frame body + */ + MgtProbeRequestHeader GetMultiLinkProbeRequest(uint8_t linkId, + const std::vector& apLinkIds, + std::optional apMldId) const; + + /** + * Enqueue the given probe request packet for transmission on the given link. + * + * @param probeReq the given Probe Request frame body + * @param linkId the ID of the given link + * @param addr1 the MAC address for the Address1 field + * @param addr3 the MAC address for the Address3 field + */ + void EnqueueProbeRequest(const MgtProbeRequestHeader& probeReq, + uint8_t linkId, + const Mac48Address& addr1 = Mac48Address::GetBroadcast(), + const Mac48Address& addr3 = Mac48Address::GetBroadcast()); /** * This method is called after wait beacon timeout or wait probe request timeout has @@ -474,6 +501,7 @@ class StaWifiMac : public WifiMac * @return true if we are waiting for an association response from an AP, false otherwise */ bool IsWaitAssocResp() const; + /** * This method is called after we have not received a beacon from the AP on any link. */ @@ -497,14 +525,24 @@ class StaWifiMac : public WifiMac */ AllSupportedRates GetSupportedRates(uint8_t linkId) const; /** - * Return the Multi-Link Element to include in the management frames transmitted + * Return the Basic Multi-Link Element to include in the management frames transmitted * on the given link * - * @param isReassoc whether the Multi-Link Element is included in a Reassociation Request + * @param isReassoc whether the Basic Multi-Link Element is included in a Reassociation Request * @param linkId the ID of the given link - * @return the Multi-Link Element + * @return the Basic Multi-Link Element */ - MultiLinkElement GetMultiLinkElement(bool isReassoc, uint8_t linkId) const; + MultiLinkElement GetBasicMultiLinkElement(bool isReassoc, uint8_t linkId) const; + + /** + * Return the Probe Request Multi-Link Element to include in the management frames to transmit. + * + * @param apLinkIds ID of the links on which the requested APs operate + * @param apMldId the AP MLD ID to include in the Common Info field + * @return the Probe Request Multi-Link Element + */ + MultiLinkElement GetProbeReqMultiLinkElement(const std::vector& apLinkIds, + std::optional apMldId) const; /** * @param apNegSupport the negotiation type supported by the AP MLD diff --git a/src/wifi/model/wifi-default-assoc-manager.cc b/src/wifi/model/wifi-default-assoc-manager.cc index e05e3b6d1..a6ac45dd6 100644 --- a/src/wifi/model/wifi-default-assoc-manager.cc +++ b/src/wifi/model/wifi-default-assoc-manager.cc @@ -90,9 +90,12 @@ WifiDefaultAssocManager::DoStartScanning() for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++) { Simulator::Schedule(GetScanParams().probeDelay, - &StaWifiMac::SendProbeRequest, + &StaWifiMac::EnqueueProbeRequest, m_mac, - linkId); + m_mac->GetProbeRequest(linkId), + linkId, + Mac48Address::GetBroadcast(), + Mac48Address::GetBroadcast()); } m_probeRequestEvent = Simulator::Schedule(GetScanParams().probeDelay + GetScanParams().maxChannelTime,