From 73751ccbde88ecaa0d7a059dfa0bb957b7ee941e Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Thu, 11 Apr 2024 19:04:36 +0200 Subject: [PATCH] wifi: Add TX duration threshold to enable RTS/CTS protection --- CHANGES.md | 1 + .../model/wifi-default-protection-manager.cc | 17 ++++++-------- .../model/wifi-default-protection-manager.h | 9 ++++---- src/wifi/model/wifi-remote-station-manager.cc | 23 ++++++++++++++----- src/wifi/model/wifi-remote-station-manager.h | 8 ++++--- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a1d8fb7f2..ff31b3871 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,7 @@ Changes from ns-3.41 to ns-3-dev redundant code in existing helpers and reducing the burden to add yet another helper when a new application model is added. * (wifi) Added a new **SingleRtsPerTxop** attribute to `WifiDefaultProtectionManager`, which, if set to true, prevents to use protection mechanisms (RTS or MU-RTS) more than once in a TXOP (unless required for specific purposes, such as transmitting an Initial Control Frame to an EMLSR client). +* (wifi) Added a new **RtsCtsTxDurationThresh** to `WifiRemoteStationManager` to enable RTS/CTS protection based on the TX duration of the data frame. Both the value of this attribute and the value of the existing **RtsCtsThreshold** attribute are evaluated: if either of the thresholds (or both) is exceeded, RTS/CTS is used. ### Changes to existing API diff --git a/src/wifi/model/wifi-default-protection-manager.cc b/src/wifi/model/wifi-default-protection-manager.cc index 9d339730e..fde22daab 100644 --- a/src/wifi/model/wifi-default-protection-manager.cc +++ b/src/wifi/model/wifi-default-protection-manager.cc @@ -121,7 +121,7 @@ WifiDefaultProtectionManager::TryAddMpdu(Ptr mpdu, const WifiTxP NS_ASSERT(!txParams.m_protection || txParams.m_protection->method == WifiProtection::NONE); std::unique_ptr protection; - protection = GetPsduProtection(hdr, txParams.GetSize(hdr.GetAddr1()), txParams.m_txVector); + protection = GetPsduProtection(hdr, txParams); // return the newly computed method if none was set or it is not NONE if (!txParams.m_protection || protection->method != WifiProtection::NONE) @@ -158,9 +158,7 @@ WifiDefaultProtectionManager::TryAggregateMsdu(Ptr msdu, } std::unique_ptr protection; - protection = GetPsduProtection(msdu->GetHeader(), - txParams.GetSize(msdu->GetHeader().GetAddr1()), - txParams.m_txVector); + protection = GetPsduProtection(msdu->GetHeader(), txParams); // the protection method may still be none if (protection->method == WifiProtection::NONE) @@ -174,10 +172,9 @@ WifiDefaultProtectionManager::TryAggregateMsdu(Ptr msdu, std::unique_ptr WifiDefaultProtectionManager::GetPsduProtection(const WifiMacHeader& hdr, - uint32_t size, - const WifiTxVector& txVector) const + const WifiTxParameters& txParams) const { - NS_LOG_FUNCTION(this << hdr << size << txVector); + NS_LOG_FUNCTION(this << hdr << &txParams); // a non-initial fragment does not need to be protected, unless it is being retransmitted if (hdr.GetFragmentNumber() > 0 && !hdr.IsRetry()) @@ -207,12 +204,12 @@ WifiDefaultProtectionManager::GetPsduProtection(const WifiMacHeader& hdr, } // check if RTS/CTS is needed - if (emlsrNeedRts || GetWifiRemoteStationManager()->NeedRts(hdr, size)) + if (emlsrNeedRts || GetWifiRemoteStationManager()->NeedRts(hdr, txParams)) { auto protection = std::make_unique(); protection->rtsTxVector = GetWifiRemoteStationManager()->GetRtsTxVector(hdr.GetAddr1(), - txVector.GetChannelWidth()); + txParams.m_txVector.GetChannelWidth()); protection->ctsTxVector = GetWifiRemoteStationManager()->GetCtsTxVector(hdr.GetAddr1(), protection->rtsTxVector.GetMode()); @@ -221,7 +218,7 @@ WifiDefaultProtectionManager::GetPsduProtection(const WifiMacHeader& hdr, // check if CTS-to-Self is needed if (GetWifiRemoteStationManager()->GetUseNonErpProtection() && - GetWifiRemoteStationManager()->NeedCtsToSelf(txVector)) + GetWifiRemoteStationManager()->NeedCtsToSelf(txParams.m_txVector)) { auto protection = std::make_unique(); protection->ctsTxVector = GetWifiRemoteStationManager()->GetCtsToSelfTxVector(); diff --git a/src/wifi/model/wifi-default-protection-manager.h b/src/wifi/model/wifi-default-protection-manager.h index fac4ecf9b..e6f0b3122 100644 --- a/src/wifi/model/wifi-default-protection-manager.h +++ b/src/wifi/model/wifi-default-protection-manager.h @@ -57,13 +57,12 @@ class WifiDefaultProtectionManager : public WifiProtectionManager * Select the protection method for a single PSDU. * * \param hdr the MAC header of the PSDU - * \param size the size in bytes of the PSDU - * \param txVector the TxVector used to transmit the PSDU + * \param txParams the TX parameters describing the PSDU * \return the selected protection method */ - virtual std::unique_ptr GetPsduProtection(const WifiMacHeader& hdr, - uint32_t size, - const WifiTxVector& txVector) const; + virtual std::unique_ptr GetPsduProtection( + const WifiMacHeader& hdr, + const WifiTxParameters& txParams) const; private: /** diff --git a/src/wifi/model/wifi-remote-station-manager.cc b/src/wifi/model/wifi-remote-station-manager.cc index 0e735e4a6..dd7d08a19 100644 --- a/src/wifi/model/wifi-remote-station-manager.cc +++ b/src/wifi/model/wifi-remote-station-manager.cc @@ -26,6 +26,7 @@ #include "wifi-mpdu.h" #include "wifi-net-device.h" #include "wifi-phy.h" +#include "wifi-tx-parameters.h" #include "ns3/boolean.h" #include "ns3/eht-configuration.h" @@ -74,6 +75,13 @@ WifiRemoteStationManager::GetTypeId() UintegerValue(4692480), MakeUintegerAccessor(&WifiRemoteStationManager::SetRtsCtsThreshold), MakeUintegerChecker(0, 4692480)) + .AddAttribute("RtsCtsTxDurationThresh", + "If this threshold is a strictly positive value and the TX duration of " + "the PSDU is greater than or equal to this threshold, we use an RTS/CTS " + "handshake before sending the data frame.", + TimeValue(Time{0}), + MakeTimeAccessor(&WifiRemoteStationManager::m_rtsCtsTxDurationThresh), + MakeTimeChecker()) .AddAttribute( "FragmentationThreshold", "If the size of the PSDU is bigger than this value, we fragment it such that the " @@ -1119,12 +1127,11 @@ WifiRemoteStationManager::ReportAmpduTxStatus(Mac48Address address, } bool -WifiRemoteStationManager::NeedRts(const WifiMacHeader& header, uint32_t size) +WifiRemoteStationManager::NeedRts(const WifiMacHeader& header, const WifiTxParameters& txParams) { - NS_LOG_FUNCTION(this << header << size); - Mac48Address address = header.GetAddr1(); - WifiTxVector txVector = GetDataTxVector(header, m_wifiPhy->GetChannelWidth()); - const auto modulationClass = txVector.GetModulationClass(); + NS_LOG_FUNCTION(this << header << &txParams); + auto address = header.GetAddr1(); + const auto modulationClass = txParams.m_txVector.GetModulationClass(); if (address.IsGroup()) { return false; @@ -1146,7 +1153,11 @@ WifiRemoteStationManager::NeedRts(const WifiMacHeader& header, uint32_t size) NS_LOG_DEBUG("WifiRemoteStationManager::NeedRTS returning true to protect non-HT stations"); return true; } - bool normally = (size > m_rtsCtsThreshold); + NS_ASSERT(txParams.m_txDuration.has_value()); + auto size = txParams.GetSize(header.GetAddr1()); + bool normally = + (size > m_rtsCtsThreshold) || (m_rtsCtsTxDurationThresh.IsStrictlyPositive() && + *txParams.m_txDuration >= m_rtsCtsTxDurationThresh); return DoNeedRts(Lookup(address), size, normally); } diff --git a/src/wifi/model/wifi-remote-station-manager.h b/src/wifi/model/wifi-remote-station-manager.h index 5aedb2f6d..396fcb944 100644 --- a/src/wifi/model/wifi-remote-station-manager.h +++ b/src/wifi/model/wifi-remote-station-manager.h @@ -49,6 +49,7 @@ class WifiMacHeader; class Packet; class WifiMpdu; class WifiTxVector; +class WifiTxParameters; struct WifiRemoteStationState; struct RxSignalInfo; @@ -955,13 +956,13 @@ class WifiRemoteStationManager : public Object void ReportRxOk(Mac48Address address, RxSignalInfo rxSignalInfo, WifiTxVector txVector); /** - * \param header MAC header - * \param size the size of the frame to send in bytes + * \param header MAC header of the data frame to send + * \param txParams the TX parameters for the data frame to send * * \return true if we want to use an RTS/CTS handshake for this * frame before sending it, false otherwise. */ - bool NeedRts(const WifiMacHeader& header, uint32_t size); + bool NeedRts(const WifiMacHeader& header, const WifiTxParameters& txParams); /** * Return if we need to do CTS-to-self before sending a DATA. * @@ -1494,6 +1495,7 @@ class WifiRemoteStationManager : public Object uint32_t m_maxSsrc; //!< Maximum STA short retry count (SSRC) uint32_t m_maxSlrc; //!< Maximum STA long retry count (SLRC) uint32_t m_rtsCtsThreshold; //!< Threshold for RTS/CTS + Time m_rtsCtsTxDurationThresh; //!< TX duration threshold for RTS/CTS uint32_t m_fragmentationThreshold; //!< Current threshold for fragmentation uint8_t m_defaultTxPowerLevel; //!< Default transmission power level WifiMode m_nonUnicastMode; //!< Transmission mode for non-unicast Data frames