wifi: (fixes #2338) Improve and fix control answer rate selection
This commit is contained in:
@@ -192,6 +192,7 @@ Bugs fixed
|
||||
- Bug 2331 - Wrong mobility model in vanet-routing-compare example
|
||||
- Bug 2332 - Assert failed when using aggregation and two pairs of AP-STA
|
||||
- Bug 2337 - WifiPhy uses channel width in Hz iso MHz
|
||||
- Bug 2338 - WifiMode selected for control frames may sometimes be invalid
|
||||
|
||||
Known issues
|
||||
------------
|
||||
|
||||
@@ -976,8 +976,7 @@ MinstrelHtWifiManager::DoGetRtsTxVector (WifiRemoteStation *st)
|
||||
uint32_t mcsIndex = station->m_groupsTable[groupId].m_ratesTable[rateId].mcsIndex;
|
||||
|
||||
WifiMode lastRate = GetMcsSupported (station, mcsIndex);
|
||||
uint8_t streams = m_minstrelGroups[groupId].streams;
|
||||
uint64_t lastDataRate = lastRate.GetNonHtReferenceRate (streams);
|
||||
uint64_t lastDataRate = lastRate.GetNonHtReferenceRate ();
|
||||
uint32_t nBasicRates = GetNBasicModes ();
|
||||
|
||||
WifiMode rtsRate;
|
||||
|
||||
@@ -250,15 +250,14 @@ double
|
||||
NistErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, double snr, uint32_t nbits) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << mode << txVector.GetMode () << snr << nbits);
|
||||
uint8_t nss = txVector.GetNss ();
|
||||
if (mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM
|
||||
|| mode.GetModulationClass () == WIFI_MOD_CLASS_OFDM
|
||||
|| mode.GetModulationClass () == WIFI_MOD_CLASS_HT
|
||||
|| mode.GetModulationClass () == WIFI_MOD_CLASS_VHT)
|
||||
{
|
||||
if (mode.GetConstellationSize (nss) == 2)
|
||||
if (mode.GetConstellationSize () == 2)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_1_2)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_1_2)
|
||||
{
|
||||
return GetFecBpskBer (snr,
|
||||
nbits,
|
||||
@@ -271,9 +270,9 @@ NistErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, d
|
||||
3); //b value
|
||||
}
|
||||
}
|
||||
else if (mode.GetConstellationSize (nss) == 4)
|
||||
else if (mode.GetConstellationSize () == 4)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_1_2)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_1_2)
|
||||
{
|
||||
return GetFecQpskBer (snr,
|
||||
nbits,
|
||||
@@ -286,9 +285,9 @@ NistErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, d
|
||||
3); //b value
|
||||
}
|
||||
}
|
||||
else if (mode.GetConstellationSize (nss) == 16)
|
||||
else if (mode.GetConstellationSize () == 16)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_1_2)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_1_2)
|
||||
{
|
||||
return GetFec16QamBer (snr,
|
||||
nbits,
|
||||
@@ -301,15 +300,15 @@ NistErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, d
|
||||
3); //b value
|
||||
}
|
||||
}
|
||||
else if (mode.GetConstellationSize (nss) == 64)
|
||||
else if (mode.GetConstellationSize () == 64)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_2_3)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_2_3)
|
||||
{
|
||||
return GetFec64QamBer (snr,
|
||||
nbits,
|
||||
2); //b value
|
||||
}
|
||||
else if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_5_6)
|
||||
else if (mode.GetCodeRate () == WIFI_CODE_RATE_5_6)
|
||||
{
|
||||
return GetFec64QamBer (snr,
|
||||
nbits,
|
||||
@@ -322,9 +321,9 @@ NistErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, d
|
||||
3); //b value
|
||||
}
|
||||
}
|
||||
else if (mode.GetConstellationSize (nss) == 256)
|
||||
else if (mode.GetConstellationSize () == 256)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_5_6)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_5_6)
|
||||
{
|
||||
return GetFec256QamBer (snr,
|
||||
nbits,
|
||||
|
||||
@@ -73,9 +73,11 @@ std::istream & operator >> (std::istream &is, WifiMode &mode)
|
||||
uint64_t
|
||||
WifiMode::GetPhyRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
|
||||
{
|
||||
//TODO: nss > 4 not supported yet
|
||||
NS_ASSERT (nss <= 4);
|
||||
uint32_t dataRate, phyRate;
|
||||
dataRate = GetDataRate (channelWidth, isShortGuardInterval, nss);
|
||||
switch (GetCodeRate (nss))
|
||||
switch (GetCodeRate ())
|
||||
{
|
||||
case WIFI_CODE_RATE_5_6:
|
||||
phyRate = dataRate * 6 / 5;
|
||||
@@ -106,15 +108,17 @@ WifiMode::GetPhyRate (WifiTxVector txVector) const
|
||||
uint64_t
|
||||
WifiMode::GetDataRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
|
||||
{
|
||||
//TODO: nss > 4 not supported yet
|
||||
NS_ASSERT (nss <= 4);
|
||||
struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
|
||||
uint64_t dataRate = 0;
|
||||
if (item->modClass == WIFI_MOD_CLASS_DSSS)
|
||||
{
|
||||
dataRate = (11000000 / 11) * log2 (GetConstellationSize (nss));
|
||||
dataRate = (11000000 / 11) * log2 (GetConstellationSize ());
|
||||
}
|
||||
else if (item->modClass == WIFI_MOD_CLASS_HR_DSSS)
|
||||
{
|
||||
dataRate = (11000000 / 8) * log2 (GetConstellationSize (nss));
|
||||
dataRate = (11000000 / 8) * log2 (GetConstellationSize ());
|
||||
}
|
||||
else if (item->modClass == WIFI_MOD_CLASS_OFDM || item->modClass == WIFI_MOD_CLASS_ERP_OFDM)
|
||||
{
|
||||
@@ -136,7 +140,7 @@ WifiMode::GetDataRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t
|
||||
}
|
||||
|
||||
double codingRate;
|
||||
switch (GetCodeRate (nss))
|
||||
switch (GetCodeRate ())
|
||||
{
|
||||
case WIFI_CODE_RATE_3_4:
|
||||
codingRate = (3.0 / 4.0);
|
||||
@@ -153,7 +157,7 @@ WifiMode::GetDataRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize (nss));
|
||||
uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize ());
|
||||
|
||||
dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate));
|
||||
}
|
||||
@@ -198,7 +202,7 @@ WifiMode::GetDataRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t
|
||||
}
|
||||
|
||||
double codingRate;
|
||||
switch (GetCodeRate (nss))
|
||||
switch (GetCodeRate ())
|
||||
{
|
||||
case WIFI_CODE_RATE_5_6:
|
||||
codingRate = (5.0 / 6.0);
|
||||
@@ -218,7 +222,7 @@ WifiMode::GetDataRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize (nss));
|
||||
uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize ());
|
||||
|
||||
dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate));
|
||||
}
|
||||
@@ -237,12 +241,11 @@ WifiMode::GetDataRate (WifiTxVector txVector) const
|
||||
}
|
||||
|
||||
enum WifiCodeRate
|
||||
WifiMode::GetCodeRate (uint8_t nss) const
|
||||
WifiMode::GetCodeRate (void) const
|
||||
{
|
||||
struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
|
||||
if (item->modClass == WIFI_MOD_CLASS_HT)
|
||||
{
|
||||
NS_ASSERT (nss <= 4);
|
||||
switch (item->mcsValue % 8)
|
||||
{
|
||||
case 0:
|
||||
@@ -263,7 +266,6 @@ WifiMode::GetCodeRate (uint8_t nss) const
|
||||
}
|
||||
else if (item->modClass == WIFI_MOD_CLASS_VHT)
|
||||
{
|
||||
NS_ASSERT (nss <= 8);
|
||||
switch (item->mcsValue)
|
||||
{
|
||||
case 0:
|
||||
@@ -291,13 +293,11 @@ WifiMode::GetCodeRate (uint8_t nss) const
|
||||
}
|
||||
|
||||
uint16_t
|
||||
WifiMode::GetConstellationSize (uint8_t nss) const
|
||||
WifiMode::GetConstellationSize (void) const
|
||||
{
|
||||
struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
|
||||
if (item->modClass == WIFI_MOD_CLASS_HT)
|
||||
{
|
||||
NS_ASSERT (nss <= 4);
|
||||
NS_ASSERT ((item->mcsValue - (8 * (nss - 1))) >= 0 || (item->mcsValue - (8 * (nss - 1))) <= 7);
|
||||
switch (item->mcsValue % 8)
|
||||
{
|
||||
case 0:
|
||||
@@ -318,7 +318,6 @@ WifiMode::GetConstellationSize (uint8_t nss) const
|
||||
}
|
||||
else if (item->modClass == WIFI_MOD_CLASS_VHT)
|
||||
{
|
||||
NS_ASSERT (nss <= 8);
|
||||
switch (item->mcsValue)
|
||||
{
|
||||
case 0:
|
||||
@@ -391,14 +390,14 @@ WifiMode::GetModulationClass () const
|
||||
}
|
||||
|
||||
uint64_t
|
||||
WifiMode::GetNonHtReferenceRate (uint8_t nss) const
|
||||
WifiMode::GetNonHtReferenceRate (void) const
|
||||
{
|
||||
uint64_t dataRate;
|
||||
struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
|
||||
if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
|
||||
{
|
||||
WifiCodeRate codeRate = GetCodeRate(nss);
|
||||
switch(GetConstellationSize(nss))
|
||||
WifiCodeRate codeRate = GetCodeRate();
|
||||
switch(GetConstellationSize())
|
||||
{
|
||||
case 2:
|
||||
if (codeRate == WIFI_CODE_RATE_1_2)
|
||||
@@ -449,6 +448,83 @@ WifiMode::GetNonHtReferenceRate (uint8_t nss) const
|
||||
return dataRate;
|
||||
}
|
||||
|
||||
bool
|
||||
WifiMode::IsHigherCodeRate (WifiMode mode) const
|
||||
{
|
||||
WifiCodeRate codeRate = mode.GetCodeRate ();
|
||||
switch (GetCodeRate ())
|
||||
{
|
||||
case WIFI_CODE_RATE_1_2:
|
||||
return false; //This is the smallest code rate.
|
||||
case WIFI_CODE_RATE_2_3:
|
||||
return (codeRate == WIFI_CODE_RATE_1_2);
|
||||
case WIFI_CODE_RATE_3_4:
|
||||
return (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3);
|
||||
case WIFI_CODE_RATE_5_6:
|
||||
return (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3 || codeRate == WIFI_CODE_RATE_3_4);
|
||||
default:
|
||||
NS_FATAL_ERROR ("Wifi Code Rate not defined");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WifiMode::IsHigherDataRate (WifiMode mode) const
|
||||
{
|
||||
struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
|
||||
switch(item->modClass)
|
||||
{
|
||||
case WIFI_MOD_CLASS_DSSS:
|
||||
if (mode.GetModulationClass () == WIFI_MOD_CLASS_DSSS)
|
||||
{
|
||||
return (GetConstellationSize () > mode.GetConstellationSize ());
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
case WIFI_MOD_CLASS_HR_DSSS:
|
||||
if (mode.GetModulationClass () == WIFI_MOD_CLASS_DSSS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (GetConstellationSize () > mode.GetConstellationSize ());
|
||||
}
|
||||
case WIFI_MOD_CLASS_ERP_OFDM:
|
||||
case WIFI_MOD_CLASS_OFDM:
|
||||
case WIFI_MOD_CLASS_HT:
|
||||
case WIFI_MOD_CLASS_VHT:
|
||||
if (mode.GetModulationClass () == WIFI_MOD_CLASS_DSSS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (mode.GetModulationClass () == WIFI_MOD_CLASS_HR_DSSS)
|
||||
{
|
||||
return (mode.GetConstellationSize () > GetConstellationSize ());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetConstellationSize () > mode.GetConstellationSize ())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (GetConstellationSize () == mode.GetConstellationSize ())
|
||||
{
|
||||
return IsHigherCodeRate (mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
default:
|
||||
NS_FATAL_ERROR ("Modulation class not defined");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WifiMode::WifiMode ()
|
||||
: m_uid (0)
|
||||
{
|
||||
|
||||
@@ -136,19 +136,13 @@ public:
|
||||
*/
|
||||
uint64_t GetDataRate (WifiTxVector txVector) const;
|
||||
/**
|
||||
*
|
||||
* \param nss the considered number of streams
|
||||
*
|
||||
* \returns the coding rate of this transmission mode
|
||||
*/
|
||||
enum WifiCodeRate GetCodeRate (uint8_t nss) const;
|
||||
enum WifiCodeRate GetCodeRate (void) const;
|
||||
/**
|
||||
*
|
||||
* \param nss the considered number of streams
|
||||
*
|
||||
* \returns the size of the modulation constellation.
|
||||
*/
|
||||
uint16_t GetConstellationSize (uint8_t nss) const;
|
||||
uint16_t GetConstellationSize (void) const;
|
||||
/**
|
||||
* \returns the MCS value.
|
||||
*/
|
||||
@@ -185,7 +179,17 @@ public:
|
||||
* use the modulation and coding rate of the HT MCS
|
||||
* and lookup in Table 9-5 of IEEE 802.11-2012.
|
||||
*/
|
||||
uint64_t GetNonHtReferenceRate (uint8_t nss) const;
|
||||
uint64_t GetNonHtReferenceRate (void) const;
|
||||
/**
|
||||
* \returns true if this WifiMode has a
|
||||
* a code rate strictly higher than mode.
|
||||
*/
|
||||
bool IsHigherCodeRate (WifiMode mode) const;
|
||||
/**
|
||||
* \returns true if this WifiMode has a
|
||||
* a rate strictly higher than mode.
|
||||
*/
|
||||
bool IsHigherDataRate (WifiMode mode) const;
|
||||
|
||||
/**
|
||||
* Create an invalid WifiMode. Calling any method on the
|
||||
|
||||
@@ -1107,6 +1107,28 @@ WifiRemoteStationManager::IsLastFragment (Mac48Address address, const WifiMacHea
|
||||
return isLast;
|
||||
}
|
||||
|
||||
bool
|
||||
WifiRemoteStationManager::IsAllowedControlAnswerModulationClass (enum WifiModulationClass modClassReq, enum WifiModulationClass modClassAnswer) const
|
||||
{
|
||||
switch (modClassReq)
|
||||
{
|
||||
case WIFI_MOD_CLASS_DSSS:
|
||||
return (modClassAnswer == WIFI_MOD_CLASS_DSSS);
|
||||
case WIFI_MOD_CLASS_HR_DSSS:
|
||||
return (modClassAnswer == WIFI_MOD_CLASS_DSSS || modClassAnswer == WIFI_MOD_CLASS_HR_DSSS);
|
||||
case WIFI_MOD_CLASS_ERP_OFDM:
|
||||
return (modClassAnswer == WIFI_MOD_CLASS_DSSS || modClassAnswer == WIFI_MOD_CLASS_HR_DSSS || modClassAnswer == WIFI_MOD_CLASS_ERP_OFDM);
|
||||
case WIFI_MOD_CLASS_OFDM:
|
||||
return (modClassAnswer == WIFI_MOD_CLASS_OFDM);
|
||||
case WIFI_MOD_CLASS_HT:
|
||||
case WIFI_MOD_CLASS_VHT:
|
||||
return true;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Modulation class not defined");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WifiMode
|
||||
WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode reqMode)
|
||||
{
|
||||
@@ -1127,17 +1149,12 @@ WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode r
|
||||
NS_LOG_FUNCTION (this << address << reqMode);
|
||||
WifiMode mode = GetDefaultMode ();
|
||||
bool found = false;
|
||||
uint8_t nss = 1; // Use one spatial stream for control response
|
||||
//First, search the BSS Basic Rate set
|
||||
for (WifiModeListIterator i = m_bssBasicRateSet.begin (); i != m_bssBasicRateSet.end (); i++)
|
||||
{
|
||||
if ((!found || i->GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss) > mode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss))
|
||||
&& (i->GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss) <= reqMode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss))
|
||||
&& (i->GetConstellationSize (nss) <= reqMode.GetConstellationSize (nss))
|
||||
&& ((i->GetModulationClass () == reqMode.GetModulationClass ())
|
||||
|| (reqMode.GetModulationClass () == WIFI_MOD_CLASS_HT)
|
||||
|| (reqMode.GetModulationClass () == WIFI_MOD_CLASS_VHT)))
|
||||
|
||||
if ((!found || i->IsHigherDataRate (mode))
|
||||
&& (!i->IsHigherDataRate (reqMode))
|
||||
&& (IsAllowedControlAnswerModulationClass (reqMode.GetModulationClass (), i->GetModulationClass ())))
|
||||
{
|
||||
mode = *i;
|
||||
//We've found a potentially-suitable transmit rate, but we
|
||||
@@ -1146,7 +1163,6 @@ WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode r
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
nss = 1; // Continue the assumption that MIMO not used for control response
|
||||
if (HasHtSupported () || HasVhtSupported ())
|
||||
{
|
||||
if (!found)
|
||||
@@ -1154,9 +1170,9 @@ WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode r
|
||||
mode = GetDefaultMcs ();
|
||||
for (WifiModeListIterator i = m_bssBasicMcsSet.begin (); i != m_bssBasicMcsSet.end (); i++)
|
||||
{
|
||||
if ((!found || i->GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss) > mode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss))
|
||||
&& i->GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss) <= reqMode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss))
|
||||
//&& thismode.GetModulationClass () == reqMode.GetModulationClass ()) //TODO: check standard
|
||||
if ((!found || i->IsHigherDataRate (mode))
|
||||
&& (!i->IsHigherDataRate (reqMode))
|
||||
&& (i->GetModulationClass () == reqMode.GetModulationClass ()))
|
||||
{
|
||||
mode = *i;
|
||||
//We've found a potentially-suitable transmit rate, but we
|
||||
@@ -1192,11 +1208,9 @@ WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode r
|
||||
* \todo Note that we're ignoring the last sentence for now, because
|
||||
* there is not yet any manipulation here of PHY options.
|
||||
*/
|
||||
nss = 1; // Continue the assumption that MIMO not used for control response
|
||||
for (uint32_t idx = 0; idx < m_wifiPhy->GetNModes (); idx++)
|
||||
{
|
||||
WifiMode thismode = m_wifiPhy->GetMode (idx);
|
||||
|
||||
/* If the rate:
|
||||
*
|
||||
* - is a mandatory rate for the PHY, and
|
||||
@@ -1207,13 +1221,9 @@ WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode r
|
||||
* ...then it's our best choice so far.
|
||||
*/
|
||||
if (thismode.IsMandatory ()
|
||||
&& (!found || thismode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss) > mode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss))
|
||||
&& (thismode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss) <= reqMode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss))
|
||||
&& (thismode.GetConstellationSize (nss) <= reqMode.GetConstellationSize (nss))
|
||||
&& ((thismode.GetModulationClass () == reqMode.GetModulationClass ())
|
||||
|| (reqMode.GetModulationClass () == WIFI_MOD_CLASS_HT)
|
||||
|| (reqMode.GetModulationClass () == WIFI_MOD_CLASS_HT)))
|
||||
|
||||
&& (!found || thismode.IsHigherDataRate (mode))
|
||||
&& (!thismode.IsHigherDataRate (reqMode))
|
||||
&& (IsAllowedControlAnswerModulationClass (reqMode.GetModulationClass (), thismode.GetModulationClass ())))
|
||||
{
|
||||
mode = thismode;
|
||||
//As above; we've found a potentially-suitable transmit
|
||||
@@ -1222,16 +1232,15 @@ WifiRemoteStationManager::GetControlAnswerMode (Mac48Address address, WifiMode r
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
nss = 1; // Continue the assumption that MIMO not used for control response
|
||||
if (HasHtSupported () || HasVhtSupported ())
|
||||
{
|
||||
for (uint32_t idx = 0; idx < m_wifiPhy->GetNMcs (); idx++)
|
||||
{
|
||||
WifiMode thismode = m_wifiPhy->GetMcs (idx);
|
||||
if (thismode.IsMandatory ()
|
||||
&& (!found || thismode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss) > mode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss))
|
||||
&& thismode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss) <= reqMode.GetPhyRate (m_wifiPhy->GetChannelWidth (), 0, nss))
|
||||
//&& thismode.GetModulationClass () == reqMode.GetModulationClass ()) //TODO: check standard
|
||||
&& (!found || thismode.IsHigherDataRate (mode))
|
||||
&& (!thismode.IsHigherCodeRate(reqMode))
|
||||
&& (thismode.GetModulationClass () == reqMode.GetModulationClass ()))
|
||||
{
|
||||
mode = thismode;
|
||||
//As above; we've found a potentially-suitable transmit
|
||||
|
||||
@@ -1140,6 +1140,18 @@ private:
|
||||
*/
|
||||
WifiRemoteStation* Lookup (Mac48Address address, const WifiMacHeader *header) const;
|
||||
|
||||
/**
|
||||
* Return whether the modulation class of the selected mode for the
|
||||
* control answer frame is allowed.
|
||||
*
|
||||
* \param modClassReq modulation class of the request frame
|
||||
* \param modClassAnswer modulation class of the answer frame
|
||||
*
|
||||
* \return true if the modulation class of the selected mode for the
|
||||
* control answer frame is allowed, false otherwise
|
||||
*/
|
||||
bool IsAllowedControlAnswerModulationClass (enum WifiModulationClass modClassReq, enum WifiModulationClass modClassAnswer) const;
|
||||
|
||||
WifiMode GetControlAnswerMode (Mac48Address address, WifiMode reqMode);
|
||||
|
||||
/**
|
||||
|
||||
@@ -188,15 +188,14 @@ double
|
||||
YansErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, double snr, uint32_t nbits) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << mode << txVector.GetMode () << snr << nbits);
|
||||
uint8_t nss = txVector.GetNss ();
|
||||
if (mode.GetModulationClass () == WIFI_MOD_CLASS_ERP_OFDM
|
||||
|| mode.GetModulationClass () == WIFI_MOD_CLASS_OFDM
|
||||
|| mode.GetModulationClass () == WIFI_MOD_CLASS_HT
|
||||
|| mode.GetModulationClass () == WIFI_MOD_CLASS_VHT)
|
||||
{
|
||||
if (mode.GetConstellationSize (nss) == 2)
|
||||
if (mode.GetConstellationSize () == 2)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_1_2)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_1_2)
|
||||
{
|
||||
return GetFecBpskBer (snr,
|
||||
nbits,
|
||||
@@ -215,9 +214,9 @@ YansErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, d
|
||||
8); //adFree
|
||||
}
|
||||
}
|
||||
else if (mode.GetConstellationSize (nss) == 4)
|
||||
else if (mode.GetConstellationSize () == 4)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_1_2)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_1_2)
|
||||
{
|
||||
return GetFecQamBer (snr,
|
||||
nbits,
|
||||
@@ -240,9 +239,9 @@ YansErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, d
|
||||
31); //adFreePlusOne
|
||||
}
|
||||
}
|
||||
else if (mode.GetConstellationSize (nss) == 16)
|
||||
else if (mode.GetConstellationSize () == 16)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_1_2)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_1_2)
|
||||
{
|
||||
return GetFecQamBer (snr,
|
||||
nbits,
|
||||
@@ -265,9 +264,9 @@ YansErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, d
|
||||
31); //adFreePlusOne
|
||||
}
|
||||
}
|
||||
else if (mode.GetConstellationSize (nss) == 64)
|
||||
else if (mode.GetConstellationSize () == 64)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_2_3)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_2_3)
|
||||
{
|
||||
return GetFecQamBer (snr,
|
||||
nbits,
|
||||
@@ -278,7 +277,7 @@ YansErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, d
|
||||
1, //adFree
|
||||
16); //adFreePlusOne
|
||||
}
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_5_6)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_5_6)
|
||||
{
|
||||
//Table B.32 in Pâl Frenger et al., "Multi-rate Convolutional Codes".
|
||||
return GetFecQamBer (snr,
|
||||
@@ -302,9 +301,9 @@ YansErrorRateModel::GetChunkSuccessRate (WifiMode mode, WifiTxVector txVector, d
|
||||
31); //adFreePlusOne
|
||||
}
|
||||
}
|
||||
else if (mode.GetConstellationSize (nss) == 256)
|
||||
else if (mode.GetConstellationSize () == 256)
|
||||
{
|
||||
if (mode.GetCodeRate (nss) == WIFI_CODE_RATE_5_6)
|
||||
if (mode.GetCodeRate () == WIFI_CODE_RATE_5_6)
|
||||
{
|
||||
return GetFecQamBer (snr,
|
||||
nbits,
|
||||
|
||||
Reference in New Issue
Block a user