From ff32f672b46f192c4fd2b3e9bbf53338e41aa611 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Fri, 20 Jun 2025 11:12:29 +0200 Subject: [PATCH] wifi: Split reception and reply for EML OMN frames --- src/wifi/model/ap-wifi-mac.cc | 145 +++++++++++++++++++--------------- src/wifi/model/ap-wifi-mac.h | 28 ++++++- 2 files changed, 106 insertions(+), 67 deletions(-) diff --git a/src/wifi/model/ap-wifi-mac.cc b/src/wifi/model/ap-wifi-mac.cc index 829215904..9ad828f98 100644 --- a/src/wifi/model/ap-wifi-mac.cc +++ b/src/wifi/model/ap-wifi-mac.cc @@ -2148,6 +2148,7 @@ ApWifiMac::Receive(Ptr mpdu, uint8_t linkId) MgtEmlOmn frame; pkt->RemoveHeader(frame); ReceiveEmlOmn(frame, hdr->GetAddr2(), linkId); + RespondToEmlOmn(frame, hdr->GetAddr2(), linkId); return; } break; @@ -2488,7 +2489,7 @@ ApWifiMac::ParseReportedStaInfo(const AssocReqRefVariant& assoc, Mac48Address fr } void -ApWifiMac::ReceiveEmlOmn(MgtEmlOmn& frame, const Mac48Address& sender, uint8_t linkId) +ApWifiMac::ReceiveEmlOmn(const MgtEmlOmn& frame, const Mac48Address& sender, uint8_t linkId) { NS_LOG_FUNCTION(this << frame << sender << linkId); @@ -2512,11 +2513,12 @@ ApWifiMac::ReceiveEmlOmn(MgtEmlOmn& frame, const Mac48Address& sender, uint8_t l emlCapabilities->get().emlsrPaddingDelay = frame.m_emlsrParamUpdate->paddingDelay; emlCapabilities->get().emlsrTransitionDelay = frame.m_emlsrParamUpdate->transitionDelay; } +} - auto mldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(sender); - NS_ASSERT_MSG(mldAddress, "No MLD address stored for STA " << sender); - auto emlsrLinks = - frame.m_emlControl.emlsrMode == 1 ? frame.GetLinkBitmap() : std::list{}; +void +ApWifiMac::RespondToEmlOmn(MgtEmlOmn frame, const Mac48Address& sender, uint8_t linkId) +{ + NS_LOG_FUNCTION(this << frame << sender << linkId); // The AP MLD has to consider the changes carried by the received EML Notification frame // as effective at the same time as the non-AP MLD. Therefore, we need to start a time @@ -2532,65 +2534,13 @@ ApWifiMac::ReceiveEmlOmn(MgtEmlOmn& frame, const Mac48Address& sender, uint8_t l auto ackDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, GetLink(linkId).phy->GetPhyBand()); - m_transitionTimeoutEvents[sender] = Simulator::Schedule( - ackDuration + ehtConfiguration->m_transitionTimeout, - [=, this]() { - for (uint8_t id = 0; id < GetNLinks(); id++) - { - auto linkAddress = - GetWifiRemoteStationManager(id)->GetAffiliatedStaAddress(*mldAddress); - if (!linkAddress) - { - // this link has not been setup by the non-AP MLD - continue; - } - - if (!emlsrLinks.empty()) - { - // the non-AP MLD is enabling EMLSR mode - /** - * After the successful transmission of the EML Operating Mode - * Notification frame by the non-AP STA affiliated with the non-AP MLD, - * the non-AP MLD shall operate in the EMLSR mode and the other non-AP - * STAs operating on the corresponding EMLSR links shall transition to - * active mode after the transition delay indicated in the Transition - * Timeout subfield in the EML Capabilities subfield of the Basic - * Multi-Link element or immediately after receiving an EML Operating - * Mode Notification frame from one of the APs operating on the EMLSR - * links and affiliated with the AP MLD (Sec. 35.3.17 of 802.11be D3.0) - */ - auto enabled = std::find(emlsrLinks.cbegin(), emlsrLinks.cend(), id) != - emlsrLinks.cend(); - if (enabled) - { - StaSwitchingToActiveModeOrDeassociated(*linkAddress, id); - } - GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, enabled); - } - else - { - // the non-AP MLD is disabling EMLSR mode - /** - * After the successful transmission of the EML Operating Mode - * Notification frame by the non-AP STA affiliated with the non-AP MLD, - * the non-AP MLD shall disable the EMLSR mode and the other non-AP - * STAs operating on the corresponding EMLSR links shall transition to - * power save mode after the transition delay indicated in the - * Transition Timeout subfield in the EML Capabilities subfield of the - * Basic Multi-Link element or immediately after receiving an EML - * Operating Mode Notification frame from one of the APs operating on - * the EMLSR links and affiliated with the AP MLD. (Sec. 35.3.17 of - * 802.11be D3.0) - */ - if (id != linkId && - GetWifiRemoteStationManager(id)->GetEmlsrEnabled(*linkAddress)) - { - StaSwitchingToPsMode(*linkAddress, id); - } - GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, false); - } - } - }); + m_transitionTimeoutEvents[sender] = + Simulator::Schedule(ackDuration + GetEhtConfiguration()->m_transitionTimeout, + &ApWifiMac::EmlOmnExchangeCompleted, + this, + frame, + sender, + linkId); }); // connect the callback to the PHY TX begin trace to catch the Ack and disconnect @@ -2620,6 +2570,73 @@ ApWifiMac::ReceiveEmlOmn(MgtEmlOmn& frame, const Mac48Address& sender, uint8_t l ehtFem->SendEmlOmn(sender, frame); } +void +ApWifiMac::EmlOmnExchangeCompleted(const MgtEmlOmn& frame, + const Mac48Address& sender, + uint8_t linkId) +{ + NS_LOG_FUNCTION(this << frame << sender << linkId); + + auto mldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(sender); + NS_ASSERT_MSG(mldAddress, "No MLD address stored for STA " << sender); + auto emlsrLinks = + frame.m_emlControl.emlsrMode == 1 ? frame.GetLinkBitmap() : std::list{}; + + for (uint8_t id = 0; id < GetNLinks(); id++) + { + auto linkAddress = GetWifiRemoteStationManager(id)->GetAffiliatedStaAddress(*mldAddress); + if (!linkAddress) + { + // this link has not been setup by the non-AP MLD + continue; + } + + if (!emlsrLinks.empty()) + { + // the non-AP MLD is enabling EMLSR mode + /** + * After the successful transmission of the EML Operating Mode + * Notification frame by the non-AP STA affiliated with the non-AP MLD, + * the non-AP MLD shall operate in the EMLSR mode and the other non-AP + * STAs operating on the corresponding EMLSR links shall transition to + * active mode after the transition delay indicated in the Transition + * Timeout subfield in the EML Capabilities subfield of the Basic + * Multi-Link element or immediately after receiving an EML Operating + * Mode Notification frame from one of the APs operating on the EMLSR + * links and affiliated with the AP MLD (Sec. 35.3.17 of 802.11be D3.0) + */ + auto enabled = + std::find(emlsrLinks.cbegin(), emlsrLinks.cend(), id) != emlsrLinks.cend(); + if (enabled) + { + StaSwitchingToActiveModeOrDeassociated(*linkAddress, id); + } + GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, enabled); + } + else + { + // the non-AP MLD is disabling EMLSR mode + /** + * After the successful transmission of the EML Operating Mode + * Notification frame by the non-AP STA affiliated with the non-AP MLD, + * the non-AP MLD shall disable the EMLSR mode and the other non-AP + * STAs operating on the corresponding EMLSR links shall transition to + * power save mode after the transition delay indicated in the + * Transition Timeout subfield in the EML Capabilities subfield of the + * Basic Multi-Link element or immediately after receiving an EML + * Operating Mode Notification frame from one of the APs operating on + * the EMLSR links and affiliated with the AP MLD. (Sec. 35.3.17 of + * 802.11be D3.0) + */ + if (id != linkId && GetWifiRemoteStationManager(id)->GetEmlsrEnabled(*linkAddress)) + { + StaSwitchingToPsMode(*linkAddress, id); + } + GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, false); + } + } +} + void ApWifiMac::DeaggregateAmsduAndForward(Ptr mpdu) { diff --git a/src/wifi/model/ap-wifi-mac.h b/src/wifi/model/ap-wifi-mac.h index a29c2cbf2..e6566d2cd 100644 --- a/src/wifi/model/ap-wifi-mac.h +++ b/src/wifi/model/ap-wifi-mac.h @@ -329,14 +329,36 @@ 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. + * Process the EML Operating Mode Notification frame received 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 ReceiveEmlOmn(MgtEmlOmn& frame, const Mac48Address& sender, uint8_t linkId); + void ReceiveEmlOmn(const MgtEmlOmn& frame, const Mac48Address& sender, uint8_t linkId); + + /** + * Respond to the EML Operating Mode Notification frame received 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 RespondToEmlOmn(MgtEmlOmn frame, const Mac48Address& sender, uint8_t linkId); + + /** + * Take necessary actions upon completion of an exchange of EML Operating Mode Notification + * frames. + * + * @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 EmlOmnExchangeCompleted(const MgtEmlOmn& frame, + const Mac48Address& sender, + uint8_t linkId); /** * The packet we sent was successfully received by the receiver