wifi: Determine WifiMode to use for groupcast frames

This commit is contained in:
Sébastien Deronne
2023-08-12 10:52:18 +02:00
parent 0f1eb73c4a
commit 75c8da6cfc
2 changed files with 118 additions and 13 deletions

View File

@@ -9,6 +9,7 @@
#include "wifi-remote-station-manager.h"
#include "ap-wifi-mac.h"
#include "gcr-manager.h"
#include "sta-wifi-mac.h"
#include "wifi-mac-header.h"
#include "wifi-mac-trailer.h"
@@ -604,21 +605,10 @@ WifiTxVector
WifiRemoteStationManager::GetDataTxVector(const WifiMacHeader& header, MHz_u allowedWidth)
{
NS_LOG_FUNCTION(this << header << allowedWidth);
Mac48Address address = header.GetAddr1();
const auto address = header.GetAddr1();
if (!header.IsMgt() && address.IsGroup())
{
WifiMode mode = GetNonUnicastMode();
WifiTxVector v;
v.SetMode(mode);
v.SetPreambleType(
GetPreambleForTransmission(mode.GetModulationClass(), GetShortPreambleEnabled()));
v.SetTxPowerLevel(m_defaultTxPowerLevel);
v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mode, allowedWidth));
v.SetGuardInterval(GetGuardIntervalForMode(mode, m_wifiPhy->GetDevice()));
v.SetNTx(GetNumberOfAntennas());
v.SetNss(1);
v.SetNess(0);
return v;
return GetGroupcastTxVector(header, allowedWidth);
}
WifiTxVector txVector;
if (header.IsMgt())
@@ -1945,6 +1935,112 @@ WifiRemoteStationManager::GetNonUnicastMode() const
}
}
WifiTxVector
WifiRemoteStationManager::GetGroupcastTxVector(const WifiMacHeader& header, MHz_u allowedWidth)
{
const auto& to = header.GetAddr1();
NS_ASSERT(to.IsGroup());
WifiTxVector groupcastTxVector{};
const auto mode = GetNonUnicastMode();
groupcastTxVector.SetMode(mode);
groupcastTxVector.SetPreambleType(
GetPreambleForTransmission(mode.GetModulationClass(), GetShortPreambleEnabled()));
groupcastTxVector.SetTxPowerLevel(m_defaultTxPowerLevel);
groupcastTxVector.SetChannelWidth(m_wifiPhy->GetTxBandwidth(mode, allowedWidth));
groupcastTxVector.SetNTx(GetNumberOfAntennas());
if (to.IsBroadcast())
{
return groupcastTxVector;
}
auto apMac = DynamicCast<ApWifiMac>(m_wifiMac);
if (!apMac)
{
return groupcastTxVector;
}
auto gcrManager = apMac->GetGcrManager();
if (!gcrManager)
{
return groupcastTxVector;
}
const auto& groupStas = gcrManager->GetMemberStasForGroupAddress(to);
if (groupStas.empty())
{
return groupcastTxVector;
}
// If we are here, that means the mode will be used for the transmission of a groupcast frame
// using the GCR service. We should loop over each member STA that is going to receive the
// groupcast frame and select the highest possible mode over all STAs.
std::optional<WifiMode> groupcastMode;
auto maxWidth = allowedWidth;
auto maxNss = m_wifiPhy->GetMaxSupportedTxSpatialStreams();
std::map<WifiModulationClass, Time> minGisPerMc{/* non-HT OFDM is always 800 ns */
{WIFI_MOD_CLASS_HT, NanoSeconds(400)},
{WIFI_MOD_CLASS_HE, NanoSeconds(800)}};
const std::map<WifiModulationClass, WifiModulationClass> giRefModClass{
/* HT/VHT: short or long GI */
{WIFI_MOD_CLASS_HT, WIFI_MOD_CLASS_HT},
{WIFI_MOD_CLASS_VHT, WIFI_MOD_CLASS_HT},
/* HE/EHT: 3 possible GIs */
{WIFI_MOD_CLASS_HE, WIFI_MOD_CLASS_HE},
{WIFI_MOD_CLASS_EHT, WIFI_MOD_CLASS_HE}};
for (const auto& staAddress : groupStas)
{
// Get the equivalent TXVECTOR if the frame would be a unicast frame to that STA in order to
// get what rate would be selected for that STA.
WifiMacHeader hdr(WIFI_MAC_QOSDATA);
hdr.SetAddr1(staAddress);
const auto unicastTxVector = GetDataTxVector(hdr, allowedWidth);
// update the groupcast mode if:
// - this is the first mode to inspect;
// - this mode has a lower modulation class than the currently selected groupcast mode;
// - when the modulation class is similar, this mode has a lower MCS than the currently
// selected groupcast mode.
if (!groupcastMode.has_value() ||
(unicastTxVector.GetModulationClass() < groupcastMode->GetModulationClass()) ||
((unicastTxVector.GetModulationClass() == groupcastMode->GetModulationClass()) &&
(unicastTxVector.GetMode().GetMcsValue() < groupcastMode->GetMcsValue())))
{
groupcastMode = unicastTxVector.GetMode();
}
maxWidth = std::min(unicastTxVector.GetChannelWidth(), maxWidth);
maxNss = std::min(unicastTxVector.GetNss(), maxNss);
auto mc = unicastTxVector.GetModulationClass();
if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
{
mc = it->second;
}
if (auto it = minGisPerMc.find(mc); it != minGisPerMc.end())
{
it->second = std::max(unicastTxVector.GetGuardInterval(), it->second);
}
}
NS_ASSERT(groupcastMode.has_value());
groupcastTxVector.SetMode(*groupcastMode);
groupcastTxVector.SetPreambleType(
GetPreambleForTransmission(groupcastMode->GetModulationClass(), GetShortPreambleEnabled()));
groupcastTxVector.SetChannelWidth(maxWidth);
groupcastTxVector.SetNss(maxNss);
auto mc = groupcastMode->GetModulationClass();
if (const auto it = giRefModClass.find(mc); it != giRefModClass.cend())
{
mc = it->second;
}
if (const auto it = minGisPerMc.find(mc); it != minGisPerMc.cend())
{
groupcastTxVector.SetGuardInterval(it->second);
}
return groupcastTxVector;
}
bool
WifiRemoteStationManager::DoNeedRts(WifiRemoteStation* station, uint32_t size, bool normally)
{

View File

@@ -697,6 +697,15 @@ class WifiRemoteStationManager : public Object
*/
WifiMode GetNonUnicastMode() const;
/**
* Return the TXVECTOR to use for a groupcast packet.
*
* @param header the MAC header of the groupcast packet
* @param allowedWidth the allowed width in MHz to send this packet
* @return the TXVECTOR to use to send the groupcast packet
*/
WifiTxVector GetGroupcastTxVector(const WifiMacHeader& header, MHz_u allowedWidth);
/**
* Invoked in a STA or AP to store the set of
* modes supported by a destination which is