wifi: Default protection manager enables MU-RTS when TXing to EMLSR clients

This commit is contained in:
Stefano Avallone
2023-03-03 19:40:16 +01:00
committed by Stefano Avallone
parent ec1d25cc68
commit efeff2f531
3 changed files with 106 additions and 24 deletions

View File

@@ -68,14 +68,22 @@ WifiDefaultProtectionManager::TryAddMpdu(Ptr<const WifiMpdu> mpdu, const WifiTxP
{
NS_LOG_FUNCTION(this << *mpdu << &txParams);
// For a DL MU PPDU containing more than one PSDU, call a separate method.
// Call a separate method that handles MU-RTS/CTS protection in case of DL MU PPDU containing
// more than one PSDU or in case the MPDU being added is addressed to an EMLSR client or in
// case the protection method is already MU-RTS/CTS.
// A DL MU PPDU contains more than one PSDU if either the TX params' PSDU info map
// contains more than one entry or it contains one entry but the MPDU being added is
// addressed to a different receiver (hence generating a new entry if the MPDU is added)
if (const auto& psduInfoMap = txParams.GetPsduInfoMap();
const auto& psduInfoMap = txParams.GetPsduInfoMap();
auto dlMuPpdu =
txParams.m_txVector.IsDlMu() &&
(psduInfoMap.size() > 1 ||
(psduInfoMap.size() == 1 && psduInfoMap.begin()->first != mpdu->GetHeader().GetAddr1())))
(psduInfoMap.size() == 1 && psduInfoMap.begin()->first != mpdu->GetHeader().GetAddr1()));
auto isEmlsrDestination =
GetWifiRemoteStationManager()->GetEmlsrEnabled(mpdu->GetHeader().GetAddr1());
if (dlMuPpdu || isEmlsrDestination ||
(txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS))
{
return TryAddMpduToMuPpdu(mpdu, txParams);
}
@@ -208,13 +216,24 @@ WifiDefaultProtectionManager::TryAddMpduToMuPpdu(Ptr<const WifiMpdu> mpdu,
const WifiTxParameters& txParams)
{
NS_LOG_FUNCTION(this << *mpdu << &txParams);
NS_ASSERT(txParams.m_txVector.IsDlMu());
auto receiver = mpdu->GetHeader().GetAddr1();
const auto& psduInfoMap = txParams.GetPsduInfoMap();
auto dlMuPpdu = txParams.m_txVector.IsDlMu() &&
(psduInfoMap.size() > 1 ||
(psduInfoMap.size() == 1 && psduInfoMap.begin()->first != receiver));
auto isEmlsrDestination = GetWifiRemoteStationManager()->GetEmlsrEnabled(receiver);
NS_ASSERT(
dlMuPpdu || isEmlsrDestination ||
(txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS));
auto isProtected =
m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas().count(receiver) == 1;
bool needMuRts =
(txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS) ||
(dlMuPpdu && m_sendMuRts && !isProtected) || (isEmlsrDestination && !isProtected);
if (!m_sendMuRts || isProtected)
if (!needMuRts)
{
// No protection needed
if (txParams.m_protection && txParams.m_protection->method == WifiProtection::NONE)
@@ -235,7 +254,10 @@ WifiDefaultProtectionManager::TryAddMpduToMuPpdu(Ptr<const WifiMpdu> mpdu,
// we get here if this is the first MPDU for this receiver.
NS_ABORT_MSG_IF(m_mac->GetTypeOfStation() != AP, "HE APs only can send DL MU PPDUs");
auto apMac = StaticCast<ApWifiMac>(m_mac);
auto txWidth = txParams.m_txVector.GetChannelWidth();
auto modClass = txParams.m_txVector.GetModulationClass();
auto txWidth = modClass == WIFI_MOD_CLASS_DSSS || modClass == WIFI_MOD_CLASS_HR_DSSS
? 20
: txParams.m_txVector.GetChannelWidth();
if (protection != nullptr)
{
@@ -256,15 +278,12 @@ WifiDefaultProtectionManager::TryAddMpduToMuPpdu(Ptr<const WifiMpdu> mpdu,
protection->muRts.SetType(TriggerFrameType::MU_RTS_TRIGGER);
protection->muRts.SetUlBandwidth(txWidth);
NS_ASSERT_MSG(txParams.GetPsduInfoMap().size() == 1,
"There should be one PSDU in the DL MU PPDU when creating a new "
"WifiMuRtsCtsProtection object");
// this is the first MPDU for the second receiver added to the DL MU PPDU.
// Add a User Info field for the first receiver
AddUserInfoToMuRts(protection->muRts,
txWidth,
txParams.GetPsduInfoMap().cbegin()->first);
// Add a User Info field for each of the receivers already in the TX params
for (const auto& [address, info] : txParams.GetPsduInfoMap())
{
NS_ASSERT_MSG(address != receiver, "This must be the first MPDU for " << receiver);
AddUserInfoToMuRts(protection->muRts, txWidth, address);
}
// compute the TXVECTOR to use to send the MU-RTS Trigger Frame
protection->muRtsTxVector = GetWifiRemoteStationManager()->GetRtsTxVector(receiver);
@@ -272,6 +291,20 @@ WifiDefaultProtectionManager::TryAddMpduToMuPpdu(Ptr<const WifiMpdu> mpdu,
// a CTS frame response in a 20 MHz channel that is not occupied by the PPDU that
// contains the MU-RTS Trigger frame. (Sec. 26.2.6.2 of 802.11ax)
protection->muRtsTxVector.SetChannelWidth(txWidth);
// OFDM is needed to transmit the PPDU over a bandwidth that is a multiple of 20 MHz
const auto modulation = protection->muRtsTxVector.GetModulationClass();
if (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)
{
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 (isEmlsrDestination && !isProtected)
{
GetWifiRemoteStationManager()->AdjustTxVectorForIcf(protection->muRtsTxVector);
}
// Add a User Info field for the new receiver
@@ -296,12 +329,6 @@ WifiDefaultProtectionManager::TryUlMuTransmission(Ptr<const WifiMpdu> mpdu,
NS_LOG_FUNCTION(this << *mpdu << &txParams);
NS_ASSERT(mpdu->GetHeader().IsTrigger());
if (!m_sendMuRts)
{
// No protection because sending MU-RTS is disabled
return std::make_unique<WifiNoProtection>();
}
CtrlTriggerHeader trigger;
mpdu->GetPacket()->PeekHeader(trigger);
NS_ASSERT(trigger.GetNUserInfoFields() > 0);
@@ -321,6 +348,7 @@ WifiDefaultProtectionManager::TryUlMuTransmission(Ptr<const WifiMpdu> mpdu,
std::remove_reference_t<decltype(staList)>::const_iterator staIt;
bool allProtected = true;
bool isUnprotectedEmlsrDst = false;
for (const auto& userInfo : trigger)
{
@@ -330,12 +358,18 @@ WifiDefaultProtectionManager::TryUlMuTransmission(Ptr<const WifiMpdu> mpdu,
staIt = staList.find(userInfo.GetAid12());
NS_ASSERT(staIt != staList.cend());
AddUserInfoToMuRts(protection->muRts, txWidth, staIt->second);
allProtected =
allProtected &&
bool isProtected =
m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas().count(staIt->second) == 1;
allProtected = allProtected && isProtected;
isUnprotectedEmlsrDst =
isUnprotectedEmlsrDst ||
(!isProtected && GetWifiRemoteStationManager()->GetEmlsrEnabled(staIt->second));
}
if (allProtected)
bool needMuRts = (m_sendMuRts && !allProtected) || isUnprotectedEmlsrDst;
if (!needMuRts)
{
// No protection needed
return std::make_unique<WifiNoProtection>();
@@ -354,6 +388,13 @@ WifiDefaultProtectionManager::TryUlMuTransmission(Ptr<const WifiMpdu> 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);
}
return protection;
}

View File

@@ -30,6 +30,7 @@
#include "ns3/boolean.h"
#include "ns3/eht-configuration.h"
#include "ns3/enum.h"
#include "ns3/erp-ofdm-phy.h"
#include "ns3/he-configuration.h"
#include "ns3/ht-configuration.h"
#include "ns3/ht-phy.h"
@@ -746,6 +747,39 @@ WifiRemoteStationManager::GetCtsTxVector(Mac48Address to, WifiMode rtsTxMode) co
return v;
}
void
WifiRemoteStationManager::AdjustTxVectorForIcf(WifiTxVector& txVector) const
{
NS_LOG_FUNCTION(this << txVector);
auto txMode = txVector.GetMode();
if (txMode.GetModulationClass() >= WIFI_MOD_CLASS_HT)
{
auto rate = txMode.GetDataRate(txVector);
if (rate >= 24e6)
{
rate = 24e6;
}
else if (rate >= 12e6)
{
rate = 12e6;
}
else
{
rate = 6e6;
}
txVector.SetPreambleType(WIFI_PREAMBLE_LONG);
if (m_wifiPhy->GetPhyBand() == WIFI_PHY_BAND_2_4GHZ)
{
txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(rate));
}
else
{
txVector.SetMode(OfdmPhy::GetOfdmRate(rate));
}
}
}
WifiTxVector
WifiRemoteStationManager::GetAckTxVector(Mac48Address to, const WifiTxVector& dataTxVector) const
{

View File

@@ -842,6 +842,13 @@ class WifiRemoteStationManager : public Object
* transmission of the data packet itself.
*/
WifiTxVector GetCtsToSelfTxVector();
/**
* Adjust the TXVECTOR for an initial Control frame to ensure that the modulation class
* is non-HT and the rate is 6 Mbps, 12 Mbps or 24 Mbps.
*
* \param txVector the TXVECTOR to adjust
*/
void AdjustTxVectorForIcf(WifiTxVector& txVector) const;
/**
* Return a TXVECTOR for the Ack frame given the destination and the mode of the Data
* used by the sender.