diff --git a/src/wifi/model/rate-control/constant-rate-wifi-manager.cc b/src/wifi/model/rate-control/constant-rate-wifi-manager.cc index 659dd7b10..91901006a 100644 --- a/src/wifi/model/rate-control/constant-rate-wifi-manager.cc +++ b/src/wifi/model/rate-control/constant-rate-wifi-manager.cc @@ -21,6 +21,7 @@ #include "ns3/string.h" #include "ns3/log.h" #include "constant-rate-wifi-manager.h" +#include "ns3/wifi-phy.h" #include "ns3/wifi-tx-vector.h" #include "ns3/wifi-utils.h" @@ -123,14 +124,14 @@ ConstantRateWifiManager::DoGetDataTxVector (WifiRemoteStation *st) { nss = 1 + (m_dataMode.GetMcsValue () / 8); } - return WifiTxVector (m_dataMode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (m_dataMode.GetModulationClass (), GetShortPreambleEnabled ()), ConvertGuardIntervalToNanoSeconds (m_dataMode, GetShortGuardIntervalSupported (st), NanoSeconds (GetGuardInterval (st))), GetNumberOfAntennas (), nss, 0, GetChannelWidthForTransmission (m_dataMode, GetChannelWidth (st)), GetAggregation (st)); + return WifiTxVector (m_dataMode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (m_dataMode.GetModulationClass (), GetShortPreambleEnabled ()), ConvertGuardIntervalToNanoSeconds (m_dataMode, GetShortGuardIntervalSupported (st), NanoSeconds (GetGuardInterval (st))), GetNumberOfAntennas (), nss, 0, GetChannelWidthForTransmission (m_dataMode, GetPhy ()->GetChannelWidth (), GetChannelWidth (st)), GetAggregation (st)); } WifiTxVector ConstantRateWifiManager::DoGetRtsTxVector (WifiRemoteStation *st) { NS_LOG_FUNCTION (this << st); - return WifiTxVector (m_ctlMode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (m_ctlMode.GetModulationClass (), GetShortPreambleEnabled ()), ConvertGuardIntervalToNanoSeconds (m_ctlMode, GetShortGuardIntervalSupported (st), NanoSeconds (GetGuardInterval (st))), 1, 1, 0, GetChannelWidthForTransmission (m_ctlMode, GetChannelWidth (st)), GetAggregation (st)); + return WifiTxVector (m_ctlMode, GetDefaultTxPowerLevel (), GetPreambleForTransmission (m_ctlMode.GetModulationClass (), GetShortPreambleEnabled ()), ConvertGuardIntervalToNanoSeconds (m_ctlMode, GetShortGuardIntervalSupported (st), NanoSeconds (GetGuardInterval (st))), 1, 1, 0, GetChannelWidthForTransmission (m_ctlMode, GetPhy ()->GetChannelWidth (), GetChannelWidth (st)), GetAggregation (st)); } } //namespace ns3 diff --git a/src/wifi/model/rate-control/minstrel-ht-wifi-manager.cc b/src/wifi/model/rate-control/minstrel-ht-wifi-manager.cc index 439286d90..d5b1f0e02 100644 --- a/src/wifi/model/rate-control/minstrel-ht-wifi-manager.cc +++ b/src/wifi/model/rate-control/minstrel-ht-wifi-manager.cc @@ -990,7 +990,7 @@ MinstrelHtWifiManager::DoGetRtsTxVector (WifiRemoteStation *st) NS_ASSERT (rateFound); return WifiTxVector (rtsRate, GetDefaultTxPowerLevel (), GetPreambleForTransmission (rtsRate.GetModulationClass (), GetShortPreambleEnabled ()), - 800, 1, 1, 0, GetChannelWidthForTransmission (rtsRate, GetChannelWidth (station)), GetAggregation (station)); + 800, 1, 1, 0, GetChannelWidthForTransmission (rtsRate, GetPhy ()->GetChannelWidth (), GetChannelWidth (station)), GetAggregation (station)); } } diff --git a/src/wifi/model/wifi-phy-common.cc b/src/wifi/model/wifi-phy-common.cc index b7180f365..6d89620b2 100644 --- a/src/wifi/model/wifi-phy-common.cc +++ b/src/wifi/model/wifi-phy-common.cc @@ -65,10 +65,10 @@ ConvertGuardIntervalToNanoSeconds (WifiMode mode, bool htShortGuardInterval, Tim } uint16_t -GetChannelWidthForTransmission (WifiMode mode, uint16_t maxSupportedChannelWidth) +GetChannelWidthForTransmission (WifiMode mode, uint16_t maxAllowedChannelWidth) { WifiModulationClass modulationClass = mode.GetModulationClass (); - if (maxSupportedChannelWidth > 20 + if (maxAllowedChannelWidth > 20 && (modulationClass == WifiModulationClass::WIFI_MOD_CLASS_OFDM // all non-HT OFDM control and management frames || modulationClass == WifiModulationClass::WIFI_MOD_CLASS_ERP_OFDM)) // special case of beacons at 2.4 GHz { @@ -80,7 +80,15 @@ GetChannelWidthForTransmission (WifiMode mode, uint16_t maxSupportedChannelWidth { return 22; } - return maxSupportedChannelWidth; + return maxAllowedChannelWidth; +} + +uint16_t +GetChannelWidthForTransmission (WifiMode mode, uint16_t operatingChannelWidth, + uint16_t maxSupportedChannelWidth) +{ + return GetChannelWidthForTransmission (mode, (operatingChannelWidth < maxSupportedChannelWidth) + ? operatingChannelWidth : maxSupportedChannelWidth); } WifiPreamble diff --git a/src/wifi/model/wifi-phy-common.h b/src/wifi/model/wifi-phy-common.h index 24ee9bdc2..b22073f02 100644 --- a/src/wifi/model/wifi-phy-common.h +++ b/src/wifi/model/wifi-phy-common.h @@ -371,15 +371,28 @@ uint16_t ConvertGuardIntervalToNanoSeconds (WifiMode mode, bool htShortGuardInte WifiPreamble GetPreambleForTransmission (WifiModulationClass modulation, bool useShortPreamble); /** - * Return the channel width that corresponds to the selected mode (instead of - * letting the PHY's default channel width). This is especially useful when using - * non-HT modes with HT/VHT/HE capable stations (with default width above 20 MHz). + * Return the channel width that is allowed based on the selected mode and the given + * maximum channel width. This is especially useful when using non-HT modes with + * HT/VHT/HE capable stations (with default width above 20 MHz). * * \param mode selected WifiMode - * \param maxSupportedChannelWidth maximum channel width supported by the PHY layer + * \param maxAllowedChannelWidth maximum channel width allowed for the transmission * \return channel width adapted to the selected mode */ -uint16_t GetChannelWidthForTransmission (WifiMode mode, uint16_t maxSupportedChannelWidth); +uint16_t GetChannelWidthForTransmission (WifiMode mode, uint16_t maxAllowedChannelWidth); +/** + * Return the channel width that is allowed based on the selected mode, the current + * width of the operating channel and the maximum channel width supported by the + * receiver. This is especially useful when using non-HT modes with HT/VHT/HE + * capable stations (with default width above 20 MHz). + * + * \param mode selected WifiMode + * \param operatingChannelWidth operating channel width + * \param maxSupportedChannelWidth maximum channel width supported by the receiver + * \return channel width adapted to the selected mode + */ +uint16_t GetChannelWidthForTransmission (WifiMode mode, uint16_t operatingChannelWidth, + uint16_t maxSupportedChannelWidth); /** * Return whether the modulation class of the selected mode for the diff --git a/src/wifi/model/wifi-remote-station-manager.cc b/src/wifi/model/wifi-remote-station-manager.cc index 442657d35..f414f89e3 100644 --- a/src/wifi/model/wifi-remote-station-manager.cc +++ b/src/wifi/model/wifi-remote-station-manager.cc @@ -545,7 +545,17 @@ WifiRemoteStationManager::GetDataTxVector (const WifiMacHeader &header) txVector.SetMode (mgtMode); txVector.SetPreambleType (GetPreambleForTransmission (mgtMode.GetModulationClass (), GetShortPreambleEnabled ())); txVector.SetTxPowerLevel (m_defaultTxPowerLevel); - txVector.SetChannelWidth (GetChannelWidthForTransmission (mgtMode, m_wifiPhy->GetChannelWidth ())); + uint16_t channelWidth = m_wifiPhy->GetChannelWidth (); + if (!header.GetAddr1 ().IsGroup ()) + { + if (uint16_t rxWidth = GetChannelWidthSupported (header.GetAddr1 ()); + rxWidth < channelWidth) + { + channelWidth = rxWidth; + } + } + + txVector.SetChannelWidth (GetChannelWidthForTransmission (mgtMode, channelWidth)); txVector.SetGuardInterval (ConvertGuardIntervalToNanoSeconds (mgtMode, m_wifiPhy->GetDevice ())); } else