From 233cb96506cb43e386021551dbc672e77b49333d Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Mon, 6 Feb 2023 14:05:46 +0100 Subject: [PATCH] wifi: APs reply to received EML Operating Mode Notification frame --- src/wifi/model/ap-wifi-mac.cc | 69 ++++++++++++++++++++++++++++++++--- src/wifi/model/ap-wifi-mac.h | 13 +++++++ 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/wifi/model/ap-wifi-mac.cc b/src/wifi/model/ap-wifi-mac.cc index 4a3af1362..4c9c82f93 100644 --- a/src/wifi/model/ap-wifi-mac.cc +++ b/src/wifi/model/ap-wifi-mac.cc @@ -23,7 +23,6 @@ #include "amsdu-subframe-header.h" #include "channel-access-manager.h" -#include "frame-exchange-manager.h" #include "mac-rx-middle.h" #include "mac-tx-middle.h" #include "mgt-headers.h" @@ -36,6 +35,7 @@ #include "wifi-phy.h" #include "ns3/eht-configuration.h" +#include "ns3/eht-frame-exchange-manager.h" #include "ns3/he-configuration.h" #include "ns3/ht-configuration.h" #include "ns3/log.h" @@ -1636,8 +1636,10 @@ ApWifiMac::Receive(Ptr mpdu, uint8_t linkId) } else if (hdr->GetAddr1() == GetFrameExchangeManager(linkId)->GetAddress()) { - if (hdr->IsAssocReq() || hdr->IsReassocReq()) + switch (hdr->GetType()) { + case WIFI_MAC_MGT_ASSOCIATION_REQUEST: + case WIFI_MAC_MGT_REASSOCIATION_REQUEST: { NS_LOG_DEBUG(((hdr->IsAssocReq()) ? "Association" : "Reassociation") << " request received from " << from << ((GetNLinks() > 1) ? " on link ID " + std::to_string(linkId) : "")); @@ -1662,8 +1664,7 @@ ApWifiMac::Receive(Ptr mpdu, uint8_t linkId) SendAssocResp(hdr->GetAddr2(), hdr->IsReassocReq(), linkId); return; } - else if (hdr->IsDisassociation()) - { + case WIFI_MAC_MGT_DISASSOCIATION: { NS_LOG_DEBUG("Disassociation received from " << from); GetWifiRemoteStationManager(linkId)->RecordDisassociated(from); auto& staList = GetLink(linkId).staList; @@ -1689,6 +1690,25 @@ ApWifiMac::Receive(Ptr mpdu, uint8_t linkId) } return; } + case WIFI_MAC_MGT_ACTION: { + auto pkt = mpdu->GetPacket()->Copy(); + auto [category, action] = WifiActionHeader::Remove(pkt); + if (category == WifiActionHeader::PROTECTED_EHT && + action.protectedEhtAction == + WifiActionHeader::PROTECTED_EHT_EML_OPERATING_MODE_NOTIFICATION && + IsAssociated(hdr->GetAddr2())) + { + // received an EML Operating Mode Notification frame from an associated station + MgtEmlOperatingModeNotification frame; + pkt->RemoveHeader(frame); + ReceiveEmlNotification(frame, hdr->GetAddr2(), linkId); + return; + } + break; + } + default:; + // do nothing + } } } @@ -1808,7 +1828,7 @@ ApWifiMac::ReceiveAssocRequest(const AssocReqRefVariant& assoc, { remoteStationManager->AddStationHtCapabilities(from, *htCapabilities); } - // const ExtendedCapabilities& extendedCapabilities = frame.GetExtendedCapabilities (); + // const ExtendedCapabilities& extendedCapabilities = frame.GetExtendedCapabilities(); // TODO: to be completed } if (GetVhtSupported(linkId)) @@ -1917,6 +1937,45 @@ ApWifiMac::ParseReportedStaInfo(const AssocReqRefVariant& assoc, Mac48Address fr std::visit(recvMle, assoc); } +void +ApWifiMac::ReceiveEmlNotification(MgtEmlOperatingModeNotification& frame, + const Mac48Address& sender, + uint8_t linkId) +{ + NS_LOG_FUNCTION(this << frame << sender << linkId); + + auto ehtConfiguration = GetEhtConfiguration(); + + if (BooleanValue emlsrActivated; + !ehtConfiguration || + !ehtConfiguration->GetAttributeFailSafe("EmlsrActivated", emlsrActivated) || + !emlsrActivated.Get()) + { + NS_LOG_DEBUG( + "Received an EML Operating Mode Notification frame but EMLSR is not activated"); + return; + } + + // An AP MLD with dot11EHTEMLSROptionActivated equal to true sets the EMLSR Mode subfield + // to the value obtained from the EMLSR Mode subfield of the received EML Operating Mode + // Notification frame. (Sec. 9.6.35.8 of 802.11be D3.0) + + // When included in a frame sent by an AP affiliated with an AP MLD, the EMLSR Parameter + // Update Control subfield is set to 0. (Sec. 9.6.35.8 of 802.11be D3.0) + frame.m_emlControl.emlsrParamUpdateCtrl = 0; + + // An AP MLD with dot11EHTEMLSROptionImplemented equal to true sets the EMLSR Link Bitmap + // subfield to the value obtained from the EMLSR Link Bitmap subfield of the received + // EML Operating Mode Notification frame. (Sec. 9.6.35.8 of 802.11be D3.0) + + // The EMLSR Parameter Update field [..] is present if [..] the Action frame is sent by + // a non-AP STA affiliated with a non-AP MLD (Sec. 9.6.35.8 of 802.11be D3.0) + frame.m_emlsrParamUpdate.reset(); + + auto ehtFem = StaticCast(GetFrameExchangeManager(linkId)); + ehtFem->SendEmlOperatingModeNotification(sender, frame); +} + void ApWifiMac::DeaggregateAmsduAndForward(Ptr mpdu) { diff --git a/src/wifi/model/ap-wifi-mac.h b/src/wifi/model/ap-wifi-mac.h index a6addbc39..d716b13f9 100644 --- a/src/wifi/model/ap-wifi-mac.h +++ b/src/wifi/model/ap-wifi-mac.h @@ -48,6 +48,7 @@ class UniformRandomVariable; class MgtAssocRequestHeader; class MgtReassocRequestHeader; class MgtAssocResponseHeader; +class MgtEmlOperatingModeNotification; /// variant holding a reference to a (Re)Association Request using AssocReqRefVariant = std::variant, @@ -237,6 +238,18 @@ class ApWifiMac : public WifiMac */ void ParseReportedStaInfo(const AssocReqRefVariant& assoc, Mac48Address from, uint8_t linkId); + /** + * Take necessary actions upon receiving the given EML Operating Mode Notification frame + * from the given station on the given link. + * + * \param frame the received EML Operating Mode Notification frame + * \param sender the MAC address of the sender of the frame + * \param linkId the ID of the link over which the frame was received + */ + void ReceiveEmlNotification(MgtEmlOperatingModeNotification& frame, + const Mac48Address& sender, + uint8_t linkId); + /** * The packet we sent was successfully received by the receiver * (i.e. we received an Ack from the receiver). If the packet