diff --git a/src/wifi/model/he/rr-multi-user-scheduler.cc b/src/wifi/model/he/rr-multi-user-scheduler.cc index d3ec4de77..6501f2ca0 100644 --- a/src/wifi/model/he/rr-multi-user-scheduler.cc +++ b/src/wifi/model/he/rr-multi-user-scheduler.cc @@ -320,7 +320,8 @@ RrMultiUserScheduler::TrySendingBsrpTf() m_txParams.Clear(); // set the TXVECTOR used to send the Trigger Frame m_txParams.m_txVector = - m_apMac->GetWifiRemoteStationManager(m_linkId)->GetRtsTxVector(m_triggerMacHdr.GetAddr1()); + m_apMac->GetWifiRemoteStationManager(m_linkId)->GetRtsTxVector(m_triggerMacHdr.GetAddr1(), + m_allowedWidth); if (!GetHeFem(m_linkId)->TryAddMpdu(item, m_txParams, m_availableTime)) { @@ -442,7 +443,8 @@ RrMultiUserScheduler::TrySendingBasicTf() m_txParams.Clear(); // set the TXVECTOR used to send the Trigger Frame m_txParams.m_txVector = - m_apMac->GetWifiRemoteStationManager(m_linkId)->GetRtsTxVector(m_triggerMacHdr.GetAddr1()); + m_apMac->GetWifiRemoteStationManager(m_linkId)->GetRtsTxVector(m_triggerMacHdr.GetAddr1(), + m_allowedWidth); if (!GetHeFem(m_linkId)->TryAddMpdu(item, m_txParams, m_availableTime)) { diff --git a/src/wifi/model/qos-frame-exchange-manager.cc b/src/wifi/model/qos-frame-exchange-manager.cc index 8549c3b9b..3c9d98fac 100644 --- a/src/wifi/model/qos-frame-exchange-manager.cc +++ b/src/wifi/model/qos-frame-exchange-manager.cc @@ -97,7 +97,8 @@ QosFrameExchangeManager::SendCfEndIfNeeded() cfEnd.SetAddr1(Mac48Address::GetBroadcast()); cfEnd.SetAddr2(m_self); - WifiTxVector cfEndTxVector = GetWifiRemoteStationManager()->GetRtsTxVector(cfEnd.GetAddr1()); + WifiTxVector cfEndTxVector = + GetWifiRemoteStationManager()->GetRtsTxVector(cfEnd.GetAddr1(), m_allowedWidth); auto mpdu = Create(Create(), cfEnd); auto txDuration = diff --git a/src/wifi/model/wifi-default-ack-manager.cc b/src/wifi/model/wifi-default-ack-manager.cc index ca286330b..0e27d77f7 100644 --- a/src/wifi/model/wifi-default-ack-manager.cc +++ b/src/wifi/model/wifi-default-ack-manager.cc @@ -572,7 +572,9 @@ WifiDefaultAckManager::GetAckInfoIfTfMuBar(Ptr mpdu, m_mac->GetBaTypeAsOriginator(receiver, tid)}); acknowledgment->barTypes.push_back(m_mac->GetBarTypeAsOriginator(receiver, tid)); - acknowledgment->muBarTxVector = GetWifiRemoteStationManager()->GetRtsTxVector(receiver); + acknowledgment->muBarTxVector = + GetWifiRemoteStationManager()->GetRtsTxVector(receiver, + txParams.m_txVector.GetChannelWidth()); acknowledgment->SetQosAckPolicy(receiver, tid, WifiMacHeader::BLOCK_ACK); return std::unique_ptr(acknowledgment); } diff --git a/src/wifi/model/wifi-default-protection-manager.cc b/src/wifi/model/wifi-default-protection-manager.cc index 69d684de9..6dc833b8e 100644 --- a/src/wifi/model/wifi-default-protection-manager.cc +++ b/src/wifi/model/wifi-default-protection-manager.cc @@ -207,7 +207,9 @@ WifiDefaultProtectionManager::GetPsduProtection(const WifiMacHeader& hdr, if (emlsrNeedRts || GetWifiRemoteStationManager()->NeedRts(hdr, size)) { auto protection = std::make_unique(); - protection->rtsTxVector = GetWifiRemoteStationManager()->GetRtsTxVector(hdr.GetAddr1()); + protection->rtsTxVector = + GetWifiRemoteStationManager()->GetRtsTxVector(hdr.GetAddr1(), + txVector.GetChannelWidth()); protection->ctsTxVector = GetWifiRemoteStationManager()->GetCtsTxVector(hdr.GetAddr1(), protection->rtsTxVector.GetMode()); @@ -301,7 +303,8 @@ WifiDefaultProtectionManager::TryAddMpduToMuPpdu(Ptr mpdu, } // compute the TXVECTOR to use to send the MU-RTS Trigger Frame - protection->muRtsTxVector = GetWifiRemoteStationManager()->GetRtsTxVector(receiver); + protection->muRtsTxVector = + GetWifiRemoteStationManager()->GetRtsTxVector(receiver, txWidth); // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send // 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) @@ -391,7 +394,7 @@ WifiDefaultProtectionManager::TryUlMuTransmission(Ptr mpdu, // compute the TXVECTOR to use to send the MU-RTS Trigger Frame protection->muRtsTxVector = - GetWifiRemoteStationManager()->GetRtsTxVector(mpdu->GetHeader().GetAddr1()); + GetWifiRemoteStationManager()->GetRtsTxVector(mpdu->GetHeader().GetAddr1(), txWidth); // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send // 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) diff --git a/src/wifi/model/wifi-remote-station-manager.cc b/src/wifi/model/wifi-remote-station-manager.cc index 2ec797f2c..90e3ca29d 100644 --- a/src/wifi/model/wifi-remote-station-manager.cc +++ b/src/wifi/model/wifi-remote-station-manager.cc @@ -701,13 +701,13 @@ WifiRemoteStationManager::GetCtsToSelfTxVector() } WifiTxVector -WifiRemoteStationManager::GetRtsTxVector(Mac48Address address) +WifiRemoteStationManager::GetRtsTxVector(Mac48Address address, uint16_t allowedWidth) { - NS_LOG_FUNCTION(this << address); + NS_LOG_FUNCTION(this << address << allowedWidth); + WifiTxVector v; if (address.IsGroup()) { WifiMode mode = GetNonUnicastMode(); - WifiTxVector v; v.SetMode(mode); v.SetPreambleType( GetPreambleForTransmission(mode.GetModulationClass(), GetShortPreambleEnabled())); @@ -717,9 +717,31 @@ WifiRemoteStationManager::GetRtsTxVector(Mac48Address address) v.SetNTx(GetNumberOfAntennas()); v.SetNss(1); v.SetNess(0); - return v; } - return DoGetRtsTxVector(Lookup(address)); + else + { + v = DoGetRtsTxVector(Lookup(address)); + } + auto modulation = v.GetModulationClass(); + + if (allowedWidth >= 40 && + (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)) + { + // RTS must be sent in a non-HT duplicate PPDU because it must protect a frame being + // transmitted on at least 40 MHz. Change the modulation class to ERP-OFDM and the rate + // to 6 Mbps + v.SetMode(ErpOfdmPhy::GetErpOfdmRate6Mbps()); + modulation = v.GetModulationClass(); + } + // do not set allowedWidth as the TX width if the modulation class is (HR-)DSSS (allowedWidth + // may be >= 40 MHz) or allowedWidth is 22 MHz (the selected modulation class may be OFDM) + if (modulation != WIFI_MOD_CLASS_DSSS && modulation != WIFI_MOD_CLASS_HR_DSSS && + allowedWidth != 22) + { + v.SetChannelWidth(allowedWidth); + } + + return v; } WifiTxVector diff --git a/src/wifi/model/wifi-remote-station-manager.h b/src/wifi/model/wifi-remote-station-manager.h index c4e35e351..a5067db08 100644 --- a/src/wifi/model/wifi-remote-station-manager.h +++ b/src/wifi/model/wifi-remote-station-manager.h @@ -816,11 +816,12 @@ class WifiRemoteStationManager : public Object WifiTxVector GetDataTxVector(const WifiMacHeader& header, uint16_t allowedWidth); /** * \param address remote address + * \param allowedWidth the allowed width in MHz for the data frame being protected * * \return the TXVECTOR to use to send the RTS prior to the * transmission of the data packet itself. */ - WifiTxVector GetRtsTxVector(Mac48Address address); + WifiTxVector GetRtsTxVector(Mac48Address address, uint16_t allowedWidth); /** * Return a TXVECTOR for the CTS frame given the destination and the mode of the RTS * used by the sender. diff --git a/src/wifi/test/wifi-emlsr-test.cc b/src/wifi/test/wifi-emlsr-test.cc index 2380344bd..361e1c0ab 100644 --- a/src/wifi/test/wifi-emlsr-test.cc +++ b/src/wifi/test/wifi-emlsr-test.cc @@ -2026,7 +2026,8 @@ EmlsrDlTxopTest::CheckBlockAck(const WifiConstPsduMap& psduMap, auto txDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, apPhy->GetPhyBand()); auto cfEndTxDuration = WifiPhy::CalculateTxDuration( Create(Create(), WifiMacHeader(WIFI_MAC_CTL_END)), - m_apMac->GetWifiRemoteStationManager(linkId)->GetRtsTxVector(Mac48Address::GetBroadcast()), + m_apMac->GetWifiRemoteStationManager(linkId)->GetRtsTxVector(Mac48Address::GetBroadcast(), + txVector.GetChannelWidth()), apPhy->GetPhyBand()); m_countBlockAck++; diff --git a/src/wifi/test/wifi-mac-ofdma-test.cc b/src/wifi/test/wifi-mac-ofdma-test.cc index c10288967..0deef55af 100644 --- a/src/wifi/test/wifi-mac-ofdma-test.cc +++ b/src/wifi/test/wifi-mac-ofdma-test.cc @@ -186,7 +186,8 @@ TestMultiUserScheduler::SelectTxFormat() m_txParams.Clear(); // set the TXVECTOR used to send the Trigger Frame m_txParams.m_txVector = - m_apMac->GetWifiRemoteStationManager()->GetRtsTxVector(m_triggerHdr.GetAddr1()); + m_apMac->GetWifiRemoteStationManager()->GetRtsTxVector(m_triggerHdr.GetAddr1(), + m_allowedWidth); if (!GetHeFem(SINGLE_LINK_OP_ID)->TryAddMpdu(item, m_txParams, m_availableTime) || (m_availableTime != Time::Min() &&