diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.cc b/src/wifi/model/eht/eht-frame-exchange-manager.cc index a42b5fccb..f9a918eea 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.cc +++ b/src/wifi/model/eht/eht-frame-exchange-manager.cc @@ -331,6 +331,31 @@ EhtFrameExchangeManager::ForwardPsduDown(Ptr psdu, WifiTxVector& auto txDuration = WifiPhy::CalculateTxDuration(psdu, txVector, m_phy->GetPhyBand()); + if (m_apMac && psdu->GetHeader(0).IsTrigger()) + { + for (const auto& client : m_sentRtsTo) + { + if (!GetWifiRemoteStationManager()->GetEmlsrEnabled(client)) + { + continue; + } + auto clientMld = GetWifiRemoteStationManager()->GetMldAddress(client); + NS_ASSERT(clientMld); + + // block transmissions on the other EMLSR links of the EMLSR clients + for (uint8_t linkId = 0; linkId < m_apMac->GetNLinks(); ++linkId) + { + if (linkId != m_linkId && + m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*clientMld)) + { + m_mac->BlockUnicastTxOnLinks(WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK, + *clientMld, + {linkId}); + } + } + } + } + HeFrameExchangeManager::ForwardPsduDown(psdu, txVector); UpdateTxopEndOnTxStart(txDuration, psdu->GetDuration()); @@ -676,54 +701,51 @@ EhtFrameExchangeManager::GetMostRecentRssi(const Mac48Address& address) const } void -EhtFrameExchangeManager::SendMuRts(const WifiTxParameters& txParams) +EhtFrameExchangeManager::SetIcfPaddingAndTxVector(CtrlTriggerHeader& trigger, + WifiTxVector& txVector) const { - NS_LOG_FUNCTION(this << &txParams); + NS_LOG_FUNCTION(this << trigger << txVector); - uint8_t maxPaddingDelay = 0; - - // block transmissions on the other EMLSR links of the EMLSR clients - for (const auto& address : m_sentRtsTo) + if (!trigger.IsMuRts() && !trigger.IsBsrp()) { - if (!GetWifiRemoteStationManager()->GetEmlsrEnabled(address)) + NS_LOG_INFO("Not an ICF"); + return; + } + + const auto recipients = GetTfRecipients(trigger); + uint8_t maxPaddingDelay = 0; + bool isUnprotectedEmlsrDst = false; + + for (const auto& address : recipients) + { + if (!GetWifiRemoteStationManager()->GetEmlsrEnabled(address) || + m_protectedStas.contains(address)) { - continue; + continue; // not an EMLSR client or EMLSR client already protected } + isUnprotectedEmlsrDst = true; auto emlCapabilities = GetWifiRemoteStationManager()->GetStationEmlCapabilities(address); NS_ASSERT(emlCapabilities); maxPaddingDelay = std::max(maxPaddingDelay, emlCapabilities->get().emlsrPaddingDelay); + } - auto mldAddress = GetWifiRemoteStationManager()->GetMldAddress(address); - NS_ASSERT(mldAddress); - - for (uint8_t linkId = 0; linkId < m_apMac->GetNLinks(); linkId++) - { - if (linkId != m_linkId && - m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress)) - { - m_mac->BlockUnicastTxOnLinks(WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK, - *mldAddress, - {linkId}); - } - } + if (isUnprotectedEmlsrDst) + { + // The initial Control frame of frame exchanges shall be sent in the non-HT PPDU or + // non-HT duplicate PPDU format using a rate of 6 Mb/s, 12 Mb/s, or 24 Mb/s. + // (Sec. 35.3.17 of 802.11be D3.0) + GetWifiRemoteStationManager()->AdjustTxVectorForIcf(txVector); } // add padding (if needed) if (maxPaddingDelay > 0) { - NS_ASSERT(txParams.m_protection && - txParams.m_protection->method == WifiProtection::MU_RTS_CTS); - auto protection = static_cast(txParams.m_protection.get()); - NS_ASSERT(protection->muRts.IsMuRts()); - // see formula (35-1) in Sec. 35.5.2.2.3 of 802.11be D3.0 - auto rate = protection->muRtsTxVector.GetMode().GetDataRate(protection->muRtsTxVector); + auto rate = txVector.GetMode().GetDataRate(txVector); std::size_t nDbps = rate / 1e6 * 4; // see Table 17-4 of 802.11-2020 - protection->muRts.SetPaddingSize((1 << (maxPaddingDelay + 2)) * nDbps / 8); + trigger.SetPaddingSize((1 << (maxPaddingDelay + 2)) * nDbps / 8); } - - HeFrameExchangeManager::SendMuRts(txParams); } void diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.h b/src/wifi/model/eht/eht-frame-exchange-manager.h index 124fdf7cc..7bc0be450 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.h +++ b/src/wifi/model/eht/eht-frame-exchange-manager.h @@ -161,6 +161,15 @@ class EhtFrameExchangeManager : public HeFrameExchangeManager */ EventId& GetOngoingTxopEndEvent(); + /** + * Set the padding and the TXVECTOR of the given Trigger Frame, in case it is an Initial + * Control Frame for some EMLSR client(s). + * + * \param trigger the given Trigger Frame + * \param txVector the TXVECTOR used to transmit the Trigger Frame + */ + void SetIcfPaddingAndTxVector(CtrlTriggerHeader& trigger, WifiTxVector& txVector) const; + /// ICF drop reason traced callback (WifiMac exposes this trace source) TracedCallback m_icfDropCallback; @@ -169,7 +178,6 @@ class EhtFrameExchangeManager : public HeFrameExchangeManager void RxStartIndication(WifiTxVector txVector, Time psduDuration) override; void ForwardPsduDown(Ptr psdu, WifiTxVector& txVector) override; void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector& txVector) override; - void SendMuRts(const WifiTxParameters& txParams) override; void CtsAfterMuRtsTimeout(Ptr muRts, const WifiTxVector& txVector) override; void SendCtsAfterMuRts(const WifiMacHeader& muRtsHdr, const CtrlTriggerHeader& trigger, diff --git a/src/wifi/model/he/he-frame-exchange-manager.cc b/src/wifi/model/he/he-frame-exchange-manager.cc index f158a8bae..555bed9a9 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.cc +++ b/src/wifi/model/he/he-frame-exchange-manager.cc @@ -265,7 +265,12 @@ HeFrameExchangeManager::StartProtection(const WifiTxParameters& txParams) "Cannot use RTS/CTS with MU PPDUs"); if (txParams.m_protection->method == WifiProtection::MU_RTS_CTS) { - RecordSentMuRtsTo(txParams); + auto protection = static_cast(txParams.m_protection.get()); + + NS_ASSERT(protection->muRts.IsMuRts()); + NS_ASSERT(m_sentRtsTo.empty()); + m_sentRtsTo = GetTfRecipients(protection->muRts); + SendMuRts(txParams); } else @@ -274,25 +279,21 @@ HeFrameExchangeManager::StartProtection(const WifiTxParameters& txParams) } } -void -HeFrameExchangeManager::RecordSentMuRtsTo(const WifiTxParameters& txParams) +std::set +HeFrameExchangeManager::GetTfRecipients(const CtrlTriggerHeader& trigger) const { - NS_LOG_FUNCTION(this << &txParams); - - NS_ASSERT(txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS); - auto protection = static_cast(txParams.m_protection.get()); - - NS_ASSERT(protection->muRts.IsMuRts()); - NS_ASSERT_MSG(m_apMac, "APs only can send MU-RTS TF"); + std::set recipients; + NS_ASSERT_MSG(m_apMac, "APs only can send Trigger Frames"); const auto& aidAddrMap = m_apMac->GetStaList(m_linkId); - NS_ASSERT(m_sentRtsTo.empty()); - for (const auto& userInfo : protection->muRts) + for (const auto& userInfo : trigger) { const auto addressIt = aidAddrMap.find(userInfo.GetAid12()); NS_ASSERT_MSG(addressIt != aidAddrMap.end(), "AID not found"); - m_sentRtsTo.insert(addressIt->second); + recipients.insert(addressIt->second); } + + return recipients; } void diff --git a/src/wifi/model/he/he-frame-exchange-manager.h b/src/wifi/model/he/he-frame-exchange-manager.h index b21f68053..422bfd82c 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.h +++ b/src/wifi/model/he/he-frame-exchange-manager.h @@ -129,6 +129,14 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager */ bool UlMuCsMediumIdle(const CtrlTriggerHeader& trigger) const; + /** + * Get the (link) address of the non-AP stations solicited by the given Trigger Frame. + * + * \param trigger the given Trigger Frame + * \return the (link) address of the non-AP stations solicited by the given Trigger Frame + */ + std::set GetTfRecipients(const CtrlTriggerHeader& trigger) const; + protected: void DoDispose() override; void Reset() override; @@ -180,13 +188,6 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager Time txDuration, Time response) const; - /** - * Record the stations being solicited by an MU-RTS TF. - * - * \param txParams the TX parameters for the data frame protected by the MU-RTS TF. - */ - void RecordSentMuRtsTo(const WifiTxParameters& txParams); - /** * Send an MU-RTS to begin an MU-RTS/CTS frame exchange protecting an MU PPDU. * diff --git a/src/wifi/model/wifi-default-protection-manager.cc b/src/wifi/model/wifi-default-protection-manager.cc index 91b753ad3..230d390d3 100644 --- a/src/wifi/model/wifi-default-protection-manager.cc +++ b/src/wifi/model/wifi-default-protection-manager.cc @@ -9,12 +9,12 @@ #include "wifi-default-protection-manager.h" #include "ap-wifi-mac.h" -#include "frame-exchange-manager.h" #include "sta-wifi-mac.h" #include "wifi-mpdu.h" #include "wifi-tx-parameters.h" #include "ns3/boolean.h" +#include "ns3/eht-frame-exchange-manager.h" #include "ns3/emlsr-manager.h" #include "ns3/erp-ofdm-phy.h" #include "ns3/log.h" @@ -310,12 +310,12 @@ WifiDefaultProtectionManager::TryAddMpduToMuPpdu(Ptr mpdu, } } - // The initial Control frame of frame exchanges shall be sent in the non-HT PPDU or - // non-HT duplicate PPDU format using a rate of 6 Mb/s, 12 Mb/s, or 24 Mb/s. - // (Sec. 35.3.17 of 802.11be D3.0) if (isEmlsrDestination && !isProtected) { - GetWifiRemoteStationManager()->AdjustTxVectorForIcf(protection->muRtsTxVector); + // This MU-RTS is an ICF for some EMLSR client + auto ehtFem = + StaticCast(m_mac->GetFrameExchangeManager(m_linkId)); + ehtFem->SetIcfPaddingAndTxVector(protection->muRts, protection->muRtsTxVector); } return std::unique_ptr(protection); @@ -395,12 +395,11 @@ WifiDefaultProtectionManager::TryUlMuTransmission(Ptr mpdu, { protection->muRtsTxVector.SetMode(ErpOfdmPhy::GetErpOfdmRate6Mbps()); } - // The initial Control frame of frame exchanges shall be sent in the non-HT PPDU or - // non-HT duplicate PPDU format using a rate of 6 Mb/s, 12 Mb/s, or 24 Mb/s. - // (Sec. 35.3.17 of 802.11be D3.0) if (isUnprotectedEmlsrDst) { - GetWifiRemoteStationManager()->AdjustTxVectorForIcf(protection->muRtsTxVector); + // This MU-RTS is an ICF for some EMLSR client + auto ehtFem = StaticCast(m_mac->GetFrameExchangeManager(m_linkId)); + ehtFem->SetIcfPaddingAndTxVector(protection->muRts, protection->muRtsTxVector); } return protection;