wifi: Determine WifiMode to use for groupcast frames
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user