wifi: (fixes #2338) Improve and fix control answer rate selection

This commit is contained in:
Sébastien Deronne
2016-03-21 20:51:12 +01:00
parent 4d3c98e210
commit 11847e5332
8 changed files with 176 additions and 77 deletions

View File

@@ -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
------------

View File

@@ -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;

View File

@@ -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,

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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

View File

@@ -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);
/**

View File

@@ -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,